<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>clbigdata (chenlong)</title>
    <link>https://soldev.cn/clbigdata</link>
    <description/>
    <language>en-us</language>
    <item>
      <title>如何开发 solana 移动客户端</title>
      <description>&lt;p&gt;下面我将展示如何搭建一个连接到 Solana 本地测试网的移动客户端，并实现查看账户余额和发送交易的功能。我们将使用 React Native 和 Expo 来进行开发。
好的，下面我将展示如何搭建一个连接到 Solana 本地测试网的移动客户端，并实现查看账户余额和发送交易的功能。我们将使用 React Native 和 Expo 来进行开发。&lt;/p&gt;
&lt;h3 id="1. 设置开发环境"&gt;1. 设置开发环境&lt;/h3&gt;&lt;h4 id="1.1 安装 Node.js 和 npm"&gt;1.1 安装 Node.js 和 npm&lt;/h4&gt;
&lt;p&gt;确保你已经安装了 Node.js 和 npm，可以从 &lt;a href="https://nodejs.org/" rel="nofollow" target="_blank" title=""&gt;Node.js 官网&lt;/a&gt; 下载并安装它们。&lt;/p&gt;
&lt;h4 id="1.2 安装 Expo CLI"&gt;1.2 安装 Expo CLI&lt;/h4&gt;
&lt;p&gt;Expo CLI 是一个强大的工具，可以帮助你快速创建和管理 React Native 项目。&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; expo-cli
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="1.3 创建新的 React Native 项目"&gt;1.3 创建新的 React Native 项目&lt;/h4&gt;
&lt;p&gt;使用 Expo CLI 创建一个新的 React Native 项目：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;expo init SolanaMobileApp
&lt;span class="nb"&gt;cd &lt;/span&gt;SolanaMobileApp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在创建项目时，选择 "blank" 模板。&lt;/p&gt;
&lt;h4 id="1.4 启动开发服务器"&gt;1.4 启动开发服务器&lt;/h4&gt;
&lt;p&gt;运行以下命令启动开发服务器：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;expo start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者下边三个命令随便选一个启动，但前提都是，本地已经安装了 android 或者 ios 的开发环境&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;- npm run android
- npm run ios
- npm run web
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这将启动一个开发服务器，并在浏览器中打开一个控制面板。你可以使用 Expo Go 应用在手机上扫描 QR 码来预览应用。
&lt;img src="/uploads/photo/clbigdata/88fc4f4a-67e1-4268-8a33-d5c4859c67e9.png!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="2. 安装 Solana Web3.js 库"&gt;2. 安装 Solana Web3.js 库&lt;/h3&gt;
&lt;p&gt;在项目目录中安装 Solana Web3.js 库：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @solana/web3.js
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="3. 启动 Solana 本地测试网"&gt;3. 启动 Solana 本地测试网&lt;/h3&gt;
&lt;p&gt;使用 Solana CLI 启动本地测试验证器：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;solana-test-validator
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="4. 编写代码实现查看余额和发送交易的功能"&gt;4. 编写代码实现查看余额和发送交易的功能&lt;/h3&gt;&lt;h4 id="4.1 修改 App.js"&gt;4.1 修改 App.js&lt;/h4&gt;
&lt;p&gt;打开 &lt;code&gt;App.js&lt;/code&gt; 文件，并将其内容替换为以下代码：&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;View&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TextInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Alert&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clusterApiUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LAMPORTS_PER_SOL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Keypair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SystemProgram&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@solana/web3.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPublicKey&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBalance&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;recipient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setRecipient&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAmount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 连接到 Solana 的本地测试网&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:8899&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 检查余额&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCheckBalance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pubKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pubKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;LAMPORTS_PER_SOL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Alert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid public key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// 发送交易&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSendTransaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// 使用你的私钥生成 Keypair&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fromKeypair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromSecretKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="cm"&gt;/* your secret key array here */&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toPubkey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recipient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;SystemProgram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;fromPubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fromKeypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;toPubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toPubkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;lamports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;LAMPORTS_PER_SOL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fromKeypair&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;confirmTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;Alert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`Transaction successful with signature: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Alert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Transaction failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Solana&lt;/span&gt; &lt;span class="nx"&gt;Mobile&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TextInput&lt;/span&gt;
        &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter Public Key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;onChangeText&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setPublicKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Check Balance&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onPress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCheckBalance&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;SOL&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TextInput&lt;/span&gt;
        &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Recipient Public Key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;recipient&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;onChangeText&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setRecipient&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TextInput&lt;/span&gt;
        &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Amount (SOL)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;keyboardType&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;onChangeText&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setAmount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Send Transaction&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onPress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSendTransaction&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;borderColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gray&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;borderWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="关键点解释"&gt;关键点解释&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;连接到 Solana 本地测试网&lt;/strong&gt;：&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:8899&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们使用 &lt;code&gt;Connection&lt;/code&gt; 对象连接到 Solana 的本地测试网络。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;检查余额&lt;/strong&gt;：&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pubKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;LAMPORTS_PER_SOL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用 &lt;code&gt;getBalance&lt;/code&gt; 方法获取指定公钥的余额，并转换为 SOL 单位。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;发送交易&lt;/strong&gt;：&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="nx"&gt;SystemProgram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;fromPubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fromKeypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;toPubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toPubkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;lamports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;LAMPORTS_PER_SOL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fromKeypair&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;confirmTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;创建和发送一个简单的 SOL 转账交易，并等待确认。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="5. 启动应用"&gt;5. 启动应用&lt;/h3&gt;
