新着:HeliusがLight Protocolを買収
「Introducing Kite」というテキストの上に凧が浮かんでいる、モダンなSolana TypeScriptフレームワークの画像。
ブログ/開発

Kiteのご紹介:モダンなSolana TypeScriptフレームワーク

開発者教育XのMike MacCanaLinkedInのMike MacCana
読了時間:4分
目次

    本日、ブラウザとNode.jsの両方に対応するモダンなTypeScriptフレームワーク、Kiteを発表します。KiteはSolana web3.jsバージョン2の力を基盤としながら、一般的なタスクを大幅に簡素化します。

    Kiteを選ぶ理由

    KiteはSolana web3.jsバージョン2の速度と洗練性を活かしながら、日常的なSolanaタスクを1つの関数で実行できるようにします。

    Kiteは主要な処理にweb3.jsバージョン2を使用しているため、web3.jsバージョン2の全機能を利用できます。Kiteが不要になった場合は、簡単に削除して通常のweb3.jsバージョン2を使用できます。

    Kiteは、原作者がweb3.jsバージョン1向けに開発した最も人気のある高レベルライブラリである@solana-developers/helpersをweb3.js v2向けに更新したものです。

    Kiteパッケージには、Helius、Solana Foundation、Anza、Turbin3、Unboxed Software、StarAtlasからのコントリビューションを含む、従来のヘルパーの大半を更新したバージョンが含まれています。

    @solana-developers/helpersにあり、Kiteにはまだない関数も近日中に追加します。

    Kiteはブラウザとnode.jsの両方で動作し、依存関係は最小限です。

    Kiteでできること

    Kiteには、以下を実行するための関数が含まれています。

    ウォレット

    SOL

    トークン

    トランザクション

    Explorer

    • Solana Explorerのリンクを取得 — 使用しているRPCでトランザクション、ブロック、アドレスを表示するために必要なすべての詳細を、1つのステップで取得します。

    KiteとSolana web3.js 2の比較:

    トークンを作成する簡単な例を見てみましょう

    Kiteを使用する場合

    Kiteはweb3.js v2上に構築されたフレームワークであるため、同じ型とweb3.js v2の基盤機能を使用して処理を実行します。

    Making a token (including metadata) using Kite
    import { connect } from "@helius-dev/kite";
    const connection = connect();
    const mintAddress = await connection.makeTokenMint(
      mintAuthority,
      6,
      "My Token",
      "MTKN",
      "https://example.com/metadata.json",
      {
        description: "A sample token",
        website: "https://example.com",
      },
    );
    console.log(connection.getExplorerLink(mintAddress));

    Solana web3.js v2を使用する場合

    ...Kiteなしで実行します。

    Making a token using web3.js version 2
    import {
      airdropFactory,
      appendTransactionMessageInstructions,
      createSolanaRpc,
      createSolanaRpcSubscriptions,
      createTransactionMessage,
      generateKeyPairSigner,
      getSignatureFromTransaction,
      lamports,
      pipe,
      sendAndConfirmTransactionFactory,
      setTransactionMessageFeePayerSigner,
      setTransactionMessageLifetimeUsingBlockhash,
      signTransactionMessageWithSigners,
      some,
    } from "@solana/web3.js";
    import { getCreateAccountInstruction } from "@solana-program/system";
    import {
      getInitializeMintInstruction,
      getMintSize,
      TOKEN_2022_PROGRAM_ADDRESS,
      extension,
      getInitializeMetadataPointerInstruction,
      getInitializeTokenMetadataInstruction,
      tokenMetadataField,
      getUpdateTokenMetadataFieldInstruction,
    } from "@solana-program/token-2022";
    
    const rpc = createSolanaRpc("http://127.0.0.1:8899");
    const rpcSubscriptions = createSolanaRpcSubscriptions("ws://127.0.0.1:8900");
    
    const feePayer = await generateKeyPairSigner();
    console.log(feePayer.address);
    const mint = await generateKeyPairSigner();
    
    await airdropFactory({ rpc, rpcSubscriptions })({
      recipientAddress: feePayer.address,
      lamports: lamports(1_000_000_000n),
      commitment: "confirmed",
    });
    
    const balance = await rpc.getBalance(feePayer.address).send();
    console.log("balance:", balance.value);
    
    const metadataPointerExtension = extension("MetadataPointer", {
      authority: some(feePayer.address),
      metadataAddress: some(mint.address),
    });
    
    const tokenMetadataExtension = extension("TokenMetadata", {
      updateAuthority: some(feePayer.address),
      mint: mint.address,
      name: "OPOS",
      symbol: "OPOS",
      uri: "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json",
      additionalMetadata: new Map<string, string>([["description", "Only Possible On Solana"]]),
    });
    
    const spaceWithoutMetadata = BigInt(getMintSize([metadataPointerExtension]));
    
    const spaceWithMetadata = BigInt(getMintSize([metadataPointerExtension, tokenMetadataExtension]));
    
    const rent = await rpc.getMinimumBalanceForRentExemption(spaceWithMetadata).send();
    
    const createAccountInstruction = getCreateAccountInstruction({
      payer: feePayer,
      newAccount: mint,
      lamports: rent,
      space: spaceWithoutMetadata,
      programAddress: TOKEN_2022_PROGRAM_ADDRESS,
    });
    
    const initializeMetadataPointerInstruction = getInitializeMetadataPointerInstruction({
      mint: mint.address,
      authority: feePayer.address,
      metadataAddress: mint.address,
    });
    
    const initializeMintInstruction = getInitializeMintInstruction({
      mint: mint.address,
      decimals: 2,
      mintAuthority: feePayer.address,
    });
    
    const initializeTokenMetadataInstruction = getInitializeTokenMetadataInstruction({
      metadata: mint.address,
      updateAuthority: feePayer.address,
      mint: mint.address,
      mintAuthority: feePayer,
      name: tokenMetadataExtension.name,
      symbol: tokenMetadataExtension.symbol,
      uri: tokenMetadataExtension.uri,
    });
    
    const updateTokenMetadataInstruction = getUpdateTokenMetadataFieldInstruction({
      metadata: mint.address,
      updateAuthority: feePayer,
      field: tokenMetadataField("Key", ["description"]),
      value: "Only Possible On Solana",
    });
    
    const instructions = [
      createAccountInstruction,
      initializeMetadataPointerInstruction,
      initializeMintInstruction,
      initializeTokenMetadataInstruction,
      updateTokenMetadataInstruction,
    ];
    
    const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
    
    const transactionMessage = pipe(
      createTransactionMessage({ version: 0 }),
      (message) => setTransactionMessageFeePayerSigner(feePayer, message),
      (message) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, message),
      (message) => appendTransactionMessageInstructions(instructions, message),
    );
    
    const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
    
    const transactionSignature = getSignatureFromTransaction(signedTransaction);
    
    await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction, {
      commitment: "confirmed",
      skipPreflight: true,
    });
    
    console.log("Transaction Signature:", `https://explorer.solana.com/tx/${transactionSignature}?cluster=custom`);
    

    ご覧のとおり、Kiteを使わない場合は、5つの命令と関連オプションを含むトランザクションメッセージを作成し、そのメッセージに署名してRPCへ送信する必要があります。Kiteでは、makeTokenMintを実行するだけで、新しいミントのアドレスが返されます。

    KiteとPoseidonの比較

    Kiteは、ブラウザとnode.js向けの完全なクライアントサイドライブラリです。TypeScriptを使用したオンチェーンアプリ(スマートコントラクトなど)の構築に興味がある場合は、Poseidonをご覧ください。 

    コントリビューション

    Kiteは誕生したばかりですが、誰もがSolana開発に取り組みやすくなる堅牢なフレームワークへ成長させていきます。

    一般的なタスクを簡素化し、ボイラープレートコードを減らすことで、より多くの開発者がSolana上で優れたものを構築できるよう支援できます。

    次の方法でご協力いただけます。

    今すぐKiteを試す

    Solana開発をもっと簡単にする準備はできましたか?

    Kiteを使い始めましょう。

    Installing Kite
    npm i @helius-dev/kite

    詳しいドキュメントとサンプルについては、GitHubリポジトリをご覧ください。

    一緒にSolana開発を加速しましょう! 🪁

    Heliusを購読

    Solana開発の最新情報や新しい記事の公開通知を受け取れます