ホームページ >ウェブフロントエンド >jsチュートリアル >OKX DEX API Essentials: Avalanche C チェーンでのシングルチェーンおよびクロスチェーンのスワップ

OKX DEX API Essentials: Avalanche C チェーンでのシングルチェーンおよびクロスチェーンのスワップ

DDD
DDDオリジナル
2024-11-28 05:32:11995ブラウズ

OKX DEX API Essentials: Single and Cross-Chain Swaps on Avalanche C-Chain

DEX アグリゲーションとクロスチェーン スワップを EVM DApp に統合する準備はできましたか?このチュートリアルでは、OKX DEX API を操作して、単一チェーン内と Avalanche C チェーンの異なるブロックチェーン間でトークン スワップを実行する方法を説明します。実装では Web3.js と OKX DEX API を使用して、見積もり、承認、スワップ実行の堅牢な処理を作成します。デフォルトでは、この実装は以下を示します:

  • シングルチェーンスワップ: Avalanche C チェーン上の AVAX から WAVAX へ
  • クロスチェーンスワップ: Avalanche C-Chain 上の AVAX から Polygon 上の POL へ

ファイル構造

このチュートリアルは、OKX DEX API と対話するために必要なすべての関数を含むユーティリティ ファイルである dexUtils.js の実装に焦点を当てています。このファイルは以下を処理します:

  • ネットワークとトークンの構成
  • ヘッダーの構築
  • API エンドポイントと呼び出しの構築
  • 見積もりの​​取得
  • トークンの承認
  • シングルチェーンスワップ
  • クロスチェーンスワップ

前提条件

始める前に以下が必要です:

  • Node.js がインストールされている (v20 以降)
  • Web3 とブロックチェーンの概念に関する基礎知識
  • ウォレットアドレスと秘密鍵
  • OKX 開発者ポータルからの OKX API 認証情報 (API キー、秘密キー、およびパスフレーズ)
  • OKX 開発者ポータルからのプロジェクト ID
  • マシンにインストールされている Git

設定

開始するには 2 つのオプションがあります:

オプション 1: 地域開発

  1. リポジトリのクローンを作成し、デモ ブランチに切り替えます。
git clone https://github.com/Julian-dev28/okx-os-evm-swap-app.git
cd okx-os-evm-swap-app
git checkout avalanche-demo
  1. 依存関係をインストールします。
npm install
  1. 環境変数を設定します。
REACT_APP_API_KEY=your_api_key
REACT_APP_SECRET_KEY=your_secret_key
REACT_APP_API_PASSPHRASE=your_passphrase
REACT_APP_PROJECT_ID=your_project_id
REACT_APP_USER_ADDRESS=your_wallet_address
REACT_APP_PRIVATE_KEY=your_private_key

オプション 2: リプリットの使用

  1. Replit プロジェクトをフォークします:
    OKX OS Avalanche スワップ アプリ

  2. [Replit Secrets] タブ ([ツール] パネルにあります) に環境変数を追加します。

    • 「秘密」をクリックします
    • 各環境変数を追加します。
      • REACT_APP_API_KEY
      • REACT_APP_SECRET_KEY
      • REACT_APP_API_PASSPHRASE
      • REACT_APP_PROJECT_ID
      • REACT_APP_USER_ADDRESS
      • REACT_APP_PRIVATE_KEY
  3. 「実行」をクリックして開発環境を開始します

初期設定

このセクションでは、Avalanche C チェーン上の OKX DEX と対話するために必要なネットワーク構成とトークン アドレスを設定する方法を示します。

import Web3 from "web3";
import cryptoJS from "crypto-js";

// RPC endpoint for Avalanche C-Chain
const avalancheCMainnet = "https://avalanche-c-chain-rpc.publicnode.com";

// OKX DEX contract address on Avalanche
// Used to show token allowance
const okxDexAddress = "0x40aA958dd87FC8305b97f2BA922CDdCa374bcD7f";

// Standard token addresses
// baseTokenAddress represents the native token (ETH/AVAX) across chains
const baseTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
// WAVAX token address on Avalanche
const wavaxTokenAddress = "0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7";