&lt;p&gt;确保你已经启动了开发服务器，并使用 Expo Go 应用扫描 QR 码来预览你的应用。&lt;/p&gt;

&lt;p&gt;&lt;img src="/uploads/photo/clbigdata/dcea1923-3bc9-40fc-bdef-5a8148ec979b.png!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="总结"&gt;总结&lt;/h3&gt;
&lt;p&gt;通过上述步骤，我们搭建了一个基本的 React Native 开发环境，并编写了一个简单的 Solana 移动客户端，具备查看余额和发送交易的功能。这个示例使用了 React Native 和 Solana 的 Web3.js 库，展示了如何与 Solana 区块链进行交互。你可以根据需要扩展这个示例，添加更多功能和优化。
所有的代码托管到了：&lt;a href="https://github.com/rogers3333/SolanaMobileApp" rel="nofollow" target="_blank"&gt;https://github.com/rogers3333/SolanaMobileApp&lt;/a&gt;&lt;/p&gt;</description>
      <author>clbigdata</author>
      <pubDate>Thu, 26 Dec 2024 23:04:44 +0800</pubDate>
      <link>https://soldev.cn/topics/129</link>
      <guid>https://soldev.cn/topics/129</guid>
    </item>
    <item>
      <title>Solana@Web3.js-2.0：新特性</title>
      <description>&lt;h2 id="2.0 版新增功能"&gt;2.0 版新增功能&lt;/h2&gt;
&lt;p&gt;Solana JavaScript SDK 2.0 版，是在使用 web3.js 开发 Solana 应用程序时，对许多痛点进行了优化。&lt;/p&gt;
&lt;h2 id="Tree-Shakability"&gt;Tree-Shakability&lt;/h2&gt;
&lt;p&gt;web3.js（1.x）API 的面向对象设计使优化编译器无法从生产构建中，“tree-shake”未使用的代码。无论您在应用程序中使用了多少 web3.js API，到目前为止，都必须将其全部打包。&lt;/p&gt;

&lt;p&gt;在这里了解有关 tree-shaking 的更多信息：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking" rel="nofollow" target="_blank" title=""&gt;Mozilla 开发者文档：Tree Shaking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webpack.js.org/guides/tree-shaking/" rel="nofollow" target="_blank" title=""&gt;WebPack 文档：Tree Shaking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/articles/reduce-javascript-payloads-with-tree-shaking" rel="nofollow" target="_blank" title=""&gt;Web.Dev 博客文章：使用 Tree Shaking 减少 JavaScript 负载&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;一个 API 不能是树 shaken 的例子是 Connection 类。它有几十个方法，但因为它是一个类，你别无选择，只能将每个方法都包含在应用程序的最终包中，无论你实际使用了多少方法。&lt;/p&gt;

&lt;p&gt;微小的 JavaScript 捆绑包可能会导致部署到 Cloudflare 或 AWS Lambda 等云计算提供商时出现问题。由于下载和 JavaScript 解析时间较长，它们还会影响 Web 应用程序的启动性能。&lt;/p&gt;

&lt;p&gt;2.0 版本是完全树抖动的，并将通过构建时检查强制执行。优化编译器现在可以消除应用程序不使用的库部分。&lt;/p&gt;

&lt;p&gt;新库本身由&lt;a href="/solana" class="user-mention" title="@solana"&gt;&lt;i&gt;@&lt;/i&gt;solana&lt;/a&gt;组织下的几个较小的模块化包组成，包括：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/accounts&amp;lt;/font&amp;gt;&lt;/code&gt;：用于获取和解码账户
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/codecs&amp;lt;/font&amp;gt;&lt;/code&gt;：用于从一组原语中编写数据（反）序列化器或构建自定义数据（反）序列化器
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/errors&amp;lt;/font&amp;gt;&lt;/code&gt;：用于识别和细化&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana&amp;lt;/font&amp;gt;&lt;/code&gt;命名空间中抛出的编码错误
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc&amp;lt;/font&amp;gt;&lt;/code&gt;：用于发送 RPC 请求
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc-subscriptions&amp;lt;/font&amp;gt;&lt;/code&gt;：用于订阅 RPC 通知
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/signers&amp;lt;/font&amp;gt;&lt;/code&gt;：用于构建消息和/或交易签名者对象
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/sysvars&amp;lt;/font&amp;gt;&lt;/code&gt;：用于获取和解码 sysvar 帐户
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/transaction-messages&amp;lt;/font&amp;gt;&lt;/code&gt;：用于构建和转换 Solana 交易消息对象
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/transactions&amp;lt;/font&amp;gt;&lt;/code&gt;：用于编译和签署交易以提交给网络
&lt;/li&gt;
&lt;li&gt;还有更多！&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其中一些包本身由较小的包组成。例如，由（针对核心 JSON RPC 规范类型）、（针对 Solana 特定的 RPC 方法）、（针对默认 HTTP 传输）等&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc&amp;lt;/font&amp;gt;&lt;/code&gt;组成。&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc-spec&amp;lt;/font&amp;gt;&lt;/code&gt;&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc-api&amp;lt;/font&amp;gt;&lt;/code&gt;&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc-transport-http&amp;lt;/font&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;开发人员可以使用主库（）中的默认配置&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/web3.js@next&amp;lt;/font&amp;gt;&lt;/code&gt;，或者导入任何需要通过组合进行定制的子包。&lt;/p&gt;
&lt;h2 id="可组合内部构件"&gt;可组合内部构件&lt;/h2&gt;
&lt;p&gt;根据您的用例和对某些应用程序行为的容忍度，您可能希望将您的应用程序配置为与其他开发人员进行不同的权衡。web3.js（1.x）API 对所有开发人员强加了一套严格的通用默认设置，其中一些是不可能改变的。&lt;/p&gt;

