{"id":3,"date":"2026-06-21T16:36:53","date_gmt":"2026-06-21T16:36:53","guid":{"rendered":"http:\/\/shypoints.online\/?page_id=3"},"modified":"2026-06-21T17:37:48","modified_gmt":"2026-06-21T17:37:48","slug":"exchange","status":"publish","type":"page","link":"https:\/\/shypoints.online\/en\/exchange\/","title":{"rendered":""},"content":{"rendered":"<p><!DOCTYPE html><br \/>\n<html lang=\"zh-CN\"><br \/>\n<head><br \/>\n    <meta charset=\"UTF-8\" \/><br \/>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \/><br \/>\n    <title id=\"pageTitle\">SHY\uff08\u4eba\u5de5\u751f\u547d\u4f7f\u7528\u70b9\u6570\uff09\u7528\u6237\u64cd\u4f5c\u5e73\u53f0<\/title>\n    <link rel=\"icon\" type=\"image\/svg+xml\" href=\"\/logo.svg\" id=\"favicon\" \/>\n<link rel=\"icon\" type=\"image\/svg+xml\" href=\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%23131d2f'\/%3E%3Cpath d='M32 12 L44 20 L44 44 L32 52 L20 44 L20 20 L32 12Z' fill='%233b82f6' opacity='0.9'\/%3E%3Cpath d='M32 20 L38 24 L38 40 L32 44 L26 40 L26 24 L32 20Z' fill='%23a78bfa'\/%3E%3Ctext x='32' y='46' text-anchor='middle' font-size='42' font-weight='700' fill='%23e8edf5' font-family='system-ui'%3E%C4%A6%3C\/text%3E%3C\/svg%3E\" id=\"favicon\" \/>\n<link rel=\"apple-touch-icon\" sizes=\"192x192\" href=\"\/icon-192.png\" \/>\n<link rel=\"manifest\" href=\"\/manifest.json\" \/>\n    <link rel=\"apple-touch-icon\" sizes=\"192x192\" href=\"\/icon-192.png\" \/>\n    <link rel=\"manifest\" href=\"\/manifest.json\" \/>\n<style>\n    <link rel=\"manifest\" href=\"\/manifest.json\" \/>\n<style>\n        * {\n            margin: 0;\n            padding: 0;\n            box-sizing: border-box;\n        }<\/p>\n<p>        :root {\n            --primary: #3b82f6;\n            --primary-hover: #2563eb;\n            --bg-primary: #0b1120;\n            --bg-secondary: #131d2f;\n            --bg-card: #131d2f;\n            --bg-input: #0b1220;\n            --border-color: #1e2d44;\n            --text-primary: #e8edf5;\n            --text-secondary: #94a3b8;\n            --radius: 20px;\n            --radius-sm: 12px;\n            --spacing: 24px;\n            --font-mono: 'JetBrains Mono', 'Cascadia Code', monospace;\n        }<\/p>\n<p>        body {\n            font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n            background: var(--bg-primary);\n            color: var(--text-primary);\n            min-height: 100vh;\n            padding: var(--spacing);\n        }<\/p>\n<p>        .container {\n            max-width: 1320px;\n            margin: 0 auto;\n        }<\/p>\n<p>        .header {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            padding: 16px 24px;\n            background: var(--bg-secondary);\n            border-radius: var(--radius);\n            border: 1px solid var(--border-color);\n            margin-bottom: var(--spacing);\n            flex-wrap: wrap;\n            gap: 12px;\n        }<\/p>\n<p>        .header-left {\n            display: flex;\n            align-items: center;\n            gap: 14px;\n        }<\/p>\n<p>        .logo {\n            display: flex;\n            align-items: center;\n            gap: 10px;\n            text-decoration: none;\n            color: inherit;\n            flex-shrink: 0;\n        }<\/p>\n<p>        .logo img {\n            height: 36px;\n            width: auto;\n            display: block;\n        }<\/p>\n<p>        .logo-placeholder {\n            width: 36px;\n            height: 36px;\n            border-radius: 10px;\n            background: linear-gradient(135deg, #3b82f6, #8b5cf6);\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            font-weight: 700;\n            font-size: 16px;\n            color: #fff;\n            flex-shrink: 0;\n        }<\/p>\n<p>        .logo h1 {\n            font-size: 18px;\n            font-weight: 700;\n            background: linear-gradient(135deg, #60a5fa, #a78bfa);\n            -webkit-background-clip: text;\n            -webkit-text-fill-color: transparent;\n            background-clip: text;\n            white-space: nowrap;\n        }<\/p>\n<p>        .header-right {\n            display: flex;\n            align-items: center;\n            gap: 10px;\n            flex-wrap: wrap;\n        }<\/p>\n<p>        .lang-switcher {\n            display: flex;\n            gap: 4px;\n            background: var(--bg-input);\n            padding: 4px;\n            border-radius: 10px;\n            border: 1px solid var(--border-color);\n        }<\/p>\n<p>        .lang-btn {\n            padding: 5px 10px;\n            border: none;\n            border-radius: 7px;\n            background: transparent;\n            color: var(--text-secondary);\n            font-size: 12px;\n            cursor: pointer;\n            transition: all 0.2s;\n            font-weight: 500;\n            display: flex;\n            align-items: center;\n            gap: 4px;\n        }<\/p>\n<p>        .lang-btn:hover {\n            background: #1e2a41;\n            color: var(--text-primary);\n        }<\/p>\n<p>        .lang-btn.active {\n            background: var(--primary);\n            color: #fff;\n        }<\/p>\n<p>        .lang-btn .flag {\n            font-size: 14px;\n        }<\/p>\n<p>        @media (max-width: 500px) {\n            .lang-btn .lang-label {\n                display: none;\n            }\n            .lang-btn {\n                padding: 5px 8px;\n            }\n        }<\/p>\n<p>        .wallet-badge {\n            background: #1e2a41;\n            padding: 6px 16px;\n            border-radius: 40px;\n            font-size: 13px;\n            font-family: var(--font-mono);\n            color: var(--text-secondary);\n            border: 1px solid var(--border-color);\n        }<\/p>\n<p>        .wallet-badge.connected {\n            color: #4ade80;\n            border-color: #4ade8040;\n        }<\/p>\n<p>        .btn {\n            padding: 8px 20px;\n            border: none;\n            border-radius: var(--radius-sm);\n            font-size: 14px;\n            font-weight: 600;\n            cursor: pointer;\n            transition: all 0.2s;\n            display: inline-flex;\n            align-items: center;\n            gap: 6px;\n            white-space: nowrap;\n        }<\/p>\n<p>        .btn-primary {\n            background: var(--primary);\n            color: #fff;\n        }\n        .btn-primary:hover {\n            background: var(--primary-hover);\n            transform: translateY(-1px);\n        }<\/p>\n<p>        .btn-success {\n            background: #22c55e;\n            color: #fff;\n        }\n        .btn-success:hover {\n            background: #16a34a;\n        }<\/p>\n<p>        .btn-danger {\n            background: #ef4444;\n            color: #fff;\n        }\n        .btn-danger:hover {\n            background: #dc2626;\n        }<\/p>\n<p>        .btn-warning {\n            background: #f59e0b;\n            color: #0b1120;\n        }\n        .btn-warning:hover {\n            background: #d97706;\n        }<\/p>\n<p>        .btn-outline {\n            background: transparent;\n            color: var(--text-secondary);\n            border: 1px solid var(--border-color);\n        }\n        .btn-outline:hover {\n            background: #1e2a41;\n        }<\/p>\n<p>        .btn-email {\n            background: #8b5cf6;\n            color: #fff;\n        }\n        .btn-email:hover {\n            background: #7c3aed;\n            transform: translateY(-1px);\n        }<\/p>\n<p>        .btn-sm {\n            padding: 5px 12px;\n            font-size: 12px;\n            border-radius: 8px;\n        }\n        .btn:disabled {\n            opacity: 0.5;\n            cursor: not-allowed;\n            transform: none !important;\n        }<\/p>\n<p>        .btn-disconnect {\n            background: #ef4444;\n            color: #fff;\n        }\n        .btn-disconnect:hover {\n            background: #dc2626;\n            transform: translateY(-1px);\n        }<\/p>\n<p>        .token-banner {\n            display: grid;\n            grid-template-columns: 1fr 1fr 1fr 1fr;\n            gap: 16px;\n            padding: 16px 24px;\n            background: linear-gradient(135deg, #131d2f, #1a2538);\n            border-radius: var(--radius);\n            border: 1px solid var(--border-color);\n            margin-bottom: var(--spacing);\n        }<\/p>\n<p>        .token-banner .banner-item {\n            display: flex;\n            flex-direction: column;\n            gap: 4px;\n        }<\/p>\n<p>        .token-banner .banner-item .banner-label {\n            font-size: 12px;\n            color: var(--text-secondary);\n            text-transform: uppercase;\n            letter-spacing: 0.5px;\n        }<\/p>\n<p>        .token-banner .banner-item .banner-value {\n            font-size: 18px;\n            font-weight: 600;\n            color: var(--text-primary);\n            font-family: var(--font-mono);\n            word-break: break-all;\n        }<\/p>\n<p>        .token-banner .banner-item .banner-value .green {\n            color: #4ade80;\n        }<\/p>\n<p>        .token-banner .banner-item .banner-value .red {\n            color: #f87171;\n        }<\/p>\n<p>        .token-banner .banner-item .banner-value .yellow {\n            color: #facc15;\n        }<\/p>\n<p>        .token-banner .banner-actions {\n            display: flex;\n            align-items: flex-end;\n            justify-content: flex-end;\n            gap: 8px;\n        }<\/p>\n<p>        @media (max-width: 1024px) {\n            .token-banner {\n                grid-template-columns: 1fr 1fr;\n            }\n        }<\/p>\n<p>        @media (max-width: 640px) {\n            .token-banner {\n                grid-template-columns: 1fr;\n                gap: 10px;\n                padding: 14px 18px;\n            }\n            .token-banner .banner-item .banner-value {\n                font-size: 16px;\n            }\n            .token-banner .banner-actions {\n                justify-content: flex-start;\n                margin-top: 4px;\n            }\n        }<\/p>\n<p>        .exchange-preview {\n            background: var(--bg-input);\n            border-radius: var(--radius-sm);\n            padding: 10px 14px;\n            margin-top: 8px;\n            border: 1px solid var(--border-color);\n            font-size: 13px;\n            color: var(--text-secondary);\n            display: none;\n        }<\/p>\n<p>        .exchange-preview.show {\n            display: block;\n        }<\/p>\n<p>        .exchange-preview .preview-row {\n            display: flex;\n            justify-content: space-between;\n            padding: 2px 0;\n            gap: 12px;\n        }<\/p>\n<p>        .exchange-preview .preview-row .preview-label {\n            color: var(--text-secondary);\n        }<\/p>\n<p>        .exchange-preview .preview-row .preview-value {\n            color: var(--text-primary);\n            font-family: var(--font-mono);\n        }<\/p>\n<p>        .exchange-preview .preview-row .preview-value.green {\n            color: #4ade80;\n        }<\/p>\n<p>        .exchange-preview .preview-row .preview-value.yellow {\n            color: #facc15;\n        }<\/p>\n<p>        .exchange-preview .preview-row .preview-value.red {\n            color: #f87171;\n        }<\/p>\n<p>        .status-bar {\n            display: flex;\n            gap: 20px;\n            flex-wrap: wrap;\n            padding: 12px 20px;\n            background: #0f1a2a;\n            border-radius: 14px;\n            border: 1px solid var(--border-color);\n            margin-bottom: var(--spacing);\n            font-size: 13px;\n            color: var(--text-secondary);\n        }<\/p>\n<p>        .status-bar strong {\n            color: var(--text-primary);\n            font-weight: 500;\n        }<\/p>\n<p>        .grid {\n            display: grid;\n            grid-template-columns: 1fr 1fr;\n            gap: var(--spacing);\n            margin-bottom: var(--spacing);\n            justify-content: center;\n            align-items: start;\n        }<\/p>\n<p>        .grid-center {\n            display: flex;\n            justify-content: center;\n            gap: var(--spacing);\n            flex-wrap: wrap;\n            margin-bottom: var(--spacing);\n        }<\/p>\n<p>        .grid-center .card {\n            flex: 1;\n            min-width: 320px;\n            max-width: 560px;\n        }<\/p>\n<p>        @media (max-width: 768px) {\n            .grid {\n                grid-template-columns: 1fr;\n                gap: 16px;\n            }\n            .grid-center .card {\n                min-width: 100%;\n                max-width: 100%;\n            }\n        }<\/p>\n<p>        @media (max-width: 480px) {\n            .grid {\n                grid-template-columns: 1fr;\n                gap: 14px;\n            }\n            body {\n                padding: 12px;\n            }\n            .header {\n                padding: 12px 16px;\n            }\n            .logo h1 {\n                font-size: 14px;\n            }\n            .header-left {\n                gap: 10px;\n            }\n        }<\/p>\n<p>        .card {\n            background: var(--bg-secondary);\n            border-radius: var(--radius);\n            border: 1px solid var(--border-color);\n            padding: 20px 24px;\n            transition: border-color 0.2s;\n            min-width: 0;\n        }<\/p>\n<p>        .card:hover {\n            border-color: #2d405a;\n        }<\/p>\n<p>        .card-header {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            margin-bottom: 16px;\n            padding-bottom: 12px;\n            border-bottom: 1px solid #0f1a2a;\n            flex-wrap: wrap;\n            gap: 8px;\n        }<\/p>\n<p>        .card-header h3 {\n            font-size: 16px;\n            font-weight: 600;\n            color: #c8d0dc;\n            display: flex;\n            align-items: center;\n            gap: 8px;\n        }<\/p>\n<p>        .badge {\n            font-size: 11px;\n            padding: 2px 10px;\n            border-radius: 40px;\n            background: #1a2538;\n            color: #7a8aa0;\n            font-weight: 400;\n        }<\/p>\n<p>        .form-group {\n            margin-bottom: 12px;\n        }<\/p>\n<p>        .form-group label {\n            display: block;\n            font-size: 13px;\n            color: var(--text-secondary);\n            margin-bottom: 4px;\n        }<\/p>\n<p>        .form-group input,\n        .form-group select,\n        .form-group textarea {\n            width: 100%;\n            padding: 10px 14px;\n            background: var(--bg-input);\n            border: 1px solid var(--border-color);\n            border-radius: var(--radius-sm);\n            color: var(--text-primary);\n            font-size: 14px;\n            font-family: var(--font-mono);\n            outline: none;\n            transition: border 0.2s;\n            resize: vertical;\n        }<\/p>\n<p>        .form-group input:focus,\n        .form-group select:focus,\n        .form-group textarea:focus {\n            border-color: var(--primary);\n            box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);\n        }<\/p>\n<p>        .form-group input::placeholder,\n        .form-group textarea::placeholder {\n            color: #475569;\n        }<\/p>\n<p>        .form-group textarea {\n            min-height: 60px;\n            font-family: 'Inter', sans-serif;\n        }<\/p>\n<p>        .form-row {\n            display: flex;\n            gap: 12px;\n        }\n        .form-row .form-group {\n            flex: 1;\n        }<\/p>\n<p>        @media (max-width: 640px) {\n            .form-row {\n                flex-direction: column;\n                gap: 8px;\n            }\n        }<\/p>\n<p>        .card-actions {\n            display: flex;\n            gap: 8px;\n            flex-wrap: wrap;\n        }<\/p>\n<p>        .info-row {\n            display: flex;\n            justify-content: space-between;\n            padding: 6px 0;\n            font-size: 13px;\n            border-bottom: 1px solid #0f1a2a;\n            gap: 8px;\n        }<\/p>\n<p>        .info-row:last-child {\n            border-bottom: none;\n        }<\/p>\n<p>        .info-row .label {\n            color: var(--text-secondary);\n            flex-shrink: 0;\n        }<\/p>\n<p>        .info-row .value {\n            color: var(--text-primary);\n            font-family: var(--font-mono);\n            font-size: 13px;\n            word-break: break-all;\n            text-align: right;\n        }<\/p>\n<p>        .info-row .value.green {\n            color: #4ade80;\n        }\n        .info-row .value.red {\n            color: #f87171;\n        }\n        .info-row .value.yellow {\n            color: #facc15;\n        }<\/p>\n<p>        .request-list {\n            max-height: 180px;\n            overflow-y: auto;\n            margin-top: 10px;\n        }<\/p>\n<p>        .request-list .req-item {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            padding: 8px 12px;\n            background: var(--bg-input);\n            border-radius: var(--radius-sm);\n            margin-bottom: 6px;\n            border: 1px solid #0f1a2a;\n            flex-wrap: wrap;\n            gap: 6px;\n        }<\/p>\n<p>        .request-list .req-item .req-info {\n            font-family: var(--font-mono);\n            font-size: 12px;\n            color: var(--text-secondary);\n            word-break: break-all;\n        }<\/p>\n<p>        .request-list .req-item .req-actions {\n            display: flex;\n            gap: 4px;\n            flex-shrink: 0;\n        }<\/p>\n<p>        .request-list .empty {\n            color: #475569;\n            text-align: center;\n            padding: 20px 0;\n            font-size: 13px;\n        }<\/p>\n<p>        .toast {\n            position: fixed;\n            bottom: 24px;\n            right: 24px;\n            padding: 14px 24px;\n            border-radius: var(--radius-sm);\n            font-size: 14px;\n            max-width: 420px;\n            z-index: 999;\n            animation: slideUp 0.3s ease;\n            background: var(--bg-secondary);\n            border: 1px solid var(--border-color);\n            color: var(--text-primary);\n            box-shadow: 0 8px 40px rgba(0, 0, 0, 0.6);\n        }<\/p>\n<p>        .toast.success {\n            border-color: #4ade80;\n        }\n        .toast.error {\n            border-color: #f87171;\n        }\n        .toast.info {\n            border-color: #60a5fa;\n        }<\/p>\n<p>        @keyframes slideUp {\n            from {\n                transform: translateY(20px);\n                opacity: 0;\n            }\n            to {\n                transform: translateY(0);\n                opacity: 1;\n            }\n        }<\/p>\n<p>        .spinner {\n            display: inline-block;\n            width: 18px;\n            height: 18px;\n            border: 2px solid #1e2d44;\n            border-top-color: var(--primary);\n            border-radius: 50%;\n            animation: spin 0.7s linear infinite;\n        }<\/p>\n<p>        @keyframes spin {\n            to {\n                transform: rotate(360deg);\n            }\n        }<\/p>\n<p>        .protocol-warning,\n        .no-wallet-box {\n            display: none;\n            border-radius: var(--radius-sm);\n            padding: 12px 18px;\n            margin-bottom: 12px;\n            font-size: 14px;\n        }<\/p>\n<p>        .protocol-warning {\n            background: #1e2a1a;\n            border: 1px solid #3d5a3a;\n            color: #facc15;\n        }\n        .protocol-warning a {\n            color: #60a5fa;\n        }<\/p>\n<p>        .no-wallet-box {\n            background: #1e1a2a;\n            border: 1px solid #3d2a3a;\n            color: #f87171;\n        }<\/p>\n<p>        .protocol-warning.show,\n        .no-wallet-box.show {\n            display: block;\n        }<\/p>\n<p>        .full-width {\n            grid-column: 1 \/ -1;\n        }<\/p>\n<p>        .footnote {\n            text-align: center;\n            font-size: 12px;\n            color: #475569;\n            padding: 16px 0;\n            border-top: 1px solid #0f1a2a;\n            margin-top: 8px;\n        }<\/p>\n<p>        hr {\n            border: none;\n            border-top: 1px solid #0f1a2a;\n            margin: 16px 0;\n        }<\/p>\n<p>        .address-hint {\n            font-size: 12px;\n            color: #475569;\n            margin-top: 4px;\n            font-style: italic;\n        }<\/p>\n<p>        .info-box {\n            background: #0b1220;\n            border-radius: var(--radius-sm);\n            padding: 12px 16px;\n            margin-bottom: 12px;\n            border-left: 3px solid var(--primary);\n            font-size: 13px;\n            color: var(--text-secondary);\n            line-height: 1.6;\n        }<\/p>\n<p>        .info-box strong {\n            color: var(--text-primary);\n        }<\/p>\n<p>        .info-box.warning {\n            border-left-color: #f59e0b;\n        }<\/p>\n<p>        .info-box.danger {\n            border-left-color: #ef4444;\n        }<\/p>\n<p>        .info-box.success {\n            border-left-color: #22c55e;\n        }<\/p>\n<p>        .email-fallback {\n            margin-top: 6px;\n            padding: 8px 12px;\n            background: #1e2a1a;\n            border-radius: 6px;\n            font-size: 12px;\n            color: #94a3b8;\n            border: 1px solid #2d405a;\n            word-break: break-all;\n        }<\/p>\n<p>        .email-fallback strong {\n            color: #60a5fa;\n        }<\/p>\n<p>        .email-fallback .copy-email {\n            color: #22c55e;\n            cursor: pointer;\n            text-decoration: underline;\n        }\n        .email-fallback .copy-email:hover {\n            color: #4ade80;\n        }<\/p>\n<p>        .address-manager {\n            display: flex;\n            gap: 12px;\n            align-items: center;\n            background: #0b1220;\n            border-radius: var(--radius-sm);\n            padding: 12px 16px;\n            border: 1px solid var(--border-color);\n            flex-wrap: wrap;\n        }<\/p>\n<p>        .address-manager input {\n            flex: 1;\n            min-width: 200px;\n            background: transparent;\n            border: none;\n            color: var(--text-primary);\n            font-family: var(--font-mono);\n            font-size: 14px;\n            outline: none;\n            padding: 0;\n        }<\/p>\n<p>        .address-manager input::placeholder {\n            color: #475569;\n        }<\/p>\n<p>        .address-manager .sync-badge {\n            font-size: 11px;\n            color: #4ade80;\n            background: #22c55e20;\n            padding: 2px 10px;\n            border-radius: 20px;\n            white-space: nowrap;\n            font-weight: 500;\n        }<\/p>\n<p>        .address-manager .sync-badge .sync-icon {\n            margin-right: 4px;\n        }<\/p>\n<p>        .address-manager-actions {\n            display: flex;\n            gap: 8px;\n            flex-wrap: wrap;\n            margin-top: 8px;\n        }<\/p>\n<p>        .address-sync-hint {\n            font-size: 11px;\n            color: #475569;\n            margin-top: 4px;\n            padding-left: 4px;\n            min-height: 20px;\n        }<\/p>\n<p>        .address-sync-hint .verified {\n            color: #4ade80;\n        }<\/p>\n<p>        .address-sync-hint .invalid {\n            color: #f87171;\n        }<\/p>\n<p>        \/* \u5361\u7247\u5c45\u4e2d *\/\n        .card-center {\n            margin-left: auto;\n            margin-right: auto;\n        }\n    <\/style>\n<p><\/head><br \/>\n<body><\/p>\n<div class=\"container\" id=\"app\">\n        <!-- ===== HEADER ===== --><\/p>\n<header class=\"header\">\n<div class=\"header-left\">\n                <a href=\"#\" class=\"logo\" id=\"logoLink\"><br \/>\n                    <img decoding=\"async\" src=\"\/logo.svg\" alt=\"SHY Logo\" id=\"logoImage\" onerror=\"this.style.display='none'\" \/><\/p>\n<div class=\"logo-placeholder\" id=\"logoPlaceholder\" style=\"display:none;\">S<\/div>\n<h1 id=\"appTitle\">SHY\uff08\u4eba\u5de5\u751f\u547d\u4f7f\u7528\u70b9\u6570\uff09\u7528\u6237\u64cd\u4f5c\u5e73\u53f0<\/h1>\n<p>                <\/a>\n            <\/div>\n<div class=\"header-right\">\n<div class=\"lang-switcher\" id=\"langSwitcher\">\n                    <button class=\"lang-btn active\" data-lang=\"zh\" onclick=\"switchLanguage('zh')\"><br \/>\n                        <span class=\"flag\">\ud83c\udde8\ud83c\uddf3<\/span><br \/>\n                        <span class=\"lang-label\">\u4e2d\u6587<\/span><br \/>\n                    <\/button><br \/>\n                    <button class=\"lang-btn\" data-lang=\"en\" onclick=\"switchLanguage('en')\"><br \/>\n                        <span class=\"flag\">\ud83c\uddfa\ud83c\uddf8<\/span><br \/>\n                        <span class=\"lang-label\">English<\/span><br \/>\n                    <\/button><br \/>\n                    <button class=\"lang-btn\" data-lang=\"ko\" onclick=\"switchLanguage('ko')\"><br \/>\n                        <span class=\"flag\">\ud83c\uddf0\ud83c\uddf7<\/span><br \/>\n                        <span class=\"lang-label\">\ud55c\uad6d\uc5b4<\/span><br \/>\n                    <\/button><br \/>\n                    <button class=\"lang-btn\" data-lang=\"fr\" onclick=\"switchLanguage('fr')\"><br \/>\n                        <span class=\"flag\">\ud83c\uddeb\ud83c\uddf7<\/span><br \/>\n                        <span class=\"lang-label\">Fran\u00e7ais<\/span><br \/>\n                    <\/button>\n                <\/div>\n<p>                <span class=\"wallet-badge\" id=\"walletDisplay\">\u26d3\ufe0f <span data-i18n=\"notConnected\">\u672a\u8fde\u63a5<\/span><\/span><br \/>\n                <button class=\"btn btn-primary\" id=\"connectBtn\"><span data-i18n=\"connectWallet\">\ud83d\udd0c \u8fde\u63a5\u94b1\u5305<\/span><\/button><br \/>\n                <button class=\"btn btn-outline btn-sm\" id=\"switchNetworkBtn\" style=\"display:none;\"><span data-i18n=\"switchNetwork\">\ud83d\udd04 \u5207\u6362\u5230 Base<\/span><\/button>\n            <\/div>\n<\/header>\n<p>        <!-- ===== \u8b66\u544a ===== --><\/p>\n<div class=\"protocol-warning\" id=\"protocolWarning\">\n            \u26a0\ufe0f <span data-i18n=\"protocolWarning\">\u68c0\u6d4b\u5230 file:\/\/ \u534f\u8bae\uff0cChrome \u4f1a\u963b\u6b62\u94b1\u5305\u6ce8\u5165\u3002\u8bf7\u4f7f\u7528 Live Server \u6216 http:\/\/ \u534f\u8bae\u6253\u5f00\u3002<\/span>\n        <\/div>\n<div class=\"no-wallet-box\" id=\"noWalletBox\">\n            \u26a0\ufe0f <span data-i18n=\"noWallet\">\u672a\u68c0\u6d4b\u5230\u94b1\u5305\u6269\u5c55\uff0c\u8bf7\u5b89\u88c5 MetaMask \u6216 TokenPocket\u3002<\/span>\n        <\/div>\n<p>        <!-- ===== \u72b6\u6001\u680f ===== --><\/p>\n<div class=\"status-bar\">\n            <span>\ud83d\udd17 <span data-i18n=\"network\">\u7f51\u7edc<\/span>: <strong id=\"networkDisplay\"><span data-i18n=\"notConnected\">\u672a\u8fde\u63a5<\/span><\/strong><\/span><br \/>\n            <span>\ud83d\udcb0 <span data-i18n=\"balance\">\u4f59\u989d<\/span>: <strong id=\"shyBalance\">0.0000<\/strong><\/span><br \/>\n            <span>\ud83d\udc64 <span data-i18n=\"role\">\u89d2\u8272<\/span>: <strong id=\"userRole\">\u2014<\/strong><\/span>\n        <\/div>\n<p>        <!-- ===== \u6a2a\u5e45\u5f0f\u4ee3\u5e01\u4fe1\u606f ===== --><\/p>\n<div class=\"token-banner\" id=\"tokenBanner\">\n<div class=\"banner-item\">\n                <span class=\"banner-label\"><span data-i18n=\"shyToken\">SHY \u70b9\u6570<\/span><\/span><br \/>\n                <span class=\"banner-value\" style=\"font-size:14px;color:var(--text-secondary);font-weight:400;font-family:var(--font-mono);\">0xC7Ed10fbA207...<\/span>\n            <\/div>\n<div class=\"banner-item\">\n                <span class=\"banner-label\"><span data-i18n=\"myBalance\">\u6211\u7684\u4f59\u989d<\/span><\/span><br \/>\n                <span class=\"banner-value\"><span class=\"green\" id=\"userBalance\">0.0000 SHY<\/span><\/span>\n            <\/div>\n<div class=\"banner-item\">\n                <span class=\"banner-label\"><span data-i18n=\"totalSupply\">\u603b\u4f9b\u5e94\u91cf<\/span><\/span><br \/>\n                <span class=\"banner-value\" id=\"totalSupply\">\u52a0\u8f7d\u4e2d...<\/span>\n            <\/div>\n<div class=\"banner-item\">\n                <span class=\"banner-label\"><span data-i18n=\"tradingStatus\">\u4ea4\u6613\u5f00\u5173<\/span><\/span><br \/>\n                <span class=\"banner-value\" id=\"tradingStatus\">\u52a0\u8f7d\u4e2d...<\/span>\n            <\/div>\n<div class=\"banner-actions\">\n                <button class=\"btn btn-outline btn-sm\" id=\"refreshBtn\">\ud83d\udd04 <span data-i18n=\"refresh\">\u5237\u65b0<\/span><\/button>\n            <\/div>\n<\/p><\/div>\n<p>        <!-- ===== GRID ===== --><\/p>\n<div class=\"grid-center\">\n<p>            <!-- ===== \u5361\u72470: \u5ba1\u6279\u4eba & \u505a\u5e02\u5546\u5730\u5740 ===== --><\/p>\n<div class=\"card full-width\" style=\"max-width:100%;min-width:100%;\">\n<div class=\"card-header\">\n<h3>\ud83d\udd10 <span data-i18n=\"agentAndMaker\">\u5ba1\u6279\u4eba &amp; \u505a\u5e02\u5546<\/span> <span class=\"badge\"><span data-i18n=\"sharedAddress\">\u5171\u7528\u5730\u5740<\/span><\/span><\/h3>\n<\/p><\/div>\n<div class=\"address-manager\">\n                    <input type=\"text\" id=\"sharedAddressInput\" placeholder=\"0x...\" \/><br \/>\n                    <span class=\"sync-badge\"><span class=\"sync-icon\">\ud83d\udd04<\/span> <span data-i18n=\"syncLabel\">\u540c\u6b65<\/span><\/span>\n                <\/div>\n<div class=\"address-sync-hint\" id=\"addressSyncHint\">\ud83d\udca1 <span data-i18n=\"syncHint\">\u6b64\u5904\u586b\u5199\u540e\uff0c\u5ba1\u6279\u4eba\u548c\u505a\u5e02\u5546\u5c06\u81ea\u52a8\u4f7f\u7528\u540c\u4e00\u5730\u5740<\/span><\/div>\n<div class=\"address-manager-actions\">\n                    <button class=\"btn btn-outline btn-sm\" id=\"addressClearBtn\">\ud83d\uddd1\ufe0f <span data-i18n=\"clearAddress\">\u6e05\u7a7a\u5730\u5740<\/span><\/button><br \/>\n                    <button class=\"btn btn-outline btn-sm\" id=\"addressFillWalletBtn\">\ud83d\udd11 <span data-i18n=\"fillWalletAddress\">\u586b\u5165\u6211\u7684\u94b1\u5305<\/span><\/button>\n                <\/div>\n<\/p><\/div>\n<p>            <!-- ===== \u5361\u72471: SHY\u53d1\u9001\uff08\u539f\u53d7\u63a7\u8f6c\u8d26\uff09 ===== --><\/p>\n<div class=\"card card-center\">\n<div class=\"card-header\">\n<h3>\ud83d\udd04 <span data-i18n=\"shyTransfer\">SHY\u53d1\u9001<\/span> <span class=\"badge\">ControlledTransfer<\/span><\/h3>\n<\/p><\/div>\n<div class=\"form-group\">\n                    <label><span data-i18n=\"recipientAddress\">\u63a5\u6536\u65b9\u5730\u5740<\/span><\/label><br \/>\n                    <input type=\"text\" id=\"transferTo\" placeholder=\"0x...\" \/>\n                <\/div>\n<div class=\"form-row\">\n<div class=\"form-group\">\n                        <label><span data-i18n=\"amount\">\u6570\u91cf<\/span> (SHY)<\/label><br \/>\n                        <input type=\"number\" id=\"transferAmount\" placeholder=\"100\" step=\"0.0001\" \/>\n                    <\/div>\n<\/p><\/div>\n<p>                <button class=\"btn btn-primary\" id=\"requestTransferBtn\" style=\"width:100%;\">\ud83d\udce4 <span data-i18n=\"requestTransfer\">\u53d1\u8d77\u53d1\u9001\u8bf7\u6c42<\/span><\/button><\/p>\n<hr style=\"border-color:#0f1a2a;margin:12px 0;\" \/>\n<div class=\"form-group\">\n                    <label><span data-i18n=\"requestId\">\u5ba1\u6279\u8bf7\u6c42 ID<\/span><\/label><br \/>\n                    <input type=\"number\" id=\"approveRequestId\" placeholder=\"\u8f93\u5165 ID\" \/>\n                <\/div>\n<div class=\"card-actions\">\n                    <button class=\"btn btn-success\" id=\"approveTransferBtn\">\u2705 <span data-i18n=\"approve\">\u6279\u51c6<\/span><\/button><br \/>\n                    <button class=\"btn btn-danger\" id=\"rejectTransferBtn\">\u274c <span data-i18n=\"reject\">\u62d2\u7edd<\/span><\/button><br \/>\n                    <button class=\"btn btn-outline btn-sm\" id=\"refreshRequestsBtn\">\ud83d\udd04 <span data-i18n=\"refreshPending\">\u5237\u65b0\u5f85\u5ba1\u6279<\/span><\/button>\n                <\/div>\n<div style=\"margin-top:10px;\">\n                    <label style=\"font-size:13px;color:var(--text-secondary);\">\ud83d\udccb <span data-i18n=\"pendingRequests\">\u5f85\u5ba1\u6279\u8bf7\u6c42<\/span><\/label><\/p>\n<div class=\"request-list\" id=\"pendingRequestsList\">\n<div class=\"empty\"><span data-i18n=\"connectWalletFirst\">\u8bf7\u8fde\u63a5\u94b1\u5305<\/span><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p>            <!-- ===== \u5361\u72472: SHY\u4e70\u5165\/\u5356\u51fa\uff08\u539f\u7a33\u5b9a\u5e01\u5151\u6362\uff09 ===== --><\/p>\n<div class=\"card card-center\">\n<div class=\"card-header\">\n<h3>\ud83d\udcb1 <span data-i18n=\"shyBuySell\">SHY\u4e70\u5165\/\u5356\u51fa<\/span> <span class=\"badge\">AutoExchange<\/span><\/h3>\n<\/p><\/div>\n<div class=\"form-group\">\n                    <label><span data-i18n=\"selectStable\">\u9009\u62e9\u7a33\u5b9a\u5e01<\/span><\/label><br \/>\n                    <select id=\"stableCoinSelect\"><option value=\"\">\u2014 <span data-i18n=\"connectWalletFirst\">\u8bf7\u8fde\u63a5\u94b1\u5305<\/span> \u2014<\/option><\/select>\n                <\/div>\n<div style=\"background:var(--bg-input);border-radius:var(--radius-sm);padding:12px;margin-bottom:12px;\">\n<div class=\"info-row\">\n                        <span class=\"label\"><span data-i18n=\"currentRate\">\u5f53\u524d\u6c47\u7387<\/span><\/span><br \/>\n                        <span class=\"value\" id=\"currentRate\">\u2014<\/span>\n                    <\/div>\n<div class=\"info-row\">\n                        <span class=\"label\"><span data-i18n=\"fee\">\u624b\u7eed\u8d39<\/span><\/span><br \/>\n                        <span class=\"value\" id=\"currentFee\">\u2014<\/span>\n                    <\/div>\n<\/p><\/div>\n<p>                <!-- ===== \u4e70\u5165\u533a\u57df ===== --><\/p>\n<div class=\"form-group\">\n                    <label><span data-i18n=\"buy\">\u4e70\u5165<\/span> (<span class=\"stable-symbol-label\">\u7a33\u5b9a\u5e01<\/span> \u2192 SHY)<\/label><br \/>\n                    <input type=\"number\" id=\"buyAmount\" placeholder=\"\u6570\u91cf\" step=\"0.01\" oninput=\"updateBuyPreview()\" \/>\n                <\/div>\n<div class=\"exchange-preview\" id=\"buyPreview\">\n<div class=\"preview-row\">\n                        <span class=\"preview-label\"><span data-i18n=\"expectedReceive\">\u9884\u8ba1\u83b7\u5f97<\/span><\/span><br \/>\n                        <span class=\"preview-value green\" id=\"buyReceive\">\u2014<\/span>\n                    <\/div>\n<div class=\"preview-row\">\n                        <span class=\"preview-label\"><span data-i18n=\"feeAmount\">\u624b\u7eed\u8d39<\/span><\/span><br \/>\n                        <span class=\"preview-value yellow\" id=\"buyFee\">\u2014<\/span>\n                    <\/div>\n<\/p><\/div>\n<p>                <button class=\"btn btn-success\" id=\"buyShyBtn\" style=\"width:100%;\">\ud83d\udfe2 <span data-i18n=\"buy\">\u4e70\u5165<\/span><\/button><\/p>\n<hr style=\"border-color:#0f1a2a;margin:12px 0;\" \/>\n<p>                <!-- ===== \u5356\u51fa\u533a\u57df ===== --><\/p>\n<div id=\"sellSection\">\n<div class=\"form-group\">\n                        <label><span data-i18n=\"sell\">\u5356\u51fa<\/span> (SHY \u2192 <span class=\"stable-symbol-label\">\u7a33\u5b9a\u5e01<\/span>)<\/label><br \/>\n                        <input type=\"number\" id=\"sellAmount\" placeholder=\"SHY \u6570\u91cf\" step=\"0.0001\" oninput=\"updateSellPreview()\" \/>\n                    <\/div>\n<div class=\"exchange-preview\" id=\"sellPreview\">\n<div class=\"preview-row\">\n                            <span class=\"preview-label\"><span data-i18n=\"expectedReceive\">\u9884\u8ba1\u83b7\u5f97<\/span><\/span><br \/>\n                            <span class=\"preview-value green\" id=\"sellReceive\">\u2014<\/span>\n                        <\/div>\n<div class=\"preview-row\">\n                            <span class=\"preview-label\"><span data-i18n=\"feeAmount\">\u624b\u7eed\u8d39<\/span><\/span><br \/>\n                            <span class=\"preview-value yellow\" id=\"sellFee\">\u2014<\/span>\n                        <\/div>\n<div class=\"preview-row\">\n                            <span class=\"preview-label\"><span data-i18n=\"netReceive\">\u51c0\u5f97<\/span><\/span><br \/>\n                            <span class=\"preview-value green\" id=\"sellNet\">\u2014<\/span>\n                        <\/div>\n<\/p><\/div>\n<p>                    <button class=\"btn btn-warning\" id=\"sellShyBtn\" style=\"width:100%;\">\ud83d\udfe1 <span data-i18n=\"sell\">\u5356\u51fa<\/span><\/button>\n                <\/div>\n<\/p><\/div>\n<p>            <!-- ===== \u5361\u72473: \u7528\u6237\u6ce8\u518c\u7533\u8bf7 ===== --><\/p>\n<div class=\"card full-width\" style=\"max-width:100%;min-width:100%;\">\n<div class=\"card-header\">\n<h3>\ud83d\udcdd <span data-i18n=\"registerApply\">\u7528\u6237\u6ce8\u518c\u7533\u8bf7<\/span> <span class=\"badge\"><span data-i18n=\"applyNow\">\u7acb\u5373\u7533\u8bf7<\/span><\/span><\/h3>\n<\/p><\/div>\n<div class=\"info-box\" id=\"applyInfoBox\">\n                    <strong data-i18n=\"applyNoticeTitle\">\ud83d\udccb \u7533\u8bf7\u987b\u77e5<\/strong><br \/>\n                    <span data-i18n=\"applyNotice1\">1. \u8bf7\u586b\u5199\u4ee5\u4e0b\u4fe1\u606f\uff0c\u70b9\u51fb\u300c\u53d1\u9001\u7533\u8bf7\u300d\u5c06\u81ea\u52a8\u6253\u5f00\u60a8\u7684\u90ae\u4ef6\u5ba2\u6237\u7aef\u3002<\/span><br \/>\n                    <span data-i18n=\"applyNotice2\">2. \u7533\u8bf7\u90ae\u4ef6\u5e94\u5305\u542b\uff1a\u59d3\u540d\u3001\u5730\u533a\u3001\u8eab\u4efd\u8bc1\u4ef6\u53f7\u7801\u3001\u5728\u7ebf\u8054\u7cfb\u65b9\u5f0f\uff08\u7528\u4e8e\u89c6\u9891\u89c1\u8bc1\uff09\u3002<\/span><br \/>\n                    <span data-i18n=\"applyNotice3\">3. <strong>\u6570\u5b57\u8d27\u5e01\u4ea4\u6613\u53d7\u9650\u5730\u533a<\/strong>\u7684\u7533\u8bf7\u5c06<strong>\u4e0d\u4e88\u901a\u8fc7<\/strong>\uff0c\u6216\u9650\u5b9a\u4e3a<strong>\u4e8c\u7c7b\u7528\u6237<\/strong>\u3002<\/span><\/p>\n<div class=\"email-fallback\">\n                        \ud83d\udce7 <span data-i18n=\"emailFallback\">\u5982\u65e0\u6cd5\u6253\u5f00\u90ae\u4ef6\u5ba2\u6237\u7aef\uff0c\u8bf7\u5c06\u7533\u8bf7\u5185\u5bb9\u76f4\u63a5\u53d1\u9001\u81f3\uff1a<\/span><br \/>\n                        <strong class=\"copy-email\" id=\"fallbackEmailDisplay\" onclick=\"copyEmailToClipboard()\">shy-apply@your-domain.com<\/strong><br \/>\n                        <span style=\"color:#475569;font-size:11px;margin-left:8px;\" data-i18n=\"clickToCopy\">\uff08\u70b9\u51fb\u590d\u5236\uff09<\/span>\n                    <\/div>\n<\/p><\/div>\n<div class=\"form-row\">\n<div class=\"form-group\">\n                        <label><span data-i18n=\"fullName\">\u59d3\u540d<\/span> *<\/label><br \/>\n                        <input type=\"text\" id=\"applyName\" placeholder=\"\u5f20\u4e09\" \/>\n                    <\/div>\n<div class=\"form-group\">\n                        <label><span data-i18n=\"region\">\u5730\u533a\/\u56fd\u5bb6<\/span> *<\/label><br \/>\n                        <input type=\"text\" id=\"applyRegion\" placeholder=\"\u4e2d\u56fd \/ China\" \/>\n                    <\/div>\n<\/p><\/div>\n<div class=\"form-row\">\n<div class=\"form-group\">\n                        <label><span data-i18n=\"idNumber\">\u8eab\u4efd\u8bc1\u4ef6\u53f7\u7801<\/span> *<\/label><br \/>\n                        <input type=\"text\" id=\"applyIdNumber\" placeholder=\"ID \/ Passport Number\" \/>\n                    <\/div>\n<div class=\"form-group\">\n                        <label><span data-i18n=\"contactMethod\">\u5728\u7ebf\u8054\u7cfb\u65b9\u5f0f<\/span> *<\/label><br \/>\n                        <input type=\"text\" id=\"applyContact\" placeholder=\"Telegram \/ WhatsApp \/ Email\" \/>\n                    <\/div>\n<\/p><\/div>\n<div class=\"form-group\">\n                    <label><span data-i18n=\"walletAddress\">\u94b1\u5305\u5730\u5740<\/span><\/label><br \/>\n                    <input type=\"text\" id=\"applyWalletAddress\" placeholder=\"0x...\" readonly style=\"background:#1a2538;color:#94a3b8;\" \/>\n                <\/div>\n<div style=\"display:flex;gap:10px;flex-wrap:wrap;margin-top:4px;\">\n                    <button class=\"btn btn-email\" id=\"applySubmitBtn\">\ud83d\udce7 <span data-i18n=\"sendApplication\">\u53d1\u9001\u7533\u8bf7<\/span><\/button><br \/>\n                    <button class=\"btn btn-outline btn-sm\" id=\"applyClearBtn\">\ud83d\uddd1\ufe0f <span data-i18n=\"clearFields\">\u6e05\u7a7a<\/span><\/button><br \/>\n                    <button class=\"btn btn-outline btn-sm\" id=\"applyFillWalletBtn\">\ud83d\udd11 <span data-i18n=\"fillWallet\">\u586b\u5165\u6211\u7684\u94b1\u5305<\/span><\/button><br \/>\n                    <button class=\"btn btn-outline btn-sm\" id=\"applyCopyEmailBtn\">\ud83d\udccb <span data-i18n=\"copyEmailAddress\">\u590d\u5236\u90ae\u7bb1\u5730\u5740<\/span><\/button>\n                <\/div>\n<div style=\"margin-top:12px;padding:10px 14px;background:#0b1220;border-radius:var(--radius-sm);font-size:12px;color:#475569;word-break:break-all;\">\n                    <span data-i18n=\"emailPreview\">\ud83d\udce7 \u90ae\u4ef6\u9884\u89c8<\/span>: <span id=\"applyEmailPreview\" style=\"color:#94a3b8;font-family:var(--font-mono);\">\u7b49\u5f85\u586b\u5199...<\/span>\n                <\/div>\n<\/p><\/div>\n<p>            <!-- ===== \u5361\u72474: \u7528\u6237\u89d2\u8272\u67e5\u8be2 ===== --><\/p>\n<div class=\"card full-width\" style=\"max-width:100%;min-width:100%;\">\n<div class=\"card-header\">\n<h3>\ud83d\udc65 <span data-i18n=\"userRoleQuery\">\u7528\u6237\u89d2\u8272\u67e5\u8be2<\/span> <span class=\"badge\"><span data-i18n=\"permissionCheck\">\u6743\u9650\u68c0\u67e5<\/span><\/span><\/h3>\n<\/p><\/div>\n<div class=\"form-row\">\n<div class=\"form-group\">\n                        <label><span data-i18n=\"addressToQuery\">\u67e5\u8be2\u5730\u5740<\/span><\/label><br \/>\n                        <input type=\"text\" id=\"roleCheckAddress\" placeholder=\"0x...\" \/>\n                    <\/div>\n<div class=\"form-group\" style=\"display:flex;align-items:flex-end;\">\n                        <button class=\"btn btn-primary\" id=\"checkRoleBtn\">\ud83d\udd0d <span data-i18n=\"query\">\u67e5\u8be2<\/span><\/button>\n                    <\/div>\n<\/p><\/div>\n<div id=\"roleResult\" style=\"margin-top:12px;padding:12px;background:var(--bg-input);border-radius:var(--radius-sm);font-size:14px;color:var(--text-secondary);min-height:48px;\">\n                    <span data-i18n=\"enterAddressToQuery\">\u8f93\u5165\u5730\u5740\u540e\u70b9\u51fb\u67e5\u8be2<\/span>\n                <\/div>\n<\/p><\/div>\n<\/p><\/div>\n<div class=\"footnote\">SHY \u00b7 <span data-i18n=\"threeContracts\">\u4e09\u5408\u7ea6\u96c6\u6210<\/span><\/div>\n<\/p><\/div>\n<p>    <!-- ========================================================== --><br \/>\n    <!-- \u5f15\u5165 ethers.js                                             --><br \/>\n    <!-- ========================================================== --><br \/>\n    <script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/ethers\/6.14.0\/ethers.umd.min.js\">\n    <\/script><\/p>\n<p>    <script>\n        \/\/ ================================================================\n        \/\/  \ud83d\udd27 \u7533\u8bf7\u90ae\u4ef6\u63a5\u6536\u5730\u5740\n        \/\/ ================================================================<\/p>\n<p>        const APPLICATION_EMAIL = \"shy-apply@your-domain.com\";<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \ud83d\udd27 \u5171\u7528\u5730\u5740\uff08\u5ba1\u6279\u4eba + \u505a\u5e02\u5546\uff09\n        \/\/ ================================================================<\/p>\n<p>        let sharedAddress = \"\";<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u591a\u8bed\u8a00\u7ffb\u8bd1\u8868\n        \/\/ ================================================================<\/p>\n<p>        const TRANSLATIONS = {\n            zh: {\n                appTitle: 'SHY\uff08\u4eba\u5de5\u751f\u547d\u4f7f\u7528\u70b9\u6570\uff09\u7528\u6237\u64cd\u4f5c\u5e73\u53f0',\n                notConnected: '\u672a\u8fde\u63a5',\n                connectWallet: '\ud83d\udd0c \u8fde\u63a5\u94b1\u5305',\n                disconnectWallet: '\ud83d\udd0c \u65ad\u5f00\u94b1\u5305',\n                switchNetwork: '\ud83d\udd04 \u5207\u6362\u5230 Base',\n                protocolWarning: '\u68c0\u6d4b\u5230 file:\/\/ \u534f\u8bae\uff0cChrome \u4f1a\u963b\u6b62\u94b1\u5305\u6ce8\u5165\u3002\u8bf7\u4f7f\u7528 Live Server \u6216 http:\/\/ \u534f\u8bae\u6253\u5f00\u3002',\n                noWallet: '\u672a\u68c0\u6d4b\u5230\u94b1\u5305\u6269\u5c55\uff0c\u8bf7\u5b89\u88c5 MetaMask \u6216 TokenPocket\u3002',\n                network: '\u7f51\u7edc',\n                balance: '\u4f59\u989d',\n                role: '\u89d2\u8272',\n                totalSupply: '\u603b\u4f9b\u5e94\u91cf',\n                loading: '\u52a0\u8f7d\u4e2d...',\n                refresh: '\u5237\u65b0',\n                shyToken: 'SHY \u70b9\u6570',\n                contractAddress: '\u5408\u7ea6\u5730\u5740',\n                myBalance: '\u6211\u7684\u4f59\u989d',\n                tradingStatus: '\u4ea4\u6613\u5f00\u5173',\n                shyTransfer: 'SHY\u53d1\u9001',\n                recipientAddress: '\u63a5\u6536\u65b9\u5730\u5740',\n                amount: '\u6570\u91cf',\n                requestTransfer: '\u53d1\u9001\/\u8bf7\u6c42',\n                requestId: '\u5ba1\u6279\u8bf7\u6c42 ID',\n                enterId: '\u8f93\u5165 ID',\n                approve: '\u6279\u51c6',\n                reject: '\u62d2\u7edd',\n                refreshPending: '\u5237\u65b0\u5f85\u5ba1\u6279',\n                pendingRequests: '\u5f85\u5ba1\u6279\u8bf7\u6c42',\n                connectWalletFirst: '\u8bf7\u8fde\u63a5\u94b1\u5305',\n                shyBuySell: 'SHY\u4e70\u5165\/\u5356\u51fa',\n                selectStable: '\u9009\u62e9\u7a33\u5b9a\u5e01',\n                currentRate: '\u5f53\u524d\u6c47\u7387',\n                fee: '\u624b\u7eed\u8d39',\n                buy: '\u4e70\u5165',\n                sell: '\u5356\u51fa',\n                userRoleQuery: '\u7528\u6237\u89d2\u8272\u67e5\u8be2',\n                permissionCheck: '\u6743\u9650\u68c0\u67e5',\n                addressToQuery: '\u67e5\u8be2\u5730\u5740',\n                query: '\u67e5\u8be2',\n                enterAddressToQuery: '\u8f93\u5165\u5730\u5740\u540e\u70b9\u51fb\u67e5\u8be2',\n                threeContracts: '\u4e09\u5408\u7ea6\u96c6\u6210',\n                enabled: '\u5df2\u5f00\u542f',\n                disabled: '\u5df2\u5173\u95ed',\n                notApprover: '\u5f53\u524d\u5730\u5740\u4e0d\u662f\u5ba1\u6279\u4eba',\n                noPendingRequests: '\u6682\u65e0\u5f85\u5ba1\u6279\u8bf7\u6c42',\n                loadFailed: '\u52a0\u8f7d\u5931\u8d25',\n                noStableCoins: '\u6682\u65e0\u7a33\u5b9a\u5e01',\n                processing: '\u5904\u7406\u4e2d...',\n                unableToConnect: '\u65e0\u6cd5\u8fde\u63a5',\n                stableCoin: '\u7a33\u5b9a\u5e01',\n                amountPlaceholder: '\u6570\u91cf',\n                shyAmountPlaceholder: 'SHY \u6570\u91cf',\n                enterIdPlaceholder: '\u8f93\u5165 ID',\n                registerApply: '\u7528\u6237\u6ce8\u518c\u7533\u8bf7',\n                applyNow: '\u7acb\u5373\u7533\u8bf7',\n                applyNoticeTitle: '\ud83d\udccb \u7533\u8bf7\u987b\u77e5',\n                applyNotice1: '1. \u8bf7\u586b\u5199\u4ee5\u4e0b\u4fe1\u606f\uff0c\u70b9\u51fb\u300c\u53d1\u9001\u7533\u8bf7\u300d\u5c06\u81ea\u52a8\u6253\u5f00\u60a8\u7684\u90ae\u4ef6\u5ba2\u6237\u7aef\u3002',\n                applyNotice2: '2. \u7533\u8bf7\u90ae\u4ef6\u5e94\u5305\u542b\uff1a\u59d3\u540d\u3001\u5730\u533a\u3001\u8eab\u4efd\u8bc1\u4ef6\u53f7\u7801\u3001\u5728\u7ebf\u8054\u7cfb\u65b9\u5f0f\uff08\u7528\u4e8e\u89c6\u9891\u89c1\u8bc1\uff09\u3002',\n                applyNotice3: '3. \u6570\u5b57\u8d27\u5e01\u4ea4\u6613\u53d7\u9650\u5730\u533a\u7684\u7533\u8bf7\u5c06\u4e0d\u4e88\u901a\u8fc7\uff0c\u6216\u9650\u5b9a\u4e3a\u4e8c\u7c7b\u7528\u6237\u3002',\n                fullName: '\u59d3\u540d',\n                region: '\u5730\u533a\/\u56fd\u5bb6',\n                idNumber: '\u8eab\u4efd\u8bc1\u4ef6\u53f7\u7801',\n                contactMethod: '\u5728\u7ebf\u8054\u7cfb\u65b9\u5f0f',\n                walletAddress: '\u94b1\u5305\u5730\u5740',\n                sendApplication: '\ud83d\udce7 \u53d1\u9001\u7533\u8bf7',\n                clearFields: '\ud83d\uddd1\ufe0f \u6e05\u7a7a',\n                fillWallet: '\ud83d\udd11 \u586b\u5165\u6211\u7684\u94b1\u5305',\n                emailPreview: '\ud83d\udce7 \u90ae\u4ef6\u9884\u89c8',\n                applySuccess: '\u2705 \u90ae\u4ef6\u5ba2\u6237\u7aef\u5df2\u6253\u5f00\uff0c\u8bf7\u68c0\u67e5\u5e76\u53d1\u9001\u60a8\u7684\u7533\u8bf7\u3002',\n                applyFail: '\u274c \u8bf7\u5b8c\u6574\u586b\u5199\u6240\u6709\u5fc5\u586b\u5b57\u6bb5\u3002',\n                applyWalletHint: '\u8bf7\u5148\u8fde\u63a5\u94b1\u5305',\n                regionRestricted: '\u26a0\ufe0f \u60a8\u6240\u5728\u5730\u533a\u53ef\u80fd\u53d7\u6570\u5b57\u8d27\u5e01\u4ea4\u6613\u9650\u5236\uff0c\u5c06\u88ab\u9650\u5b9a\u4e3a\u4e8c\u7c7b\u7528\u6237\u3002',\n                emailFallback: '\u5982\u65e0\u6cd5\u6253\u5f00\u90ae\u4ef6\u5ba2\u6237\u7aef\uff0c\u8bf7\u5c06\u7533\u8bf7\u5185\u5bb9\u76f4\u63a5\u53d1\u9001\u81f3\uff1a',\n                clickToCopy: '\uff08\u70b9\u51fb\u590d\u5236\uff09',\n                copyEmailAddress: '\ud83d\udccb \u590d\u5236\u90ae\u7bb1\u5730\u5740',\n                emailCopied: '\u2705 \u90ae\u7bb1\u5730\u5740\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f',\n                agentAndMaker: '\u5ba1\u6279\u4eba & \u505a\u5e02\u5546',\n                sharedAddress: '\u5171\u7528\u5730\u5740',\n                syncLabel: '\u540c\u6b65',\n                syncHint: '\u6b64\u5904\u586b\u5199\u540e\uff0c\u5ba1\u6279\u4eba\u548c\u505a\u5e02\u5546\u5c06\u81ea\u52a8\u4f7f\u7528\u540c\u4e00\u5730\u5740',\n                clearAddress: '\u6e05\u7a7a\u5730\u5740',\n                fillWalletAddress: '\u586b\u5165\u6211\u7684\u94b1\u5305',\n                addressCopied: '\u2705 \u5730\u5740\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f',\n                addressActive: '\u5730\u5740\u5df2\u540c\u6b65',\n                notLevel1: '\u274c \u5730\u5740\u4e0d\u5728 SHY \u5408\u7ea6\u7684\u4e00\u7c7b\u767d\u540d\u5355\u4e2d',\n                level1Verified: '\u2705 \u4e00\u7c7b\u767d\u540d\u5355\u5df2\u9a8c\u8bc1',\n                checkingLevel1: '\u23f3 \u6b63\u5728\u9a8c\u8bc1\u767d\u540d\u5355...',\n                pleaseFillMaker: '\u8bf7\u586b\u5199\u505a\u5e02\u5546\u5730\u5740',\n                expectedReceive: '\u9884\u8ba1\u83b7\u5f97',\n                feeAmount: '\u624b\u7eed\u8d39',\n                netReceive: '\u51c0\u5f97'\n            },\n            en: {\n                appTitle: 'SHY (Artificial Life Usage Points) User Platform',\n                notConnected: 'Not Connected',\n                connectWallet: '\ud83d\udd0c Connect Wallet',\n                disconnectWallet: '\ud83d\udd0c Disconnect Wallet',\n                switchNetwork: '\ud83d\udd04 Switch to Base',\n                protocolWarning: 'file:\/\/ protocol detected. Chrome blocks wallet injection. Please use Live Server or http:\/\/',\n                noWallet: 'No wallet detected. Please install MetaMask or TokenPocket.',\n                network: 'Network',\n                balance: 'Balance',\n                role: 'Role',\n                totalSupply: 'Total Supply',\n                loading: 'Loading...',\n                refresh: 'Refresh',\n                shyToken: 'SHY Points',\n                contractAddress: 'Contract Address',\n                myBalance: 'My Balance',\n                tradingStatus: 'Trading Status',\n                shyTransfer: 'SHY Sent',\n                recipientAddress: 'Recipient Address',\n                amount: 'Amount',\n                requestTransfer: 'Request Send',\n                requestId: 'Request ID',\n                enterId: 'Enter ID',\n                approve: 'Approve',\n                reject: 'Reject',\n                refreshPending: 'Refresh Pending',\n                pendingRequests: 'Pending Requests',\n                connectWalletFirst: 'Please connect wallet',\n                shyBuySell: 'SHY Buy\/Sell',\n                selectStable: 'Select Stable Coin',\n                currentRate: 'Current Rate',\n                fee: 'Fee',\n                buy: 'Buy',\n                sell: 'Sell',\n                userRoleQuery: 'User Role Query',\n                permissionCheck: 'Permission Check',\n                addressToQuery: 'Address to Query',\n                query: 'Query',\n                enterAddressToQuery: 'Enter address and click Query',\n                threeContracts: '3-Contract Integration',\n                enabled: 'Enabled',\n                disabled: 'Disabled',\n                notApprover: 'Current address is not an approver',\n                noPendingRequests: 'No pending requests',\n                loadFailed: 'Load failed',\n                noStableCoins: 'No stable coins available',\n                processing: 'Processing...',\n                unableToConnect: 'Unable to connect',\n                stableCoin: 'Stable Coin',\n                amountPlaceholder: 'Amount',\n                shyAmountPlaceholder: 'SHY Amount',\n                enterIdPlaceholder: 'Enter ID',\n                registerApply: 'User Registration Application',\n                applyNow: 'Apply Now',\n                applyNoticeTitle: '\ud83d\udccb Application Notice',\n                applyNotice1: '1. Fill in the information below and click \"Send Application\" to open your email client.',\n                applyNotice2: '2. The application email should include: Name, Region, ID\/Passport Number, Online Contact (for video verification).',\n                applyNotice3: '3. Applications from crypto-restricted regions will be denied or limited to Level 2 users.',\n                fullName: 'Full Name',\n                region: 'Region \/ Country',\n                idNumber: 'ID \/ Passport Number',\n                contactMethod: 'Online Contact',\n                walletAddress: 'Wallet Address',\n                sendApplication: '\ud83d\udce7 Send Application',\n                clearFields: '\ud83d\uddd1\ufe0f Clear',\n                fillWallet: '\ud83d\udd11 Fill My Wallet',\n                emailPreview: '\ud83d\udce7 Email Preview',\n                applySuccess: '\u2705 Email client opened. Please review and send your application.',\n                applyFail: '\u274c Please fill in all required fields.',\n                applyWalletHint: 'Please connect wallet first',\n                regionRestricted: '\u26a0\ufe0f Your region may have crypto trading restrictions. You will be limited to Level 2 user.',\n                emailFallback: 'If you cannot open the email client, please send the application directly to:',\n                clickToCopy: '(click to copy)',\n                copyEmailAddress: '\ud83d\udccb Copy Email Address',\n                emailCopied: '\u2705 Email address copied to clipboard',\n                agentAndMaker: 'Approver & Market Maker',\n                sharedAddress: 'Shared Address',\n                syncLabel: 'Sync',\n                syncHint: 'Fill this in and both Approver and Market Maker will use the same address',\n                clearAddress: 'Clear Address',\n                fillWalletAddress: 'Fill My Wallet',\n                addressCopied: '\u2705 Address copied to clipboard',\n                addressActive: 'Address synced',\n                notLevel1: '\u274c Address is not in SHY Level 1 whitelist',\n                level1Verified: '\u2705 Level 1 whitelist verified',\n                checkingLevel1: '\u23f3 Verifying whitelist...',\n                pleaseFillMaker: 'Please fill in maker address',\n                expectedReceive: 'Expected Receive',\n                feeAmount: 'Fee',\n                netReceive: 'Net Receive'\n            },\n            ko: {\n                appTitle: 'SHY (\uc778\uacf5\uc0dd\uba85 \uc0ac\uc6a9 \ud3ec\uc778\ud2b8) \uc0ac\uc6a9\uc790 \ud50c\ub7ab\ud3fc',\n                notConnected: '\uc5f0\uacb0\ub418\uc9c0 \uc54a\uc74c',\n                connectWallet: '\ud83d\udd0c \uc9c0\uac11 \uc5f0\uacb0',\n                disconnectWallet: '\ud83d\udd0c \uc9c0\uac11 \uc5f0\uacb0 \ud574\uc81c',\n                switchNetwork: '\ud83d\udd04 Base\ub85c \uc804\ud658',\n                protocolWarning: 'file:\/\/ \ud504\ub85c\ud1a0\ucf5c \uac10\uc9c0\ub428. Chrome\uc740 \uc9c0\uac11 \uc8fc\uc785\uc744 \ucc28\ub2e8\ud569\ub2c8\ub2e4. Live Server \ub610\ub294 http:\/\/\ub97c \uc0ac\uc6a9\ud558\uc138\uc694.',\n                noWallet: '\uc9c0\uac11\uc774 \uac10\uc9c0\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. MetaMask \ub610\ub294 TokenPocket\uc744 \uc124\uce58\ud558\uc138\uc694.',\n                network: '\ub124\ud2b8\uc6cc\ud06c',\n                balance: '\uc794\uc561',\n                role: '\uc5ed\ud560',\n                totalSupply: '\ucd1d \uacf5\uae09\ub7c9',\n                loading: '\ub85c\ub529 \uc911...',\n                refresh: '\uc0c8\ub85c\uace0\uce68',\n                shyToken: 'SHY \ud3ec\uc778\ud2b8',\n                contractAddress: '\ucee8\ud2b8\ub799\ud2b8 \uc8fc\uc18c',\n                myBalance: '\ub0b4 \uc794\uc561',\n                tradingStatus: '\uac70\ub798 \uc0c1\ud0dc',\n                shyTransfer: 'SHY \ubcf4\ub0b4\uae30',\n                recipientAddress: '\uc218\uc2e0\uc790 \uc8fc\uc18c',\n                amount: '\uc218\ub7c9',\n                requestTransfer: '\ubcf4\ub0b4\uae30 \uc694\uccad',\n                requestId: '\uc694\uccad ID',\n                enterId: 'ID \uc785\ub825',\n                approve: '\uc2b9\uc778',\n                reject: '\uac70\ubd80',\n                refreshPending: '\ub300\uae30 \uc911 \uc0c8\ub85c\uace0\uce68',\n                pendingRequests: '\ub300\uae30 \uc911 \uc694\uccad',\n                connectWalletFirst: '\uc9c0\uac11\uc744 \uc5f0\uacb0\ud558\uc138\uc694',\n                shyBuySell: 'SHY \ub9e4\uc218\/\ub9e4\ub3c4',\n                selectStable: '\uc2a4\ud14c\uc774\ube14 \ucf54\uc778 \uc120\ud0dd',\n                currentRate: '\ud604\uc7ac \ud658\uc728',\n                fee: '\uc218\uc218\ub8cc',\n                buy: '\ub9e4\uc218',\n                sell: '\ub9e4\ub3c4',\n                userRoleQuery: '\uc0ac\uc6a9\uc790 \uc5ed\ud560 \uc870\ud68c',\n                permissionCheck: '\uad8c\ud55c \ud655\uc778',\n                addressToQuery: '\uc870\ud68c\ud560 \uc8fc\uc18c',\n                query: '\uc870\ud68c',\n                enterAddressToQuery: '\uc8fc\uc18c\ub97c \uc785\ub825\ud558\uace0 \uc870\ud68c\ub97c \ud074\ub9ad\ud558\uc138\uc694',\n                threeContracts: '3\uac1c \ucee8\ud2b8\ub799\ud2b8 \ud1b5\ud569',\n                enabled: '\ud65c\uc131\ud654\ub428',\n                disabled: '\ube44\ud65c\uc131\ud654\ub428',\n                notApprover: '\ud604\uc7ac \uc8fc\uc18c\ub294 \uc2b9\uc778\uc790\uac00 \uc544\ub2d9\ub2c8\ub2e4',\n                noPendingRequests: '\ub300\uae30 \uc911\uc778 \uc694\uccad\uc774 \uc5c6\uc2b5\ub2c8\ub2e4',\n                loadFailed: '\ub85c\ub4dc \uc2e4\ud328',\n                noStableCoins: '\uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc2a4\ud14c\uc774\ube14 \ucf54\uc778\uc774 \uc5c6\uc2b5\ub2c8\ub2e4',\n                processing: '\ucc98\ub9ac \uc911...',\n                unableToConnect: '\uc5f0\uacb0\ud560 \uc218 \uc5c6\uc74c',\n                stableCoin: '\uc2a4\ud14c\uc774\ube14 \ucf54\uc778',\n                amountPlaceholder: '\uc218\ub7c9',\n                shyAmountPlaceholder: 'SHY \uc218\ub7c9',\n                enterIdPlaceholder: 'ID \uc785\ub825',\n                registerApply: '\uc0ac\uc6a9\uc790 \ub4f1\ub85d \uc2e0\uccad',\n                applyNow: '\uc9c0\uae08 \uc2e0\uccad',\n                applyNoticeTitle: '\ud83d\udccb \uc2e0\uccad \uc548\ub0b4',\n                applyNotice1: '1. \uc544\ub798 \uc815\ubcf4\ub97c\u586b\u5199\ud558\uace0 \"\uc2e0\uccad \ubcf4\ub0b4\uae30\"\ub97c \ud074\ub9ad\ud558\uba74 \uc774\uba54\uc77c \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc5f4\ub9bd\ub2c8\ub2e4.',\n                applyNotice2: '2. \uc2e0\uccad \uc774\uba54\uc77c\uc5d0\ub294 \uc774\ub984, \uc9c0\uc5ed, \uc2e0\ubd84\uc99d \ubc88\ud638, \uc628\ub77c\uc778 \uc5f0\ub77d\ucc98(\ud654\uc0c1 \ud655\uc778\uc6a9)\uac00 \ud3ec\ud568\ub418\uc5b4\uc57c \ud569\ub2c8\ub2e4.',\n                applyNotice3: '3. \uc554\ud638\ud654\ud3d0 \uac70\ub798 \uc81c\ud55c \uc9c0\uc5ed\uc758 \uc2e0\uccad\uc740 \uac70\ubd80\ub418\uac70\ub098 2\ub4f1\uae09 \uc0ac\uc6a9\uc790\ub85c \uc81c\ud55c\ub429\ub2c8\ub2e4.',\n                fullName: '\uc774\ub984',\n                region: '\uc9c0\uc5ed\/\uad6d\uac00',\n                idNumber: '\uc2e0\ubd84\uc99d \ubc88\ud638',\n                contactMethod: '\uc628\ub77c\uc778 \uc5f0\ub77d\ucc98',\n                walletAddress: '\uc9c0\uac11 \uc8fc\uc18c',\n                sendApplication: '\ud83d\udce7 \uc2e0\uccad \ubcf4\ub0b4\uae30',\n                clearFields: '\ud83d\uddd1\ufe0f \uc9c0\uc6b0\uae30',\n                fillWallet: '\ud83d\udd11 \ub0b4 \uc9c0\uac11 \ucc44\uc6b0\uae30',\n                emailPreview: '\ud83d\udce7 \uc774\uba54\uc77c \ubbf8\ub9ac\ubcf4\uae30',\n                applySuccess: '\u2705 \uc774\uba54\uc77c \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc5f4\ub838\uc2b5\ub2c8\ub2e4. \uc2e0\uccad \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcf4\ub0b4\uc138\uc694.',\n                applyFail: '\u274c \ubaa8\ub4e0 \ud544\uc218 \ud544\ub4dc\ub97c \uc791\uc131\ud574\uc8fc\uc138\uc694.',\n                applyWalletHint: '\uba3c\uc800 \uc9c0\uac11\uc744 \uc5f0\uacb0\ud558\uc138\uc694',\n                regionRestricted: '\u26a0\ufe0f \uadc0\ud558\uc758 \uc9c0\uc5ed\uc740 \uc554\ud638\ud654\ud3d0 \uac70\ub798 \uc81c\ud55c\uc774 \uc788\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4. 2\ub4f1\uae09 \uc0ac\uc6a9\uc790\ub85c \uc81c\ud55c\ub429\ub2c8\ub2e4.',\n                emailFallback: '\uc774\uba54\uc77c \ud074\ub77c\uc774\uc5b8\ud2b8\ub97c \uc5f4 \uc218 \uc5c6\ub294 \uacbd\uc6b0, \uc2e0\uccad \ub0b4\uc6a9\uc744 \ub2e4\uc74c \uc8fc\uc18c\ub85c \uc9c1\uc811 \ubcf4\ub0b4\uc8fc\uc138\uc694:',\n                clickToCopy: '(\ud074\ub9ad\ud558\uc5ec \ubcf5\uc0ac)',\n                copyEmailAddress: '\ud83d\udccb \uc774\uba54\uc77c \uc8fc\uc18c \ubcf5\uc0ac',\n                emailCopied: '\u2705 \uc774\uba54\uc77c \uc8fc\uc18c\uac00 \ud074\ub9bd\ubcf4\ub4dc\uc5d0 \ubcf5\uc0ac\ub418\uc5c8\uc2b5\ub2c8\ub2e4',\n                agentAndMaker: '\uc2b9\uc778\uc790 & \ub9c8\ucf13 \uba54\uc774\ucee4',\n                sharedAddress: '\uacf5\uc720 \uc8fc\uc18c',\n                syncLabel: '\ub3d9\uae30\ud654',\n                syncHint: '\uc5ec\uae30\uc5d0 \uc785\ub825\ud558\uba74 \uc2b9\uc778\uc790\uc640 \ub9c8\ucf13 \uba54\uc774\ucee4\uac00 \ub3d9\uc77c\ud55c \uc8fc\uc18c\ub97c \uc0ac\uc6a9\ud569\ub2c8\ub2e4',\n                clearAddress: '\uc8fc\uc18c \uc9c0\uc6b0\uae30',\n                fillWalletAddress: '\ub0b4 \uc9c0\uac11 \ucc44\uc6b0\uae30',\n                addressCopied: '\u2705 \uc8fc\uc18c\uac00 \ud074\ub9bd\ubcf4\ub4dc\uc5d0 \ubcf5\uc0ac\ub418\uc5c8\uc2b5\ub2c8\ub2e4',\n                addressActive: '\uc8fc\uc18c \ub3d9\uae30\ud654\ub428',\n                notLevel1: '\u274c \uc8fc\uc18c\uac00 SHY 1\ub4f1\uae09 \ud654\uc774\ud2b8\ub9ac\uc2a4\ud2b8\uc5d0 \uc5c6\uc2b5\ub2c8\ub2e4',\n                level1Verified: '\u2705 1\ub4f1\uae09 \ud654\uc774\ud2b8\ub9ac\uc2a4\ud2b8 \ud655\uc778\ub428',\n                checkingLevel1: '\u23f3 \ud654\uc774\ud2b8\ub9ac\uc2a4\ud2b8 \ud655\uc778 \uc911...',\n                pleaseFillMaker: '\uba54\uc774\ucee4 \uc8fc\uc18c\ub97c \uc785\ub825\ud558\uc138\uc694',\n                expectedReceive: '\uc608\uc0c1 \uc218\ub839',\n                feeAmount: '\uc218\uc218\ub8cc',\n                netReceive: '\uc21c \uc218\ub839'\n            },\n            fr: {\n                appTitle: 'SHY (Points d\\'utilisation de vie artificielle) Plateforme utilisateur',\n                notConnected: 'Non connect\u00e9',\n                connectWallet: '\ud83d\udd0c Connecter le portefeuille',\n                disconnectWallet: '\ud83d\udd0c D\u00e9connecter le portefeuille',\n                switchNetwork: '\ud83d\udd04 Passer \u00e0 Base',\n                protocolWarning: 'Protocole file:\/\/ d\u00e9tect\u00e9. Chrome bloque l\\'injection du portefeuille. Utilisez Live Server ou http:\/\/',\n                noWallet: 'Aucun portefeuille d\u00e9tect\u00e9. Veuillez installer MetaMask ou TokenPocket.',\n                network: 'R\u00e9seau',\n                balance: 'Solde',\n                role: 'R\u00f4le',\n                totalSupply: 'Offre totale',\n                loading: 'Chargement...',\n                refresh: 'Rafra\u00eechir',\n                shyToken: 'Points SHY',\n                contractAddress: 'Adresse du contrat',\n                myBalance: 'Mon solde',\n                tradingStatus: 'Statut des transactions',\n                shyTransfer: 'Send SHY',\n                recipientAddress: 'Adresse du destinataire',\n                amount: 'Montant',\n                requestTransfer: 'Demander un Send',\n                requestId: 'ID de la demande',\n                enterId: 'Entrer ID',\n                approve: 'Approuver',\n                reject: 'Rejeter',\n                refreshPending: 'Rafra\u00eechir les attentes',\n                pendingRequests: 'Demandes en attente',\n                connectWalletFirst: 'Veuillez connecter le portefeuille',\n                shyBuySell: 'Achat\/Vente SHY',\n                selectStable: 'S\u00e9lectionner un stablecoin',\n                currentRate: 'Taux actuel',\n                fee: 'Frais',\n                buy: 'Acheter',\n                sell: 'Vendre',\n                userRoleQuery: 'Requ\u00eate de r\u00f4le utilisateur',\n                permissionCheck: 'V\u00e9rification des droits',\n                addressToQuery: 'Adresse \u00e0 v\u00e9rifier',\n                query: 'V\u00e9rifier',\n                enterAddressToQuery: 'Entrez une adresse et cliquez sur V\u00e9rifier',\n                threeContracts: 'Int\u00e9gration 3 contrats',\n                enabled: 'Activ\u00e9',\n                disabled: 'D\u00e9sactiv\u00e9',\n                notApprover: 'Cette adresse n\\'est pas un approbateur',\n                noPendingRequests: 'Aucune demande en attente',\n                loadFailed: '\u00c9chec du chargement',\n                noStableCoins: 'Aucun stablecoin disponible',\n                processing: 'Traitement...',\n                unableToConnect: 'Impossible de se connecter',\n                stableCoin: 'Stablecoin',\n                amountPlaceholder: 'Montant',\n                shyAmountPlaceholder: 'Montant SHY',\n                enterIdPlaceholder: 'Entrer ID',\n                registerApply: 'Demande d\\'inscription utilisateur',\n                applyNow: 'Postuler',\n                applyNoticeTitle: '\ud83d\udccb Avis de demande',\n                applyNotice1: '1. Remplissez les informations ci-dessous et cliquez sur \"Envoyer la demande\" pour ouvrir votre client de messagerie.',\n                applyNotice2: '2. L\\'email de demande doit inclure: Nom, R\u00e9gion, Num\u00e9ro d\\'identit\u00e9, Contact en ligne (pour v\u00e9rification vid\u00e9o).',\n                applyNotice3: '3. Les demandes des r\u00e9gions restreintes aux cryptomonnaies seront refus\u00e9es ou limit\u00e9es aux utilisateurs de niveau 2.',\n                fullName: 'Nom complet',\n                region: 'R\u00e9gion \/ Pays',\n                idNumber: 'Num\u00e9ro d\\'identit\u00e9',\n                contactMethod: 'Contact en ligne',\n                walletAddress: 'Adresse du portefeuille',\n                sendApplication: '\ud83d\udce7 Envoyer la demande',\n                clearFields: '\ud83d\uddd1\ufe0f Effacer',\n                fillWallet: '\ud83d\udd11 Remplir mon portefeuille',\n                emailPreview: '\ud83d\udce7 Aper\u00e7u de l\\'email',\n                applySuccess: '\u2705 Client de messagerie ouvert. Veuillez v\u00e9rifier et envoyer votre demande.',\n                applyFail: '\u274c Veuillez remplir tous les champs obligatoires.',\n                applyWalletHint: 'Veuillez d\\'abord connecter le portefeuille',\n                regionRestricted: '\u26a0\ufe0f Votre r\u00e9gion peut avoir des restrictions sur les cryptomonnaies. Vous serez limit\u00e9 \u00e0 un utilisateur de niveau 2.',\n                emailFallback: 'Si vous ne pouvez pas ouvrir le client de messagerie, veuillez envoyer la demande directement \u00e0 :',\n                clickToCopy: '(cliquer pour copier)',\n                copyEmailAddress: '\ud83d\udccb Copier l\\'adresse email',\n                emailCopied: '\u2705 Adresse email copi\u00e9e dans le presse-papiers',\n                agentAndMaker: 'Approbateur & Market Maker',\n                sharedAddress: 'Adresse partag\u00e9e',\n                syncLabel: 'Synchroniser',\n                syncHint: 'Remplissez ceci et l\\'approbateur et le Market Maker utiliseront la m\u00eame adresse',\n                clearAddress: 'Effacer l\\'adresse',\n                fillWalletAddress: 'Remplir mon portefeuille',\n                addressCopied: '\u2705 Adresse copi\u00e9e dans le presse-papiers',\n                addressActive: 'Adresse synchronis\u00e9e',\n                notLevel1: '\u274c L\\'adresse n\\'est pas dans la liste blanche Niveau 1 de SHY',\n                level1Verified: '\u2705 Liste blanche Niveau 1 v\u00e9rifi\u00e9e',\n                checkingLevel1: '\u23f3 V\u00e9rification de la liste blanche...',\n                pleaseFillMaker: 'Veuillez saisir l\\'adresse du Maker',\n                expectedReceive: 'R\u00e9ception pr\u00e9vue',\n                feeAmount: 'Frais',\n                netReceive: 'R\u00e9ception nette'\n            }\n        };<\/p>\n<p>        let currentLang = 'zh';<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u8bed\u8a00\u5207\u6362\n        \/\/ ================================================================<\/p>\n<p>        function switchLanguage(lang) {\n            if (!TRANSLATIONS[lang]) return;\n            currentLang = lang;<\/p>\n<p>            document.querySelectorAll('.lang-btn').forEach(btn => {\n                btn.classList.toggle('active', btn.dataset.lang === lang);\n            });<\/p>\n<p>            document.querySelectorAll('[data-i18n]').forEach(el => {\n                const key = el.dataset.i18n;\n                const t = TRANSLATIONS[lang];\n                if (t && t[key]) {\n                    el.textContent = t[key];\n                }\n            });<\/p>\n<p>            const placeholders = [\n                { id: 'sharedAddressInput', key: 'enterIdPlaceholder' },\n                { id: 'transferTo', key: 'recipientAddress' },\n                { id: 'approveRequestId', key: 'enterIdPlaceholder' },\n                { id: 'buyAmount', key: 'amountPlaceholder' },\n                { id: 'sellAmount', key: 'shyAmountPlaceholder' },\n                { id: 'roleCheckAddress', key: 'addressToQuery' },\n                { id: 'applyName', key: 'fullName' },\n                { id: 'applyRegion', key: 'region' },\n                { id: 'applyIdNumber', key: 'idNumber' },\n                { id: 'applyContact', key: 'contactMethod' }\n            ];\n            placeholders.forEach(({ id, key }) => {\n                const el = document.getElementById(id);\n                if (el && TRANSLATIONS[lang][key]) {\n                    el.placeholder = TRANSLATIONS[lang][key];\n                }\n            });<\/p>\n<p>            const titleKey = 'appTitle';\n            if (TRANSLATIONS[lang] && TRANSLATIONS[lang][titleKey]) {\n                document.title = TRANSLATIONS[lang][titleKey];\n                const titleEl = document.getElementById('appTitle');\n                if (titleEl) titleEl.textContent = TRANSLATIONS[lang][titleKey];\n            }<\/p>\n<p>            const fallbackDisplay = document.getElementById('fallbackEmailDisplay');\n            if (fallbackDisplay) {\n                fallbackDisplay.textContent = APPLICATION_EMAIL;\n            }<\/p>\n<p>            updateConnectButtonText();\n            updateTradingStatusText();\n            refreshUserRole();\n            refreshStableCoinDisplay();\n            updateEmailPreview();\n            updateAddressSyncHint();<\/p>\n<p>            updateBuyPreview();\n            updateSellPreview();<\/p>\n<p>            try {\n                localStorage.setItem('shy-lang', lang);\n            } catch (e) {}<\/p>\n<p>            console.log('\ud83c\udf10 \u8bed\u8a00\u5207\u6362\u81f3:', lang);\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u66f4\u65b0\u8fde\u63a5\u6309\u94ae\u6587\u672c\n        \/\/ ================================================================<\/p>\n<p>        function updateConnectButtonText() {\n            const btn = document.getElementById('connectBtn');\n            if (!btn) return;\n            const lang = currentLang;\n            const isConnected = userAddress && userAddress !== '';<\/p>\n<p>            if (isConnected) {\n                btn.textContent = TRANSLATIONS[lang]?.disconnectWallet || '\ud83d\udd0c \u65ad\u5f00\u94b1\u5305';\n                btn.className = 'btn btn-disconnect';\n                btn.disabled = false;\n            } else {\n                btn.textContent = TRANSLATIONS[lang]?.connectWallet || '\ud83d\udd0c \u8fde\u63a5\u94b1\u5305';\n                btn.className = 'btn btn-primary';\n                btn.disabled = false;\n            }\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u66f4\u65b0\u4ea4\u6613\u72b6\u6001\n        \/\/ ================================================================<\/p>\n<p>        function updateTradingStatusText() {\n            const el = document.getElementById('tradingStatus');\n            if (!el) return;\n            const enabled = el.dataset.enabled === 'true';\n            const lang = currentLang;\n            const texts = {\n                enabled: { zh: '\u5df2\u5f00\u542f', en: 'Enabled', ko: '\ud65c\uc131\ud654\ub428', fr: 'Activ\u00e9' },\n                disabled: { zh: '\u5df2\u5173\u95ed', en: 'Disabled', ko: '\ube44\ud65c\uc131\ud654\ub428', fr: 'D\u00e9sactiv\u00e9' }\n            };\n            const text = enabled ? texts.enabled[lang] : texts.disabled[lang];\n            el.innerHTML = (enabled ? '\u2705 ' : '\u274c ') + text;\n            el.className = 'value ' + (enabled ? 'green' : 'red');\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u5408\u7ea6\u5730\u5740\n        \/\/ ================================================================<\/p>\n<p>        const CONFIG = {\n            customToken: \"0xC7Ed10fbA20789811a410415A9Bec074ECb7D3Dd\",\n            controlledTransfer: \"0xdDC8677ff6E17164d26150283a76EE24AEe424f4\",\n            autoExchange: \"0x5344c9175849bb41a1556b0ce3f8e652848b7edc\",\n            network: { chainId: 8453, name: \"Base Mainnet\" }\n        };<\/p>\n<p>        \/\/ ================================================================\n        \/\/  ABI\n        \/\/ ================================================================<\/p>\n<p>        const ABI = {\n            customToken: [\n                \"function balanceOf(address) view returns (uint256)\",\n                \"function totalSupply() view returns (uint256)\",\n                \"function decimals() view returns (uint8)\",\n                \"function tradingEnabled() view returns (bool)\",\n                \"function whitelistLevel1(address) view returns (bool)\"\n            ],\n            controlledTransfer: [\n                \"function requestTransfer(address,uint256,address)\",\n                \"function approveTransfer(uint256)\",\n                \"function rejectTransfer(uint256)\",\n                \"function getPendingRequestsByApprover(address) view returns (uint256[])\",\n                \"function getTransferRequest(uint256) view returns (address,address,uint256,uint256,uint256,address,bool,bool,bool,uint256)\",\n                \"function isLevel1User(address) view returns (bool)\",\n                \"function isLevel2User(address) view returns (bool)\",\n                \"function isApprover(address) view returns (bool)\",\n                \"function isOperator(address) view returns (bool)\"\n            ],\n            autoExchange: [\n                \"function buyShy(address,uint256,address)\",\n                \"function sellShy(address,uint256,address)\",\n                \"function getExchangeRate(address) view returns (uint256)\",\n                \"function getReceiverFeeRate(address,address) view returns (uint256)\",\n                \"function getAllSupportedStableCoins() view returns (address[])\",\n                \"function isLevel1User(address) view returns (bool)\",\n                \"function isLevel2User(address) view returns (bool)\",\n                \"function isReceiver(address) view returns (bool)\"\n            ]\n        };<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u72b6\u6001\n        \/\/ ================================================================<\/p>\n<p>        let provider = null;\n        let signer = null;\n        let userAddress = \"\";\n        let contracts = {};\n        let readOnlyProvider = null;\n        let isConnecting = false;\n        let currentStableSymbol = '';<\/p>\n<p>        const stableSymbolCache = {};<\/p>\n<p>        const $ = (id) => document.getElementById(id);\n        const walletDisplay = $(\"walletDisplay\");\n        const networkDisplay = $(\"networkDisplay\");\n        const shyBalance = $(\"shyBalance\");\n        const userRole = $(\"userRole\");\n        const userBalance = $(\"userBalance\");\n        const totalSupply = $(\"totalSupply\");\n        const tradingStatus = $(\"tradingStatus\");\n        const connectBtn = $(\"connectBtn\");\n        const switchNetworkBtn = $(\"switchNetworkBtn\");\n        const refreshBtn = $(\"refreshBtn\");\n        const noWalletBox = $(\"noWalletBox\");\n        const protocolWarning = $(\"protocolWarning\");<\/p>\n<p>        const sharedAddressInput = $(\"sharedAddressInput\");\n        const addressSyncHint = $(\"addressSyncHint\");\n        const addressClearBtn = $(\"addressClearBtn\");\n        const addressFillWalletBtn = $(\"addressFillWalletBtn\");<\/p>\n<p>        const applyName = $(\"applyName\");\n        const applyRegion = $(\"applyRegion\");\n        const applyIdNumber = $(\"applyIdNumber\");\n        const applyContact = $(\"applyContact\");\n        const applyWalletAddress = $(\"applyWalletAddress\");\n        const applySubmitBtn = $(\"applySubmitBtn\");\n        const applyClearBtn = $(\"applyClearBtn\");\n        const applyFillWalletBtn = $(\"applyFillWalletBtn\");\n        const applyCopyEmailBtn = $(\"applyCopyEmailBtn\");\n        const applyEmailPreview = $(\"applyEmailPreview\");\n        const fallbackEmailDisplay = $(\"fallbackEmailDisplay\");<\/p>\n<p>        const stableCoinSelect = $(\"stableCoinSelect\");\n        const currentRate = $(\"currentRate\");\n        const currentFee = $(\"currentFee\");<\/p>\n<p>        const buyAmount = $(\"buyAmount\");\n        const buyPreview = $(\"buyPreview\");\n        const buyReceive = $(\"buyReceive\");\n        const buyFee = $(\"buyFee\");\n        const buyShyBtn = $(\"buyShyBtn\");<\/p>\n<p>        const sellAmount = $(\"sellAmount\");\n        const sellPreview = $(\"sellPreview\");\n        const sellReceive = $(\"sellReceive\");\n        const sellFee = $(\"sellFee\");\n        const sellNet = $(\"sellNet\");\n        const sellShyBtn = $(\"sellShyBtn\");\n        const sellSection = $(\"sellSection\");<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u68c0\u67e5\u534f\u8bae\n        \/\/ ================================================================<\/p>\n<p>        if (window.location.protocol === 'file:') {\n            protocolWarning.classList.add('show');\n        } else {\n            protocolWarning.classList.remove('show');\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  Toast\n        \/\/ ================================================================<\/p>\n<p>        function showToast(msg, type = \"info\") {\n            const old = document.querySelector(\".toast\");\n            if (old) old.remove();\n            const div = document.createElement(\"div\");\n            div.className = `toast ${type}`;\n            div.textContent = msg;\n            document.body.appendChild(div);\n            setTimeout(() => { if (div.parentNode) div.remove(); }, 5000);\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  Loading\n        \/\/ ================================================================<\/p>\n<p>        function setLoading(btn, loading) {\n            if (!btn) return;\n            if (loading) {\n                btn.disabled = true;\n                btn.innerHTML = '<span class=\"spinner\"><\/span> <span data-i18n=\"processing\">\u5904\u7406\u4e2d...<\/span>';\n            } else {\n                btn.disabled = false;\n                btn.innerHTML = btn.dataset.original || btn.textContent;\n            }\n        }<\/p>\n<p>        function storeOriginal(btn) {\n            if (btn && !btn.dataset.original) btn.dataset.original = btn.innerHTML;\n        }\n        [connectBtn, refreshBtn, applySubmitBtn, buyShyBtn, sellShyBtn].forEach(storeOriginal);<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u68c0\u6d4b\u94b1\u5305\n        \/\/ ================================================================<\/p>\n<p>        function hasWallet() {\n            if (window.location.protocol === 'file:') return false;\n            return typeof window.ethereum !== 'undefined';\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u83b7\u53d6\u7a33\u5b9a\u5e01\u7b26\u53f7\n        \/\/ ================================================================<\/p>\n<p>        async function getStableCoinSymbol(address) {\n            const key = address.toLowerCase();\n            if (stableSymbolCache[key]) return stableSymbolCache[key];<\/p>\n<p>            try {\n                const prov = readOnlyProvider || signer;\n                if (!prov) {\n                    const short = address.slice(0, 6) + '...' + address.slice(-4);\n                    stableSymbolCache[key] = short;\n                    return short;\n                }<\/p>\n<p>                const contract = new ethers.Contract(address, [\n                    \"function symbol() view returns (string)\"\n                ], prov);<\/p>\n<p>                const symbol = await contract.symbol();\n                stableSymbolCache[key] = symbol;\n                return symbol;\n            } catch (e) {\n                console.warn('\u83b7\u53d6\u7a33\u5b9a\u5e01\u7b26\u53f7\u5931\u8d25:', address, e);\n                const short = address.slice(0, 6) + '...' + address.slice(-4);\n                stableSymbolCache[key] = short;\n                return short;\n            }\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u521d\u59cb\u5316\u53ea\u8bfb\n        \/\/ ================================================================<\/p>\n<p>        function initReadOnlyProvider() {\n            try {\n                readOnlyProvider = new ethers.JsonRpcProvider(\"https:\/\/mainnet.base.org\");\n                const readContract = (addr, abi) => new ethers.Contract(addr, abi, readOnlyProvider);\n                contracts.customToken = readContract(CONFIG.customToken, ABI.customToken);\n                console.log(\"\u2705 \u53ea\u8bfb Provider \u521d\u59cb\u5316\u6210\u529f\");\n            } catch (e) {\n                console.warn(\"\u53ea\u8bfb Provider \u5931\u8d25:\", e);\n                try {\n                    readOnlyProvider = new ethers.JsonRpcProvider(\"https:\/\/base.llamarpc.com\");\n                    const readContract = (addr, abi) => new ethers.Contract(addr, abi, readOnlyProvider);\n                    contracts.customToken = readContract(CONFIG.customToken, ABI.customToken);\n                    console.log(\"\u2705 \u5907\u7528 RPC \u6210\u529f\");\n                } catch (e2) {\n                    console.error(\"\u274c \u6240\u6709 RPC \u5931\u8d25:\", e2);\n                }\n            }\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u52a0\u8f7d\u516c\u5f00\u6570\u636e\n        \/\/ ================================================================<\/p>\n<p>        async function loadPublicData() {\n            if (!contracts.customToken) {\n                totalSupply.textContent = \"\u26a0\ufe0f \" + (TRANSLATIONS[currentLang]?.unableToConnect || '\u65e0\u6cd5\u8fde\u63a5');\n                tradingStatus.textContent = \"\u26a0\ufe0f\";\n                return;\n            }\n            try {\n                const supply = await contracts.customToken.totalSupply();\n                const formatted = ethers.formatUnits(supply, 4);\n                totalSupply.textContent = formatted + \" SHY\";<\/p>\n<p>                const enabled = await contracts.customToken.tradingEnabled();\n                tradingStatus.dataset.enabled = enabled ? 'true' : 'false';\n                updateTradingStatusText();\n                console.log(\"\u2705 \u516c\u5f00\u6570\u636e\u52a0\u8f7d\u6210\u529f\");\n            } catch (e) {\n                console.error(\"\u52a0\u8f7d\u516c\u5f00\u6570\u636e\u5931\u8d25:\", e);\n                totalSupply.textContent = \"\u26a0\ufe0f \" + (TRANSLATIONS[currentLang]?.loadFailed || '\u52a0\u8f7d\u5931\u8d25');\n                tradingStatus.textContent = \"\u26a0\ufe0f \" + (TRANSLATIONS[currentLang]?.loadFailed || '\u52a0\u8f7d\u5931\u8d25');\n            }\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u8fde\u63a5\/\u65ad\u5f00\u94b1\u5305\n        \/\/ ================================================================<\/p>\n<p>        async function toggleWallet() {\n            if (userAddress) {\n                disconnectWallet();\n            } else {\n                await connectWallet();\n            }\n        }<\/p>\n<p>        function disconnectWallet() {\n            userAddress = \"\";\n            signer = null;\n            provider = null;\n            contracts = {};\n            walletDisplay.textContent = \"\u26d3\ufe0f \" + (TRANSLATIONS[currentLang]?.notConnected || '\u672a\u8fde\u63a5');\n            walletDisplay.className = \"wallet-badge\";\n            networkDisplay.textContent = TRANSLATIONS[currentLang]?.notConnected || '\u672a\u8fde\u63a5';\n            userRole.textContent = \"\u2014\";\n            shyBalance.textContent = \"0.0000\";\n            userBalance.textContent = \"0.0000 SHY\";\n            updateConnectButtonText();\n            sharedAddressInput.value = '';\n            sharedAddress = '';\n            updateAddressSyncHint();\n            stableCoinSelect.innerHTML = '<option value=\"\">\u2014 <span data-i18n=\"connectWalletFirst\">\u8bf7\u8fde\u63a5\u94b1\u5305<\/span> \u2014<\/option>';\n            currentRate.textContent = \"\u2014\";\n            currentFee.textContent = \"\u2014\";\n            sellSection.style.display = 'block';\n            buyPreview.classList.remove('show');\n            sellPreview.classList.remove('show');\n            showToast('\u2705 \u5df2\u65ad\u5f00\u8fde\u63a5', 'info');\n        }<\/p>\n<p>        async function connectWallet() {\n            if (isConnecting) return;\n            isConnecting = true;<\/p>\n<p>            if (window.location.protocol === 'file:') {\n                showToast(\"\u26a0\ufe0f \u8bf7\u4f7f\u7528 Live Server \u6216 http:\/\/ \u534f\u8bae\u6253\u5f00\u6b64\u9875\u9762\", \"error\");\n                isConnecting = false;\n                return;\n            }<\/p>\n<p>            if (!hasWallet()) {\n                noWalletBox.classList.add(\"show\");\n                showToast(\"\u672a\u68c0\u6d4b\u5230\u94b1\u5305\uff0c\u8bf7\u5b89\u88c5 MetaMask \u6216 TokenPocket\", \"error\");\n                isConnecting = false;\n                return;\n            }\n            noWalletBox.classList.remove(\"show\");<\/p>\n<p>            try {\n                setLoading(connectBtn, true);\n                console.log(\"\ud83d\udd04 \u6b63\u5728\u8fde\u63a5\u94b1\u5305...\");<\/p>\n<p>                const timeoutPromise = new Promise((_, reject) => {\n                    setTimeout(() => reject(new Error(\"\u8fde\u63a5\u8d85\u65f6\uff0c\u8bf7\u68c0\u67e5\u94b1\u5305\u662f\u5426\u5df2\u89e3\u9501\")), 30000);\n                });<\/p>\n<p>                const providerPromise = (async () => {\n                    const prov = new ethers.BrowserProvider(window.ethereum);\n                    await prov.send(\"eth_requestAccounts\", []);\n                    return prov;\n                })();<\/p>\n<p>                provider = await Promise.race([providerPromise, timeoutPromise]);\n                signer = await provider.getSigner();\n                userAddress = await signer.getAddress();<\/p>\n<p>                const network = await provider.getNetwork();\n                const chainId = Number(network.chainId);<\/p>\n<p>                if (chainId !== CONFIG.network.chainId) {\n                    showToast(`\u8bf7\u5207\u6362\u5230 ${CONFIG.network.name} (Chain ID: ${CONFIG.network.chainId})`, \"error\");\n                    switchNetworkBtn.style.display = \"inline-block\";\n                    setLoading(connectBtn, false);\n                    isConnecting = false;\n                    return;\n                }<\/p>\n<p>                switchNetworkBtn.style.display = \"none\";\n                walletDisplay.textContent = userAddress.slice(0, 6) + \"...\" + userAddress.slice(-4);\n                walletDisplay.className = \"wallet-badge connected\";\n                networkDisplay.textContent = CONFIG.network.name;<\/p>\n<p>                updateConnectButtonText();<\/p>\n<p>                contracts.customToken = new ethers.Contract(CONFIG.customToken, ABI.customToken, signer);\n                contracts.controlledTransfer = new ethers.Contract(CONFIG.controlledTransfer, ABI.controlledTransfer, signer);\n                contracts.autoExchange = new ethers.Contract(CONFIG.autoExchange, ABI.autoExchange, signer);<\/p>\n<p>                if (applyWalletAddress) {\n                    applyWalletAddress.value = userAddress;\n                }<\/p>\n<p>                await loadPublicData();\n                await refreshBalance();\n                await refreshPendingRequests();\n                await refreshExchangeInfo();\n                await refreshUserRole();\n                await loadStableCoins();<\/p>\n<p>                await checkUserLevelAndShowSell();<\/p>\n<p>                showToast(\"\u2705 \u94b1\u5305\u8fde\u63a5\u6210\u529f\uff01\", \"success\");\n                console.log(\"\u2705 \u8fde\u63a5\u6210\u529f:\", userAddress);<\/p>\n<p>            } catch (e) {\n                console.error(\"\u274c \u8fde\u63a5\u5931\u8d25:\", e);\n                if (e.message && e.message.includes(\"timeout\")) {\n                    showToast(\"\u8fde\u63a5\u8d85\u65f6\uff0c\u8bf7\u786e\u8ba4\u94b1\u5305\u5df2\u89e3\u9501\", \"error\");\n                } else if (e.message && e.message.includes(\"user rejected\")) {\n                    showToast(\"\u7528\u6237\u62d2\u7edd\u8fde\u63a5\", \"info\");\n                } else {\n                    showToast(\"\u8fde\u63a5\u5931\u8d25: \" + e.message, \"error\");\n                }\n            } finally {\n                setLoading(connectBtn, false);\n                isConnecting = false;\n            }\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u5207\u6362\u7f51\u7edc\n        \/\/ ================================================================<\/p>\n<p>        async function switchToBase() {\n            try {\n                if (window.ethereum && window.ethereum.request) {\n                    await window.ethereum.request({\n                        method: \"wallet_switchEthereumChain\",\n                        params: [{ chainId: `0x${CONFIG.network.chainId.toString(16)}` }],\n                    });\n                    showToast(\"\u5df2\u5207\u6362\u5230 Base\uff0c\u8bf7\u91cd\u65b0\u8fde\u63a5\", \"info\");\n                    setTimeout(connectWallet, 1500);\n                }\n            } catch (e) {\n                showToast(\"\u5207\u6362\u5931\u8d25: \" + e.message, \"error\");\n            }\n        }\n        switchNetworkBtn.onclick = switchToBase;<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u5237\u65b0\n        \/\/ ================================================================<\/p>\n<p>        async function refreshAll() {\n            await loadPublicData();\n            if (userAddress) {\n                await Promise.all([\n                    refreshBalance(),\n                    refreshPendingRequests(),\n                    refreshExchangeInfo(),\n                    refreshUserRole(),\n                    loadStableCoins()\n                ]);\n                await checkUserLevelAndShowSell();\n            }\n        }<\/p>\n<p>        async function refreshBalance() {\n            if (!contracts.customToken || !userAddress) return;\n            try {\n                const balance = await contracts.customToken.balanceOf(userAddress);\n                const formatted = ethers.formatUnits(balance, 4);\n                userBalance.textContent = formatted + \" SHY\";\n                shyBalance.textContent = formatted;\n            } catch (e) { console.error(e); }\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u68c0\u67e5\u7528\u6237\u7b49\u7ea7\uff0c\u63a7\u5236\u5356\u51fa\u663e\u793a\n        \/\/ ================================================================<\/p>\n<p>        async function checkUserLevelAndShowSell() {\n            if (!userAddress) {\n                sellSection.style.display = 'block';\n                console.log('\ud83d\udd13 \u672a\u8fde\u63a5\u94b1\u5305\uff0c\u5356\u51fa\u529f\u80fd\u663e\u793a\uff08\u70b9\u51fb\u65f6\u63d0\u793a\u8fde\u63a5\uff09');\n                return;\n            }<\/p>\n<p>            if (!contracts.autoExchange) {\n                if (signer) {\n                    contracts.autoExchange = new ethers.Contract(CONFIG.autoExchange, ABI.autoExchange, signer);\n                } else {\n                    sellSection.style.display = 'block';\n                    return;\n                }\n            }<\/p>\n<p>            try {\n                const isLevel2 = await contracts.autoExchange.isLevel2User(userAddress);<\/p>\n<p>                if (isLevel2) {\n                    sellSection.style.display = 'none';\n                    console.log('\ud83d\udd12 \u4e8c\u7ea7\u7528\u6237\uff0c\u5356\u51fa\u529f\u80fd\u5df2\u9690\u85cf');\n                } else {\n                    sellSection.style.display = 'block';\n                    console.log('\ud83d\udd13 \u975e\u4e8c\u7ea7\u7528\u6237\uff0c\u5356\u51fa\u529f\u80fd\u5df2\u663e\u793a');\n                }\n            } catch (e) {\n                console.warn('\u68c0\u67e5\u7528\u6237\u7b49\u7ea7\u5931\u8d25:', e);\n                sellSection.style.display = 'block';\n            }\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u5237\u65b0\u7528\u6237\u89d2\u8272\n        \/\/ ================================================================<\/p>\n<p>        async function refreshUserRole() {\n            if (!userAddress) {\n                userRole.textContent = \"\u2014\";\n                return;\n            }\n            try {\n                let roles = [];\n                if (contracts.controlledTransfer) {\n                    const l1 = await contracts.controlledTransfer.isLevel1User(userAddress);\n                    const l2 = await contracts.controlledTransfer.isLevel2User(userAddress);\n                    const app = await contracts.controlledTransfer.isApprover(userAddress);\n                    const op = await contracts.controlledTransfer.isOperator(userAddress);\n                    if (l1) roles.push(\"\u4e00\u7c7b\u7528\u6237\");\n                    if (l2) roles.push(\"\u4e8c\u7c7b\u7528\u6237\");\n                    if (app) roles.push(\"\u5ba1\u6279\u4eba\");\n                    if (op) roles.push(\"\u64cd\u4f5c\u8005\");\n                }\n                if (contracts.autoExchange && roles.length === 0) {\n                    const l1 = await contracts.autoExchange.isLevel1User(userAddress);\n                    const l2 = await contracts.autoExchange.isLevel2User(userAddress);\n                    const rec = await contracts.autoExchange.isReceiver(userAddress);\n                    if (l1) roles.push(\"\u4e00\u7ea7\u7528\u6237(\u5151\u6362)\");\n                    if (l2) roles.push(\"\u4e8c\u7ea7\u7528\u6237(\u5151\u6362)\");\n                    if (rec) roles.push(\"\u63a5\u6536\u65b9\");\n                }\n                const lang = currentLang;\n                const roleMap = {\n                    '\u4e00\u7c7b\u7528\u6237': { zh: '\u4e00\u7c7b\u7528\u6237', en: 'Level 1 User', ko: '\ub808\ubca8 1 \uc0ac\uc6a9\uc790', fr: 'Utilisateur Niveau 1' },\n                    '\u4e8c\u7c7b\u7528\u6237': { zh: '\u4e8c\u7c7b\u7528\u6237', en: 'Level 2 User', ko: '\ub808\ubca8 2 \uc0ac\uc6a9\uc790', fr: 'Utilisateur Niveau 2' },\n                    '\u5ba1\u6279\u4eba': { zh: '\u5ba1\u6279\u4eba', en: 'Approver', ko: '\uc2b9\uc778\uc790', fr: 'Approbateur' },\n                    '\u64cd\u4f5c\u8005': { zh: '\u64cd\u4f5c\u8005', en: 'Operator', ko: '\uc6b4\uc601\uc790', fr: 'Op\u00e9rateur' },\n                    '\u4e00\u7ea7\u7528\u6237(\u5151\u6362)': { zh: '\u4e00\u7ea7\u7528\u6237(\u5151\u6362)', en: 'Level 1 User (Swap)', ko: '\ub808\ubca8 1 \uc0ac\uc6a9\uc790(\uc2a4\uc651)',\n                        fr: 'Utilisateur Niveau 1 (Swap)' },\n                    '\u4e8c\u7ea7\u7528\u6237(\u5151\u6362)': { zh: '\u4e8c\u7ea7\u7528\u6237(\u5151\u6362)', en: 'Level 2 User (Swap)', ko: '\ub808\ubca8 2 \uc0ac\uc6a9\uc790(\uc2a4\uc651)',\n                        fr: 'Utilisateur Niveau 2 (Swap)' },\n                    '\u63a5\u6536\u65b9': { zh: '\u63a5\u6536\u65b9', en: 'Receiver', ko: '\uc218\uc2e0\uc790', fr: 'Destinataire' }\n                };\n                const translatedRoles = roles.map(r => {\n                    const map = roleMap[r];\n                    return map ? map[lang] || r : r;\n                });\n                userRole.textContent = roles.length > 0 ? translatedRoles.join(\", \") : \"\u666e\u901a\u7528\u6237\";\n            } catch (e) { userRole.textContent = \"\u26a0\ufe0f\"; }\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u5f85\u5ba1\u6279\u8bf7\u6c42\n        \/\/ ================================================================<\/p>\n<p>        async function refreshPendingRequests() {\n            if (!contracts.controlledTransfer || !userAddress) {\n                pendingRequestsList.innerHTML = '<\/p>\n<div class=\"empty\"><span data-i18n=\"connectWalletFirst\">\u8bf7\u8fde\u63a5\u94b1\u5305<\/span><\/div>\n<p>';\n                return;\n            }\n            try {\n                const isApprover = await contracts.controlledTransfer.isApprover(userAddress);\n                if (!isApprover) {\n                    pendingRequestsList.innerHTML = '<\/p>\n<div class=\"empty\"><span data-i18n=\"notApprover\">\u5f53\u524d\u5730\u5740\u4e0d\u662f\u5ba1\u6279\u4eba<\/span><\/div>\n<p>';\n                    return;\n                }\n                const ids = await contracts.controlledTransfer.getPendingRequestsByApprover(userAddress);\n                if (ids.length === 0) {\n                    pendingRequestsList.innerHTML = '<\/p>\n<div class=\"empty\"><span data-i18n=\"noPendingRequests\">\u6682\u65e0\u5f85\u5ba1\u6279\u8bf7\u6c42<\/span><\/div>\n<p>';\n                    return;\n                }\n                let html = '';\n                for (const id of ids) {\n                    try {\n                        const req = await contracts.controlledTransfer.getTransferRequest(Number(id));\n                        html += `<\/p>\n<div class=\"req-item\">\n                                <span class=\"req-info\">\n                                    #${id} | ${req[0].slice(0,6)}... \u2192 ${req[1].slice(0,6)}... \n                                    ${ethers.formatUnits(req[2], 4)} SHY\n                                <\/span><\/p>\n<div class=\"req-actions\">\n                                    <button class=\"btn btn-success btn-sm\" onclick=\"quickApprove(${id})\">\u2705<\/button>\n                                    <button class=\"btn btn-danger btn-sm\" onclick=\"quickReject(${id})\">\u274c<\/button>\n                                <\/div>\n<\/p><\/div>\n<p>                        `;\n                    } catch (e) {}\n                }\n                pendingRequestsList.innerHTML = html;\n            } catch (e) {\n                pendingRequestsList.innerHTML = '<\/p>\n<div class=\"empty\"><span data-i18n=\"loadFailed\">\u52a0\u8f7d\u5931\u8d25<\/span><\/div>\n<p>';\n            }\n        }<\/p>\n<p>        window.quickApprove = async function(id) {\n            if (!contracts.controlledTransfer) return;\n            try {\n                const tx = await contracts.controlledTransfer.approveTransfer(id);\n                await tx.wait();\n                showToast(`\u2705 \u8bf7\u6c42 #${id} \u5df2\u6279\u51c6`, \"success\");\n                await refreshPendingRequests();\n                await refreshBalance();\n            } catch (e) {\n                showToast(\"\u5ba1\u6279\u5931\u8d25: \" + e.message, \"error\");\n            }\n        };<\/p>\n<p>        window.quickReject = async function(id) {\n            if (!contracts.controlledTransfer) return;\n            try {\n                const tx = await contracts.controlledTransfer.rejectTransfer(id);\n                await tx.wait();\n                showToast(`\u274c \u8bf7\u6c42 #${id} \u5df2\u62d2\u7edd`, \"info\");\n                await refreshPendingRequests();\n                await refreshBalance();\n            } catch (e) {\n                showToast(\"\u62d2\u7edd\u5931\u8d25: \" + e.message, \"error\");\n            }\n        };<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u7a33\u5b9a\u5e01\u52a0\u8f7d\n        \/\/ ================================================================<\/p>\n<p>        async function loadStableCoins() {\n            const select = document.getElementById('stableCoinSelect');\n            if (!contracts.autoExchange) {\n                select.innerHTML = '<option value=\"\">\u2014 <span data-i18n=\"connectWalletFirst\">\u8bf7\u8fde\u63a5\u94b1\u5305<\/span> \u2014<\/option>';\n                return;\n            }\n            try {\n                const addresses = await contracts.autoExchange.getAllSupportedStableCoins();\n                if (!addresses || addresses.length === 0) {\n                    select.innerHTML = '<option value=\"\"><span data-i18n=\"noStableCoins\">\u6682\u65e0\u7a33\u5b9a\u5e01<\/span><\/option>';\n                    return;\n                }<\/p>\n<p>                const lang = currentLang;\n                const selectLabel = TRANSLATIONS[lang]?.selectStable || '\u9009\u62e9\u7a33\u5b9a\u5e01';\n                let html = `<option value=\"\">${selectLabel}<\/option>`;<\/p>\n<p>                for (const addr of addresses) {\n                    const symbol = await getStableCoinSymbol(addr);\n                    const short = addr.slice(0, 6) + '...' + addr.slice(-4);\n                    html += `<option value=\"${addr}\">${symbol} (${short})<\/option>`;\n                }\n                select.innerHTML = html;\n                select.onchange = function() {\n                    refreshStableCoinDisplay();\n                    refreshExchangeInfo();\n                    updateBuyPreview();\n                    updateSellPreview();\n                };\n            } catch (e) {\n                select.innerHTML = '<option value=\"\"><span data-i18n=\"loadFailed\">\u52a0\u8f7d\u5931\u8d25<\/span><\/option>';\n            }\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u5237\u65b0\u7a33\u5b9a\u5e01\u663e\u793a\n        \/\/ ================================================================<\/p>\n<p>        async function refreshStableCoinDisplay() {\n            const addr = stableCoinSelect.value;\n            const lang = currentLang;\n            const stableLabel = TRANSLATIONS[lang]?.stableCoin || '\u7a33\u5b9a\u5e01';<\/p>\n<p>            if (!addr) {\n                document.querySelectorAll('.stable-symbol-label').forEach(el => {\n                    el.textContent = stableLabel;\n                });\n                return;\n            }\n            const symbol = await getStableCoinSymbol(addr);\n            currentStableSymbol = symbol;\n            document.querySelectorAll('.stable-symbol-label').forEach(el => {\n                el.textContent = symbol;\n            });\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u5237\u65b0\u6c47\u7387\u548c\u624b\u7eed\u8d39\n        \/\/ ================================================================<\/p>\n<p>        async function refreshExchangeInfo() {\n            const addr = stableCoinSelect.value;\n            const receiver = sharedAddress;<\/p>\n<p>            if (!addr || !contracts.autoExchange) {\n                currentRate.textContent = \"\u2014\";\n                currentFee.textContent = \"\u2014\";\n                return;\n            }<\/p>\n<p>            try {\n                const rate = await contracts.autoExchange.getExchangeRate(addr);\n                const symbol = await getStableCoinSymbol(addr);\n                currentRate.textContent = `1 SHY = ${Number(rate) \/ 10000} ${symbol}`;<\/p>\n<p>                if (receiver && ethers.isAddress(receiver)) {\n                    const fee = await contracts.autoExchange.getReceiverFeeRate(receiver, addr);\n                    currentFee.textContent = `${Number(fee) \/ 100}%`;\n                    updateBuyPreview();\n                    updateSellPreview();\n                } else {\n                    const hintText = TRANSLATIONS[currentLang]?.pleaseFillMaker || '\u8bf7\u586b\u5199\u505a\u5e02\u5546\u5730\u5740';\n                    currentFee.textContent = '\u26a0\ufe0f ' + hintText;\n                }\n            } catch (e) {\n                currentRate.textContent = \"\u26a0\ufe0f \u83b7\u53d6\u5931\u8d25\";\n                currentFee.textContent = \"\u26a0\ufe0f \u83b7\u53d6\u5931\u8d25\";\n            }\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u4e70\u5165\u9884\u89c8\n        \/\/ ================================================================<\/p>\n<p>        async function updateBuyPreview() {\n            const addr = stableCoinSelect.value;\n            const amount = parseFloat(buyAmount.value);\n            const receiver = sharedAddress;\n            const preview = buyPreview;<\/p>\n<p>            if (!addr || !contracts.autoExchange || !receiver || !ethers.isAddress(receiver) || !amount || amount <= 0) {\n                preview.classList.remove('show');\n                return;\n            }\n\n            try {\n                const rate = await contracts.autoExchange.getExchangeRate(addr);\n                const feeRate = await contracts.autoExchange.getReceiverFeeRate(receiver, addr);\n                const symbol = await getStableCoinSymbol(addr);\n\n                const stableAmount = amount;\n                const shyAmount = (stableAmount * 10000) \/ Number(rate);\n                const fee = (stableAmount * Number(feeRate)) \/ 10000;\n\n                buyReceive.textContent = `${shyAmount.toFixed(4)} SHY`;\n                buyFee.textContent = `${fee.toFixed(4)} ${symbol}`;\n\n                preview.classList.add('show');\n            } catch (e) {\n                console.warn('\u9884\u89c8\u8ba1\u7b97\u5931\u8d25:', e);\n                preview.classList.remove('show');\n            }\n        }\n\n        \/\/ ================================================================\n        \/\/  \u5356\u51fa\u9884\u89c8\n        \/\/ ================================================================\n\n        async function updateSellPreview() {\n            const addr = stableCoinSelect.value;\n            const amount = parseFloat(sellAmount.value);\n            const receiver = sharedAddress;\n            const preview = sellPreview;\n\n            if (!addr || !contracts.autoExchange || !receiver || !ethers.isAddress(receiver) || !amount || amount <= 0) {\n                preview.classList.remove('show');\n                return;\n            }\n\n            try {\n                const rate = await contracts.autoExchange.getExchangeRate(addr);\n                const feeRate = await contracts.autoExchange.getReceiverFeeRate(receiver, addr);\n                const symbol = await getStableCoinSymbol(addr);\n\n                const shyAmount = amount;\n                const stableAmount = (shyAmount * Number(rate)) \/ 10000;\n                const fee = (stableAmount * Number(feeRate)) \/ 10000;\n                const netStable = stableAmount - fee;\n\n                sellReceive.textContent = `${stableAmount.toFixed(4)} ${symbol}`;\n                sellFee.textContent = `${fee.toFixed(4)} ${symbol}`;\n                sellNet.textContent = `${netStable.toFixed(4)} ${symbol}`;\n\n                preview.classList.add('show');\n            } catch (e) {\n                console.warn('\u9884\u89c8\u8ba1\u7b97\u5931\u8d25:', e);\n                preview.classList.remove('show');\n            }\n        }\n\n        \/\/ ================================================================\n        \/\/  \u5171\u7528\u5730\u5740\u540c\u6b65\u529f\u80fd\n        \/\/ ================================================================\n\n        async function updateAddressSyncHint() {\n            const val = sharedAddressInput.value.trim();\n            const hint = addressSyncHint;\n            if (!hint) return;\n\n            if (!val) {\n                const hintText = TRANSLATIONS[currentLang]?.syncHint ||\n                    '\ud83d\udca1 \u6b64\u5904\u586b\u5199\u540e\uff0c\u5ba1\u6279\u4eba\u548c\u505a\u5e02\u5546\u5c06\u81ea\u52a8\u4f7f\u7528\u540c\u4e00\u5730\u5740';\n                hint.innerHTML = '\ud83d\udca1 ' + hintText;\n                currentFee.textContent = \"\u2014\";\n                return;\n            }\n\n            if (!ethers.isAddress(val)) {\n                hint.innerHTML = '\u26a0\ufe0f <span style=\"color:#f87171;\">\u65e0\u6548\u7684\u5730\u5740\u683c\u5f0f<\/span>';\n                currentFee.textContent = '\u26a0\ufe0f \u65e0\u6548\u5730\u5740';\n                return;\n            }<\/p>\n<p>            try {\n                if (contracts.customToken) {\n                    hint.innerHTML = '\u23f3 ' + (TRANSLATIONS[currentLang]?.checkingLevel1 || '\u6b63\u5728\u9a8c\u8bc1\u767d\u540d\u5355...');\n                    const isLevel1 = await contracts.customToken.whitelistLevel1(val);\n                    if (isLevel1) {\n                        hint.innerHTML =\n                            `\u2705 <span style=\"color:#4ade80;\">${TRANSLATIONS[currentLang]?.addressActive || '\u5730\u5740\u5df2\u540c\u6b65'}<\/span> | \u2705 <span style=\"color:#4ade80;\">${TRANSLATIONS[currentLang]?.level1Verified || '\u4e00\u7c7b\u767d\u540d\u5355\u5df2\u9a8c\u8bc1'}<\/span>`;\n                    } else {\n                        hint.innerHTML =\n                            `\u2705 <span style=\"color:#4ade80;\">${TRANSLATIONS[currentLang]?.addressActive || '\u5730\u5740\u5df2\u540c\u6b65'}<\/span> | \u274c <span style=\"color:#f87171;\">${TRANSLATIONS[currentLang]?.notLevel1 || '\u5730\u5740\u4e0d\u5728 SHY \u5408\u7ea6\u7684\u4e00\u7c7b\u767d\u540d\u5355\u4e2d'}<\/span>`;\n                    }\n                } else {\n                    hint.innerHTML = '\u26a0\ufe0f <span style=\"color:#facc15;\">\u5408\u7ea6\u672a\u8fde\u63a5\uff0c\u65e0\u6cd5\u9a8c\u8bc1\u767d\u540d\u5355<\/span>';\n                }\n            } catch (e) {\n                console.warn('\u767d\u540d\u5355\u9a8c\u8bc1\u5931\u8d25:', e);\n                hint.innerHTML = '\u26a0\ufe0f <span style=\"color:#f87171;\">\u767d\u540d\u5355\u9a8c\u8bc1\u5931\u8d25\uff0c\u8bf7\u68c0\u67e5\u7f51\u7edc<\/span>';\n            }<\/p>\n<p>            await refreshExchangeInfo();\n            updateBuyPreview();\n            updateSellPreview();\n        }<\/p>\n<p>        function updateSharedAddress() {\n            sharedAddress = sharedAddressInput.value.trim();\n            updateAddressSyncHint();\n        }<\/p>\n<p>        function clearSharedAddress() {\n            sharedAddressInput.value = '';\n            sharedAddress = '';\n            updateAddressSyncHint();\n            showToast(TRANSLATIONS[currentLang]?.clearAddress || '\u5df2\u6e05\u7a7a\u5730\u5740', 'info');\n        }<\/p>\n<p>        function fillWalletToShared() {\n            if (userAddress) {\n                sharedAddressInput.value = userAddress;\n                updateSharedAddress();\n                showToast('\u2705 \u5df2\u586b\u5165\u94b1\u5305\u5730\u5740', 'success');\n            } else {\n                showToast('\u26a0\ufe0f \u8bf7\u5148\u8fde\u63a5\u94b1\u5305', 'warning');\n            }\n        }<\/p>\n<p>        if (sharedAddressInput) {\n            sharedAddressInput.addEventListener('input', updateSharedAddress);\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u7533\u8bf7\u90ae\u4ef6\u529f\u80fd\n        \/\/ ================================================================<\/p>\n<p>        function updateEmailPreview() {\n            const name = applyName.value.trim();\n            const region = applyRegion.value.trim();\n            const idNum = applyIdNumber.value.trim();\n            const contact = applyContact.value.trim();\n            const wallet = applyWalletAddress.value.trim() || '\u672a\u8fde\u63a5';<\/p>\n<p>            if (!name && !region && !idNum && !contact) {\n                applyEmailPreview.textContent = '\u7b49\u5f85\u586b\u5199...';\n                return;\n            }<\/p>\n<p>            const lang = currentLang;\n            const t = TRANSLATIONS[lang];\n            const subject = encodeURIComponent(`SHY \u7528\u6237\u6ce8\u518c\u7533\u8bf7 - ${name || '\u672a\u586b\u5199'}`);\n            const body = encodeURIComponent(\n                `${t.fullName || '\u59d3\u540d'}: ${name}\\n` +\n                `${t.region || '\u5730\u533a'}: ${region}\\n` +\n                `${t.idNumber || '\u8eab\u4efd\u8bc1\u4ef6\u53f7\u7801'}: ${idNum}\\n` +\n                `${t.contactMethod || '\u5728\u7ebf\u8054\u7cfb\u65b9\u5f0f'}: ${contact}\\n` +\n                `${t.walletAddress || '\u94b1\u5305\u5730\u5740'}: ${wallet}\\n\\n` +\n                `---\\n${t.applyNotice3 || '\u6570\u5b57\u8d27\u5e01\u4ea4\u6613\u53d7\u9650\u5730\u533a\u7684\u7533\u8bf7\u5c06\u4e0d\u4e88\u901a\u8fc7\uff0c\u6216\u9650\u5b9a\u4e3a\u4e8c\u7c7b\u7528\u6237\u3002'}`\n            );<\/p>\n<p>            const preview = `mailto:${APPLICATION_EMAIL}?subject=${subject}&body=${body}`;\n            applyEmailPreview.textContent = preview.length > 80 ? preview.slice(0, 80) + '...' : preview;\n            applyEmailPreview.dataset.mailto = `mailto:${APPLICATION_EMAIL}?subject=${subject}&body=${body}`;\n        }<\/p>\n<p>        function sendApplication() {\n            const name = applyName.value.trim();\n            const region = applyRegion.value.trim();\n            const idNum = applyIdNumber.value.trim();\n            const contact = applyContact.value.trim();\n            const wallet = applyWalletAddress.value.trim();<\/p>\n<p>            if (!name || !region || !idNum || !contact) {\n                showToast(TRANSLATIONS[currentLang]['applyFail'] || '\u8bf7\u5b8c\u6574\u586b\u5199\u6240\u6709\u5fc5\u586b\u5b57\u6bb5', 'error');\n                return;\n            }<\/p>\n<p>            if (!wallet || wallet === '\u672a\u8fde\u63a5') {\n                showToast(TRANSLATIONS[currentLang]['applyWalletHint'] || '\u8bf7\u5148\u8fde\u63a5\u94b1\u5305', 'warning');\n                return;\n            }<\/p>\n<p>            const lang = currentLang;\n            const t = TRANSLATIONS[lang];\n            const subject = encodeURIComponent(`SHY \u7528\u6237\u6ce8\u518c\u7533\u8bf7 - ${name}`);\n            const body = encodeURIComponent(\n                `${t.fullName || '\u59d3\u540d'}: ${name}\\n` +\n                `${t.region || '\u5730\u533a'}: ${region}\\n` +\n                `${t.idNumber || '\u8eab\u4efd\u8bc1\u4ef6\u53f7\u7801'}: ${idNum}\\n` +\n                `${t.contactMethod || '\u5728\u7ebf\u8054\u7cfb\u65b9\u5f0f'}: ${contact}\\n` +\n                `${t.walletAddress || '\u94b1\u5305\u5730\u5740'}: ${wallet}\\n\\n` +\n                `---\\n${t.applyNotice3 || '\u6570\u5b57\u8d27\u5e01\u4ea4\u6613\u53d7\u9650\u5730\u533a\u7684\u7533\u8bf7\u5c06\u4e0d\u4e88\u901a\u8fc7\uff0c\u6216\u9650\u5b9a\u4e3a\u4e8c\u7c7b\u7528\u6237\u3002'}`\n            );<\/p>\n<p>            const mailtoLink = `mailto:${APPLICATION_EMAIL}?subject=${subject}&body=${body}`;\n            window.open(mailtoLink, '_blank');<\/p>\n<p>            showToast(t.applySuccess || '\u2705 \u90ae\u4ef6\u5ba2\u6237\u7aef\u5df2\u6253\u5f00\uff0c\u8bf7\u68c0\u67e5\u5e76\u53d1\u9001\u60a8\u7684\u7533\u8bf7\u3002', 'success');\n        }<\/p>\n<p>        function clearApplyForm() {\n            applyName.value = '';\n            applyRegion.value = '';\n            applyIdNumber.value = '';\n            applyContact.value = '';\n            updateEmailPreview();\n            showToast('\u5df2\u6e05\u7a7a', 'info');\n        }<\/p>\n<p>        function fillWalletAddress() {\n            if (userAddress) {\n                applyWalletAddress.value = userAddress;\n                updateEmailPreview();\n                showToast('\u2705 \u5df2\u586b\u5165\u94b1\u5305\u5730\u5740', 'success');\n            } else {\n                showToast('\u26a0\ufe0f \u8bf7\u5148\u8fde\u63a5\u94b1\u5305', 'warning');\n            }\n        }<\/p>\n<p>        function copyEmailToClipboard() {\n            const email = APPLICATION_EMAIL;\n            if (navigator.clipboard && navigator.clipboard.writeText) {\n                navigator.clipboard.writeText(email).then(() => {\n                    showToast(TRANSLATIONS[currentLang]['emailCopied'] || '\u2705 \u90ae\u7bb1\u5730\u5740\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f', 'success');\n                }).catch(() => {\n                    fallbackCopyEmail(email);\n                });\n            } else {\n                fallbackCopyEmail(email);\n            }\n        }<\/p>\n<p>        function fallbackCopyEmail(email) {\n            const textarea = document.createElement('textarea');\n            textarea.value = email;\n            textarea.style.position = 'fixed';\n            textarea.style.opacity = '0';\n            document.body.appendChild(textarea);\n            textarea.select();\n            try {\n                document.execCommand('copy');\n                showToast(TRANSLATIONS[currentLang]['emailCopied'] || '\u2705 \u90ae\u7bb1\u5730\u5740\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f', 'success');\n            } catch (e) {\n                showToast('\u26a0\ufe0f \u590d\u5236\u5931\u8d25\uff0c\u8bf7\u624b\u52a8\u590d\u5236', 'error');\n            }\n            document.body.removeChild(textarea);\n        }<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u4e8b\u4ef6\u7ed1\u5b9a\n        \/\/ ================================================================<\/p>\n<p>        connectBtn.onclick = toggleWallet;<\/p>\n<p>        refreshBtn.onclick = async function() {\n            await loadPublicData();\n            if (userAddress) await refreshAll();\n            showToast(\"\u5df2\u5237\u65b0\", \"info\");\n        };<\/p>\n<p>        if (addressClearBtn) addressClearBtn.onclick = clearSharedAddress;\n        if (addressFillWalletBtn) addressFillWalletBtn.onclick = fillWalletToShared;<\/p>\n<p>        const transferTo = $(\"transferTo\");\n        const transferAmount = $(\"transferAmount\");\n        const requestTransferBtn = $(\"requestTransferBtn\");<\/p>\n<p>        requestTransferBtn.onclick = async function() {\n            const to = transferTo.value.trim();\n            const amount = transferAmount.value.trim();\n            const approver = sharedAddress;<\/p>\n<p>            if (!to || !amount) {\n                showToast(\"\u8bf7\u586b\u5199\u63a5\u6536\u65b9\u548c\u6570\u91cf\", \"error\");\n                return;\n            }\n            if (!approver || !ethers.isAddress(approver)) {\n                showToast(\"\u8bf7\u5148\u586b\u5199\u6709\u6548\u7684\u5171\u7528\u5730\u5740\", \"error\");\n                return;\n            }\n            if (!contracts.controlledTransfer) {\n                if (signer) {\n                    contracts.controlledTransfer = new ethers.Contract(CONFIG.controlledTransfer, ABI.controlledTransfer,\n                        signer);\n                } else {\n                    showToast(\"\u5408\u7ea6\u672a\u8fde\u63a5\uff0c\u8bf7\u91cd\u65b0\u8fde\u63a5\u94b1\u5305\", \"error\");\n                    return;\n                }\n            }<\/p>\n<p>            try {\n                const isLevel1 = await contracts.customToken.whitelistLevel1(approver);\n                if (!isLevel1) {\n                    showToast(\"\u274c \u5ba1\u6279\u4eba\u4e0d\u5728 SHY \u5408\u7ea6\u7684\u4e00\u7c7b\u767d\u540d\u5355\u4e2d\", \"error\");\n                    return;\n                }<\/p>\n<p>                setLoading(requestTransferBtn, true);\n                const tx = await contracts.controlledTransfer.requestTransfer(to, ethers.parseUnits(amount, 4), approver);\n                await tx.wait();\n                showToast(\"\u2705 \u8f6c\u79fb\u8bf7\u6c42\u5df2\u53d1\u8d77\", \"success\");\n                transferTo.value = \"\";\n                transferAmount.value = \"\";\n                await refreshBalance();\n            } catch (e) {\n                showToast(\"\u5931\u8d25: \" + e.message, \"error\");\n            } finally {\n                setLoading(requestTransferBtn, false);\n            }\n        };<\/p>\n<p>        const approveRequestId = $(\"approveRequestId\");\n        const approveTransferBtn = $(\"approveTransferBtn\");\n        const rejectTransferBtn = $(\"rejectTransferBtn\");\n        const refreshRequestsBtn = $(\"refreshRequestsBtn\");\n        const pendingRequestsList = $(\"pendingRequestsList\");<\/p>\n<p>        approveTransferBtn.onclick = async function() {\n            const id = parseInt(approveRequestId.value.trim());\n            if (isNaN(id)) {\n                showToast(\"\u8bf7\u8f93\u5165\u6709\u6548ID\", \"error\");\n                return;\n            }\n            if (!contracts.controlledTransfer) {\n                if (signer) {\n                    contracts.controlledTransfer = new ethers.Contract(CONFIG.controlledTransfer, ABI.controlledTransfer,\n                        signer);\n                } else {\n                    showToast(\"\u5408\u7ea6\u672a\u8fde\u63a5\uff0c\u8bf7\u91cd\u65b0\u8fde\u63a5\u94b1\u5305\", \"error\");\n                    return;\n                }\n            }\n            try {\n                setLoading(approveTransferBtn, true);\n                const tx = await contracts.controlledTransfer.approveTransfer(id);\n                await tx.wait();\n                showToast(`\u2705 \u8bf7\u6c42 #${id} \u5df2\u6279\u51c6`, \"success\");\n                approveRequestId.value = \"\";\n                await refreshPendingRequests();\n                await refreshBalance();\n            } catch (e) {\n                showToast(\"\u5931\u8d25: \" + e.message, \"error\");\n            } finally {\n                setLoading(approveTransferBtn, false);\n            }\n        };<\/p>\n<p>        rejectTransferBtn.onclick = async function() {\n            const id = parseInt(approveRequestId.value.trim());\n            if (isNaN(id)) {\n                showToast(\"\u8bf7\u8f93\u5165\u6709\u6548ID\", \"error\");\n                return;\n            }\n            if (!contracts.controlledTransfer) {\n                if (signer) {\n                    contracts.controlledTransfer = new ethers.Contract(CONFIG.controlledTransfer, ABI.controlledTransfer,\n                        signer);\n                } else {\n                    showToast(\"\u5408\u7ea6\u672a\u8fde\u63a5\uff0c\u8bf7\u91cd\u65b0\u8fde\u63a5\u94b1\u5305\", \"error\");\n                    return;\n                }\n            }\n            try {\n                setLoading(rejectTransferBtn, true);\n                const tx = await contracts.controlledTransfer.rejectTransfer(id);\n                await tx.wait();\n                showToast(`\u274c \u8bf7\u6c42 #${id} \u5df2\u62d2\u7edd`, \"info\");\n                approveRequestId.value = \"\";\n                await refreshPendingRequests();\n                await refreshBalance();\n            } catch (e) {\n                showToast(\"\u5931\u8d25: \" + e.message, \"error\");\n            } finally {\n                setLoading(rejectTransferBtn, false);\n            }\n        };<\/p>\n<p>        refreshRequestsBtn.onclick = refreshPendingRequests;<\/p>\n<p>        buyShyBtn.onclick = async function() {\n            const stable = stableCoinSelect.value;\n            const amount = buyAmount.value.trim();\n            const receiver = sharedAddress;<\/p>\n<p>            if (!stable || !amount) {\n                showToast(\"\u8bf7\u9009\u62e9\u7a33\u5b9a\u5e01\u5e76\u586b\u5199\u6570\u91cf\", \"error\");\n                return;\n            }\n            if (!receiver || !ethers.isAddress(receiver)) {\n                showToast(\"\u8bf7\u5148\u586b\u5199\u6709\u6548\u7684\u5171\u7528\u5730\u5740\", \"error\");\n                return;\n            }<\/p>\n<p>            if (!contracts.autoExchange) {\n                if (signer) {\n                    contracts.autoExchange = new ethers.Contract(CONFIG.autoExchange, ABI.autoExchange, signer);\n                } else {\n                    showToast(\"\u5408\u7ea6\u672a\u8fde\u63a5\uff0c\u8bf7\u91cd\u65b0\u8fde\u63a5\u94b1\u5305\", \"error\");\n                    return;\n                }\n            }<\/p>\n<p>            try {\n                const isLevel1 = await contracts.customToken.whitelistLevel1(receiver);\n                if (!isLevel1) {\n                    showToast(\"\u274c \u505a\u5e02\u5546\u4e0d\u5728 SHY \u5408\u7ea6\u7684\u4e00\u7c7b\u767d\u540d\u5355\u4e2d\", \"error\");\n                    return;\n                }<\/p>\n<p>                setLoading(buyShyBtn, true);\n                const tx = await contracts.autoExchange.buyShy(stable, ethers.parseUnits(amount, 6), receiver);\n                await tx.wait();\n                showToast(\"\u2705 \u4e70\u5165\u6210\u529f\", \"success\");\n                buyAmount.value = \"\";\n                buyPreview.classList.remove('show');\n                await refreshBalance();\n            } catch (e) {\n                console.error(\"\u4e70\u5165\u5931\u8d25:\", e);\n                showToast(\"\u5931\u8d25: \" + e.message, \"error\");\n            } finally {\n                setLoading(buyShyBtn, false);\n            }\n        };<\/p>\n<p>        sellShyBtn.onclick = async function() {\n            if (!userAddress) {\n                showToast(\"\u8bf7\u5148\u8fde\u63a5\u94b1\u5305\", \"warning\");\n                return;\n            }<\/p>\n<p>            const stable = stableCoinSelect.value;\n            const amount = sellAmount.value.trim();\n            const receiver = sharedAddress;<\/p>\n<p>            if (!stable || !amount) {\n                showToast(\"\u8bf7\u9009\u62e9\u7a33\u5b9a\u5e01\u5e76\u586b\u5199\u6570\u91cf\", \"error\");\n                return;\n            }\n            if (!receiver || !ethers.isAddress(receiver)) {\n                showToast(\"\u8bf7\u5148\u586b\u5199\u6709\u6548\u7684\u5171\u7528\u5730\u5740\", \"error\");\n                return;\n            }<\/p>\n<p>            if (!contracts.autoExchange) {\n                if (signer) {\n                    contracts.autoExchange = new ethers.Contract(CONFIG.autoExchange, ABI.autoExchange, signer);\n                } else {\n                    showToast(\"\u5408\u7ea6\u672a\u8fde\u63a5\uff0c\u8bf7\u91cd\u65b0\u8fde\u63a5\u94b1\u5305\", \"error\");\n                    return;\n                }\n            }<\/p>\n<p>            try {\n                const isLevel1 = await contracts.customToken.whitelistLevel1(receiver);\n                if (!isLevel1) {\n                    showToast(\"\u274c \u505a\u5e02\u5546\u4e0d\u5728 SHY \u5408\u7ea6\u7684\u4e00\u7c7b\u767d\u540d\u5355\u4e2d\", \"error\");\n                    return;\n                }<\/p>\n<p>                setLoading(sellShyBtn, true);\n                const tx = await contracts.autoExchange.sellShy(stable, ethers.parseUnits(amount, 4), receiver);\n                await tx.wait();\n                showToast(\"\u2705 \u5356\u51fa\u6210\u529f\", \"success\");\n                sellAmount.value = \"\";\n                sellPreview.classList.remove('show');\n                await refreshBalance();\n            } catch (e) {\n                console.error(\"\u5356\u51fa\u5931\u8d25:\", e);\n                showToast(\"\u5931\u8d25: \" + e.message, \"error\");\n            } finally {\n                setLoading(sellShyBtn, false);\n            }\n        };<\/p>\n<p>        const roleCheckAddress = $(\"roleCheckAddress\");\n        const checkRoleBtn = $(\"checkRoleBtn\");\n        const roleResult = $(\"roleResult\");<\/p>\n<p>        checkRoleBtn.onclick = async function() {\n            const addr = roleCheckAddress.value.trim();\n            if (!addr) {\n                roleResult.textContent = \"\u26a0\ufe0f \u8bf7\u8f93\u5165\u5730\u5740\";\n                return;\n            }\n            if (!contracts.controlledTransfer) {\n                if (signer) {\n                    contracts.controlledTransfer = new ethers.Contract(CONFIG.controlledTransfer, ABI.controlledTransfer,\n                        signer);\n                } else {\n                    roleResult.textContent = \"\u26a0\ufe0f \u5408\u7ea6\u672a\u8fde\u63a5\";\n                    return;\n                }\n            }\n            try {\n                const l1 = await contracts.controlledTransfer.isLevel1User(addr);\n                const l2 = await contracts.controlledTransfer.isLevel2User(addr);\n                const app = await contracts.controlledTransfer.isApprover(addr);\n                const op = await contracts.controlledTransfer.isOperator(addr);\n                let result = `\ud83d\udccc ${addr.slice(0,6)}...${addr.slice(-4)}: `;\n                const roles = [];\n                if (l1) roles.push(\"\u4e00\u7c7b\u7528\u6237\");\n                if (l2) roles.push(\"\u4e8c\u7c7b\u7528\u6237\");\n                if (app) roles.push(\"\u5ba1\u6279\u4eba\");\n                if (op) roles.push(\"\u64cd\u4f5c\u8005\");\n                if (roles.length === 0) {\n                    result += \"\u666e\u901a\u7528\u6237\";\n                } else {\n                    result += roles.join(\", \");\n                }\n                roleResult.textContent = result;\n            } catch (e) {\n                roleResult.textContent = \"\u26a0\ufe0f \u67e5\u8be2\u5931\u8d25: \" + e.message;\n            }\n        };<\/p>\n<p>        \/\/ ================================================================\n        \/\/  \u521d\u59cb\u5316\n        \/\/ ================================================================<\/p>\n<p>        try {\n            const saved = localStorage.getItem('shy-lang');\n            if (saved && TRANSLATIONS[saved]) {\n                switchLanguage(saved);\n            } else {\n                const browserLang = navigator.language || 'zh';\n                const langCode = browserLang.startsWith('en') ? 'en' :\n                    browserLang.startsWith('ko') ? 'ko' :\n                    browserLang.startsWith('fr') ? 'fr' : 'zh';\n                switchLanguage(langCode);\n            }\n        } catch (e) {\n            switchLanguage('zh');\n        }<\/p>\n<p>        if (fallbackEmailDisplay) {\n            fallbackEmailDisplay.textContent = APPLICATION_EMAIL;\n        }<\/p>\n<p>        updateAddressSyncHint();<\/p>\n<p>        initReadOnlyProvider();\n        loadPublicData();<\/p>\n<p>        if (userAddress && applyWalletAddress) {\n            applyWalletAddress.value = userAddress;\n        }<\/p>\n<p>        updateConnectButtonText();<\/p>\n<p>        sellSection.style.display = 'block';<\/p>\n<p>        console.log(\"\u2705 SHY \u7528\u6237\u64cd\u4f5c\u5e73\u53f0\u5df2\u542f\u52a8\");\n        console.log(\"\ud83d\udce6 \u5408\u7ea6\u5730\u5740:\", CONFIG.customToken);\n        console.log(\"\ud83d\udd10 \u8f6c\u8d26\u5408\u7ea6:\", CONFIG.controlledTransfer);\n        console.log(\"\ud83d\udcb1 \u5151\u6362\u5408\u7ea6:\", CONFIG.autoExchange);\n        console.log(\"\ud83d\udd12 \u5171\u7528\u5730\u5740:\", sharedAddress || '(\u672a\u8bbe\u7f6e)');\n        console.log(\"\ud83d\udce7 \u7533\u8bf7\u90ae\u7bb1:\", APPLICATION_EMAIL);\n        console.log(\"\ud83e\udd8a \u94b1\u5305\u68c0\u6d4b\u7ed3\u679c:\", hasWallet() ? \"\u2705 \u5df2\u68c0\u6d4b\u5230\" : \"\u274c \u672a\u68c0\u6d4b\u5230\");\n        console.log(\"\ud83d\udcc4 \u534f\u8bae:\", window.location.protocol);\n        console.log(\"\ud83c\udf10 \u5f53\u524d\u8bed\u8a00:\", currentLang);<\/p>\n<p>        if (!hasWallet()) {\n            noWalletBox.classList.add(\"show\");\n        }<\/p>\n<p>        if (applyName) applyName.addEventListener('input', updateEmailPreview);\n        if (applyRegion) applyRegion.addEventListener('input', updateEmailPreview);\n        if (applyIdNumber) applyIdNumber.addEventListener('input', updateEmailPreview);\n        if (applyContact) applyContact.addEventListener('input', updateEmailPreview);\n        if (applyWalletAddress) applyWalletAddress.addEventListener('input', updateEmailPreview);<\/p>\n<p>        if (applySubmitBtn) applySubmitBtn.onclick = sendApplication;\n        if (applyClearBtn) applyClearBtn.onclick = clearApplyForm;\n        if (applyFillWalletBtn) applyFillWalletBtn.onclick = fillWalletAddress;\n        if (applyCopyEmailBtn) applyCopyEmailBtn.onclick = copyEmailToClipboard;<\/p>\n<p>        if (buyAmount) buyAmount.addEventListener('input', updateBuyPreview);\n        if (sellAmount) sellAmount.addEventListener('input', updateSellPreview);<\/p>\n<p>        window.contracts = contracts;\n        window.loadPublicData = loadPublicData;\n        window.refreshAll = refreshAll;\n        window.switchLanguage = switchLanguage;\n        window.updateTradingStatusText = updateTradingStatusText;\n        window.updateEmailPreview = updateEmailPreview;\n        window.copyEmailToClipboard = copyEmailToClipboard;\n        window.updateSharedAddress = updateSharedAddress;\n        window.clearSharedAddress = clearSharedAddress;\n        window.fillWalletToShared = fillWalletToShared;\n        window.updateAddressSyncHint = updateAddressSyncHint;\n        window.updateConnectButtonText = updateConnectButtonText;\n        window.toggleWallet = toggleWallet;\n        window.disconnectWallet = disconnectWallet;\n        window.getStableCoinSymbol = getStableCoinSymbol;\n        window.refreshStableCoinDisplay = refreshStableCoinDisplay;\n        window.updateBuyPreview = updateBuyPreview;\n        window.updateSellPreview = updateSellPreview;\n        window.checkUserLevelAndShowSell = checkUserLevelAndShowSell;\n    <\/script><br \/>\n<\/body><br \/>\n<\/html><\/p>\n","protected":false},"excerpt":{"rendered":"<p>SHY\uff08\u4eba\u5de5\u751f\u547d\u4f7f\u7528\u70b9\u6570\uff09\u7528\u6237\u64cd\u4f5c\u5e73\u53f0 S SHY\uff08\u4eba\u5de5\u751f\u547d\u4f7f\u7528\u70b9\u6570\uff09\u7528\u6237\u64cd\u4f5c\u5e73\u53f0 \ud83c\udde8\ud83c\uddf3 \u4e2d\u6587 \ud83c\uddfa\ud83c\uddf8 Engl [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"open","template":"wp-custom-template-2","meta":{"footnotes":""},"class_list":["post-3","page","type-page","status-publish","hentry"],"_hostinger_reach_plugin_has_subscription_block":false,"_hostinger_reach_plugin_is_elementor":false,"_links":{"self":[{"href":"https:\/\/shypoints.online\/en\/wp-json\/wp\/v2\/pages\/3","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/shypoints.online\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/shypoints.online\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/shypoints.online\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/shypoints.online\/en\/wp-json\/wp\/v2\/comments?post=3"}],"version-history":[{"count":2,"href":"https:\/\/shypoints.online\/en\/wp-json\/wp\/v2\/pages\/3\/revisions"}],"predecessor-version":[{"id":55,"href":"https:\/\/shypoints.online\/en\/wp-json\/wp\/v2\/pages\/3\/revisions\/55"}],"wp:attachment":[{"href":"https:\/\/shypoints.online\/en\/wp-json\/wp\/v2\/media?parent=3"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}