Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I can't get the wallet to open to initiate a transaction. #981

Closed
keolamation opened this issue Jun 3, 2024 · 5 comments
Closed

I can't get the wallet to open to initiate a transaction. #981

keolamation opened this issue Jun 3, 2024 · 5 comments
Labels
question Add this to close an issue with instructions on how to repost as a question on Stack Exchange

Comments

@keolamation
Copy link

Describe the bug
after connecting, if I hit the "buy" button it just reopens to model to "connect" a wallet and the developer tools complain the the public key field isn't satisfied.

To Reproduce
my app.jsx

import React, { useState, useEffect, useMemo, useCallback } from 'react';
import { transactionPush, fetchLaunchDate } from '@middleware/middleware';
import './App.css';
import './index.css';
import Wallet from './components/Wallet';
import { WalletNotConnectedError } from '@solana/wallet-adapter-base';
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui';
import { ConnectionProvider, WalletProvider, useConnection, useWallet } from '@solana/wallet-adapter-react';
import '@solana/wallet-adapter-react-ui/styles.css';
import AppWalletProvider from './AppWalletProvider';
import FetchConnection from './components/FetchConnection';
import useEthereumProvider from './hooks/useEthereumProvider';
import { clusterApiUrl, PublicKey, Transaction, SystemProgram } from '@solana/web3.js';
import TransactionComponent from './TransactionComponent';

import WalletConnectModal from './WalletConnectModal';

const PaymentTypes = [
  {
    ID: 1,
    PaymentName: 'Solana',
    NameBrev: 'SOL',
    USDRate: 172.11,
    IconImg: './images/Solana_Icon200px.png',
    IsSelected: false,
  },
  {
    ID: 2,
    PaymentName: 'United States Dollar Coin',
    NameBrev: 'USDC',
    USDRate: 1,
    IconImg: './images/USDC_Icon200px.png',
    IsSelected: false,
  },
  {
    ID: 3,
    PaymentName: 'United States Dollar',
    NameBrev: 'FIAT',
    USDRate: 1,
    IconImg: './images/FIAT_Icon200px.png',
    IsSelected: false,
  },
];

const InputFields = [
  {
    id: 1,
    type: 'currency',
    value: '',
    placeholder: 'Enter amount',
  },
  {
    id: 2,
    type: 'token',
    value: '',
    placeholder: 'Enter amount',
  },
];

const presaleRate = 0.34;