&lt;p&gt;到目前为止，无法自定义 web3.js 一直是令人十分伤心的原因：&lt;/p&gt;

&lt;p&gt;Mango 团队希望定制交易确认策略，但所有这些功能都隐藏在 confirmTransaction 后面——一种静态的 Connection 方法。&lt;a href="https://github.com/solana-labs/solana-web3.js/blob/69a8ad25ef09f9e6d5bff1ffa8428d9be0bd32ac/packages/library-legacy/src/connection.ts#L3734v" rel="nofollow" target="_blank" title=""&gt;这是 GitHub 上 confirmTransaction 的代码&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;Solana 开发人员'mPaella'希望我们在 RPC 中添加一个功能，在主 URL 失败的情况下，该功能将故障转移到一组备份 URL。&lt;/p&gt;

&lt;p&gt;Solana 开发人员“epicface”希望在 RPC 传输中为自动时间窗口批处理提供一流的支持。这是他们的拉取请求。&lt;/p&gt;

&lt;p&gt;许多人表示需要为失败的请求或事务定制重试逻辑。这是来自“dafyddd”的 pull 请求和来自“abrkn”的另一个 pull 请求，它们试图修改重试逻辑以适应各自的用例。&lt;/p&gt;

&lt;p&gt;2.0 版本暴露了更多的内部内容，特别是在与 RPC 通信的情况下，并允许有意愿的开发人员从默认实现中组合新的实现，这些实现体现了几乎无限的自定义数组。&lt;/p&gt;

&lt;p&gt;组成 web3.js 的各个模块以默认配置组装，让人联想到作为 npm 包&lt;a href="/solana" class="user-mention" title="@solana"&gt;&lt;i&gt;@&lt;/i&gt;solana&lt;/a&gt;一部分的遗留库/web3.js@next，但那些希望以不同配置组装它们的人可以这样做。&lt;/p&gt;

&lt;p&gt;通用类型在许多地方提供，允许您指定新的功能，通过组合和超类型对每个 API 进行扩展，并鼓励您创建自己的更高层次的固执己见的抽象。&lt;/p&gt;

&lt;p&gt;事实上，我们希望你这样做，并将其中一些开源，供其他有类似需求的人使用。&lt;/p&gt;
&lt;h2 id="现代 JavaScript；零依赖"&gt;现代 JavaScript；零依赖&lt;/h2&gt;
&lt;p&gt;现代 JavaScript 功能的进步为加密应用程序的开发人员提供了机会，例如使用本机 Ed25519 密钥并将大值表示为本机 bigint 的能力。&lt;/p&gt;

&lt;p&gt;Web 孵化器社区小组主张在 Web Crypto API 中添加 Ed25519 支持，并且大多数现代 JavaScript 运行时都已获得支持。&lt;/p&gt;

&lt;p&gt;引擎对 bigint 值的支持也变得司空见惯。JavaScript 中较旧的数字基元的最大值为 2^53-1，而 Rust 的 u64 可以表示高达 2^64 的值。&lt;/p&gt;

&lt;p&gt;2.0 版本消除了 Ed25519 密码学、大量 polyfills 等的用户空间实现，转而支持自定义实现或使用原生 JavaScript 功能，从而减小了库的大小。它不依赖于第三方。&lt;/p&gt;
&lt;h2 id="功能架构"&gt;功能架构&lt;/h2&gt;
&lt;p&gt;web3.js（1.x）的面向对象、基于类的架构导致了不必要的包膨胀。你的应用程序别无选择，只能捆绑一个类的所有功能和依赖关系，无论你在运行时实际使用了多少方法。&lt;/p&gt;

&lt;p&gt;基于类的架构也给触发双包危险的开发人员带来了独特的风险。这描述了如果你同时为 CommonJS 和 ES 模块构建，你可能会遇到的情况。当依赖树中存在同一类的两个副本时，就会出现这种情况，导致 instanceof 等检查失败。这引入了加重和难以调试的问题。&lt;/p&gt;

&lt;p&gt;阅读更多关于双包装危险的信息：&lt;/p&gt;

&lt;p&gt;NodeJS：双包危险&lt;/p&gt;