// Initialize Web3 instance with Avalanche RPC
const web3 = new Web3(avalancheCMainnet);

// Base URL for API requests
const apiBaseUrl = "https://www.okx.com/api/v5/dex/aggregator";

/**
 * Helper function for constructing API URLs
 * @param {string} methodName - API endpoint path
 * @param {Object} queryParams - URL parameters
 * @returns {string} Complete API URL
 */
function getAggregatorRequestUrl(methodName, queryParams) {
    return (
        apiBaseUrl +
        methodName +
        "?" +
        new URLSearchParams(queryParams).toString()
    );
}

トークン見積もりの​​取得

見積もり機能は、現在の価格とスワップルートを取得します。実装は次のとおりです:

ヘッダーの生成

git clone https://github.com/Julian-dev28/okx-os-evm-swap-app.git
cd okx-os-evm-swap-app
git checkout avalanche-demo

APIの呼び出し

npm install

トークンの承認

交換する前に、ERC20 トークンに対して次の承認機能を実装します。

ヘッダーの生成

REACT_APP_API_KEY=your_api_key
REACT_APP_SECRET_KEY=your_secret_key
REACT_APP_API_PASSPHRASE=your_passphrase
REACT_APP_PROJECT_ID=your_project_id
REACT_APP_USER_ADDRESS=your_wallet_address
REACT_APP_PRIVATE_KEY=your_private_key

APIの呼び出し

import Web3 from "web3";
import cryptoJS from "crypto-js";

// RPC endpoint for Avalanche C-Chain
const avalancheCMainnet = "https://avalanche-c-chain-rpc.publicnode.com";

// OKX DEX contract address on Avalanche
// Used to show token allowance
const okxDexAddress = "0x40aA958dd87FC8305b97f2BA922CDdCa374bcD7f";

// Standard token addresses
// baseTokenAddress represents the native token (ETH/AVAX) across chains
const baseTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
// WAVAX token address on Avalanche
const wavaxTokenAddress = "0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7";

// Initialize Web3 instance with Avalanche RPC
const web3 = new Web3(avalancheCMainnet);

// Base URL for API requests
const apiBaseUrl = "https://www.okx.com/api/v5/dex/aggregator";

/**
 * Helper function for constructing API URLs
 * @param {string} methodName - API endpoint path
 * @param {Object} queryParams - URL parameters
 * @returns {string} Complete API URL
 */
function getAggregatorRequestUrl(methodName, queryParams) {
    return (
        apiBaseUrl +
        methodName +
        "?" +
        new URLSearchParams(queryParams).toString()
    );
}

シングルチェーンスワップ

次の実装は、同じチェーン内、具体的には Avalanche C チェーン上の AVAX から WAVAX へのスワップの実行を示しています。

/**
 * Generates headers required for OKX DEX quote API calls
 * Headers include timestamp, signature, and API credentials
 * 
 * @param {Object} quoteParams - Parameters for the quote request
 * @returns {Object} Headers object with required authentication
 */
function getQuoteHeaders(quoteParams) {
    const date = new Date();
    const timestamp = date.toISOString();

    // Create signature string following OKX API requirements
    const stringToSign =
        timestamp +
        "GET" +
        "/api/v5/dex/aggregator/quote?" +
        new URLSearchParams(quoteParams).toString();

    // Return headers with HMAC signature
    return {
        "Content-Type": "application/json",
        "OK-ACCESS-KEY": apiKey,
        "OK-ACCESS-SIGN": cryptoJS.enc.Base64.stringify(
            cryptoJS.HmacSHA256(stringToSign, secretKey)
        ),
        "OK-ACCESS-TIMESTAMP": timestamp,
        "OK-ACCESS-PASSPHRASE": apiPassphrase,
    };
}

クロスチェーンスワップ

次の実装は、相場の取得やトランザクションの実行を含め、AVAX (Avalanche C-Chain) から MATIC (Polygon) へのクロスチェーン スワップを実行する方法を示しています。

