11import { useEffect , useState } from "react" ;
2+ import type { PublicKey } from "@solana/web3.js" ;
23
34import { Emoji } from "../../../constants" ;
45import {
@@ -24,12 +25,16 @@ export const useAirdrop = () => {
2425 await PgTerminal . process ( async ( ) => {
2526 if ( ! airdropAmount ) return ;
2627
28+ if ( ! PgWallet . current ) {
29+ throw new Error ( "Wallet is not connected." ) ;
30+ }
31+
2732 let msg ;
2833 try {
2934 PgTerminal . println ( PgTerminal . info ( "Sending an airdrop request..." ) ) ;
3035
3136 const conn = PgConnection . current ;
32- const walletPk = PgWallet . current ! . publicKey ;
37+ const walletPk = PgWallet . current . publicKey ;
3338
3439 // Airdrop tx is sometimes successful even when the balance hasn't
3540 // changed. To solve this, we check before and after balance instead
@@ -55,8 +60,11 @@ export const useAirdrop = () => {
5560 "Error receiving airdrop."
5661 ) } `;
5762 }
58- } catch ( e : any ) {
59- const convertedError = PgTerminal . convertErrorMessage ( e . message ) ;
63+ } catch ( error : unknown ) {
64+ const convertedError = convertAirdropErrorMessage ( error , {
65+ walletPublicKey : PgWallet . current . publicKey ,
66+ airdropAmount : airdropAmount ,
67+ } ) ;
6068 msg = `${ Emoji . CROSS } ${ PgTerminal . error (
6169 "Error receiving airdrop:"
6270 ) } : ${ convertedError } `;
@@ -68,3 +76,51 @@ export const useAirdrop = () => {
6876
6977 return { airdrop, airdropCondition : ! ! airdropAmount } ;
7078} ;
79+
80+ function convertAirdropErrorMessage (
81+ error : unknown ,
82+ params : { walletPublicKey : PublicKey ; airdropAmount : number }
83+ ) : string {
84+ // Case 0: Not expected, return something debuggable.
85+ if ( ! ( error instanceof Error ) ) return String ( error ) ;
86+
87+ const { message } = error ;
88+ const { walletPublicKey, airdropAmount } = params ;
89+
90+ // Case 1: Internal error is clean, but not user-friendly;
91+ // so enhance the message with instructions, keeping the original message.
92+ if ( message . toLowerCase ( ) . includes ( "internal error" ) ) {
93+ return createUserFriendlyErrorMessage ( message , {
94+ walletPublicKey,
95+ airdropAmount,
96+ } ) ;
97+ }
98+
99+ // Case 2: User friendly message is presented, but the format is ugly and contains technical details.
100+ // Use the cleaned message instead of the original message, enhanced with instructions.
101+ const helpfulErrorMessages = [
102+ "You've either reached your airdrop limit today or the airdrop faucet has run dry." ,
103+ ] ;
104+ const helpfulMessage = helpfulErrorMessages . find ( ( helpfulMessage ) =>
105+ message . includes ( helpfulMessage )
106+ ) ;
107+ if ( helpfulMessage ) {
108+ return createUserFriendlyErrorMessage ( helpfulMessage , {
109+ walletPublicKey,
110+ airdropAmount,
111+ } ) ;
112+ }
113+
114+ // Case 3: Use more generic message converter
115+ return PgTerminal . convertErrorMessage ( message ) ;
116+ }
117+
118+ function createUserFriendlyErrorMessage (
119+ originalMessage : string ,
120+ params : { walletPublicKey : PublicKey ; airdropAmount : number }
121+ ) {
122+ const { walletPublicKey, airdropAmount } = params ;
123+ const link = `https://faucet.solana.com/?walletAddress=${ walletPublicKey . toBase58 ( ) } &amount=${ airdropAmount } ` ;
124+ const instruction = `Try requesting devnet SOL from Faucet (pre-filled with your wallet):\n${ link } ` ;
125+ return `${ originalMessage } \n${ instruction } ` ;
126+ }
0 commit comments