&lt;p&gt;2.0 版本没有实现任何类（SolanaError 类除外），并在函数边界实现了尽可能薄的接口。&lt;/p&gt;
&lt;h2 id="统计数据"&gt;统计数据&lt;/h2&gt;
&lt;p&gt; 2.0 版和旧版 1.x 之间的统计对比。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;table class="table table-bordered table-striped"&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;1.x (Legacy)&lt;/th&gt;
&lt;th&gt;2.0&lt;/th&gt;
&lt;th&gt;+/- %&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total minified size of library&lt;/td&gt;
&lt;td&gt;81 KB&lt;/td&gt;
&lt;td&gt;57.5 KB&lt;/td&gt;
&lt;td&gt;-29%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total minified size of library (when runtime supports Ed25519)&lt;/td&gt;
&lt;td&gt;81 KB&lt;/td&gt;
&lt;td&gt;53 KB&lt;/td&gt;
&lt;td&gt;-33%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bundled size of a web application that executes a transfer of lamports&lt;/td&gt;
&lt;td&gt;111 KB&lt;/td&gt;
&lt;td&gt;23.9 KB&lt;/td&gt;
&lt;td&gt;-78%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bundled size of a web application that executes a transfer of lamports (when runtime supports Ed25519)&lt;/td&gt;
&lt;td&gt;111 KB&lt;/td&gt;
&lt;td&gt;18.2 KB&lt;/td&gt;
&lt;td&gt;-83%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance of key generation, signing, and verifying signatures (Brave with Experimental API flag)&lt;/td&gt;
&lt;td&gt;700 ops/s&lt;/td&gt;
&lt;td&gt;7000 ops/s&lt;/td&gt;
&lt;td&gt;+900%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First-load size for Solana Explorer&lt;/td&gt;
&lt;td&gt;311 KB&lt;/td&gt;
&lt;td&gt;228 KB&lt;/td&gt;
&lt;td&gt;-26%&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;重新设计的库在很大程度上通过使用现代 JavaScript API 实现了这些加速和捆绑包大小的减少。&lt;/p&gt;

&lt;p&gt;为了验证我们的工作，我们在 Solana Explorer 的主页上用新的 2.0 库替换了旧的 1.x 库。在不删除任何功能的情况下，首次加载包的总大小下降了 26%。如果你想深入了解，这里有一个 Callum McIntyre 的 X 线程。&lt;/p&gt;
&lt;h2 id="2.0 版 API 概览"&gt;2.0 版 API 概览&lt;/h2&gt;
&lt;p&gt;以下是如何使用新库与 RPC 交互、配置网络传输、使用 Ed25519 密钥以及序列化数据的概述。&lt;/p&gt;
&lt;h2 id="RPC"&gt;RPC&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.jsonrpc.org/specification" rel="nofollow" target="_blank" title=""&gt;2.0 版附带了 JSON RPC 规范&lt;/a&gt;的实现和&lt;a href="https://docs.solana.com/api" rel="nofollow" target="_blank" title=""&gt;Solana JSON RPC&lt;/a&gt;的类型规范。&lt;/p&gt;

&lt;p&gt;负责管理与 RPC 通信的主要包是&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc&amp;lt;/font&amp;gt;&lt;/code&gt;。但是，此包利用更细粒度的包将 RPC 逻辑分解为更小的部分。即，这些包是：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc&amp;lt;/font&amp;gt;&lt;/code&gt;：包含与发送 Solana RPC 调用相关的所有逻辑。
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc-api&amp;lt;/font&amp;gt;&lt;/code&gt;：使用类型描述所有 Solana RPC 方法。
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc-transport-http&amp;lt;/font&amp;gt;&lt;/code&gt;：提供使用 HTTP 请求的 RPC 传输的具体实现。
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc-spec&amp;lt;/font&amp;gt;&lt;/code&gt;：定义用于发送 RPC 请求的 JSON RPC 规范。
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc-spec-types&amp;lt;/font&amp;gt;&lt;/code&gt;&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc&amp;lt;/font&amp;gt;&lt;/code&gt;：和两者使用的共享 JSON RPC 规范类型和帮助程序&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc-subscriptions&amp;lt;/font&amp;gt;&lt;/code&gt;（在下一节中描述）。
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc-types&amp;lt;/font&amp;gt;&lt;/code&gt;&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc&amp;lt;/font&amp;gt;&lt;/code&gt;：和使用的共享 Solana RPC 类型和帮助程序&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc-subscriptions&amp;lt;/font&amp;gt;&lt;/code&gt;。
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;主&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/web3.js&amp;lt;/font&amp;gt;&lt;/code&gt;包重新导出&lt;code&gt;&amp;lt;font style="color:rgb(34, 34, 34);background-color:rgb(242, 244, 248);"&amp;gt;@solana/rpc&amp;lt;/font&amp;gt;&lt;/code&gt;包，因此，接下来我们将直接从库中导入 RPC 类型和函数。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;h2 id="例子"&gt;例子&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;自己先创建一个前端项目，然后引入相关的依赖&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save @solana/web3.js@next
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所有的代码示例托管到了，github&lt;/p&gt;
&lt;h2 id="发送一个请求"&gt;发送一个请求&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;createSolanaRpc&lt;/code&gt;函数使用应满足大多数用例的默认 HTTP 传输与 RPC 服务器通信。您可以提供自己的传输或包装现有的传输，以您认为合适的任何方式与 RPC 服务器通信。在下面的示例中，我们显式创建了一个传输，并使用它通过 createSolanaRpcFromTransport 函数创建一个新的 RPC 客户端。&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSolanaRpcFromTransport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createDefaultRpcTransport&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@solana/web3.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create an HTTP transport or any custom transport of your choice.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.devnet.solana.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Create an RPC client using that transport.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rpc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSolanaRpcFromTransport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//    ^? Rpc&amp;lt;SolanaRpcApi&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Send a request.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;rpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSlot&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;点击按钮弹出如下信息
&lt;img src="/uploads/photo/clbigdata/2972c597-72fb-4808-9f08-25e6dc7375bc.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;自定义传输可以实现专门的功能，如协调多个传输、实现重试等。让我们来看一些具体的例子。&lt;/p&gt;
&lt;h2 id="轮询"&gt;轮询&lt;/h2&gt;
&lt;p&gt;“轮询”传输是一种按顺序将请求分发到端点列表的传输。&lt;/p&gt;

