feat: add phantom integration
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
# PolyNote · Polygon message pusher
|
# PolyNote · Polygon message pusher
|
||||||
|
|
||||||
Send hex-encoded messages on Polygon mainnet using the Trust Wallet browser extension or in-app browser. The app builds a zero-value transaction with your message in the data field, so only gas is spent.
|
Send hex-encoded messages on Polygon mainnet using the Trust Wallet or Phantom browser extensions. The app builds a zero-value transaction with your message in the data field, so only gas is spent.
|
||||||
|
|
||||||
## What it does
|
## What it does
|
||||||
- Connects to an injected EIP-1193 provider (Trust Wallet) and targets Polygon mainnet.
|
- Connects to injected EIP-1193 providers (Trust Wallet or Phantom) and targets Polygon mainnet.
|
||||||
- Hex-encodes up to 280 characters and sends a 0 MATIC transaction carrying the payload.
|
- Hex-encodes up to 280 characters and sends a 0 MATIC transaction carrying the payload.
|
||||||
- Internationalization (English, Spanish, French, German, Italian, Swedish) with a locale picker and auto language detection.
|
- Internationalization (English, Spanish, French, German, Italian, Swedish) with a locale picker and auto language detection.
|
||||||
- Live feedback, copy-to-clipboard for the tx hash, Polygonscan deep links, and a session “recent messages” view.
|
- Live feedback, copy-to-clipboard for the tx hash, Polygonscan deep links, and a session “recent messages” view.
|
||||||
|
|||||||
@@ -593,6 +593,52 @@ button:hover:not(:disabled) {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wallet-selector {
|
||||||
|
margin-top: 12px;
|
||||||
|
padding: 14px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 14px;
|
||||||
|
background: var(--surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wallet-selector-head {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wallet-toggle {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wallet-chip {
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
background: var(--surface-soft);
|
||||||
|
color: var(--ink);
|
||||||
|
padding: 10px 14px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wallet-chip.active {
|
||||||
|
border-color: var(--accent);
|
||||||
|
background: rgba(14, 165, 233, 0.12);
|
||||||
|
color: var(--accent-strong);
|
||||||
|
box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wallet-icon {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
padding: 14px 18px;
|
padding: 14px 18px;
|
||||||
|
|||||||
@@ -9,15 +9,16 @@
|
|||||||
"light": "Heller Modus"
|
"light": "Heller Modus"
|
||||||
},
|
},
|
||||||
"hero": {
|
"hero": {
|
||||||
"eyebrow": "Eingebettetes Trust Wallet • Polygon Mainnet",
|
"eyebrow": "Trust Wallet oder Phantom • Polygon Mainnet",
|
||||||
"title": "PolyNote · Trust Wallet zu Polygon",
|
"title": "PolyNote · Eingebettete Wallets zu Polygon",
|
||||||
"lede": "Verbinde dich mit der Trust-Wallet-Erweiterung oder dem In-App-Browser. Wir kodieren deinen Text in Hex und senden eine Null-MATIC-Transaktion auf Polygon – nur Gasgebühren fallen an."
|
"lede": "Verbinde dich mit den Erweiterungen von Trust Wallet oder Phantom. Wir kodieren deinen Text in Hex und senden eine 0-MATIC-Transaktion auf Polygon – nur Gasgebühren fallen an."
|
||||||
},
|
},
|
||||||
"connection": {
|
"connection": {
|
||||||
"title": "Verbindung",
|
"title": "Verbindung",
|
||||||
"subtitle": "Eingebettetes Trust Wallet (Browser-Erweiterung oder In-App dApp Browser).",
|
"subtitle": "Eingebettete Wallet (Trust Wallet- oder Phantom-Erweiterung).",
|
||||||
"pill": "Nur Polygon",
|
"pill": "Nur Polygon",
|
||||||
"connect": "Trust Wallet verbinden",
|
"connect": "Trust Wallet verbinden",
|
||||||
|
"connectWallet": "{wallet} verbinden",
|
||||||
"disconnect": "Trennen",
|
"disconnect": "Trennen",
|
||||||
"account": "Konto",
|
"account": "Konto",
|
||||||
"chain": "Netzwerk",
|
"chain": "Netzwerk",
|
||||||
@@ -59,6 +60,12 @@
|
|||||||
"footer": {
|
"footer": {
|
||||||
"repo": "Quellcode auf Gitea"
|
"repo": "Quellcode auf Gitea"
|
||||||
},
|
},
|
||||||
|
"wallet": {
|
||||||
|
"pick": "Wallet wählen",
|
||||||
|
"helper": "Nur injizierte Erweiterungen. Wähle Trust Wallet oder Phantom und verbinde dich.",
|
||||||
|
"trust": "Trust Wallet",
|
||||||
|
"phantom": "Phantom"
|
||||||
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"waiting": "Warten auf Verbindung…",
|
"waiting": "Warten auf Verbindung…",
|
||||||
"preparingConnect": "Verbindung wird vorbereitet…",
|
"preparingConnect": "Verbindung wird vorbereitet…",
|
||||||
@@ -78,7 +85,7 @@
|
|||||||
"disconnected": "Getrennt."
|
"disconnected": "Getrennt."
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"noWallet": "Keine eingebettete Wallet gefunden. Verwende die Trust-Wallet-Erweiterung oder den In-App-Browser.",
|
"noWallet": "Keine injizierte {wallet} gefunden. Installiere die Erweiterung und versuche es erneut.",
|
||||||
"noAccounts": "Die Wallet hat keine Konten zurückgegeben.",
|
"noAccounts": "Die Wallet hat keine Konten zurückgegeben.",
|
||||||
"sendFailed": "Nachrichten-Transaktion konnte nicht gesendet werden.",
|
"sendFailed": "Nachrichten-Transaktion konnte nicht gesendet werden.",
|
||||||
"connectionFailed": "Verbindung fehlgeschlagen."
|
"connectionFailed": "Verbindung fehlgeschlagen."
|
||||||
|
|||||||
@@ -9,15 +9,16 @@
|
|||||||
"light": "Light mode"
|
"light": "Light mode"
|
||||||
},
|
},
|
||||||
"hero": {
|
"hero": {
|
||||||
"eyebrow": "Injected Trust Wallet • Polygon mainnet",
|
"eyebrow": "Trust Wallet or Phantom • Polygon mainnet",
|
||||||
"title": "PolyNote · Trust Wallet to Polygon",
|
"title": "PolyNote · Injected wallets to Polygon",
|
||||||
"lede": "Connect with the Trust Wallet extension or the in-app browser. We hex-encode your text and submit a zero-value Polygon transaction that only costs gas."
|
"lede": "Connect with the Trust Wallet or Phantom browser extensions. We hex-encode your text and submit a zero-value Polygon transaction that only costs gas."
|
||||||
},
|
},
|
||||||
"connection": {
|
"connection": {
|
||||||
"title": "Connection",
|
"title": "Connection",
|
||||||
"subtitle": "Injected Trust Wallet (browser extension or in-app dApp browser).",
|
"subtitle": "Injected wallet (Trust Wallet or Phantom extension).",
|
||||||
"pill": "Polygon only",
|
"pill": "Polygon only",
|
||||||
"connect": "Connect Trust Wallet",
|
"connect": "Connect Trust Wallet",
|
||||||
|
"connectWallet": "Connect {wallet}",
|
||||||
"disconnect": "Disconnect",
|
"disconnect": "Disconnect",
|
||||||
"account": "Account",
|
"account": "Account",
|
||||||
"chain": "Chain",
|
"chain": "Chain",
|
||||||
@@ -59,6 +60,12 @@
|
|||||||
"footer": {
|
"footer": {
|
||||||
"repo": "Source on Gitea"
|
"repo": "Source on Gitea"
|
||||||
},
|
},
|
||||||
|
"wallet": {
|
||||||
|
"pick": "Choose a wallet",
|
||||||
|
"helper": "Injected extensions only. Pick Trust Wallet or Phantom, then connect.",
|
||||||
|
"trust": "Trust Wallet",
|
||||||
|
"phantom": "Phantom"
|
||||||
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"waiting": "Waiting to connect…",
|
"waiting": "Waiting to connect…",
|
||||||
"preparingConnect": "Preparing to connect…",
|
"preparingConnect": "Preparing to connect…",
|
||||||
@@ -78,7 +85,7 @@
|
|||||||
"disconnected": "Disconnected."
|
"disconnected": "Disconnected."
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"noWallet": "No injected wallet found. Try the Trust Wallet extension or app browser.",
|
"noWallet": "No injected {wallet} found. Install the extension and try again.",
|
||||||
"noAccounts": "No accounts returned from injected wallet.",
|
"noAccounts": "No accounts returned from injected wallet.",
|
||||||
"sendFailed": "Failed to send message transaction.",
|
"sendFailed": "Failed to send message transaction.",
|
||||||
"connectionFailed": "Connection failed."
|
"connectionFailed": "Connection failed."
|
||||||
|
|||||||
@@ -9,15 +9,16 @@
|
|||||||
"light": "Modo claro"
|
"light": "Modo claro"
|
||||||
},
|
},
|
||||||
"hero": {
|
"hero": {
|
||||||
"eyebrow": "Trust Wallet inyectado • Polygon mainnet",
|
"eyebrow": "Trust Wallet o Phantom • Polygon mainnet",
|
||||||
"title": "PolyNote · Trust Wallet a Polygon",
|
"title": "PolyNote · Wallets inyectadas a Polygon",
|
||||||
"lede": "Conecta con la extensión de Trust Wallet o el navegador dentro de la app. Codificamos tu texto en hex y enviamos una transacción de valor cero en Polygon; solo pagas gas."
|
"lede": "Conecta con las extensiones de Trust Wallet o Phantom. Codificamos tu texto en hex y enviamos una transacción de valor cero en Polygon; solo pagas gas."
|
||||||
},
|
},
|
||||||
"connection": {
|
"connection": {
|
||||||
"title": "Conexión",
|
"title": "Conexión",
|
||||||
"subtitle": "Trust Wallet inyectado (extensión o navegador dentro de la app).",
|
"subtitle": "Wallet inyectada (extensión Trust Wallet o Phantom).",
|
||||||
"pill": "Solo Polygon",
|
"pill": "Solo Polygon",
|
||||||
"connect": "Conectar Trust Wallet",
|
"connect": "Conectar Trust Wallet",
|
||||||
|
"connectWallet": "Conectar {wallet}",
|
||||||
"disconnect": "Desconectar",
|
"disconnect": "Desconectar",
|
||||||
"account": "Cuenta",
|
"account": "Cuenta",
|
||||||
"chain": "Red",
|
"chain": "Red",
|
||||||
@@ -59,6 +60,12 @@
|
|||||||
"footer": {
|
"footer": {
|
||||||
"repo": "Código fuente en Gitea"
|
"repo": "Código fuente en Gitea"
|
||||||
},
|
},
|
||||||
|
"wallet": {
|
||||||
|
"pick": "Elige una wallet",
|
||||||
|
"helper": "Solo extensiones inyectadas. Elige Trust Wallet o Phantom y conecta.",
|
||||||
|
"trust": "Trust Wallet",
|
||||||
|
"phantom": "Phantom"
|
||||||
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"waiting": "Esperando conexión…",
|
"waiting": "Esperando conexión…",
|
||||||
"preparingConnect": "Preparando conexión…",
|
"preparingConnect": "Preparando conexión…",
|
||||||
@@ -78,7 +85,7 @@
|
|||||||
"disconnected": "Desconectado."
|
"disconnected": "Desconectado."
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"noWallet": "No se encontró una wallet inyectada. Usa la extensión de Trust Wallet o el navegador de la app.",
|
"noWallet": "No se encontró una {wallet} inyectada. Instala la extensión e inténtalo de nuevo.",
|
||||||
"noAccounts": "La wallet no devolvió cuentas.",
|
"noAccounts": "La wallet no devolvió cuentas.",
|
||||||
"sendFailed": "No se pudo enviar la transacción con mensaje.",
|
"sendFailed": "No se pudo enviar la transacción con mensaje.",
|
||||||
"connectionFailed": "Fallo de conexión."
|
"connectionFailed": "Fallo de conexión."
|
||||||
|
|||||||
@@ -9,15 +9,16 @@
|
|||||||
"light": "Mode clair"
|
"light": "Mode clair"
|
||||||
},
|
},
|
||||||
"hero": {
|
"hero": {
|
||||||
"eyebrow": "Trust Wallet injecté • Polygon mainnet",
|
"eyebrow": "Trust Wallet ou Phantom • Polygon mainnet",
|
||||||
"title": "PolyNote · Trust Wallet vers Polygon",
|
"title": "PolyNote · Wallets injectés vers Polygon",
|
||||||
"lede": "Connecte-toi avec l’extension Trust Wallet ou le navigateur intégré. Nous encodons ton texte en hex et envoyons une transaction à 0 MATIC sur Polygon ; seuls les frais de gas sont dus."
|
"lede": "Connecte-toi avec les extensions Trust Wallet ou Phantom. Nous encodons ton texte en hex et envoyons une transaction à 0 MATIC sur Polygon ; seuls les frais de gas sont dus."
|
||||||
},
|
},
|
||||||
"connection": {
|
"connection": {
|
||||||
"title": "Connexion",
|
"title": "Connexion",
|
||||||
"subtitle": "Trust Wallet injecté (extension navigateur ou navigateur dApp intégré).",
|
"subtitle": "Wallet injectée (extension Trust Wallet ou Phantom).",
|
||||||
"pill": "Polygon uniquement",
|
"pill": "Polygon uniquement",
|
||||||
"connect": "Connecter Trust Wallet",
|
"connect": "Connecter Trust Wallet",
|
||||||
|
"connectWallet": "Connecter {wallet}",
|
||||||
"disconnect": "Déconnecter",
|
"disconnect": "Déconnecter",
|
||||||
"account": "Compte",
|
"account": "Compte",
|
||||||
"chain": "Réseau",
|
"chain": "Réseau",
|
||||||
@@ -59,6 +60,12 @@
|
|||||||
"footer": {
|
"footer": {
|
||||||
"repo": "Code source sur Gitea"
|
"repo": "Code source sur Gitea"
|
||||||
},
|
},
|
||||||
|
"wallet": {
|
||||||
|
"pick": "Choisis un wallet",
|
||||||
|
"helper": "Extensions injectées uniquement. Choisis Trust Wallet ou Phantom, puis connecte-toi.",
|
||||||
|
"trust": "Trust Wallet",
|
||||||
|
"phantom": "Phantom"
|
||||||
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"waiting": "En attente de connexion…",
|
"waiting": "En attente de connexion…",
|
||||||
"preparingConnect": "Préparation de la connexion…",
|
"preparingConnect": "Préparation de la connexion…",
|
||||||
@@ -78,7 +85,7 @@
|
|||||||
"disconnected": "Déconnecté."
|
"disconnected": "Déconnecté."
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"noWallet": "Aucune wallet injectée trouvée. Utilise l’extension Trust Wallet ou le navigateur de l’app.",
|
"noWallet": "Aucun {wallet} injecté trouvé. Installe l’extension et réessaie.",
|
||||||
"noAccounts": "La wallet n’a renvoyé aucun compte.",
|
"noAccounts": "La wallet n’a renvoyé aucun compte.",
|
||||||
"sendFailed": "Impossible d’envoyer la transaction message.",
|
"sendFailed": "Impossible d’envoyer la transaction message.",
|
||||||
"connectionFailed": "Échec de connexion."
|
"connectionFailed": "Échec de connexion."
|
||||||
|
|||||||
@@ -9,15 +9,16 @@
|
|||||||
"light": "Modalità chiara"
|
"light": "Modalità chiara"
|
||||||
},
|
},
|
||||||
"hero": {
|
"hero": {
|
||||||
"eyebrow": "Trust Wallet iniettato • Polygon mainnet",
|
"eyebrow": "Trust Wallet o Phantom • Polygon mainnet",
|
||||||
"title": "PolyNote · Trust Wallet su Polygon",
|
"title": "PolyNote · Wallet iniettate su Polygon",
|
||||||
"lede": "Connetti con l’estensione di Trust Wallet o il browser integrato. Codifichiamo il testo in hex e inviamo una transazione a 0 MATIC su Polygon; paghi solo il gas."
|
"lede": "Connettiti con le estensioni di Trust Wallet o Phantom. Codifichiamo il testo in hex e inviamo una transazione a 0 MATIC su Polygon; paghi solo il gas."
|
||||||
},
|
},
|
||||||
"connection": {
|
"connection": {
|
||||||
"title": "Connessione",
|
"title": "Connessione",
|
||||||
"subtitle": "Trust Wallet iniettato (estensione o browser dApp integrato).",
|
"subtitle": "Wallet iniettata (estensione Trust Wallet o Phantom).",
|
||||||
"pill": "Solo Polygon",
|
"pill": "Solo Polygon",
|
||||||
"connect": "Connetti Trust Wallet",
|
"connect": "Connetti Trust Wallet",
|
||||||
|
"connectWallet": "Connetti {wallet}",
|
||||||
"disconnect": "Disconnetti",
|
"disconnect": "Disconnetti",
|
||||||
"account": "Account",
|
"account": "Account",
|
||||||
"chain": "Rete",
|
"chain": "Rete",
|
||||||
@@ -59,6 +60,12 @@
|
|||||||
"footer": {
|
"footer": {
|
||||||
"repo": "Codice sorgente su Gitea"
|
"repo": "Codice sorgente su Gitea"
|
||||||
},
|
},
|
||||||
|
"wallet": {
|
||||||
|
"pick": "Scegli un wallet",
|
||||||
|
"helper": "Solo estensioni iniettate. Scegli Trust Wallet o Phantom, poi connettiti.",
|
||||||
|
"trust": "Trust Wallet",
|
||||||
|
"phantom": "Phantom"
|
||||||
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"waiting": "In attesa di connessione…",
|
"waiting": "In attesa di connessione…",
|
||||||
"preparingConnect": "Preparazione della connessione…",
|
"preparingConnect": "Preparazione della connessione…",
|
||||||
@@ -78,7 +85,7 @@
|
|||||||
"disconnected": "Disconnesso."
|
"disconnected": "Disconnesso."
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"noWallet": "Nessun wallet iniettato trovato. Usa l’estensione Trust Wallet o il browser dell’app.",
|
"noWallet": "Nessuna {wallet} iniettata trovata. Installa l’estensione e riprova.",
|
||||||
"noAccounts": "Il wallet non ha restituito account.",
|
"noAccounts": "Il wallet non ha restituito account.",
|
||||||
"sendFailed": "Impossibile inviare la transazione con messaggio.",
|
"sendFailed": "Impossibile inviare la transazione con messaggio.",
|
||||||
"connectionFailed": "Connessione fallita."
|
"connectionFailed": "Connessione fallita."
|
||||||
|
|||||||
@@ -9,15 +9,16 @@
|
|||||||
"light": "Ljust läge"
|
"light": "Ljust läge"
|
||||||
},
|
},
|
||||||
"hero": {
|
"hero": {
|
||||||
"eyebrow": "Injektad Trust Wallet • Polygon mainnet",
|
"eyebrow": "Trust Wallet eller Phantom • Polygon mainnet",
|
||||||
"title": "PolyNote · Trust Wallet till Polygon",
|
"title": "PolyNote · Injekterade wallets till Polygon",
|
||||||
"lede": "Anslut via Trust Wallets tillägg eller den inbyggda webbläsaren. Vi kodar din text i hex och skickar en 0 MATIC-transaktion på Polygon; du betalar bara gas."
|
"lede": "Anslut med Trust Wallet- eller Phantom-tilläggen. Vi kodar din text i hex och skickar en 0 MATIC-transaktion på Polygon; du betalar bara gas."
|
||||||
},
|
},
|
||||||
"connection": {
|
"connection": {
|
||||||
"title": "Anslutning",
|
"title": "Anslutning",
|
||||||
"subtitle": "Injekterad Trust Wallet (tillägg eller in-app dApp-webbläsare).",
|
"subtitle": "Injekterad wallet (Trust Wallet- eller Phantom-tillägg).",
|
||||||
"pill": "Endast Polygon",
|
"pill": "Endast Polygon",
|
||||||
"connect": "Anslut Trust Wallet",
|
"connect": "Anslut Trust Wallet",
|
||||||
|
"connectWallet": "Anslut {wallet}",
|
||||||
"disconnect": "Koppla från",
|
"disconnect": "Koppla från",
|
||||||
"account": "Konto",
|
"account": "Konto",
|
||||||
"chain": "Nätverk",
|
"chain": "Nätverk",
|
||||||
@@ -59,6 +60,12 @@
|
|||||||
"footer": {
|
"footer": {
|
||||||
"repo": "Källkod på Gitea"
|
"repo": "Källkod på Gitea"
|
||||||
},
|
},
|
||||||
|
"wallet": {
|
||||||
|
"pick": "Välj en wallet",
|
||||||
|
"helper": "Endast injekterade tillägg. Välj Trust Wallet eller Phantom och anslut.",
|
||||||
|
"trust": "Trust Wallet",
|
||||||
|
"phantom": "Phantom"
|
||||||
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"waiting": "Väntar på anslutning…",
|
"waiting": "Väntar på anslutning…",
|
||||||
"preparingConnect": "Förbereder anslutning…",
|
"preparingConnect": "Förbereder anslutning…",
|
||||||
@@ -78,7 +85,7 @@
|
|||||||
"disconnected": "Frånkopplad."
|
"disconnected": "Frånkopplad."
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"noWallet": "Ingen injekterad plånbok hittades. Använd Trust Wallet-tillägget eller appens webbläsare.",
|
"noWallet": "Ingen injekterad {wallet} hittades. Installera tillägget och försök igen.",
|
||||||
"noAccounts": "Plånboken returnerade inga konton.",
|
"noAccounts": "Plånboken returnerade inga konton.",
|
||||||
"sendFailed": "Det gick inte att skicka meddelande-transaktionen.",
|
"sendFailed": "Det gick inte att skicka meddelande-transaktionen.",
|
||||||
"connectionFailed": "Anslutningen misslyckades."
|
"connectionFailed": "Anslutningen misslyckades."
|
||||||
|
|||||||
123
app/page.tsx
123
app/page.tsx
@@ -24,11 +24,13 @@ type Eip1193Provider = {
|
|||||||
providers?: Eip1193Provider[];
|
providers?: Eip1193Provider[];
|
||||||
isTrustWallet?: boolean;
|
isTrustWallet?: boolean;
|
||||||
isTrust?: boolean;
|
isTrust?: boolean;
|
||||||
|
isPhantom?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type EthereumWindow = Window & {
|
type EthereumWindow = Window & {
|
||||||
ethereum?: Eip1193Provider & { providers?: Eip1193Provider[] };
|
ethereum?: Eip1193Provider & { providers?: Eip1193Provider[] };
|
||||||
trustwallet?: Eip1193Provider;
|
trustwallet?: Eip1193Provider;
|
||||||
|
phantom?: { ethereum?: Eip1193Provider };
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatChain = (chainId: number | null) => {
|
const formatChain = (chainId: number | null) => {
|
||||||
@@ -45,6 +47,32 @@ type MessageEntry = {
|
|||||||
createdAt: number;
|
createdAt: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function TrustIcon() {
|
||||||
|
return (
|
||||||
|
<svg className="wallet-icon" viewBox="0 0 64 64" aria-hidden="true">
|
||||||
|
<path
|
||||||
|
fill="#2b5dff"
|
||||||
|
d="M32 6c-5.7 4.8-12.1 7-18.4 7.4l.7 21c.3 9.5 6.3 18 17.7 23.6 11.4-5.6 17.4-14 17.7-23.6l.7-21C44.1 13 37.7 10.8 32 6Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="#fff"
|
||||||
|
d="M32 11.6c5 3.6 10.3 5.4 15.6 5.9l-.6 17.8c-.3 8.1-5.1 14.9-15 19.7-9.9-4.8-14.8-11.6-15-19.7l-.6-17.8c5.3-.5 10.6-2.3 15.6-5.9Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function PhantomIcon() {
|
||||||
|
return (
|
||||||
|
<svg className="wallet-icon" viewBox="0 0 64 64" aria-hidden="true">
|
||||||
|
<path
|
||||||
|
fill="#6c3bff"
|
||||||
|
d="M54.5 25.7C52 13.9 42.2 8 33.8 8 24.1 8 12 14.5 8 29.7 5.8 37.7 10.9 41.4 14.4 41.4c4 0 7.9-2.4 10.1-5.6.5 4.1 3.9 7.5 8.1 7.5 4.7 0 8.6-4 8.6-9 0-1.5-.3-2.9-.8-4.2 0 0 6.5.5 8.3 7.1 1.1 4.2 2 7 4 7 1.7 0 3.7-2.4 1.8-18.5ZM15.5 33c-1.4 0-2.5-1.5-2.5-3.3s1.1-3.3 2.5-3.3c1.4 0 2.5 1.5 2.5 3.3S16.9 33 15.5 33Zm11 0c-1.4 0-2.5-1.5-2.5-3.3s1.1-3.3 2.5-3.3c1.4 0 2.5 1.5 2.5 3.3S27.9 33 26.5 33Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
const { locale, setLocale, t, localeOptions } = useI18n("en");
|
const { locale, setLocale, t, localeOptions } = useI18n("en");
|
||||||
const [account, setAccount] = useState<string>("");
|
const [account, setAccount] = useState<string>("");
|
||||||
@@ -55,6 +83,7 @@ export default function HomePage() {
|
|||||||
key: "status.waiting",
|
key: "status.waiting",
|
||||||
tone: "info",
|
tone: "info",
|
||||||
});
|
});
|
||||||
|
const [walletChoice, setWalletChoice] = useState<"trust" | "phantom">("trust");
|
||||||
const [connecting, setConnecting] = useState<boolean>(false);
|
const [connecting, setConnecting] = useState<boolean>(false);
|
||||||
const [sending, setSending] = useState<boolean>(false);
|
const [sending, setSending] = useState<boolean>(false);
|
||||||
const [connected, setConnected] = useState<boolean>(false);
|
const [connected, setConnected] = useState<boolean>(false);
|
||||||
@@ -72,6 +101,7 @@ export default function HomePage() {
|
|||||||
: status.tone === "error"
|
: status.tone === "error"
|
||||||
? "status-line status-error"
|
? "status-line status-error"
|
||||||
: "status-line";
|
: "status-line";
|
||||||
|
const walletLabel = walletChoice === "trust" ? t("wallet.trust") : t("wallet.phantom");
|
||||||
const chainPillClass = onPolygon ? "pill pill-live" : "pill pill-quiet";
|
const chainPillClass = onPolygon ? "pill pill-live" : "pill pill-quiet";
|
||||||
const chainPillText = onPolygon ? "Polygon" : chainLabel || t("live.chainRequired");
|
const chainPillText = onPolygon ? "Polygon" : chainLabel || t("live.chainRequired");
|
||||||
const disableSend = !connected || sending;
|
const disableSend = !connected || sending;
|
||||||
@@ -106,7 +136,7 @@ export default function HomePage() {
|
|||||||
await disconnect(false);
|
await disconnect(false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await connectInjected();
|
await connectInjected(walletChoice);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Connection failed", err);
|
console.error("Connection failed", err);
|
||||||
setStatusMessage(normalizeError(err, t("errors.connectionFailed"), t), "error");
|
setStatusMessage(normalizeError(err, t("errors.connectionFailed"), t), "error");
|
||||||
@@ -116,10 +146,14 @@ export default function HomePage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function connectInjected() {
|
async function connectInjected(choice: "trust" | "phantom") {
|
||||||
const injected = pickInjectedProvider();
|
const injected = pickInjectedProvider(choice);
|
||||||
if (!injected) {
|
if (!injected) {
|
||||||
setStatusMessage(t("errors.noWallet"), "error", "errors.noWallet");
|
setStatusMessage(
|
||||||
|
t("errors.noWallet", { wallet: t(choice === "trust" ? "wallet.trust" : "wallet.phantom") }),
|
||||||
|
"error",
|
||||||
|
"errors.noWallet"
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,6 +208,23 @@ export default function HomePage() {
|
|||||||
setTxHash("—");
|
setTxHash("—");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function refreshSigner() {
|
||||||
|
if (!providerRef.current) return;
|
||||||
|
try {
|
||||||
|
const browserProvider = new ethers.BrowserProvider(
|
||||||
|
providerRef.current as unknown as ethers.Eip1193Provider
|
||||||
|
);
|
||||||
|
const signer = await browserProvider.getSigner();
|
||||||
|
signerRef.current = signer;
|
||||||
|
const address = await signer.getAddress();
|
||||||
|
const network = await browserProvider.getNetwork();
|
||||||
|
setAccount(address);
|
||||||
|
setChainId(Number(network.chainId));
|
||||||
|
} catch (err) {
|
||||||
|
console.warn("Failed to refresh signer after chain change", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function attachProviderEvents(provider: Eip1193Provider) {
|
function attachProviderEvents(provider: Eip1193Provider) {
|
||||||
if (!provider?.on) return;
|
if (!provider?.on) return;
|
||||||
provider.on("accountsChanged", handleAccountsChanged);
|
provider.on("accountsChanged", handleAccountsChanged);
|
||||||
@@ -210,6 +261,7 @@ export default function HomePage() {
|
|||||||
if (typeof newChainId !== "string" && typeof newChainId !== "number") return;
|
if (typeof newChainId !== "string" && typeof newChainId !== "number") return;
|
||||||
const parsed = parseChainId(newChainId);
|
const parsed = parseChainId(newChainId);
|
||||||
setChainId(parsed);
|
setChainId(parsed);
|
||||||
|
void refreshSigner();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ensurePolygonChain() {
|
async function ensurePolygonChain() {
|
||||||
@@ -220,6 +272,7 @@ export default function HomePage() {
|
|||||||
params: [{ chainId: "0x89" }],
|
params: [{ chainId: "0x89" }],
|
||||||
});
|
});
|
||||||
setChainId(137);
|
setChainId(137);
|
||||||
|
await refreshSigner();
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn("Chain switch rejected", err);
|
console.warn("Chain switch rejected", err);
|
||||||
@@ -393,6 +446,33 @@ export default function HomePage() {
|
|||||||
{theme === "dark" ? t("theme.light") : t("theme.dark")}
|
{theme === "dark" ? t("theme.light") : t("theme.dark")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="wallet-selector">
|
||||||
|
<div className="wallet-selector-head">
|
||||||
|
<p className="label">{t("wallet.pick")}</p>
|
||||||
|
<p className="muted">{t("wallet.helper")}</p>
|
||||||
|
</div>
|
||||||
|
<div className="wallet-toggle">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`wallet-chip ${walletChoice === "trust" ? "active" : ""}`}
|
||||||
|
onClick={() => setWalletChoice("trust")}
|
||||||
|
aria-pressed={walletChoice === "trust"}
|
||||||
|
>
|
||||||
|
<TrustIcon />
|
||||||
|
{t("wallet.trust")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`wallet-chip ${walletChoice === "phantom" ? "active" : ""}`}
|
||||||
|
onClick={() => setWalletChoice("phantom")}
|
||||||
|
aria-pressed={walletChoice === "phantom"}
|
||||||
|
>
|
||||||
|
<PhantomIcon />
|
||||||
|
{t("wallet.phantom")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@@ -413,7 +493,9 @@ export default function HomePage() {
|
|||||||
onClick={connectWallet}
|
onClick={connectWallet}
|
||||||
disabled={disableConnect}
|
disabled={disableConnect}
|
||||||
>
|
>
|
||||||
{connecting ? t("compose.sending") : t("connection.connect")}
|
{connecting
|
||||||
|
? t("compose.sending")
|
||||||
|
: t("connection.connectWallet", { wallet: walletLabel })}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
id="disconnectBtn"
|
id="disconnectBtn"
|
||||||
@@ -566,7 +648,7 @@ export default function HomePage() {
|
|||||||
|
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<div className="footer-left">
|
<div className="footer-left">
|
||||||
<span className="version-pill">1</span>
|
<span className="version-pill">2</span>
|
||||||
</div>
|
</div>
|
||||||
<a
|
<a
|
||||||
className="footer-link"
|
className="footer-link"
|
||||||
@@ -589,18 +671,35 @@ export default function HomePage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function pickInjectedProvider(): Eip1193Provider | null {
|
function pickInjectedProvider(choice: "trust" | "phantom"): Eip1193Provider | null {
|
||||||
if (typeof window === "undefined") return null;
|
if (typeof window === "undefined") return null;
|
||||||
const { ethereum, trustwallet } = window as EthereumWindow;
|
const { ethereum, trustwallet, phantom } = window as EthereumWindow;
|
||||||
if (ethereum?.providers?.length) {
|
const providers = ethereum?.providers || [];
|
||||||
const trust = ethereum.providers.find((p) => p.isTrustWallet || p.isTrust);
|
|
||||||
|
const isTrustProvider = (p: Eip1193Provider | null | undefined) =>
|
||||||
|
Boolean(p?.isTrustWallet || p?.isTrust);
|
||||||
|
const isPhantomProvider = (p: Eip1193Provider | null | undefined) =>
|
||||||
|
Boolean(p?.isPhantom || (phantom?.ethereum && p === phantom.ethereum));
|
||||||
|
|
||||||
|
if (choice === "trust") {
|
||||||
|
const trust = providers.find(isTrustProvider);
|
||||||
if (trust) return trust;
|
if (trust) return trust;
|
||||||
return ethereum.providers[0];
|
|
||||||
}
|
|
||||||
if (trustwallet) return trustwallet;
|
if (trustwallet) return trustwallet;
|
||||||
|
if (providers.length) return providers[0];
|
||||||
return ethereum || null;
|
return ethereum || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (choice === "phantom") {
|
||||||
|
const phantomFromArray = providers.find(isPhantomProvider);
|
||||||
|
if (phantomFromArray) return phantomFromArray;
|
||||||
|
if (phantom?.ethereum) return phantom.ethereum;
|
||||||
|
if (ethereum?.isPhantom) return ethereum;
|
||||||
|
return ethereum || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function parseChainId(chainId: string | number): number {
|
function parseChainId(chainId: string | number): number {
|
||||||
if (typeof chainId === "string" && chainId.startsWith("0x")) {
|
if (typeof chainId === "string" && chainId.startsWith("0x")) {
|
||||||
return parseInt(chainId, 16);
|
return parseInt(chainId, 16);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "poly-note",
|
"name": "poly-note",
|
||||||
"version": "1.0.0",
|
"version": "2.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node scripts/ensure-middleware-manifest.cjs && pnpm exec next dev",
|
"dev": "node scripts/ensure-middleware-manifest.cjs && pnpm exec next dev",
|
||||||
|
|||||||
1
public/phantom.svg
Normal file
1
public/phantom.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
404: Not Found
|
||||||
BIN
public/trustwallet.svg
Normal file
BIN
public/trustwallet.svg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Reference in New Issue
Block a user