javascriptasync-awaitjson-rpcsolanaphantom-wallet

Problem getting the balance of Phantom wallet with json-rpc request using javascript async function?


I have a connection to the Phantom wallet.

I'm expecting phantom_balance() to return a balance or data containing the balance.

Do I have an error in the json-rpc formatting?

I'm getting the following JsonRpcEngine failure on the catch().

Phantom - RPC Error: JsonRpcEngine: Response has no error or result for request:
{
  "jsonrpc": "2.0",
  "id": 1161935556,
  "method": "getBalance",
  "params": [
    "iQKBP3tSX6g3j6pS6g3LuzhoqTQKBP3tSX6g33tSX6g3j6pS6g"
  ]
}

Here is the js

// get wallet provider, phantom
const get_provider = () => {
  if ("solana" in window) {
    const provider = window.solana;
    if (provider.isPhantom) {
      return provider;
    }
  }
  window.open("https://phantom.app/", "_blank");
};

// async get wallet balance
async function phantom_balance() {
  // alt window.solana
  const phantom = get_provider();
  console.log("Still Connected: " + phantom.isConnected);
  if (phantom.isConnected !== false) {
    const wallet_address = phantom.publicKey.toString();
    console.log("Getting Balance For: " + wallet_address);
 
    // json-rpc request (ERROR!)
      const balance = await phantom.request({
        method: "getBalance",
        params: [wallet_address]
        })
        .then(function(data) {
          console.log(data);
        }).catch(function(e) {
          console.log(e);
        });
    
  }
}

I have also tried the following and get an error saying phantom.getBalance() is not a function.

    const balance = await phantom.getBalance(wallet_address)
      .then(function(data) {
        console.log(data);
      }).catch(function(e) {
        console.log(e);
      });

I am not currently including any <script> in the head of the document. According to Phantom docs, they inject window.solana into the document (which also exposes the RPC interface). Maybe I still need web3 in the head in order to access window.solana.getBalance(wallet_address) and/or the RPC method window.solana.request(method: "getBalance") ??


Solution

  • Here is my working example.

    1. Make sure you have the Phantom wallet extension installed. phantom.app

    2. Include solana-web3 in the head of the document.

    <script src="https://unpkg.com/@solana/web3.js@latest/lib/index.iife.min.js"></script>
    
    1. Make sure your js script has type="module" defined.
    <script type="module" src="/path/to/your/main.js"></script>
    
    1. This runs in your main js file.
    // get wallet provider, phantom
    const get_provider = () => {
      if ("solana" in window) {
        const provider = window.solana;
        if (provider.isPhantom) {
          return provider;
        }
      }
      window.open("https://phantom.app/", "_blank");
    };
    
    // get balance from connected Phantom wallet
    async function phantom_balance() {
      // alt window.solana
      const phantom = get_provider();
      console.log("Wallet Connected: " + phantom.isConnected);
      if (phantom.isConnected !== false) {
    
        const wallet = phantom.publicKey;
        const wallet_b58 = phantom.publicKey.toString();
    
        // connect to the cluster
        console.log("Connecting Cluster");
        var connection = new solanaWeb3.Connection(
          solanaWeb3.clusterApiUrl('devnet'),
          'confirmed',
        );
    
        // remember, do not use base 58 encoded key with getBalance();
        console.log("Getting Balance: " + wallet_b58);
        let _balance = await connection.getBalance(wallet)
          .then(function(data) {
            console.log("Wallet Balance: " + data);
            return data;
          })
          .catch(function(error) {
            console.log(error);
            return error;
          });
    
      }
    }
    
    1. Usage
    var balance = phantom_balance();
    

    Returns Lamports Integer

    992953240