export default function App() {
  const [currencyVal, setCurrencyVal] = useState('');
  const [tokenAmount, setTokenAmount] = useState('');
  const [PaymentOptionsLi, renderList] = useState(PaymentTypes);
  const [isConnected, setConnected] = useState(false);
  const [walletPublicKey, setWalletPublicKey] = useState(null);
  const [isModalOpen, setIsModalOpen] = useState(false);
  const { connection } = useConnection();
  const { publicKey, sendTransaction } = useWallet();


 

  useEthereumProvider();

  const [launchDate, setLaunchDate] = useState(null);
  const [timeLeft, setTimeLeft] = useState('');

  useEffect(() => {
    const fetchDate = async () => {
      const date = await fetchLaunchDate();
      setLaunchDate(new Date(date));
    };
    fetchDate();
  }, []);

  useEffect(() => {
    if (launchDate) {
      const interval = setInterval(() => {
        const now = new Date();
        const difference = launchDate - now;
        const timeLeft = calculateTimeLeft(difference);
        setTimeLeft(timeLeft);
      }, 1000);
      return () => clearInterval(interval);
    }
  }, [launchDate]);

  const calculateTimeLeft = (difference) => {
    const days = Math.floor(difference / (1000 * 60 * 60 * 24));
    const hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    const minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
    const seconds = Math.floor((difference % (1000 * 60)) / 1000);
    return `${days}:${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
  };

  useEffect(() => {
    if (walletPublicKey) {
      setConnected(true);
      setIsModalOpen(false);
    } else {
      setConnected(false);
    }
  }, [walletPublicKey]);

  function handleSelected(id) {
    renderList(PaymentOptionsLi => PaymentOptionsLi.map(PaymentOption => PaymentOption.ID === id ? { ...PaymentOption, IsSelected: true } : { ...PaymentOption, IsSelected: false }));
    resetInputValues();
  }

  const selectedPaymentType = PaymentOptionsLi.find(option => option.IsSelected);

  function handleCurrencyChange(event) {
    const value = parseFloat(event.target.value);
    setCurrencyVal(value);
    if (selectedPaymentType) {
      const newTokenAmount = (value * selectedPaymentType.USDRate) / presaleRate;
      setTokenAmount(newTokenAmount.toFixed(2));
    }
  }

  function handleTokenChange(event) {
    const value = parseFloat(event.target.value);
    setTokenAmount(value);
    if (selectedPaymentType) {
      const newCurrencyVal = (value * presaleRate) / selectedPaymentType.USDRate;
      setCurrencyVal(newCurrencyVal.toFixed(2));
    }
  }

  function resetInputValues() {
    setCurrencyVal('');
    setTokenAmount('');
  }

  let tokensOwned = 0;

const handleMainButtonClick = async () => {
        if (isConnected && publicKey) {
            console.log("Initiating transaction...");
            const transactionData = {
                public_key: publicKey.toString(),
                amount: parseFloat(currencyVal),
                currency: selectedPaymentType?.NameBrev || 'SOL', // Use the selected payment type's abbreviation
            };

            try {
                const response = await fetch('http://127.0.0.1:8080/process-transaction', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify(transactionData),
                });

                const result = await response.json();
                console.log('Transaction Result:', result);

                if (result.status === 'success') {
                    const transaction = Transaction.from(Buffer.from(result.transaction, 'base64'));
                    const signedTransaction = await sendTransaction(transaction, connection);

                    await fetch('http://127.0.0.1:8080/submit-transaction', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({ signedTransaction })
                    });

                    setTransactionStatus({ status: 'success', message: 'Transaction submitted successfully' });
                } else {
                    setTransactionStatus({ status: 'error', message: 'Transaction generation failed' });
                }
            } catch (error) {
                console.error("Transaction Error:", error);
                setTransactionStatus({ status: 'error', message: error.toString() });
            }
        } else {
            setIsModalOpen(true);
        }
    };

  return (
    <AppWalletProvider>
    
    <div className='BackPanel'>
    <div className='MainPanel'>
      <p style={{marginTop:'5px',marginBottom:'5px',display:'inline'}}>🚀</p>
      <p className='LaunchHeader'style={{marginTop:'5px',marginBottom:'5px',display:'inline'}}>
      Time till launch
      </p>
      <p style={{marginTop:'5px',marginBottom:'5px',display:'inline'}}>🚀</p>
      <div className='CountDown'>
      {timeLeft}
      </div>
      
      <ICOprogress/>
      
        <h3 style={{color: 'whitesmoke', fontSize: 'medium', textAlign: 'center', 
        marginTop:'6px',marginBottom:'6px',fontWeight:350}}>
        You Own: {tokensOwned}
      </h3>
      
     
      <PaymentList paymentOP = {PaymentOptionsLi} onSelected={handleSelected}/>
      

     
      

     <div>
      <h5>
          
      </h5>
      <Inputlist
        inputFields={InputFields}
        currencyVal={currencyVal}
        tokenAmount={tokenAmount}
        handleCurrencyChange={handleCurrencyChange}
        handleTokenChange={handleTokenChange}

      />
     </div>
     <div>
     <TransactionComponent amount={currencyVal} currency={selectedPaymentType?.NameBrev || 'SOL'} />
     </div>
     <div>
     <button className="MainButton" onClick={handleMainButtonClick}>
                                {isConnected ? "Buy" : 'Connect Wallet'}
    </button>
    <WalletConnectModal isOpen={isModalOpen} onRequestClose={() => setIsModalOpen(false)} />            
    
     </div>

     <div>
     <FetchConnection setConnected={setConnected} setWalletPublicKey={setWalletPublicKey}/>
     </div>
     
    </div>
    <div className="footer-panel">
          <a href="https://linktr.ee/keolamation" target="_blank" rel="noopener noreferrer">Keolamation LLC</a>
          </div>
    </div>

   </AppWalletProvider>

  );
}

function ICOprogress() {
  const TokensSold = 0;
  const TokenPool = 30000000;
  const ProgressRate = (TokensSold / TokenPool) * 100;

  return (
    <div>
      <p style={{ marginBottom: '3px', color: '#cbcbcb', fontWeight: 50, fontSize: 12, textAlign: 'center' }}>
        Tokens sold: {TokensSold} / {TokenPool}
      </p>
      <section className='TokenMeter'>
        <section className='TokenMeter-fill' style={{ width: `${ProgressRate}%` }}></section>
      </section>
    </div>
  );
}

function CountDownTimer() {
  return (
    <div className='CountDown'>
      90:00:00:00
    </div>
  );
}

function PaymentList({paymentOP,onSelected}){

  //let PaymentsSel = PaymentOptionsLi;
  
    return(
    <section className={'PaymentTyeBtn'} style={{marginBottom:'-10px'}} >
      {paymentOP.map((payOP) =>(
      <PaymentType payOP={payOP}
        onSelected={onSelected}
        key = {payOP.ID}/>))}
    </section>
  )
  }

  function PaymentType({payOP,onSelected}){
  
    //let PaymentOp = {PaymentOptionsLi};
  
    console.log('contents of PaymentOP are,',payOP);
    return(
      <li style ={{display:'inline'}}>
        <button className={`PaymentTyeBtn ${payOP.IsSelected ? "Enabled" : "Disabled"}`} onClick={()=> onSelected(payOP.ID)}>
        <img className = 'icon' src={`${payOP.IconImg}`}style={{position:'relative',top:'5%',marginLeft:'-4px'}}>
          
        </img>
        <p style={{display:'inline',position:'relative',top:'-5%',paddingRight:'5px'}}>
        {`${payOP.NameBrev}`}
        </p>
        </button>
      </li>
    )
  }

function Inputlist({inputFields, currencyVal, tokenAmount,handleCurrencyChange, handleTokenChange}){
  return (
    <div style={{ marginTop: '5px',display:'flex', marginLeft:'11px'}}>
      {inputFields.map(field => (
        <InputField
          key={field.id}
          type={field.type}
          value={field.type === 'currency' ? currencyVal : tokenAmount}
          placeholder={field.placeholder}
          handleChange={field.type === 'currency' ? handleCurrencyChange : handleTokenChange}
        />
      ))}
    </div>
  );
}

function InputField({type, value, placeholder,handleChange}){


  return (
    <div style={{display:'inline'}}>
      <p style={{marginBottom:'2px',color:'white',marginTop:'2px',marginLeft:'12px',fontSize:'11px'}}>
        {type === 'currency'? `YOU PAY: ${value}` : `YOU GET: ${value}`}
      </p>
      <input
        className='ICOinputField'
        style={{display:'inline'}}
        type='number'
        value={value}
        onChange={handleChange}
        placeholder={placeholder}
      />
    </div>
  );
}

/*  OLD MULTIBUTTON SCR IN DIV AREA

                             {!isConnected && (
                                <WalletMultiButton style={{ display: 'none' }} />
                            )}    


*/

walletconnectmodal

// src/WalletConnectModal.jsx
import React from 'react';
import Modal from 'react-modal';
import { WalletMultiButton } from '@solana/wallet-adapter-react-ui';

Modal.setAppElement('#root');

const WalletConnectModal = ({ isOpen, onRequestClose }) => {
  return (
    <Modal
      isOpen={isOpen}
      onRequestClose={onRequestClose}
      contentLabel="Connect Wallet"
      className="modal"
      overlayClassName="overlay"
    >
        <button onClick={onRequestClose}style={{textAlign:'right'}}>❌</button>
      <h2 style={{textAlign:'center'}}>Connect Your Wallet</h2>
      <WalletMultiButton style = {{marginLeft:'55px'}} />
      
    </Modal>
  );
};

export default WalletConnectModal;

my appwalletprovider:

import React from 'react';
import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui';
import { clusterApiUrl } from '@solana/web3.js';
import {
    PhantomWalletAdapter,
    SolflareWalletAdapter,
    TorusWalletAdapter,
    LedgerWalletAdapter,
} from '@solana/wallet-adapter-wallets';

const wallets = [
    new PhantomWalletAdapter(),
    new SolflareWalletAdapter(),
    new TorusWalletAdapter(),
    new LedgerWalletAdapter(),
];

const AppWalletProvider = ({ children }) => {
    const endpoint = clusterApiUrl('mainnet-beta');

    return (
        <ConnectionProvider endpoint={endpoint}>
            <WalletProvider wallets={wallets} autoConnect>
                <WalletModalProvider>
                    {children}
                </WalletModalProvider>
            </WalletProvider>
        </ConnectionProvider>
    );
};

export default AppWalletProvider;






/*
import React from 'react';
import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui';
import { clusterApiUrl } from '@solana/web3.js';
import {
    PhantomWalletAdapter,
    SolflareWalletAdapter,
    TorusWalletAdapter,
    LedgerWalletAdapter
} from '@solana/wallet-adapter-wallets';

const wallets = [
    new PhantomWalletAdapter(),
    new SolflareWalletAdapter(),
    new TorusWalletAdapter(),
    new LedgerWalletAdapter()
];

const AppWalletProvider = ({ children }) => {
    return (
        <ConnectionProvider endpoint={clusterApiUrl('mainnet-beta')}>
            <WalletProvider wallets={wallets} autoConnect>
                <WalletModalProvider>
                    {children}
                </WalletModalProvider>
            </WalletProvider>
        </ConnectionProvider>
    );
};

export default AppWalletProvider;
*/

Expected behavior

The wallet launches in browser to request that the user sends X amount of Solana/USDC to receiver address.

Screenshots

2024-06-03.15-39-56.mp4

Desktop (please complete the following information):

  • OS: [e.g. iOS] -> Windows
  • Browser [e.g. chrome, safari] -> Opera and Chrome
  • Version [e.g. 22]

Additional context

I coded most of this but, I started asking chatgpt 4o and it seems my code got even more wrong because this documentation is too messy for chat gpt to train off of. So, I'd really like a direct answer/assistance.

@keolamation
Copy link
Author

btw, even if i connect to a diff solana wallet I still get the same error.

image

@Eiresown
Copy link

Eiresown commented Jun 9, 2024

Looks like this is not being satisfied

const handleMainButtonClick = async () => {
if (isConnected && publicKey) {

    leading to this
    
     } else {
        setIsModalOpen(true);
    }
    
   which then in turns opens your Modal here

const WalletConnectModal = ({ isOpen, onRequestClose }) => {
return (

<button onClick={onRequestClose}style={{textAlign:'right'}}>❌
<h2 style={{textAlign:'center'}}>Connect Your Wallet
<WalletMultiButton style = {{marginLeft:'55px'}} />

</Modal>

);
};

I didn't have a look through the logic of the transactions but at the moment when you press the transaction button you're just opening the modal because isConnected and publicKey are not satisfied so we never reach the transaction code. Log both just inside the handleMainButtonClick before the if statement and see what they are logging should be a simple fix to move forward.

@keolamation
Copy link
Author

keolamation commented Jun 9, 2024 via email

@jordaaash jordaaash added the question Add this to close an issue with instructions on how to repost as a question on Stack Exchange label Jun 10, 2024
Copy link
Contributor

Hi @keolamation,

Thanks for your question!

We want to make sure to keep signal strong in the GitHub issue tracker – to make sure that it remains the best place to track issues that affect the development of Wallet Adapter itself.

Questions like yours deserve a purpose-built Q & A forum. Unless there exists evidence that this is a bug with Wallet Adapter itself, please post your question to the Solana Stack Exchange using this link:

https://solana.stackexchange.com/questions/ask


This automated message is a result of having added the ‘question’ tag.

@keolamation
Copy link
Author

I'll be honest, this is why and I sware to god on this: If I ever become anyone influential I will do everything I can to make the general public aware of how AWEFUL Solana and Solana development is. This doesn't deserve the market cap it has. I haven't had any of my questions answered on Solana stack exchange and the actual devs just ban people and "move the issue" to be someone else's problem. The WORST blockchain, I've ever had the misfortune trying to develop on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Add this to close an issue with instructions on how to repost as a question on Stack Exchange
Projects
None yet
Development

No branches or pull requests

3 participants