&lt;p&gt;官方给出的 demo&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createSolanaRpcFromTransport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;RpcTransport&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@solana/web3.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create an HTTP transport for each RPC server.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://mainnet-beta.my-server-1.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nf"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://mainnet-beta.my-server-2.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nf"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://mainnet-beta.my-server-3.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Set up the round-robin transport.&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nextTransport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;roundRobinTransport&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Parameters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RpcTransport&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;transports&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;nextTransport&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;nextTransport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextTransport&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;transports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Create an RPC client using the round-robin transport.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rpc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSolanaRpcFromTransport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roundRobinTransport&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们改造一下&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 创建多个RPC客户端用于轮询（这里简化为创建两个示例）&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createRpcClients&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rpc1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSolanaRpc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:8899&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rpc2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSolanaRpc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:8898&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rpcClients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rpc1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rpc2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;roundRobinSlotRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rpcClients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRpcClients&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentRpc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rpcClients&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentRpcIndex&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;currentRpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSlot&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`通过轮询获取到的slot信息为: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slot&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;// 更新当前使用的RPC客户端索引，实现轮询效果&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentRpcIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentRpcIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rpcClients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`轮询获取slot信息时出错: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;通过多次点击按钮弹，会分别弹出如下信息
&lt;img src="/uploads/photo/clbigdata/fbff538c-1e96-4356-95e5-d27fcd2255f4.png!large" title="" alt=""&gt;&lt;/p&gt;
&lt;h2 id="分片"&gt;分片&lt;/h2&gt;
&lt;p&gt;分片传输是一种分布式传输，它根据请求本身的某些信息向特定服务器发送请求。下面是一个根据方法名称向不同服务器发送请求的示例：&lt;/p&gt;

&lt;p&gt;官方的 demo&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createSolanaRpcFromTransport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;RpcTransport&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@solana/web3.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create multiple transports.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transportA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://mainnet-beta.my-server-1.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transportB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://mainnet-beta.my-server-2.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transportC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://mainnet-beta.my-server-3.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transportD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://mainnet-beta.my-server-4.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Function to determine which shard to use based on the request method.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;selectShard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;RpcTransport&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getAccountInfo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getBalance&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;transportA&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getLatestBlockhash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getTransaction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;transportB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sendTransaction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;transportC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;transportD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Create a transport that selects the correct transport given the request method name.&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;shardingTransport&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Parameters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RpcTransport&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectedTransport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;selectShard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;selectedTransport&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;TResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Create an RPC client using the sharding transport.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rpc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSolanaRpcFromTransport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shardingTransport&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;改造后&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 创建多个传输对象（用于sharding）&lt;/span&gt;
    &lt;span class="nf"&gt;createTransports&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transportA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://mainnet-beta.my-server-1.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transportB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://mainnet-beta.my-server-2.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transportC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://mainnet-beta.my-server-3.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transportD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createDefaultRpcTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://mainnet-beta.my-server-4.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// 根据请求方法选择分片（用于sharding）&lt;/span&gt;
    &lt;span class="nf"&gt;selectShard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getAccountInfo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getBalance&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transportA&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getLatestBlockhash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getTransaction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transportB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sendTransaction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transportC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transportD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// 实现分片传输逻辑（用于sharding）&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;shardingTransport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectedTransport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;selectShard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;selectedTransport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// 创建RPC客户端并执行sharding按钮点击操作&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;shardingButtonClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transportA&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transportB&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transportC&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transportD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTransports&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="c1"&gt;// 创建RPC客户端&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rpc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSolanaRpcFromTransport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shardingTransport&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 这里可以添加具体要执行的请求操作示例，比如获取账户信息&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accountInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAccountInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your_account_address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`获取到的账户信息为: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accountInfo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`执行sharding操作时出错: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这就是 solana web3.js sdk 2.0 其中一部分新特性的演示。&lt;/p&gt;

&lt;p&gt;详情请参考&lt;/p&gt;

&lt;p&gt;&lt;a href="https://solana-labs.github.io/solana-web3.js/#a-tour-of-the-version-20-api" rel="nofollow" target="_blank" title=""&gt;https://solana-labs.github.io/solana-web3.js/#a-tour-of-the-version-20-api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;文中代码托管到了 github&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/chenlong1993/solana-web3.js-learn" rel="nofollow" target="_blank" title=""&gt;https://github.com/rogers3333/solana-web3.js-learn&lt;/a&gt;&lt;/p&gt;</description>
      <author>clbigdata</author>
      <pubDate>Sat, 30 Nov 2024 16:58:13 +0800</pubDate>
      <link>https://soldev.cn/topics/110</link>
      <guid>https://soldev.cn/topics/110</guid>
    </item>
    <item>
      <title>ZK Compression 简单介绍以及入门案例</title>
      <description>&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Web3 与 ZK（零知识证明）背景&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;零知识证明（ZK）是 Web3 领域中一项关键的加密技术，它允许一方（证明者）向另一方（验证者）证实某项信息的真实性，同时不泄露其他任何额外信息。这项技术对提高数据安全性和保护用户隐私至关重要。&lt;br&gt;