/**
 * Fetches a quote from the OKX DEX Aggregator
 * Used to get current prices and optimal swap routes
 * 
 * @param {Object} quoteParams - Parameters including tokens, amount, and chain
 * @returns {Promise<Object>} Quote data including price and route information
 */
async function getQuote(quoteParams) {
    const apiRequestUrl = `${apiBaseUrl}/quote?${new URLSearchParams(quoteParams)}`;
    const response = await fetch(apiRequestUrl, {
        method: "GET",
        headers: getQuoteHeaders(quoteParams),
    });

    if (!response.ok) {
        throw new Error("Network response was not ok");
    }

    return response.json();
}

トランザクションの署名と送信

sendSignedTransaction メソッドは、ユーザーのウォレット秘密キーを使用してトランザクションに署名し、送信します

/**
* Generates headers required for OKX DEX approve transaction API calls
* Headers include timestamp, signature, and API credentials
* 
* @param {Object} params - Parameters for the approve transaction
* @returns {Promise<Object>} Headers object with required authentication
*/
function getApproveTransactionHeaders(params) {
   const date = new Date();
   const timestamp = date.toISOString();
   const stringToSign =
       timestamp +
       "GET" +
       "/api/v5/dex/aggregator/approve-transaction?" +
       new URLSearchParams(params).toString();

   // Check if required environment variables are present
   if (!projectId || !apiKey || !secretKey || !apiPassphrase) {
       throw new Error(
           "Missing required environment variables for API authentication"
       );
   }

   return {
       "Content-Type": "application/json",
       "OK-PROJECT-ID": projectId,
       "OK-ACCESS-KEY": apiKey,
       "OK-ACCESS-SIGN": cryptoJS.enc.Base64.stringify(
           cryptoJS.HmacSHA256(stringToSign, secretKey)
       ),
       "OK-ACCESS-TIMESTAMP": timestamp,
       "OK-ACCESS-PASSPHRASE": apiPassphrase,
   };
}

機能の使い方

アプリケーションの柔軟性は、Params オブジェクト、swapParams、および quoteParams を通じて実証されます。これらのオブジェクトは構成ポイントとして機能し、ユーザーが特定の要件に基づいて見積もりリクエストとスワップをカスタマイズできるようにします。

たとえば、swapParams オブジェクト内には次のプロパティがあります:

// ABI for ERC20 token allowance function
// This minimal ABI only includes the allowance function needed for checking token approvals
// Full ERC20 ABI not needed since we're only checking allowances
const tokenABI = [
    {
        constant: true,
        inputs: [
            {
                name: "_owner",
                type: "address",
            },
            {
                name: "_spender",
                type: "address",
            },
        ],
        name: "allowance",
        outputs: [
            {
                name: "",
                type: "uint256",
            },
        ],
        payable: false,
        stateMutability: "view",
        type: "function",
    },
];

/**
 * Checks the current allowance for a token
 * Used to determine if approval is needed before swap
 * 
 * @param {string} ownerAddress - Address of token owner
 * @param {string} spenderAddress - Address of spender (DEX contract)
 * @param {string} tokenAddress - Address of token contract
 * @returns {Promise<number>} Current allowance amount
 */
async function getAllowance(ownerAddress, spenderAddress, tokenAddress) {
    const tokenContract = new web3.eth.Contract(tokenABI, tokenAddress);
    try {
        const allowance = await tokenContract.methods
            .allowance(ownerAddress, spenderAddress)
            .call();
        return parseFloat(allowance);
    } catch (error) {
        console.error("Failed to query allowance:", error);
        throw error;
    }
}


/**
 * Gets approval transaction data from the API
 * 
 * @param {string} chainId - Network chain ID
 * @param {string} tokenContractAddress - Token to approve
 * @param {string} approveAmount - Amount to approve
 * @returns {Promise<Object>} Approval transaction data
 */
