javascript 如何使用web3js通过体模正确传输Solana SOL

jutyujz0  于 2022-12-25  发布在  Java
关注(0)|答案(3)|浏览(257)

我正在使用Solana Blockchain。我试图通过Phantom传输Solana SOL。为此,我使用了堆栈溢出中的以下代码:source link
我已经在Chrome中安装了Phantom。当我运行代码时,它显示错误:
未捕获(承诺中)类型错误:无法读取null的属性(正在读取"toString")
我认为是这行代码导致了上面的错误

console.log("Public key of the emitter: ",provider.publicKey.toString());

以下是代码

import * as web3 from '@solana/web3.js';
  import * as splToken from '@solana/spl-token';
  
  const getProvider = async () => {
    if ("solana" in window) {
      const provider = window.solana;
      if (provider.isPhantom) {
        console.log("Is Phantom installed?  ", provider.isPhantom);
        return provider;
      }
    } else {
      window.open("https://www.phantom.app/", "_blank");
    }
  };

  async function transferSOL() {
    // Detecing and storing the phantom wallet of the user (creator in this case)
    var provider = await getProvider();
    console.log("Public key of the emitter: ",provider.publicKey.toString());

    // Establishing connection
    var connection = new web3.Connection(
      web3.clusterApiUrl('devnet'),
    );

    // I have hardcoded my secondary wallet address here. You can take this address either from user input or your DB or wherever
    var recieverWallet = new web3.PublicKey("CkiKLEa9eSEoG6CoTSuaahsF2WqNgArnvoCSbNZjJ7BQ");

    // Airdrop some SOL to the sender's wallet, so that it can handle the txn fee
    var airdropSignature = await connection.requestAirdrop(
      provider.publicKey,
      web3.LAMPORTS_PER_SOL,
    );

    // Confirming that the airdrop went through
    await connection.confirmTransaction(airdropSignature);
    console.log("Airdropped");

    var transaction = new web3.Transaction().add(
      web3.SystemProgram.transfer({
        fromPubkey: provider.publicKey,
        toPubkey: recieverWallet,
        lamports: web3.LAMPORTS_PER_SOL //Investing 1 SOL. Remember 1 Lamport = 10^-9 SOL.
      }),
    );

    // Setting the variables for the transaction
    transaction.feePayer = await provider.publicKey;
    let blockhashObj = await connection.getRecentBlockhash();
    transaction.recentBlockhash = await blockhashObj.blockhash;

    // Transaction constructor initialized successfully
    if(transaction) {
      console.log("Txn created successfully");
    }
    
    // Request creator to sign the transaction (allow the transaction)
    let signed = await provider.signTransaction(transaction);
    // The signature is generated
    let signature = await connection.sendRawTransaction(signed.serialize());
    // Confirm whether the transaction went through or not
    await connection.confirmTransaction(signature);

    //Signature chhap diya idhar
    console.log("Signature: ", signature);
  }
xdnvmnnf

xdnvmnnf1#

你需要连接到钱包。那部分不见了

const getProvider = async () => {
    if ("solana" in window) {

      // opens wallet to connect to
      await window.solana.connect(); 

      const provider = window.solana;
      if (provider.isPhantom) {
        console.log("Is Phantom installed?  ", provider.isPhantom);
        return provider;
      }
    } else {
      window.open("https://www.phantom.app/", "_blank");
    }
  };
8ftvxx2r

8ftvxx2r2#

我不确定这是否是最好的解决方案,但您的问题是用户登录后幻像钱包的持久性。您必须为此选择前端繁重的解决方案。其中之一是:
1.假设您正在使用React,请使用上下文API来持久化有关Wallet的数据。以下是如何通过在项目根目录的上下文文件夹下创建文件来实现此目的的粗略指南:

import React, { createContext, useState} from "react";

export const WalletDataContext=createContext();

export const WalletDataContextProvider=(props)=>{
    const [publicKey,setPublicKey]=useState(null);
    const [wallet,setWallet]=useState(null);
    
    return (
        <WalletDataContext.Provider
            value={{publicKey,setPublicKey,wallet,setWallet}}
        >
            {props.children}            
        </WalletDataContext.Provider>
    )
}

1.创建一个connectWallet函数,如下所示:

//import {WalletDataContext}
  //import other stuff:
  const {setPublicKey,setWallet}=useContext(WalletDataContext)
  const connectWallet = async() {
  const provider = await getProvider();
  if(provider) {
    await provider.connect();
    let publicKey = "";
    provider.on("connect", async () => {
      setWallet(provider);
      publicKey = provider.pubicKey.toString();
      setPublicKey(publicKey);
      /*
        // more things that you would like to do here
      */
    });
  }
}

1.在transferSOL函数中进行以下更改:

async function transferSOL() {
    //Changes are only here, in the beginning
    const phantomProvider = wallet;
    if(!phantomProvider){
      //Urge the user to sign in(connect) again
    }
    const pubKey = await phantomProvider.publicKey;
    console.log("Public Key: ", pubKey); 

    // Establishing connection
    var connection = new web3.Connection(
      web3.clusterApiUrl('devnet'),
    );

    // I have hardcoded my secondary wallet address here. You can take this address either from user input or your DB or wherever
    var recieverWallet = new web3.PublicKey("CkiKLEa9eSEoG6CoTSuaahsF2WqNgArnvoCSbNZjJ7BQ");

    // Airdrop some SOL to the sender's wallet, so that it can handle the txn fee
    var airdropSignature = await connection.requestAirdrop(
      provider.publicKey,
      web3.LAMPORTS_PER_SOL,
    );

    // Confirming that the airdrop went through
    await connection.confirmTransaction(airdropSignature);
    console.log("Airdropped");

    var transaction = new web3.Transaction().add(
      web3.SystemProgram.transfer({
        fromPubkey: provider.publicKey,
        toPubkey: recieverWallet,
        lamports: web3.LAMPORTS_PER_SOL //Investing 1 SOL. Remember 1 Lamport = 10^-9 SOL.
      }),
    );

    // Setting the variables for the transaction
    transaction.feePayer = await provider.publicKey;
    let blockhashObj = await connection.getRecentBlockhash();
    transaction.recentBlockhash = await blockhashObj.blockhash;

    // Transaction constructor initialized successfully
    if(transaction) {
      console.log("Txn created successfully");
    }
    
    // Request creator to sign the transaction (allow the transaction)
    let signed = await provider.signTransaction(transaction);
    // The signature is generated
    let signature = await connection.sendRawTransaction(signed.serialize());
    // Confirm whether the transaction went through or not
    await connection.confirmTransaction(signature);

    //Signature or the txn hash
    console.log("Signature: ", signature);
  }
bweufnob

bweufnob3#

我想你的问题就在这里:

// Request creator to sign the transaction (allow the transaction)
    let signed = await provider.signTransaction(transaction);
    // The signature is generated
    let signature = await connection.sendRawTransaction(signed.serialize());
    // Confirm whether the transaction went through or not
    await connection.confirmTransaction(signature);

您使用提供程序签名,但使用连接发送,请尝试更改此设置:

const { signature } = await provider?.signAndSendTransaction(
      transaction
    );

    await connection.getSignatureStatus(signature);
    return signature;

相关问题