在区块链应用如金融交易、身份认证中，零知识证明能够增强系统的隐私和安全性。例如，在注重隐私的区块链平台上，用户可以使用该技术证明自己有足够的余额进行转账，而无需透露具体的账户金额，从而保护了财务隐私并降低了安全风险。&lt;br&gt;
此外，零知识证明也被应用于数字身份验证、投票系统等领域，帮助个人和组织在保持隐私的同时参与在线活动，并确保操作的有效性和合法性。随着 Web3 的发展，零知识证明正成为创建更加开放透明且高度安全互联网基础设施的重要组成部分。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solana 概述与数据处理特点&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Solana 是一个高性能的区块链平台，以其高吞吐量和低延迟而闻名。在 Solana 的生态系统中，数据处理的效率对于整个网络的性能至关重要。它需要处理大量的交易数据、智能合约状态等信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solana 中 ZK Compression 的含义&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;在 Solana 中，ZK Compression（零知识证明压缩）同样是针对零知识证明相关数据的压缩机制。零知识证明在 Solana 中有多种应用场景，例如隐私保护的交易验证、去中心化身份验证等。&lt;/li&gt;
&lt;li&gt;当使用零知识证明技术时，会产生证明数据和验证数据等内容。这些数据可能包含复杂的密码学计算结果和大量的数学结构，ZK Compression 就是要对这些数据进行压缩，以适应 Solana 的高性能要求。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solana 中 ZK Compression 的重要性&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;提升网络效率&lt;/strong&gt;：

&lt;ul&gt;
&lt;li&gt;Solana 的网络性能优势部分依赖于数据的高效处理和传输。通过压缩零知识证明数据，可以减少数据在网络节点之间传输所需的带宽和时间。在高并发交易场景下，这有助于维持 Solana 的低延迟特性，使得交易能够更快地被验证和确认。&lt;/li&gt;
&lt;li&gt;当在分布式的 Web3 网络中传输零知识证明相关的数据时，例如从一个节点传输到另一个节点或者从用户端传输到区块链节点，压缩后的数据可以大大减少网络带宽的占用，提高数据传输效率。这对于实时性要求较高的应用，如快速交易确认等场景非常重要。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;优化存储成本&lt;/strong&gt;：

&lt;ul&gt;
&lt;li&gt;区块链存储需要考虑成本和空间利用效率。压缩后的零知识证明数据占用更少的存储空间，这对于 Solana 网络节点的存储资源管理非常重要。可以在有限的存储容量内存储更多的交易记录和相关证明，提高网络的整体存储效率。区块链的存储空间是有限且宝贵的。在 Web3 应用中，如去中心化金融（DeFi）、非同质化代币（NFT）市场等，大量的交易和操作需要记录。如果零知识证明的数据不进行压缩，会占用过多的区块链存储空间，导致存储成本增加并且降低整个系统的可扩展性。通过压缩，可以在相同的存储容量下记录更多的有效信息&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;增强隐私保护能力&lt;/strong&gt;：

&lt;ul&gt;
&lt;li&gt;在隐私敏感的应用场景中，如隐私保护的去中心化金融（DeFi）交易，ZK Compression 有助于进一步隐藏交易细节。较小的数据包在存储和传输过程中更难被分析和破解，从而加强了用户隐私保护。除了效率方面的好处，压缩零知识证明数据也有助于进一步保护隐私。较小的数据包在传输过程中被拦截或分析的风险相对较低，并且可以通过巧妙的压缩算法设计，将一些敏感信息更加隐蔽地存储，从而增强整个 Web3 系统的隐私保护能力&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solana 中 ZK Compression 的实现方式&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;协议层集成&lt;/strong&gt;：

&lt;ul&gt;
&lt;li&gt;Solana 可能在其协议层设计了特定的机制来处理零知识证明压缩。这可能涉及到在交易打包和验证阶段，对包含零知识证明的数据进行自动压缩。例如，在节点接收交易时，对带有隐私保护需求的交易中的零知识证明部分进行压缩处理，然后再存储和转发。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;与加密库协作&lt;/strong&gt;：

&lt;ul&gt;
&lt;li&gt;Solana 利用现有的加密库和压缩技术来实现 ZK Compression。开发人员可能会使用诸如 Ristretto、Bulletproofs 等零知识证明库，并结合高效的压缩算法（如 zstd 等）来对证明数据进行压缩。在具体实现中，可能会在智能合约的编译阶段或者运行时，对生成的零知识证明进行压缩操作。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;6.&lt;strong&gt;Solana 中 ZK Compression 的挑战与应对策略&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;兼容性问题：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;挑战&lt;/strong&gt;：Solana 生态系统中的多种应用和工具（如钱包、DApps）需要处理压缩后的零知识证明数据，这要求 ZK Compression 机制具有广泛的兼容性。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;应对策略&lt;/strong&gt;：通过制定统一标准和接口，并提供详细的开发文档和指南来帮助开发者。同时，进行广泛的测试以确保主流应用能够适应这种压缩机制。&lt;br&gt;
&lt;strong&gt;性能权衡与优化：&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;挑战&lt;/strong&gt;：虽然压缩有诸多好处，但也可能增加计算开销，影响交易验证时间和网络性能。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;应对策略&lt;/strong&gt;：研究高效的压缩算法，减少性能损耗。可以通过硬件加速或采用自适应压缩技术来提高效率，根据数据类型选择最佳压缩方法。&lt;br&gt;
&lt;strong&gt;实现方式：&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;密码学算法 + 传统压缩&lt;/strong&gt;：先用密码学手段对零知识证明数据进行预处理，再利用常规压缩算法（如 gzip）进行压缩。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;同态加密压缩&lt;/strong&gt;：对于支持同态加密的应用场景，在保持数据加密状态的同时对其进行压缩，从而在不泄露信息的前提下减小数据体积。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Solana 中 ZK Compression 的应用&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;**   **Solana 中 ZK Compression 包含两个实践&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;客户端开发&lt;/li&gt;
&lt;li&gt;链上程序开发&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;接下来从客户端开发给出简单的入门案例&lt;/p&gt;