async function approveTransaction(chainId, tokenContractAddress, approveAmount) {
    if (!chainId || !tokenContractAddress || !approveAmount) {
        throw new Error("Missing required parameters for approval");
    }

    const params = { chainId, tokenContractAddress, approveAmount };
    const apiRequestUrl = getAggregatorRequestUrl("/approve-transaction", params);
    const headersParams = getApproveTransactionHeaders(params);

    try {
        const response = await fetch(apiRequestUrl, {
            method: "GET",
            headers: headersParams,
        });

        if (!response.ok) {
            const errorData = await response.json().catch(() => null);
            throw new Error(
                `API request failed: ${response.status} ${response.statusText}${
                    errorData ? ` - ${JSON.stringify(errorData)}` : ""
                }`
            );
        }

        const data = await response.json();

        // Validate the response data
        if (!data || !data.data || !Array.isArray(data.data) || data.data.length === 0) {
            throw new Error("Invalid response format from approval API");
        }

        return data;
    } catch (error) {
        console.error("Approval request failed:", error);
        throw error;
    }
}

/**
 * Handles the approval transaction if needed
 * Checks current allowance and submits approval transaction if necessary
 * 
 * @param {string} approveAmount - Amount to approve for spending
 * @returns {Promise<Object|null>} Transaction receipt or null if approval not needed
 */
async function sendApproveTx(approveAmount) {
    // Skip approval for native tokens (ETH/AVAX)
    if (fromTokenAddress.toLowerCase() === baseTokenAddress.toLowerCase()) {
        return null;
    }

    const allowanceAmount = await getAllowance(
        user,
        spenderAddress,
        fromTokenAddress
    );

    // Only approve if current allowance is insufficient
    if (BigInt(allowanceAmount) < BigInt(approveAmount)) {
        const approvalResult = await approveTransaction(
            chainId,
            fromTokenAddress,
            approveAmount
        );

        // Prepare approval transaction with safety margins for gas
        const txObject = {
            nonce: await web3.eth.getTransactionCount(user),
            to: fromTokenAddress,
            gasLimit: BigInt(approvalResult.data[0].gasLimit) * BigInt(2),
            gasPrice: (BigInt(await web3.eth.getGasPrice()) * BigInt(3)) / BigInt(2),
            data: approvalResult.data[0].data,
            value: "0",
        };

        return sendSignedTransaction(txObject);
    }

    return null;
}

ここで、chainId (使用するブロックチェーン ネットワーク)、fromTokenAddress と toTokenAddress (スワップするトークン)、スワップするトークンの量、許容可能なスリッページ パーセンテージ、および独自のスリッページ パーセンテージを指定できます。 userWalletAddress.

dexUtils.js オブジェクトの quoteParams を使用すると、ソースおよびターゲットのブロックチェーン ネットワークを構成できます。

/**
 * Helper function to get headers for swap API calls
 * @param {Object} swapParams - Swap parameters
 * @returns {Object} Headers with authentication
 */
function getSwapHeaders(swapParams) {
    const date = new Date();
    const timestamp = date.toISOString();
    const stringToSign = 
        timestamp + 
        "GET" + 
        "/api/v5/dex/aggregator/swap?" + 
        new URLSearchParams(swapParams).toString();

    return {
        "Content-Type": "application/json",
        "OK-ACCESS-KEY": apiKey,
        "OK-ACCESS-SIGN": cryptoJS.enc.Base64.stringify(
            cryptoJS.HmacSHA256(stringToSign, secretKey)
        ),
        "OK-ACCESS-TIMESTAMP": timestamp,
        "OK-ACCESS-PASSPHRASE": apiPassphrase,
    };
}

/**
 * Helper function to get swap data from API
 * @param {Object} swapParams - Swap parameters
 * @returns {Promise<Object>} Swap transaction data
 */
async function getSwapData(swapParams) {
    const apiRequestUrl = getAggregatorRequestUrl("/swap", swapParams);
    const response = await fetch(apiRequestUrl, {
        method: "GET",
        headers: getSwapHeaders(swapParams),
    });

    if (!response.ok) {
        throw new Error("Network response was not ok");
    }

    return response.json();
}

/**
 * Executes a single-chain token swap
 * Handles the main swap transaction after approval
 * 
 * @param {Object} swapParams - Parameters for the swap
 * @returns {Promise<Object>} Transaction receipt
 */