&lt;p&gt;ZK &lt;a href="https://www.zkcompression.com/developers/json-rpc-methods" rel="nofollow" target="_blank" title=""&gt;Compression RPC API&lt;/a&gt;是客户端和链上程序之间的粘合剂。它扩展了 Solana 的默认&lt;a href="https://solana.com/docs/rpc" rel="nofollow" target="_blank" title=""&gt;JSON RPC API,&lt;/a&gt;并添加了用于与 ZK Compression 状态交互的端点。要查看受支持的端点的完整列表，请访问&lt;a href="https://www.zkcompression.com/developers/json-rpc-methods" rel="nofollow" target="_blank" title=""&gt;JSON RPC 方法&lt;/a&gt;部分。&lt;/p&gt;

&lt;p&gt;官网给出了 TypeScript 和 Rust SDK 用于与 ZK Compression 交互的教程&lt;/p&gt;
&lt;table class="table table-bordered table-striped"&gt;
&lt;tr&gt;
&lt;th&gt;语言&lt;/th&gt;
&lt;th&gt;软件开发工具包&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://github.com/Lightprotocol/light-protocol/tree/main/js/stateless.js" rel="nofollow" target="_blank" title=""&gt;&lt;/a&gt;&lt;a href="/lightprotocol" class="user-mention" title="@lightprotocol"&gt;&lt;i&gt;@&lt;/i&gt;lightprotocol&lt;/a&gt;/stateless.js&lt;/td&gt;
&lt;td&gt;SDK to interact with compression programs via the ZK Compression RPC API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://github.com/Lightprotocol/light-protocol/tree/main/js/compressed-token" rel="nofollow" target="_blank" title=""&gt;&lt;/a&gt;&lt;a href="/lightprotocol" class="user-mention" title="@lightprotocol"&gt;&lt;i&gt;@&lt;/i&gt;lightprotocol&lt;/a&gt;/compressed-token&lt;/td&gt;
&lt;td&gt;SDK to interact with the compressed token program&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/Lightprotocol/light-protocol/tree/main/sdk" rel="nofollow" target="_blank" title=""&gt;light-sdk&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Rust client&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;接下来我们创建一个项目命名为 zk-compression-learn，并托管到 github。&lt;/p&gt;

&lt;p&gt;官方给了两种安装方式&lt;/p&gt;
&lt;table class="table table-bordered table-striped"&gt;
&lt;tr&gt;
&lt;th&gt;Package Manager&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NPM&lt;/td&gt;
&lt;td&gt;Copy&lt;br&gt;&lt;code&gt;plain npm install --save \     @lightprotocol/stateless.js \     @lightprotocol/compressed-token \     @solana/web3.js \     @coral-xyz/anchor \     @lightprotocol/zk-compression-cli&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Yarn&lt;/td&gt;
&lt;td&gt;Copy&lt;br&gt;&lt;code&gt;plain yarn add \     @lightprotocol/stateless.js \     @lightprotocol/compressed-token \     @solana/web3.js \     @coral-xyz/anchor \     @lightprotocol/zk-compression-cli&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;在启动之前，我们要先搭建一下测试环境，启动一个测试节点，主要教程参考下边的连接。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/helius-labs/photon" rel="nofollow" target="_blank" title=""&gt;https://github.com/helius-labs/photon&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;我们先打开两个命令行窗口&lt;/p&gt;

&lt;p&gt;第一步：先启动 solana 的测试环境，输入如下命令&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;solana-test-validator
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="/uploads/photo/clbigdata/4645084e-1471-467a-9d2f-a22424234005.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;第二步：启动&lt;a href="https://github.com/helius-labs/photon" rel="nofollow" target="_blank" title=""&gt;photon&lt;/a&gt;，输入如下命令&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;photon
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="/uploads/photo/clbigdata/b7b48fba-7f86-457f-8a6d-d7eb15e6970f.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;这样就启动了 solana 的本地测试环境，当然了，还有个更省事的，一键启动所有的测试环境&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;light test-validator  
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;通过&lt;code&gt;&amp;lt;font style="color:#2fff12;"&amp;gt;light config --get&amp;lt;/font&amp;gt;&lt;/code&gt; 命令，可以看到当前启动的端口情况&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;────────────── ───────────────────── 
Solana RPC URL http://127.0.0.1:8899 
Indexer URL    http://127.0.0.1:8784 
Prover URL     http://127.0.0.1:3001 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接下来，我门用官方给出的例子来对关键点几个接口进行测试，拷贝下来创建一个新项目，就 OK 了&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Lightprotocol/example-web-client" rel="nofollow" target="_blank" title=""&gt;https://github.com/Lightprotocol/example-web-client&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;然后进入到项目安装 zk compression 的依赖，我们这里采用第一种 NPM 的方式&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save \
    @lightprotocol/stateless.js \
    @lightprotocol/compressed-token \
    @solana/web3.js \
    @coral-xyz/anchor \
    @lightprotocol/zk-compression-cli
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;出现如下命令表示安装成功&lt;/p&gt;

&lt;p&gt;&lt;img src="/uploads/photo/clbigdata/201938a6-c619-461e-930c-0e85c9260e99.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;进入项目，结构如图所示&lt;/p&gt;

&lt;p&gt;&lt;img src="/uploads/photo/clbigdata/292b42ab-426e-4316-b6f0-0ec8d339bc76.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;接下来，我们先来第一个案例，用于与本地的 dev 环境进行交互，代码如下&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const TestConnectionButton: FC = () =&amp;gt; {
  const onClick = useCallback(async () =&amp;gt; {
    try {
      let slot = await connectionForTest.getSlot();
      console.log("=====" + slot);

      let health = await connectionForTest.getIndexerHealth(slot);
      console.log("+++++"+health);
      // "Ok"
    } catch (error) {
      console.error("Error testing the connection:", error);
    }
  }, []);

  return (
      &amp;lt;button
          style={{
            fontSize: "1rem",
            padding: "1rem",
            backgroundColor: "#ff0000",
            cursor: "pointer",
          }}
          onClick={onClick}
          disabled={!connectionForTest}
      &amp;gt;
        测试连接
      &amp;lt;/button&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动项目，打开浏览器进行访问&lt;/p&gt;

&lt;p&gt;会发现多了一个按钮，我们打开 F12，进入浏览器开发者模式，点击浏览器的控制台，然后再次点击我们新加入的按钮。&lt;/p&gt;

&lt;p&gt;&lt;img src="/uploads/photo/clbigdata/0b86caee-ec5d-4b5d-a4b5-c1d52f57bade.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;出现如下内容，表示连接成功&lt;/p&gt;

&lt;p&gt;&lt;img src="/uploads/photo/clbigdata/c22742e4-26d4-43e0-848c-b092647c1da6.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;接下来，进行第二个案例。这个案例就是进行一系列交易操作，代码如下。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const PerformTokenOperationsButton: FC = () =&amp;gt; {
  const { publicKey, sendTransaction } = useWallet();

  const onClick = useCallback(async () =&amp;gt; {
    if (!publicKey) throw new WalletNotConnectedError();

    try {
      // Airdrop lamports to pay fees
      await confirmTx(
          connectionForTest,
          await connectionForTest.requestAirdrop(payer.publicKey, 10e9)
      );

      await confirmTx(
          connectionForTest,
          await connectionForTest.requestAirdrop(tokenRecipient.publicKey, 1e6)
      );

      // Create a compressed token mint
      const { mint, transactionSignature } = await createMint(
          connectionForTest,
          payer,
          payer.publicKey,
          9 // Number of decimals
      );

      console.log(`create-mint  success! txId: ${transactionSignature}`);

      // Mint compressed tokens to the payer's account
      const mintToTxId = await mintTo(
          connectionForTest,
          payer,
          mint,
          payer.publicKey, // Destination
          payer,
          1e9 // Amount
      );

      console.log(`Minted 1e9 tokens to ${payer.publicKey} was a success!`);
      console.log(`txId: ${mintToTxId}`);

      // Transfer compressed tokens
      // @ts-ignore
      const transferTxId = await transfer(
          connectionForTest,
          payer,
          mint,
          7e8, // Amount
          payer, // Owner
          tokenRecipient.publicKey // To address
      );

      console.log(`Transfer of 7e8 ${mint} to ${tokenRecipient.publicKey} was a success!`);
      console.log(`txId: ${transferTxId}`);
    } catch (error) {
      console.error("Error performing token operations:", error);
    }
  }, [publicKey, sendTransaction]);

  return (
      &amp;lt;button
          style={{
            fontSize: "1rem",
            padding: "1rem",
            backgroundColor: "#0066ff",
            cursor: "pointer",
          }}
          onClick={onClick}
          disabled={!publicKey}
      &amp;gt;
        交易操作
      &amp;lt;/button&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后会生成一个新的按钮&lt;/p&gt;

&lt;p&gt;&lt;img src="/uploads/photo/clbigdata/262faa97-edc2-4ee1-8a9a-b622d8be995b.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;再点击这个按钮之前，我们现连接钱包，也就是项目的第一个按钮，连接钱包后，点击交易操作按钮。会生成一系列的交易信息&lt;/p&gt;

&lt;p&gt;&lt;img src="/uploads/photo/clbigdata/e20cb536-5d5a-41ab-b203-92d80d6de52b.png!large" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;至此，zk compression 的介绍以及简单入门就结束啦。&lt;/p&gt;

&lt;p&gt;详细代码请参考链接：&lt;a href="https://github.com/chenlong1993/zk-compression-learn" rel="nofollow" target="_blank" title=""&gt;https://github.com/rogers3333/zk-compression-learn&lt;/a&gt;&lt;/p&gt;</description>
      <author>clbigdata</author>
      <pubDate>Sat, 30 Nov 2024 14:24:34 +0800</pubDate>
      <link>https://soldev.cn/topics/109</link>
      <guid>https://soldev.cn/topics/109</guid>
    </item>
  </channel>
</rss>