async function sendSwapTx(swapParams) {
    // Get swap transaction data from API
    const { data: swapData } = await getSwapData(swapParams);

    // Validate swap data
    if (!swapData || swapData.length === 0 || !swapData[0].tx) {
        throw new Error("Invalid swap data received");
    }

    const swapDataTxInfo = swapData[0].tx;
    const nonce = await web3.eth.getTransactionCount(user, "latest");

    // Prepare transaction with adjusted gas parameters for safety
    const signTransactionParams = {
        data: swapDataTxInfo.data,
        gasPrice: BigInt(swapDataTxInfo.gasPrice) * BigInt(ratio),
        to: swapDataTxInfo.to,
        value: swapDataTxInfo.value,
        gas: BigInt(swapDataTxInfo.gas) * BigInt(ratio),
        nonce,
    };

    return sendSignedTransaction(signTransactionParams);
}

この例では、fromTokenAddress と toTokenAddress に加えて、fromChainId (開始元のブロックチェーン ネットワーク) と toChainId (スワップ先のブロックチェーン ネットワーク) を指定できます。これにより、Avalanche から Polygon など、さまざまなブロックチェーン エコシステム間でトークンを簡単に移動できます。

さらに、receiveAddress を設定してスワップされたトークンの送信先を指定したり、スリッページ許容値を調整したり、不利な価格変動を防ぐために PriceImpactProtectionPercentage を設定したりすることもできます。

これらの構成オプションを公開することで、アプリケーションの適応性が高まり、ビルダーがユーザー固有のニーズに合わせてアプリケーションを調整できるようになります。

React アプリケーションのサンプルを確認すると、これらの関数がどのようにコンポーネントに実装され、アプリに統合されるかの実例がわかります。

結論

このチュートリアルをご覧いただきありがとうございます。提供された情報が、独自のプロジェクト内で OKX DEX Aggregator API の機能を活用する方法を理解するのに役立つことを願っています。

追加リソース

  • OKX DEX API ドキュメント
  • Web3.js ドキュメント
  • Avalanche C チェーンのドキュメント

これは役に立ちましたか?定型コードやドキュメントなど、記事の冒頭にあるリソースを忘れずにチェックしてください。 OKX OS コミュニティに参加して他の開発者とつながり、Twitter で Julian をフォローして Web3 開発コンテンツをさらにご覧ください!


このコンテンツは情報提供のみを目的として提供されており、お住まいの地域では利用できない製品が含まれている場合があります。これは著者の見解を表すものであり、OKX の見解を表すものではありません。これは、(i) 投資アドバイスまたは投資推奨を提供することを目的としたものではありません。 (ii) デジタル資産の購入、販売、または保有の申し出または勧誘、または (iii) 財務、会計、法律、税務上のアドバイス。ステーブルコインやNFTを含むデジタル資産の保有には高いリスクが伴い、大きく変動する可能性があります。自分の財務状況を考慮して、デジタル資産の取引または保有が自分に適しているかどうかを慎重に検討する必要があります。特定の状況に関する質問については、法律/税務/投資の専門家にご相談ください。この投稿に掲載されている情報 (市場データや統計情報が存在する場合) は、一般的な情報提供のみを目的としています。このデータとグラフを作成する際にはあらゆる合理的な注意が払われていますが、ここに記載されている事実の誤りまたは省略については、いかなる責任も負いません。 OKX Web3 ウォレットと OKX NFT マーケットプレイスの両方には、www.okx.com での個別の利用規約が適用されます。

© 2024 OKX.この記事は、非営利目的であれば、その全体を複製または配布することも、100 ワード以下の抜粋を使用することもできます。 記事全体を複製または配布する場合は、「この記事は © 2024 OKX であり、許可を得て使用されています。」と目立つように明記する必要があります。 許可される抜粋では、記事名を引用し、帰属を含める必要があります。たとえば、「OKX DEX ウィジェットをわずか 30 分で統合、Julian Martinez、© 2024 OKX」などです。 この記事の二次的著作物やその他の使用は許可されません。

以上がOKX DEX API Essentials: Avalanche C チェーンでのシングルチェーンおよびクロスチェーンのスワップの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。