diff --git a/i18n/ja/docusaurus-plugin-content-docs/current.json b/i18n/ja/docusaurus-plugin-content-docs/current.json index 3231ac36a669..3b1c64188289 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current.json +++ b/i18n/ja/docusaurus-plugin-content-docs/current.json @@ -5,23 +5,23 @@ }, "sidebar.buildSidebar.category.Get Started": { "message": "スタート", - "description": "The label for category Get Started in sidebar buildSidebar" + "description": "The label for category 'Get Started' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Smart Contracts": { "message": "スマートコントラクト", - "description": "The label for category Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Deploy Smart Contracts": { "message": "スマートコントラクトの導入", - "description": "The label for category Deploy Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Deploy Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Sample Contracts": { "message": "サンプル契約", - "description": "The label for category Sample Contracts in sidebar buildSidebar" + "description": "The label for category 'Sample Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Tutorials": { "message": "チュートリアル", - "description": "The label for category Tutorials in sidebar buildSidebar" + "description": "The label for category 'Tutorials' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Tools": { "message": "ツール", @@ -29,51 +29,51 @@ }, "sidebar.buildSidebar.category.Wallets": { "message": "財布", - "description": "The label for category Wallets in sidebar buildSidebar" + "description": "The label for category 'Wallets' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Wallet Libraries": { "message": "財布ライブラリ", - "description": "The label for category Wallet Libraries in sidebar buildSidebar" + "description": "The label for category 'Wallet Libraries' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Oracles": { "message": "神託", - "description": "The label for category Oracles in sidebar buildSidebar" + "description": "The label for category 'Oracles' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Indexers": { "message": "インデクサ", - "description": "The label for category Indexers in sidebar buildSidebar" + "description": "The label for category 'Indexers' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Cross-chain": { "message": "クロスチェーン", - "description": "The label for category Cross-chain in sidebar buildSidebar" + "description": "The label for category 'Cross-chain' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Block Explorers": { "message": "ブロック探検隊", - "description": "The label for category Block Explorers in sidebar buildSidebar" + "description": "The label for category 'Block Explorers' in sidebar 'buildSidebar'" }, "sidebar.nodeSidebar.category.Endpoint Node": { "message": "エンドポイントノード", - "description": "The label for category Endpoint Node in sidebar nodeSidebar" + "description": "The label for category 'Endpoint Node' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Core Cell": { "message": "コアセル", - "description": "The label for category Core Cell in sidebar nodeSidebar" + "description": "The label for category 'Core Cell' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Install Core Cell": { "message": "コアセルの設置", - "description": "The label for category Install Core Cell in sidebar nodeSidebar" + "description": "The label for category 'Install Core Cell' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Service Chain": { "message": "サービスチェーン", - "description": "The label for category Service Chain in sidebar nodeSidebar" + "description": "The label for category 'Service Chain' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Quick Start": { "message": "クイックスタート", - "description": "The label for category Quick Start in sidebar nodeSidebar" + "description": "The label for category 'Quick Start' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Configure Service Chain": { "message": "サービスチェーンの設定", - "description": "The label for category Configure Service Chain in sidebar nodeSidebar" + "description": "The label for category 'Configure Service Chain' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Node Package Downloads": { "message": "ノードパッケージダウンロード", @@ -81,11 +81,11 @@ }, "sidebar.refSidebar.category.RPC API Reference": { "message": "RPC APIリファレンス", - "description": "The label for category RPC API Reference in sidebar refSidebar" + "description": "The label for category 'RPC API Reference' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.SDKs and Libraries": { "message": "SDKとライブラリ", - "description": "The label for category SDKs and Libraries in sidebar refSidebar" + "description": "The label for category 'SDKs and Libraries' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.API References": { "message": "APIリファレンス", @@ -97,31 +97,31 @@ }, "sidebar.learnSidebar.category.Transaction Fees": { "message": "取引手数料", - "description": "The label for category Transaction Fees in sidebar learnSidebar" + "description": "The label for category 'Transaction Fees' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Verify Smart Contracts": { "message": "スマートコントラクトの検証", - "description": "The label for category Verify Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Verify Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.learnSidebar.category.Data Management": { "message": "データ管理", - "description": "The label for category Data Management in sidebar learnSidebar" + "description": "The label for category 'Data Management' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Governance": { "message": "ガバナンス", - "description": "The label for category Governance in sidebar learnSidebar" + "description": "The label for category 'Governance' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Node Quick Reference": { "message": "ノード・クイック・リファレンス", - "description": "The label for category Node Quick Reference in sidebar learnSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Kaia Safe": { "message": "カイア・セーフ", - "description": "The label for category Kaia Safe in sidebar buildSidebar" + "description": "The label for category 'Kaia Safe' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Node Quick Reference": { "message": "ノード・クイック・リファレンス", - "description": "The label for category Node Quick Reference in sidebar buildSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.link.KaiaScan": { "message": "カイアスキャン", @@ -129,47 +129,47 @@ }, "sidebar.nodeSidebar.category.Node Quick Reference": { "message": "ノード・クイック・リファレンス", - "description": "The label for category Node Quick Reference in sidebar nodeSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'nodeSidebar'" }, "sidebar.refSidebar.category.ethers-ext < v1.0.1": { "message": "ethers-ext < v1.0.1", - "description": "The label for category ethers-ext < v1.0.1 in sidebar refSidebar" + "description": "The label for category 'ethers-ext < v1.0.1' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore": { "message": "キーストア", - "description": "The label for category keystore in sidebar refSidebar" + "description": "The label for category 'keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.ethers-ext": { "message": "ethers-ext", - "description": "The label for category ethers-ext in sidebar refSidebar" + "description": "The label for category 'ethers-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.v5": { "message": "v5", - "description": "The label for category v5 in sidebar refSidebar" + "description": "The label for category 'v5' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.v6": { "message": "v6", - "description": "The label for category v6 in sidebar refSidebar" + "description": "The label for category 'v6' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3js-ext": { "message": "web3js-ext", - "description": "The label for category web3js-ext in sidebar refSidebar" + "description": "The label for category 'web3js-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3j-ext": { "message": "web3j-ext", - "description": "The label for category web3j-ext in sidebar refSidebar" + "description": "The label for category 'web3j-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3py-ext": { "message": "web3py-ext", - "description": "The label for category web3py-ext in sidebar refSidebar" + "description": "The label for category 'web3py-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.Node Quick Reference": { "message": "ノード・クイック・リファレンス", - "description": "The label for category Node Quick Reference in sidebar refSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'refSidebar'" }, "sidebar.buildSidebar.category.Hardware Wallets": { "message": "ハードウェア財布", - "description": "The label for category Hardware Wallets in sidebar buildSidebar" + "description": "The label for category 'Hardware Wallets' in sidebar 'buildSidebar'" }, "sidebar.miniDappSidebar.category.Build Mini dApps on LINE with Unity": { "message": "UnityでLINEのミニdAppを作る", @@ -177,107 +177,107 @@ }, "sidebar.miniDappSidebar.category.Node Quick Reference": { "message": "ノード・クイック・リファレンス", - "description": "The label for category Node Quick Reference in sidebar miniDappSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'miniDappSidebar'" }, "sidebar.learnSidebar.category.Core Concepts": { "message": "コアコンセプト", - "description": "The label for category Core Concepts in sidebar learnSidebar" + "description": "The label for category 'Core Concepts' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Smart Contracts": { "message": "スマートコントラクト", - "description": "The label for category Smart Contracts in sidebar learnSidebar" + "description": "The label for category 'Smart Contracts' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Advanced Topics": { "message": "上級者向けトピックス", - "description": "The label for category Advanced Topics in sidebar learnSidebar" + "description": "The label for category 'Advanced Topics' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Transaction Execution": { "message": "トランザクションの実行", - "description": "The label for category Transaction Execution in sidebar learnSidebar" + "description": "The label for category 'Transaction Execution' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Token Economics": { "message": "トークンエコノミクス", - "description": "The label for category Token Economics in sidebar learnSidebar" + "description": "The label for category 'Token Economics' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Transactions": { "message": "トランザクション", - "description": "The label for category Transactions in sidebar buildSidebar" + "description": "The label for category 'Transactions' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Token Management": { "message": "トークン管理", - "description": "The label for category Token Management in sidebar buildSidebar" + "description": "The label for category 'Token Management' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Team Finance": { "message": "チーム・ファイナンス", - "description": "The label for category Team Finance in sidebar buildSidebar" + "description": "The label for category 'Team Finance' in sidebar 'buildSidebar'" }, "sidebar.miniDappSidebar.category.LINE Mini DApp with Unity": { "message": "LINEミニDApp with Unity", - "description": "The label for category LINE Mini DApp with Unity in sidebar miniDappSidebar" + "description": "The label for category 'LINE Mini DApp with Unity' in sidebar 'miniDappSidebar'" }, "sidebar.miniDappSidebar.category.LINE Mini DApp with Cocos": { "message": "LINEミニDApp with Cocos", - "description": "The label for category LINE Mini DApp with Cocos in sidebar miniDappSidebar" + "description": "The label for category 'LINE Mini DApp with Cocos' in sidebar 'miniDappSidebar'" }, "sidebar.miniDappSidebar.category.Survey Mini DApp": { "message": "アンケートミニDApp", - "description": "The label for category Survey Mini DApp in sidebar miniDappSidebar" + "description": "The label for category 'Survey Mini DApp' in sidebar 'miniDappSidebar'" }, "sidebar.learnSidebar.link.Docs Updates": { "message": "ドキュメント・アップデート", - "description": "The label for link Docs Updates in sidebar learnSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'learnSidebar', linking to '/misc/updates'" }, "sidebar.buildSidebar.link.Docs Updates": { "message": "ドキュメント・アップデート", - "description": "The label for link Docs Updates in sidebar buildSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'buildSidebar', linking to '/misc/updates'" }, "sidebar.nodeSidebar.category.Debugging and Diagnostics": { "message": "デバッグと診断", - "description": "The label for category Debugging and Diagnostics in sidebar nodeSidebar" + "description": "The label for category 'Debugging and Diagnostics' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.link.Docs Updates": { "message": "ドキュメント・アップデート", - "description": "The label for link Docs Updates in sidebar nodeSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'nodeSidebar', linking to '/misc/updates'" }, "sidebar.refSidebar.link.Docs Updates": { "message": "ドキュメント・アップデート", - "description": "The label for link Docs Updates in sidebar refSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'refSidebar', linking to '/misc/updates'" }, "sidebar.miniDappSidebar.link.Docs Updates": { "message": "ドキュメント・アップデート", - "description": "The label for link Docs Updates in sidebar miniDappSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'miniDappSidebar', linking to '/misc/updates'" }, "sidebar.learnSidebar.category.Finschia to Kaia": { "message": "フィンシャ→カイア", - "description": "The label for category Finschia to Kaia in sidebar learnSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Finschia to Kaia": { "message": "フィンシャ→カイア", - "description": "The label for category Finschia to Kaia in sidebar buildSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'buildSidebar'" }, "sidebar.nodeSidebar.category.Finschia to Kaia": { "message": "フィンシャ→カイア", - "description": "The label for category Finschia to Kaia in sidebar nodeSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'nodeSidebar'" }, "sidebar.refSidebar.category.Finschia to Kaia": { "message": "フィンシャ→カイア", - "description": "The label for category Finschia to Kaia in sidebar refSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'refSidebar'" }, "sidebar.miniDappSidebar.category.Finschia to Kaia": { "message": "フィンシャ→カイア", - "description": "The label for category Finschia to Kaia in sidebar miniDappSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'miniDappSidebar'" }, "sidebar.buildSidebar.category.Wallet Configuration": { "message": "ウォレットの設定", - "description": "The label for category Wallet Configuration in sidebar buildSidebar" + "description": "The label for category 'Wallet Configuration' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Wallet Operations": { "message": "ウォレットオペレーション", - "description": "The label for category Wallet Operations in sidebar buildSidebar" + "description": "The label for category 'Wallet Operations' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.dApp Integration": { "message": "dAppとの統合", - "description": "The label for category dApp Integration in sidebar buildSidebar" + "description": "The label for category 'dApp Integration' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Implementing Transactions": { "message": "トランザクションの実装", @@ -285,27 +285,27 @@ }, "sidebar.buildSidebar.category.Cookbooks": { "message": "料理本", - "description": "The label for category Cookbooks in sidebar buildSidebar" + "description": "The label for category 'Cookbooks' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Fundamentals": { "message": "基礎", - "description": "The label for category Fundamentals in sidebar buildSidebar" + "description": "The label for category 'Fundamentals' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Token Development": { "message": "トークン開発", - "description": "The label for category Token Development in sidebar buildSidebar" + "description": "The label for category 'Token Development' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Deployment & Verification": { "message": "展開と検証", - "description": "The label for category Deployment & Verification in sidebar buildSidebar" + "description": "The label for category 'Deployment & Verification' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Integrate Gas Abstraction (GA)": { "message": "ガスアブストラクション(GA)の統合", - "description": "The label for category Integrate Gas Abstraction (GA) in sidebar buildSidebar" + "description": "The label for category 'Integrate Gas Abstraction (GA)' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Kaia Agent Kit": { "message": "カイア・エージェント・キット", - "description": "The label for category Kaia Agent Kit in sidebar buildSidebar" + "description": "The label for category 'Kaia Agent Kit' in sidebar 'buildSidebar'" }, "sidebar.refSidebar.category.Gas Abstraction": { "message": "ガス抽出", @@ -313,306 +313,306 @@ }, "sidebar.refSidebar.category.viem-ext": { "message": "ヴィエムエクスト", - "description": "The label for category viem-ext in sidebar refSidebar" + "description": "The label for category 'viem-ext' in sidebar 'refSidebar'" }, "sidebar.buildSidebar.doc.Step 1: Foundation Setup": { "message": "ステップ1:ファンデーションのセットアップ", - "description": "The label for the doc item Step 1: Foundation Setup in sidebar buildSidebar, linking to the doc build/get-started/foundation-setup" + "description": "The label for the doc item 'Step 1: Foundation Setup' in sidebar 'buildSidebar', linking to the doc build/get-started/foundation-setup" }, "sidebar.buildSidebar.doc.Step 2: Set up Account and Networks": { "message": "ステップ2:アカウントとネットワークの設定", - "description": "The label for the doc item Step 2: Set up Account and Networks in sidebar buildSidebar, linking to the doc build/get-started/wallet-config-get-started" + "description": "The label for the doc item 'Step 2: Set up Account and Networks' in sidebar 'buildSidebar', linking to the doc build/get-started/wallet-config-get-started" }, "sidebar.buildSidebar.doc.Step 3: Get KAIA": { "message": "ステップ3:KAIAを手に入れる", - "description": "The label for the doc item Step 3: Get KAIA in sidebar buildSidebar, linking to the doc build/get-started/getting-kaia" + "description": "The label for the doc item 'Step 3: Get KAIA' in sidebar 'buildSidebar', linking to the doc build/get-started/getting-kaia" }, "sidebar.buildSidebar.doc.Step 4: Deploy Hello World Contract": { "message": "ステップ4:Hello Worldコントラクトのデプロイ", - "description": "The label for the doc item Step 4: Deploy Hello World Contract in sidebar buildSidebar, linking to the doc build/get-started/kaiagreeter-get-started" + "description": "The label for the doc item 'Step 4: Deploy Hello World Contract' in sidebar 'buildSidebar', linking to the doc build/get-started/kaiagreeter-get-started" }, "sidebar.buildSidebar.doc.Step 5: Deploy your First Token Contract": { "message": "ステップ5:最初のトークン契約をデプロイする", - "description": "The label for the doc item Step 5: Deploy your First Token Contract in sidebar buildSidebar, linking to the doc build/get-started/hardhat" + "description": "The label for the doc item 'Step 5: Deploy your First Token Contract' in sidebar 'buildSidebar', linking to the doc build/get-started/hardhat" }, "sidebar.buildSidebar.doc.Step 6: Build your First dApp on Kaia": { "message": "ステップ6:Kaiaで最初のdAppを構築する", - "description": "The label for the doc item Step 6: Build your First dApp on Kaia in sidebar buildSidebar, linking to the doc build/get-started/scaffold-eth-get-started" + "description": "The label for the doc item 'Step 6: Build your First dApp on Kaia' in sidebar 'buildSidebar', linking to the doc build/get-started/scaffold-eth-get-started" }, "sidebar.buildSidebar.doc.Step 7: Build your Mini dApp on Kaia": { "message": "ステップ7:KaiaでMini dAppを構築する", - "description": "The label for the doc item Step 7: Build your Mini dApp on Kaia in sidebar buildSidebar, linking to the doc minidapps/minidapps" + "description": "The label for the doc item 'Step 7: Build your Mini dApp on Kaia' in sidebar 'buildSidebar', linking to the doc minidapps/minidapps" }, "sidebar.buildSidebar.category.smart-contract-tools": { "message": "ツール", - "description": "The label for category Tools in sidebar buildSidebar" + "description": "The label for category 'Tools' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Best Practices": { "message": "ベストプラクティス", - "description": "The label for category Best Practices in sidebar buildSidebar" + "description": "The label for category 'Best Practices' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.build-tools": { "message": "ツール", - "description": "The label for category Tools in sidebar buildSidebar" + "description": "The label for category 'Tools' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Gaming SDKs": { "message": "ゲームSDK", - "description": "The label for category Gaming SDKs in sidebar buildSidebar" + "description": "The label for category 'Gaming SDKs' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.doc.Proof of Play vRNG": { "message": "プルーフ・オブ・プレイ vRNG", - "description": "The label for the doc item Proof of Play vRNG in sidebar buildSidebar, linking to the doc build/tools/oracles/vrng-pop" + "description": "The label for the doc item 'Proof of Play vRNG' in sidebar 'buildSidebar', linking to the doc build/tools/oracles/vrng-pop" }, "sidebar.refSidebar.category.account-management-v5": { "message": "アカウント管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v5": { "message": "アカウント・キー", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v5": { "message": "サイン取引", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v5": { "message": "サインメッセージ", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-v5": { "message": "キーストア", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v5": { "message": "基本取引", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v5": { "message": "手数料 委任取引", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v5": { "message": "スマート契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-v5": { "message": "ユーティリティ", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-v6": { "message": "アカウント管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v6": { "message": "アカウント・キー", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v6": { "message": "サイン取引", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v6": { "message": "サインメッセージ", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-v6": { "message": "キーストア", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v6": { "message": "基本取引", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v6": { "message": "手数料 委任取引", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.gas-abstraction-ethers": { "message": "ガス抽出", - "description": "The label for category Gas Abstraction in sidebar refSidebar" + "description": "The label for category 'Gas Abstraction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v6": { "message": "スマート契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-v6": { "message": "ユーティリティ", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-v1": { "message": "アカウント管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v1": { "message": "アカウント・キー", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v1": { "message": "サイン取引", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v1": { "message": "サインメッセージ", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v1": { "message": "基本取引", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v1": { "message": "手数料 委任取引", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v1": { "message": "スマート契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3js": { "message": "アカウント管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3js": { "message": "アカウント・キー", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3js": { "message": "サイン取引", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3js": { "message": "サインメッセージ", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3js": { "message": "キーストア", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3js": { "message": "基本取引", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3js": { "message": "手数料 委任取引", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.gas-abstraction-web3js": { "message": "ガス抽出", - "description": "The label for category Gas Abstraction in sidebar refSidebar" + "description": "The label for category 'Gas Abstraction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3js": { "message": "スマート契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3js": { "message": "ユーティリティ", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-viem": { "message": "基本取引", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-viem": { "message": "手数料 委任取引", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-viem": { "message": "スマート契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3j": { "message": "アカウント管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3j": { "message": "アカウント・キー", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3j": { "message": "サイン取引", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3j": { "message": "サインメッセージ", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3j": { "message": "キーストア", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3j": { "message": "基本取引", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3j": { "message": "手数料 委任取引", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3j": { "message": "スマート契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3j": { "message": "ユーティリティ", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3py": { "message": "アカウント管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3py": { "message": "アカウント・キー", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3py": { "message": "サイン取引", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3py": { "message": "サインメッセージ", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3py": { "message": "キーストア", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3py": { "message": "基本取引", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3py": { "message": "手数料 委任取引", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3py": { "message": "スマート契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3py": { "message": "ユーティリティ", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.doc.getting-started-ethers": { "message": "はじめに", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/ethers-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/ethers-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-ethers-v1": { "message": "はじめに", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/ethers-ext-prior-v1-0-1/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/ethers-ext-prior-v1-0-1/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3js": { "message": "はじめに", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3js-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3js-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-viem": { "message": "はじめに", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/viem-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/viem-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3j": { "message": "はじめに", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3j-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3j-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3py": { "message": "はじめに", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3py-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3py-ext/getting-started" } } diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md b/i18n/ja/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md index ac60dd8db1ab..a014b58933da 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md @@ -10,5 +10,5 @@ Web3.unity SDKを使えば、開発者はブロックチェーン対応のゲー Web3.unity SDKは現在、Kaia MainnetとKairos Testnetの両方をサポートしています。 カイアでブロックチェーン対応のゲームを作り始めるには、以下のガイドをご覧ください: -- [カイアでのUnityゲーム開発:ChainSafeでなめこトークンを鋳造する](https://medium.com/kaiachain/unity-game-development-on-kaia-minting-fungible-tokens-with-chainsafe-beea9022c42d) -- [KaiaでChainsafeとThirdwebを使ってUnityゲームをToken-Gateする方法](https://medium.com/kaiachain/how-to-token-gate-a-unity-game-using-chainsafe-and-thirdweb-on-kaia-93c574519da2) +- [カイアでのUnityゲーム開発:ChainSafeでなめこトークンを鋳造する](https://blog.kaia.io/unity-game-development-on-kaia-minting-fungible-tokens-with-chainsafe/) +- [KaiaでChainsafeとThirdwebを使ってUnityゲームをToken-Gateする方法](https://blog.kaia.io/how-to-token-gate-a-unity-game-using-chainsafe-and-thirdweb-on-kaia/) diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md index b22647245432..bf4bb3816bd1 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md @@ -887,4 +887,4 @@ Fleekは、IPFS上にモダンなサイトやアプリを構築するための ここから、1 KAIAを静的に送信する以外に、送信するコーヒーの量のための新しい入力フィールドを追加するなど、フロントエンドで他のオプションを検討することもできます。 [github](https://github.com/ayo-klaytn/buy-me-a-coffee)にあるコードベース全体にアクセスすることができ、この[リンク](https://spring-fog-0605.on.fleek.co/)を使ってウェブサイトをテストすることもできる。 -より詳細な情報をお知りになりたい方は、[Kaia Docs](https://docs.klaytn.foundation/)、[Web3Onboard Docs](https://onboard.blocknative.com/docs/modules/react)、[Fleek Docs](https://docs.fleek.co/tutorials/hosting/)をご覧ください。 ここから、1 KAIAを静的に送信する以外に、送信するコーヒーの量のための新しい入力フィールドを追加するなど、フロントエンドで他のオプションを検討することもできます。 +より詳しい情報は、[Kaia Docs](https://docs.kaia.io)、[Web3Onboard Docs](https://onboard.blocknative.com/docs/modules/react)、[Fleek Docs](https://docs.fleek.co/tutorials/hosting/)をご覧ください。 ここから、1 KAIAを静的に送信する以外に、送信するコーヒーの量のための新しい入力フィールドを追加するなど、フロントエンドで他のオプションを検討することもできます。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md new file mode 100644 index 000000000000..fed7375558c0 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md @@ -0,0 +1,748 @@ +# チェーンリンクCCIPを用いたKaia上でのクロスチェーンNFTの構築:実践ガイド + +## はじめに + +NFTはブロックチェーン技術の最も認知度の高いユースケースの1つとなっており、ユニークで検証可能なデジタル資産の創造を可能にしている。 しかし、従来のNFTの実装は単一のブロックチェーンに縛られていた。 この制限は柔軟性を低下させ、コミュニティ、流動性、有用性が異なる生態系を自由に行き来することを妨げる。 + +クロスチェーンNFTは、NFTの一意性と出所を保持したままブロックチェーン間をシームレスに移動できるようにすることで、この課題を解決します。 チェーンリンクのCCIP(Cross-Chain Interoperability Protocol)により、開発者は標準化された安全なメッセージングフレームワークを使用して、チェーン間の信頼性の高いブリッジを構築することができます。 + +このガイドでは、バーン&ミントモデルを使用してCrosschain NFTを構築し、デプロイします。 NFTはソースチェインで焼かれ、デスティネーションチェインで同じtokenIdとメタデータで再鋳造される。 + +## 前提条件 + +始める前に、以下のセットアップが完了していることを確認してください: + +- [Node.js](https://nodejs.org/) および [npm](https://www.npmjs.com/) +- ハードハット + - インストールする:npm install --save-dev hardhat\` + - プロジェクトを初期化する: `npx hardhat --init` +- [メタマスク](https://metamask.io/en-GB/download) ウォレット + - 開発用ウォレットを作成または設定する。 + - MetaMaskにKaia Kairos TestnetとEthereum Sepoliaネットワークの両方を追加する。 +- 蛇口からのテスト・トークン + - [KAIA](https://faucet.kaia.io/): 契約の展開や取引の送信時に、カイアのガス料金を支払う。 + - [LINK](https://faucets.chain.link/kaia-testnet) (testnet): LINKで支払う場合、CCIP料金をカバー。 + - [セポリアETH](https://faucets.chain.link/sepolia):セポリアでのガス料金を支払い、選択すればネイティブETHのCCIP料金もカバーできる。 +- [ファイルベース](https://filebase.com/) アカウント + - NFTメタデータのアップロードと取得に必要(IPFSストレージ)。 + +## クロスチェーンNFTはどのように機能するのか? + +NFTは単一のブロックチェーン上に記録された固有のデジタルトークンです。 鋳造、送金、所有権などの中核的な動作は、そのチェーンに結びついたスマートコントラクトによって定義される。 このため、NFTは追加的な仕組みなしにブロックチェーン間を自然に移動することはできない。 相互運用性を実現するために、開発者はコンパニオンコントラクトを複数のチェーンに展開し、クロスチェーン・メッセージングを通じてそれらをリンクさせる。 その結果、クロスチェーンNFT:ブロックチェーンをまたがって存在する同等のトークンだが、いつでもアクティブなのは1つのコピーだけである。 + +クロスチェーンNFTは通常、3つの方法のいずれかで実装される: + +- **Burn and mint**:NFTはソースチェーンで焼かれ、デスティネーションチェーンで同等のものが鋳造される。 + +- **ロックとミント**:NFTはソースチェーン上でロックされ、デスティネーション上で複製が鋳造される。 返却するには、複製を焼いてオリジナルのロックを解除する必要がある。 + +- **ロックとアンロック**:同一のコレクションが複数のチェーンに展開される。 オーナーはあるチェーンのNFTをロックし、別のチェーンのNFTのロックを解除する。 + +このガイドでは、Crosschain NFTにburn and mintモデルを使用する。 NFTは、チェーンリンクCCIPによって、あるチェーンから取り除かれ、別のチェーンに再作成される。 + +## はじめに + +このガイドでは、Chainlink CCIPを使用して、Kaia Kairos TestnetとEthereum Sepoliaの間でクロスチェーンNFTを作成し、転送します。 + +最後には、次のことができるようになるだろう: + +- Kairos TestnetとEthereum Sepoliaの両方に設定されたHardhatプロジェクトの初期化 +- Chainlink CCIPコントラクトとインタフェースを依存関係として追加する +- クロスチェーン送金のためのバーンアンドミントメカニズムを備えたクロスチェーンNFT契約の導入 +- 両方のネットワークに契約を展開し、チェーンをまたいでNFTを送信する。 + +### ハードハット・プロジェクトの作成 + +このチュートリアルでは、[Hardhat 3](https://hardhat.org/docs/getting-started#getting-started-with-hardhat-3)を使用して、コントラクトをデプロイし、対話します。 Hardhat 3は、暗号化されたキーストアのネイティブサポート、Solidityでテストを記述する機能、プロジェクトツールの改善などの新機能を提供します。 + +以下の手順に従ってプロジェクトをセットアップしてください: + +1. Node.jsとnpmのインストールを確認する + + 以下のコマンドを実行して、Node.jsとnpmがインストールされていることを確認する: + +```bash +node -v +npm -v +``` + +2. 新しいプロジェクト・ディレクトリを初期化する + + 新しいフォルダを作成し、その中に移動して、Node.jsプロジェクトを初期化する: + +```bash +mkdir ccip-nft-kaia-hardhat-example +cd ccip-nft-kaia-hardhat-example +npm init -y +``` + +3. ハードハット・プロジェクトの作成 + + 走れ: + +```bash +npx hardhat --init +``` + +プロンプトが表示されたら、Node.js テストランナーと ethers を含むサンプルプロジェクトを選択します。 カレント・ディレクトリで初期化し、必要な依存関係をすべてインストールする。 + +### 必要な契約の取り付け + +チェーンリンクCCIP契約を取り付ける: + +```bash +npm i @chainlink/contracts-ccip --save-dev +``` + +標準的なチェーンリンク契約を取り付ける: + +```bash +npm i @chainlink/contracts --save-dev +``` + +OpenZeppelinコントラクトをインストールする(ERC-721とその他の基本実装を提供する): + +```bash +npm i @openzeppelin/contracts --save-dev +``` + +## NFTメタデータの設定 + +契約書を書く前に、NFTの仕様を定義しておこう。 各NFTは、その名前、説明、画像を記述するメタデータを必要とし、JSONファイルに格納され、IPFS上でホストされる。 + +このガイドでは、画像とメタデータの両方を保存するためにFilebaseを使用します。 独自のNFTを作成したい場合は、画像とメタデータのJSONファイルをFilebaseを通じてIPFSにアップロードしてください。 アップロード後、Filesタブでファイル名をクリックし、IPFSのURLをコピーします。 こんな感じだ: + +```bash +https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmY1LZF8JHo2r3h4X5VzLLXtJujqnBFGTyo2aqR9joXnt8 +``` + +以下は、使用可能なメタデータ・ファイルのサンプルです: + +```json +{ + "name": "Kairos NFT", + "description": "gkaia frens! gazuaaaaa!!!", + "image": "https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmRvQc4wZCp6NF7dFL4ywiWTG7FSH3KKGUAkXGgsdYfcKi" +} +``` + +## スマートコントラクトの記述 + +このセクションでは、チェーンリンクCCIPのバーン&ミントモデルを使用して、ブロックチェーン間のNFT転送を可能にするコントラクトを実装します。 + +プロジェクトのコントラクトディレクトリに`CrosschainNFT.sol`という名前で新規ファイルを作成し、以下のコードを貼り付けます: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; +import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import {ERC721URIStorage} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; +import {ERC721Burnable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; +import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import {Client} from "@chainlink/contracts-ccip/contracts/libraries/Client.sol"; +import {IRouterClient} from "@chainlink/contracts-ccip/contracts/interfaces/IRouterClient.sol"; +import {IAny2EVMMessageReceiver} from "@chainlink/contracts-ccip/contracts/interfaces/IAny2EVMMessageReceiver.sol"; +import {OwnerIsCreator} from "@chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol"; +import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; +/** + * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. + * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. + * DO NOT USE THIS CODE IN PRODUCTION. + */ + // Source chain is Ethereum Sepolia + // Destination chain is Kairos Testnet +contract CrosschainNFT is ERC721, ERC721URIStorage, ERC721Burnable, IAny2EVMMessageReceiver, ReentrancyGuard, OwnerIsCreator { + using SafeERC20 for IERC20; + enum PayFeesIn { + Native, + LINK + } + error InvalidRouter(address router); + error OnlyOnEthereumSepolia(); + error NotEnoughBalanceForFees(uint256 currentBalance, uint256 calculatedFees); + error NothingToWithdraw(); + error FailedToWithdrawEth(address owner, address target, uint256 value); + error ChainNotEnabled(uint64 chainSelector); + error SenderNotEnabled(address sender); + error OperationNotAllowedOnCurrentChain(uint64 chainSelector); + struct crosschainNFTDetails { + address crosschainNFTAddress; + bytes ccipExtraArgsBytes; + } + uint256 constant ETHEREUM_SEPOLIA_CHAIN_ID = 11155111; + string tokenNFTURI = "https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmY1LZF8JHo2r3h4X5VzLLXtJujqnBFGTyo2aqR9joXnt8"; + IRouterClient internal immutable i_ccipRouter; + LinkTokenInterface internal immutable i_linkToken; + uint64 private immutable i_currentChainSelector; + uint256 private _nextTokenId; + mapping(uint64 destChainSelector => crosschainNFTDetails crosschainNFTPerChain) public s_chains; + event ChainEnabled(uint64 chainSelector, address xNftAddress, bytes ccipExtraArgs); + event ChainDisabled(uint64 chainSelector); + event CrossChainSent( + address from, address to, uint256 tokenId, uint64 sourceChainSelector, uint64 destinationChainSelector + ); + event CrossChainReceived( + address from, address to, uint256 tokenId, uint64 sourceChainSelector, uint64 destinationChainSelector + ); + modifier onlyRouter() { + if (msg.sender != address(i_ccipRouter)) { + revert InvalidRouter(msg.sender); + } + _; + } + modifier onlyOnEthereumSepolia() { + if (block.chainid != ETHEREUM_SEPOLIA_CHAIN_ID) { + revert OnlyOnEthereumSepolia(); + } + _; + } + modifier onlyEnabledChain(uint64 _chainSelector) { + if (s_chains[_chainSelector].crosschainNFTAddress == address(0)) { + revert ChainNotEnabled(_chainSelector); + } + _; + } + modifier onlyEnabledSender(uint64 _chainSelector, address _sender) { + if (s_chains[_chainSelector].crosschainNFTAddress != _sender) { + revert SenderNotEnabled(_sender); + } + _; + } + modifier onlyOtherChains(uint64 _chainSelector) { + if (_chainSelector == i_currentChainSelector) { + revert OperationNotAllowedOnCurrentChain(_chainSelector); + } + _; + } + constructor(address ccipRouterAddress, address linkTokenAddress, uint64 currentChainSelector) + ERC721("Cross Chain NFT", "XNFT") + { + if (ccipRouterAddress == address(0)) revert InvalidRouter(address(0)); + i_ccipRouter = IRouterClient(ccipRouterAddress); + i_linkToken = LinkTokenInterface(linkTokenAddress); + i_currentChainSelector = currentChainSelector; + } + function mint() external onlyOnEthereumSepolia { + uint256 tokenId = _nextTokenId++; + _safeMint(msg.sender, tokenId); + _setTokenURI(tokenId, tokenNFTURI); + } + function enableChain(uint64 chainSelector, address crosschainNFTAddress, bytes memory ccipExtraArgs) + external + onlyOwner + onlyOtherChains(chainSelector) + { + s_chains[chainSelector] = crosschainNFTDetails({crosschainNFTAddress: crosschainNFTAddress, ccipExtraArgsBytes: ccipExtraArgs}); + emit ChainEnabled(chainSelector, crosschainNFTAddress, ccipExtraArgs); + } + function disableChain(uint64 chainSelector) external onlyOwner onlyOtherChains(chainSelector) { + delete s_chains[chainSelector]; + emit ChainDisabled(chainSelector); + } + function crossChainTransferFrom( + address from, + address to, + uint256 tokenId, + uint64 destinationChainSelector, + PayFeesIn payFeesIn + ) external nonReentrant onlyEnabledChain(destinationChainSelector) returns (bytes32 messageId) { + string memory tokenUri = tokenURI(tokenId); + _burn(tokenId); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(s_chains[destinationChainSelector].crosschainNFTAddress), + data: abi.encode(from, to, tokenId, tokenUri), + tokenAmounts: new Client.EVMTokenAmount[](0), + extraArgs: s_chains[destinationChainSelector].ccipExtraArgsBytes, + feeToken: payFeesIn == PayFeesIn.LINK ? address(i_linkToken) : address(0) + }); + // Get the fee required to send the CCIP message + uint256 fees = i_ccipRouter.getFee(destinationChainSelector, message); + if (payFeesIn == PayFeesIn.LINK) { + if (fees > i_linkToken.balanceOf(address(this))) { + revert NotEnoughBalanceForFees(i_linkToken.balanceOf(address(this)), fees); + } + // Approve the Router to transfer LINK tokens on contract's behalf. It will spend the fees in LINK + i_linkToken.approve(address(i_ccipRouter), fees); + // Send the message through the router and store the returned message ID + messageId = i_ccipRouter.ccipSend(destinationChainSelector, message); + } else { + if (fees > address(this).balance) { + revert NotEnoughBalanceForFees(address(this).balance, fees); + } + // Send the message through the router and store the returned message ID + messageId = i_ccipRouter.ccipSend{value: fees}(destinationChainSelector, message); + } + emit CrossChainSent(from, to, tokenId, i_currentChainSelector, destinationChainSelector); + } + /// @inheritdoc IAny2EVMMessageReceiver + function ccipReceive(Client.Any2EVMMessage calldata message) + external + virtual + override + onlyRouter + nonReentrant + onlyEnabledChain(message.sourceChainSelector) + onlyEnabledSender(message.sourceChainSelector, abi.decode(message.sender, (address))) + { + uint64 sourceChainSelector = message.sourceChainSelector; + (address from, address to, uint256 tokenId, string memory tokenUri) = + abi.decode(message.data, (address, address, uint256, string)); + _safeMint(to, tokenId); + _setTokenURI(tokenId, tokenUri); + emit CrossChainReceived(from, to, tokenId, sourceChainSelector, i_currentChainSelector); + } + function withdraw(address _beneficiary) public onlyOwner { + uint256 amount = address(this).balance; + if (amount == 0) revert NothingToWithdraw(); + (bool sent,) = _beneficiary.call{value: amount}(""); + if (!sent) revert FailedToWithdrawEth(msg.sender, _beneficiary, amount); + } + function withdrawToken(address _beneficiary, address _token) public onlyOwner { + uint256 amount = IERC20(_token).balanceOf(address(this)); + if (amount == 0) revert NothingToWithdraw(); + IERC20(_token).safeTransfer(_beneficiary, amount); + } + function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) { + return super.tokenURI(tokenId); + } + function getCCIPRouter() public view returns (address) { + return address(i_ccipRouter); + } + function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721URIStorage) returns (bool) { + return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || super.supportsInterface(interfaceId); + } +} +``` + +### コード・チュートリアル + +CrosschainNFTはチェーンリンクCCIPを統合し、ブロックチェーン間でNFTを移転するERC-721コントラクトです。 ソースチェーン上のNFTを焼き、同じtokenIdとtokenURIでデスティネーションに再mintする。 この契約は、enableChainを通じて承認されたデスティネーションチェーンのレジストリを維持し、クロスチェーンメッセージングをチェーンリンクルーター(IRouterClient)に依存し、ネイティブガストークンまたはLINKでの手数料支払いをサポートする。 + +主な機能 + +- イネーブルチェーン + +コントラクトの所有者が宛先ブロックチェーンを登録できるようにする。 s_chainsのマッピングに相手のNFTコントラクトアドレスとCCIP引数を格納し、チェーンを有効な転送先としてホワイトリスト化する。 セットアップが完了すると、ChainEnabledイベントが発生する。 + +- クロスチェーン転送元 + +チェインをまたいだNFTの転送を実行する。 まず、デスティネーションチェーンが有効であることを確認し、次にNFTメタデータ(tokenURI)を取得し、ソースチェーン上でトークンをバーンします。 次に、CCIPメッセージに移籍の詳細を記載し、必要な手数料を計算し、LINKかネイティブ・ガスで支払う。 メッセージがルーターを経由して送信されると、CrossChainSent イベントが発生し、転送のログが記録される。 + +CrosschainNFT.sol\`のコアフローが明らかになったところで、次のステップに進もう。 + +## スマート・コントラクトのコンパイル + +スマート・コントラクトをコンパイルするには、以下を実行する: + +```bash +npx hardhat build +``` + +## スマートコントラクトの導入 + +このセクションでは、必要な変数を設定し、「CrosschainNFT.sol」コントラクトをEthereum Sepolia(ソースチェーン)とKairos Testnet(デスティネーションチェーン)の両方にデプロイします。 + +### 暗号化キーストアの使用 + +Hardhat 3の利点の一つは、秘密鍵やRPC URLのような機密性の高い値を、プレーンテキストファイルではなく、暗号化されたキーストアに保存できることです。 このガイドでは、セポリアとカイロスの_PRIVATE_KEY_と_RPC URL_を暗号化します。 + +\*\*秘密鍵を追加する + +```bash +npx hardhat keystore set PRIVATE_KEY +``` + +このコマンドを初めて実行すると、Hardhatはキーストアのパスワードを作成するよう促します。 このパスワードは、値を追加したり更新したりするときに必要になります。 + +**各ネットワークのRPC URLを追加する**。 + +```bash +npx hardhat keystore set KAIROS_RPC_URL +npx hardhat keystore set SEPOLIA_RPC_URL +``` + +最後に、`hardhat.config.ts`ファイルを編集して、これらの暗号化された値をロードし、2つのネットワークを設定する。 + +```typescript +import type { HardhatUserConfig } from "hardhat/config"; +import hardhatToolboxMochaEthersPlugin from "@nomicfoundation/hardhat-toolbox-mocha-ethers"; +import { configVariable } from "hardhat/config"; +const config: HardhatUserConfig = { + plugins: [hardhatToolboxMochaEthersPlugin], + solidity: { + profiles: { + default: { + version: "0.8.28", + }, + production: { + version: "0.8.28", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + }, + }, + networks: { + hardhatMainnet: { + type: "edr-simulated", + chainType: "l1", + }, + hardhatOp: { + type: "edr-simulated", + chainType: "op", + }, + kairosTestnet: { + type: "http", + chainType: "l1", + url: configVariable("KAIROS_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + ethereumSepolia: { + type: "http", + chainType: "l1", + url: configVariable("SEPOLIA_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + }, +}; +export default config; +``` + +次のステップは、CrosschainNFTスマートコントラクトをそれぞれEthereum SepoliaとKairos Testnetにデプロイすることである。 + +### CrosschainNFT.solをEthereum Sepoliaにデプロイする。 + +デプロイする前に、[Chainlink CCIP Directory](https://docs.chain.link/ccip/directory/testnet/chain/ethereum-testnet-sepolia)からEthereum Sepoliaの以下の値を取得してください: + +- チェーンセレクター +- CCIPルーターアドレス +- LINKトークンのアドレス + +これらの値は、デプロイ スクリプトで必要になります。 次に、プロジェクトの _ignition/modules_ フォルダに移動し、`deployEthereumSepolia.ts` という名前の新規ファイルを作成し、以下のコードを貼り付ける: + +```typescript +// This setup uses Hardhat Ignition to manage smart contract deployments. +// Learn more about it at https://hardhat.org/ignition +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const ETHEREUM_SEPOLIA_ROUTER_ADDRESS = `0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59`; +const ETHEREUM_SEPOLIA_LINK_TOKEN_ADDRESS = `0x779877A7B0D9E8603169DdbD7836e478b4624789`; +const ETHEREUM_SEPOLIA_CHAIN_SELECTOR = `16015286601757825753`; +const CrosschainNFTSepoliaModule = buildModule("CrosschainNFTSepoliaModule", (m) => { + const crosschainNFTSepolia = m.contract("CrosschainNFT", [ETHEREUM_SEPOLIA_ROUTER_ADDRESS, ETHEREUM_SEPOLIA_LINK_TOKEN_ADDRESS, ETHEREUM_SEPOLIA_CHAIN_SELECTOR], { + }); + return { crosschainNFTSepolia }; +}); +export default CrosschainNFTSepoliaModule; +``` + +デプロイスクリプトを実行します: + +```bash +npx hardhat ignition deploy ignition/modules/deployEthereumSepolia.ts --network ethereumSepolia +``` + +### KairosテストネットにCrosschainNFT.solをデプロイする + +デプロイ前に、[Chainlink CCIP Directory](https://docs.chain.link/ccip/directory/testnet/chain/kaia-testnet-kairos)からKairos Testnetの以下の値を取得してください: + +- チェーンセレクター +- CCIPルーターアドレス +- LINKトークンのアドレス + +これらの値は、デプロイ スクリプトで必要になります。 次に、プロジェクトの _ignition/modules_ フォルダに移動し、`deployKairosTestnet.ts` という名前のファイルを新規作成し、以下のコードを貼り付けます: + +```typescript +// This setup uses Hardhat Ignition to manage smart contract deployments. +// Learn more about it at https://hardhat.org/ignition + +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const KAIROS_TESTNET_ROUTER_ADDRESS = `0x41477416677843fCE577748D2e762B6638492755`; +const KAIROS_TESTNET_LINK_TOKEN_ADDRESS = `0xAF3243f975afe2269Da8Ffa835CA3A8F8B6A5A36`; +const KAIROS_TESTNET_CHAIN_SELECTOR = `2624132734533621656`; +const CrosschainNFTKairosModule = buildModule("CrosschainNFTKairosModule", (m) => { + const crosschainNFTKairos = m.contract("CrosschainNFT", [KAIROS_TESTNET_ROUTER_ADDRESS, KAIROS_TESTNET_LINK_TOKEN_ADDRESS, KAIROS_TESTNET_CHAIN_SELECTOR], { + }); + return { crosschainNFTKairos }; +}); +export default CrosschainNFTKairosModule; +``` + +デプロイスクリプトを実行します: + +```bash +npx hardhat ignition deploy ignition/modules/deployKairosTestnet.ts --network kairosTestnet +``` + +## スマート・コントラクトとの対話 + +このセクションでは、enableChain、mint、crosschainTransferの各関数を実行することで、デプロイされたCrosschainNFTスマートコントラクトと対話する。 + +### ステップ 1: イーサリアム・セポリアで enableChain を呼び出す + +enableChainを呼び出す前に、以下の値を用意する: + +- **Sepoliaコントラクトアドレス**:Ethereum Sepolia上にデプロイされたCrosschainNFT.solコントラクトのアドレス。 +- **Kairos contract address**: Kairos TestnetにデプロイされたCrosschainNFT.solコントラクトのアドレス。 +- \*\*チェーンセレクタ2624132734533621656 (Kairos TestnetのCCIPチェーンセレクタ)。 +- **CCIP extraArgs**:0x97a657c90000000000000000000000000007A120 (これは、gasLimitが500,000に設定されたextraArgsのデフォルトのエンコード値です)。 + +次に、scriptsフォルダに新しいTypeScriptファイルを作成し、名前を`enableChainSepolia.ts`とし、以下のコードを貼り付ける: + +```typescript +// scripts/enableChainSepolia.ts +import { network } from "hardhat"; +async function main() { + const connection = await network.connect({ + network: "ethereumSepolia" + }); + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory by name + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + // Contract addresses and parameters + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + const crosschainNFTAddressKairosTestnet = `0x8c464Bb9Bf364F68b898ed0708b8f5F66EF6Cfb1`; + const chainSelectorKairosTestnet = `2624132734533621656`; + const ccipExtraArgs = `0x97a657c9000000000000000000000000000000000000000000000000000000000007A120`; + // Attach to the deployed contract + const crosschainNFTSepolia = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + console.log(`Enabling chain for Kairos Testnet...`); + const tx = await crosschainNFTSepolia.enableChain( + chainSelectorKairosTestnet, + crosschainNFTAddressKairosTestnet, + ccipExtraArgs + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Chain enabled successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +次のコマンドを実行して関数を呼び出す: + +```bash +npx hardhat run scripts/enableChainSepolia.ts --network ethereumSepolia +``` + +### ステップ2:Kairos TestnetでenableChainを呼び出す + +enableChainを呼び出す前に、以下の値を用意する: + +- **Kairosコントラクトアドレス**:KairosテストネットにデプロイされたCrosschainNFT.solコントラクトのアドレス +- **Sepoliaコントラクトアドレス**:Ethereum Sepolia上にデプロイされたCrosschainNFT.solコントラクトのアドレス +- \*\*チェーンセレクタ16015286601757825753 (Kairos TestnetのCCIPチェーンセレクタ) +- **CCIP extraArgs**:0x97a657c9000000000000000000000007A120 (これは、gasLimitが500,000に設定されたextraArgsのデフォルトのエンコード値です) + +次に、scriptsフォルダに新しいTypeScriptファイルを作成し、名前を`enableChainKairos.ts`とし、以下のコードを貼り付けます: + +```typescript +// scripts/enableChainKairos.ts +import { network } from "hardhat"; +async function main() { + const connection = await network.connect({ + network: "kairosTestnet" + }); + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory by name + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + // Contract addresses and parameters + const crosschainNFTAddressKairosTestnet = `0x8c464Bb9Bf364F68b898ed0708b8f5F66EF6Cfb1`; + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + const chainSelectorEthereumSepolia = `16015286601757825753`; + const ccipExtraArgs = `0x97a657c9000000000000000000000000000000000000000000000000000000000007A120`; + // Attach to the deployed contract on Kairos + const crosschainNFTKairos = CrosschainNFT.attach(crosschainNFTAddressKairosTestnet); + console.log(`Enabling chain for Ethereum Sepolia...`); + const tx = await crosschainNFTKairos.enableChain( + chainSelectorEthereumSepolia, + crosschainNFTAddressEthereumSepolia, + ccipExtraArgs + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Chain enabled successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +次のコマンドを実行して関数を呼び出す: + +```bash +npx hardhat run scripts/enableChainKairos.ts --network KairosTestnet +``` + +### ステップ3:イーサリアム・セポリア上のLINKでコントラクトに資金を提供する + +CCIPの手数料を賄うには、イーサリアム・セポリア(crosschainNFTAddressEthereumSepolia)上に展開されたCrosschainNFTコントラクトにLINKで資金を提供します。 付属の[蛇口](https://faucets.chain.link/sepolia)からテストLINKを入手できる。 このガイドでは、3LINKを送信すれば十分である。 + +![](/img/build/tutorials/cc-ccip-fund-link.png) + +### ステップ4:Ethereum Sepolia上で新しいCrosschainNFTをミントする + +次に、Ethereum SepoliaにデプロイされたCrosschainNFTコントラクト上で新たなNFTをミントする。 + +scriptsフォルダに新しいTypeScriptファイルを作成し、名前を`mint.ts`とし、以下のコードを貼り付けます: + +```typescript +// scripts/mint.ts +import { network } from "hardhat"; +async function main() { + // Connect to the network + const connection = await network.connect({ + network: "ethereumSepolia" + }); +if (connection.networkName !== "ethereumSepolia") { + console.error(`Must be called from Ethereum Sepolia`); + process.exitCode = 1; + return; + } + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22` + // Attach to the deployed contract + const crosschainNFT = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + console.log(`Minting NFT...`); + const tx = await crosschainNFT.mint(); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`NFT minted successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +このスクリプトは鋳造処理を行い、クロスチェーン転送のためにNFTを準備する。 + +次のコマンドを実行して関数を呼び出す: + +```bash +npx hardhat run scripts/mint.ts --network ethereumSepolia +``` + +### ステップ5:チェーン間のNFTの移動 + +Ethereum Sepoliaでは、crossChainTransferFrom関数を呼び出してNFTをKairos Testnetに送信します。 + +以下の値を設定する: + +- **from**:イーサリアム・セポリア上のあなたのEOAアドレス +- \*\*宛先:Kairos TestnetのEOAアドレス(ご自身のアドレスでも可) +- **tokenId**:譲渡したい NFT の ID +- **DestinationChainSelector**:2624132734533621656 (Kairos TestnetのCCIPチェーンセレクタ) +- **payFeesIn**:1 (CCIPの料金がLINKで支払われることを示す) + +転送スクリプトの実行 + +scriptsフォルダに新しいTypeScriptファイルを作成し、名前を`crossChainTransferNFT.ts`とし、以下のコードを貼り付けます: + +```typescript +// scripts/crossChainTransferNFT.ts +import { network } from "hardhat"; +async function main() { + // Connect to the network + const connection = await network.connect({ + network: "ethereumSepolia" + }); + // Check if we're on the correct network + if (connection.networkName !== "ethereumSepolia") { + console.error(`Must be called from Ethereum Sepolia`); + process.exitCode = 1; + return; + } + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + // Transfer parameters + const from = `0x7b467A6962bE0ac80784F131049A25CDE27d62Fb`; + const to = `0x7b467A6962bE0ac80784F131049A25CDE27d62Fb`; + const tokenId = 0; // Put NFT token id here + const destinationChainSelector = "2624132734533621656"; // Kairos Testnet + const payFeesIn = 1; // 0 - Native, 1 - LINK + // Attach to the deployed contract + const crosschainNFT = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + const tx = await crosschainNFT.crossChainTransferFrom( + from, + to, + tokenId, + destinationChainSelector, + payFeesIn + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Cross-chain transfer initiated successfully!`); + console.log(`Note: The NFT will arrive on Kairos Testnet after CCIP processes the message.`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +でスクリプトを実行する: + +```bash +npx hardhat run scripts/crossChainTransferNFT.ts --network ethereumSepolia +``` + +転送を確認する + +CCIP Explorer」(https://ccip.chain.link/#/side-drawer/msg/0x2a43cf8076ed6290dd0bf8bdbbc87abe2d238da43b6bf514e70909dd0f35c9db)でクロスチェーン送金を監視し、「Kaiascan」(https://kairos.kaiascan.io/nft/0x7dcdaa882603b1cfeee42d1c382a1ecba595d87c/0?tabId=nftTokenTransfer&page=1)で取引を確認することができます。 + +![](/img/build/tutorials/cc-nft-ccip-explorer.png) + +![](/img/build/tutorials/cc-nft-ccip-kaiascan.png) + +NFT が Kairos Testnet に到着したら、MetaMask ウォレットに追加します: + +1. MetaMaskのNFTタブを開く。 +2. NFTのインポートをクリックします。 +3. Kairos Testnet上のCrosschainNFTコントラクトアドレスと、受け取ったtokenId(例:0)を入力します。 + +NFTがMetaMaskウォレットに表示されます。 + +![](/img/build/tutorials/cc-ccip-mm-view-nft.png) + +## 結論 + +このチュートリアルでは、Chainlink CCIPを使ってKaia Kairos TestnetとEthereum Sepoliaの間でバーン&ミントモデルを使ってNFTを転送する方法を学びました。 + +CCIPをより深く理解し、その他の使用例を調べるには、公式の[Chainlink CCIP Documentation](https://docs.chain.link/ccip)をご覧ください。 + + + + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md index b853ee841442..a669cb3e08cd 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md @@ -79,5 +79,5 @@ Kairos testnet explorerで見ることができます。 これらのブロッ \*\*教育内容 -- [ガス料金を安定コインで支払えるとしたら?](https://medium.com/kaiachain/pay-for-gas-fees-with-any-token-a-deep-dive-into-kaias-trustless-gas-abstraction-d670355a096b) -- [カイア・コンセンサス流動性発表】(https://medium.com/kaiachain/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity-7c8a7393cd19) \ No newline at end of file +- [ガス料金を安定コインで支払えるとしたら?](https://blog.kaia.io/pay-for-gas-fees-with-any-token-a-deep-dive-into-kaias-trustless-gas-abstraction/) +- [カイア・コンセンサス流動性発表】(https://blog.kaia.io/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity/) \ No newline at end of file diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md index 9704cd197fc6..d3cdce579df9 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md @@ -45,4 +45,4 @@ ## 1.4 コンセンサス流動性(CL)との関係 -GAはもともと、[Consensus Liquidity tokens](https://medium.com/kaiachain/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity-7c8a7393cd19)の実用性を高めるために設計されたもので、ユーザーはCLトークン(BORA、Swapscannerなど)でガスを支払うことができる。 しかし、この機能はstablecoinを含む他のERC-20トークンもサポートすることができる。 \ No newline at end of file +GAはもともと、[Consensus Liquidity tokens](https://blog.kaia.io/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity/)の実用性を高めるために設計されたもので、ユーザーはCLトークン(BORA、Swapscannerなど)でガスを支払うことができる。 しかし、この機能はstablecoinを含む他のERC-20トークンもサポートすることができる。 \ No newline at end of file diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md new file mode 100644 index 000000000000..6df367e8dbfb --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md @@ -0,0 +1,479 @@ +--- +id: integrate-gas-free-usdt-kaia-swap +title: ガスフリーUSDTをKAIAスワップに統合 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# ガスフリーUSDTをKAIAスワップに統合 + +このガイドでは、その目的、前提条件、統合手順、APIリファレンスなど、Gas-Free USDT to KAIAスワップ機能の概要を説明します。 これは、開発者がカイアネットワーク上の分散型アプリケーション(DApps)にガスフリーのスワップ機能を統合できるように設計されている。 + +## はじめに + +GasFreeSwapKaia\`APIが導入され、ユーザーはガス料金のためにKAIAトークンを保持する必要なく、あるいはユーザーの代わりに取引コストをカバーする場合でさえ、Kaiaネットワーク上でガスなしのERC20トークンスワップ(現在はUSDTに限定)を実行できるようになった。 APIは特に、完全にガスレスなユーザー体験のために、ERC20許可署名を使用してUSDTからKAIAへのスワップをサポートしています。 + +### メリット + +- **100%ガス・レス体験**:ユーザーはスワップを行うためにKAIAトークンを必要としない。 +- **ユーザーオンボーディングの強化**:新規ユーザーはKAIAを取得することなく、すぐにトークンの交換を開始できます。 +- **ERC20許可証の統合**:標準的なERC20許可署名を使用し、安全でガスレスのトークン承認を実現 + +### 仕組み + +- **ユーザーがスワップを開始**:ユーザーはKAIAとスワップするUSDT量を選択します。 +- **フロントエンドが許可証を作成する**:DAppはユーザが署名するためのERC20許可署名を作成する。 +- \*\*ユーザーが許可証に署名する:利用者が許可メッセージに署名(ガス不要) +- \*\*DAppはAPIを呼び出す:フロントエンドはスワップ・パラメータと許可署名をAPIに送信する。 +- **バックエンドの実行**:APIが許可を検証し、スワップを実行し、すべてのガス料金を支払う。 +- **ユーザーがKAIAを受け取る**:ネイティブKAIAトークンはユーザーのウォレットに直接送られます。 + +## 前提条件と対応環境 + +\*\*サービス・エンドポイント + + + + https://fee-delegation.kaia.io + + + + https://fee-delegation-kairos.kaia.io + + + +**サポートされるトークン・ペア**。 + +APIは現在、単一の取引ペアのみをサポートしている: + + + + トークン・イン:USDT (`0xd077a400968890eacc75cdc901f0356c943e4fdb`) + +``` +Token Out: WKAIA (`0x19aac5f612f524b754ca7e7c41cbfa2e981a4432`) +``` + + + + + トークン イン: TEST (`0xcb00ba2cab67a3771f9ca1fa48fda8881b457750`) + +``` +Token Out: WKAIA (`0x043c471bEe060e00A56CcD02c0Ca286808a5A436`) +``` + + + + +\*\*テスト・トークンの取得 + +カイロス・テストネットのTESTトークンを入手する: + +- Kaiascanで[ERC20蛇口](https://kairos.kaiascan.io/address/0x78a6cacfe5d34e0566e56710c8789d207411001a?tabId=contract&page=1)を開く +- 契約タブに移動し、_契約を書く_を選択する。 +- claim(token)関数を探す +- KairosでサポートされているGAトークンのアドレスを貼り付けてください(このガイドでは、TESTのアドレスを使用してください)。 +- Query\*をクリックしてリクエストを送信します。 まもなくTESTトークンが届きます。 + +![](/img/build/tutorials/test-tokens-faucet.png) + +\*\*スマートな契約要件 + +APIはGaslessERC20PermitSwapスマート・コントラクトと相互作用する: + +- ERC20許可ベースの認可をサポート +- Uniswap V2互換DEXとの統合 +- WKAIAをネイティブKAIAに自動変換 +- セキュリティのためにスワップ上限を強制する + +\*\*ユーザー要件 + +メインネットでは、このガスレス・スワップ・サービスを利用するには、KAIAの残高がゼロでなければならない。 この要件は、オンボーディングの目的でガスなし取引が本当に必要なユーザーのみがサービスを利用することを保証する。 テストネット上では、テスト目的でこの制限が緩和されます。 + +最大スワップ額は、メインネットとテストネットの両方で1USDTに制限されています。 この機能は、ユーザーがカイアチェーンでの経験を開始するのに十分なKAIAを受け取るために設計されています。 + +## 統合ステップ + +### 完全な統合例 + +```javascript +const { JsonRpcProvider, Wallet } = require('@kaiachain/ethers-ext/v6'); +const { Contract, parseUnits, formatUnits, Signature } = require('ethers'); + +async function fetchJson(url, init) { + if (typeof fetch !== 'undefined') { + return fetch(url, init); + } + const { default: nodeFetch } = await import('node-fetch'); + return nodeFetch(url, init); +} + +const GASLESS_SWAP_ABI = [ + 'function usdtToken() view returns (address)', + 'function wkaiaToken() view returns (address)', + 'function maxUsdtAmount() view returns (uint256)', + 'function getExpectedOutput(address tokenIn, address tokenOut, uint256 amountIn) view returns (uint256)', + 'function executeSwapWithPermit(address user, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOutMin, uint256 deadline, uint8 v, bytes32 r, bytes32 s)', +]; + +const ERC20_METADATA_ABI = [ + 'function decimals() view returns (uint8)', + 'function symbol() view returns (string)', + 'function name() view returns (string)', + 'function nonces(address owner) view returns (uint256)', + 'function balanceOf(address owner) view returns (uint256)', +]; + +async function buildPermitSignature({ token, owner, spender, value, deadline, domainVersion = '1' }) { + const [name, version, network, verifyingContract, nonce] = await Promise.all([ + token.name(), + Promise.resolve(domainVersion), + owner.provider.getNetwork(), + token.getAddress(), + token.nonces(owner.address), + ]); + + const domain = { + name, + version, + chainId: Number(network.chainId), + verifyingContract, + }; + + const types = { + Permit: [ + { name: 'owner', type: 'address' }, + { name: 'spender', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'nonce', type: 'uint256' }, + { name: 'deadline', type: 'uint256' }, + ], + }; + + const message = { + owner: owner.address, + spender, + value, + nonce, + deadline, + }; + + return Signature.from(await owner.signTypedData(domain, types, message)); +} + +async function executeGaslessSwap({ + rpcUrl, + serverUrl, + userWallet, + contractAddress, + amountIn = '0.01', // Amount in USDT + slippageBps = 50, // 0.5% slippage + permitDeadlineSeconds = 600 // 10 minutes +}) { + console.log('🚀 Starting gasless swap'); + + const provider = new JsonRpcProvider(rpcUrl); + const wallet = userWallet.connect(provider); + const swap = new Contract(contractAddress, GASLESS_SWAP_ABI, provider); + + // Get token addresses from contract + const [tokenInAddress, tokenOutAddress, maxUsdtAmount] = await Promise.all([ + swap.usdtToken(), + swap.wkaiaToken(), + swap.maxUsdtAmount(), + ]); + + const tokenIn = new Contract(tokenInAddress, ERC20_METADATA_ABI, provider); + const tokenOut = new Contract(tokenOutAddress, ERC20_METADATA_ABI, provider); + + const [tokenInDecimals, tokenOutDecimals, tokenInSymbol, tokenOutSymbol] = await Promise.all([ + tokenIn.decimals(), + tokenOut.decimals(), + tokenIn.symbol(), + tokenOut.symbol(), + ]); + + const amountInWei = parseUnits(amountIn, tokenInDecimals); + + // Check if amount exceeds contract maximum + if (amountInWei > maxUsdtAmount) { + throw new Error(`Amount (${amountIn} ${tokenInSymbol}) exceeds contract cap (${formatUnits(maxUsdtAmount, tokenInDecimals)} ${tokenInSymbol})`); + } + + // Get expected output and calculate minimum with slippage + const expectedOut = await swap.getExpectedOutput(tokenInAddress, tokenOutAddress, amountInWei); + const amountOutMin = (expectedOut * BigInt(10_000 - slippageBps)) / 10_000n; + + // Create permit signature + const deadline = BigInt(Math.floor(Date.now() / 1000) + permitDeadlineSeconds); + const signature = await buildPermitSignature({ + token: tokenIn, + owner: wallet, + spender: contractAddress, + value: amountInWei, + deadline, + }); + + // Prepare API payload + const payload = { + swap: { + user: wallet.address, + tokenIn: tokenInAddress, + tokenOut: tokenOutAddress, + amountIn: amountInWei.toString(), + amountOutMin: amountOutMin.toString(), + deadline: deadline.toString(), + }, +permitSignature: signature.serialized, + }; + + console.log('From:', wallet.address); + console.log('Swap amount:', formatUnits(amountInWei, tokenInDecimals), tokenInSymbol); + console.log('Minimum out:', formatUnits(amountOutMin, tokenOutDecimals), tokenOutSymbol); + + // Check balance before swap + const balanceBefore = await provider.getBalance(wallet.address); + + // Call the API + const response = await fetchJson(`${serverUrl}/api/gasFreeSwapKaia`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + + const result = await response.json().catch(() => ({})); + console.log('HTTP status:', response.status); + console.log('Response:', JSON.stringify(result, null, 2)); + + if (response.ok && result.status) { + console.log('🎉 Gasless swap request succeeded'); + + // Check balance after swap + const balanceAfter = await provider.getBalance(wallet.address); + console.log('Balance before:', formatUnits(balanceBefore, 18), 'KAIA'); + console.log('Balance after:', formatUnits(balanceAfter, 18), 'KAIA'); + console.log('Balance difference:', formatUnits(balanceAfter - balanceBefore, 18), 'KAIA'); + + return result; + } else { + console.error('❌ Gasless swap request failed'); + throw new Error(`Swap failed: ${result.data || result.message || 'Unknown error'}`); + } +} + +// Usage example +async function main() { + try { + const userWallet = new Wallet('your_private_key'); + + const result = await executeGaslessSwap({ + rpcUrl: 'https://public-en-kairos.node.kaia.io', + serverUrl: 'https://fee-delegation-kairos.kaia.io', + userWallet: userWallet, + contractAddress: '0xaaFe47636ACe87E2B8CAaFADb03E87090277Ff7B', + amountIn: '0.002', + slippageBps: 50, + }); + + console.log('Transaction hash:', result.data.hash); + } catch (error) { + console.error('💥 Swap failed:', error.message); + } +} + +main(); +``` + +## APIリファレンス・エンドポイント + +- URL:/api/gasFreeSwapKaia\`。 +- メソッドPOST +- コンテントタイプ:application/json + +### リクエスト・ボディ + +```javascript +{ + "swap": { + "user": "0x742d35Cc6635C0532925a3b8D400e6D2A4b8E0bb", + "tokenIn": "0xcb00ba2cab67a3771f9ca1fa48fda8881b457750", + "tokenOut": "0x043c471bEe060e00A56CcD02c0Ca286808a5A436", + "amountIn": "1000000", + "amountOutMin": "950000000000000000", + "deadline": "1699123456" + }, + "permitSignature": "0x…65-byte signature string…" +} +``` + +### パラメータ + +**swap**(オブジェクト、必須): + +- user (文字列):許可証に署名したトークン所有者のアドレス +- tokenIn (文字列):入力トークンのアドレス (設定されたUSDTアドレスと一致する必要があります) +- tokenOut (文字列):出力トークンのアドレス(設定されたWKAIAアドレスと一致しなければならない) +- amountIn (string):文字列としての入力トークンの量 (ウェイ/最小単位) +- amountOutMin (文字列):予想される最小出力トークン (スリッページ保護) +- deadline (文字列):許可期限とスワップ期限の Unix タイムスタンプ (秒)。 + +**permitSignature**(文字列、必須): + +- 65バイトの有効な16進文字列でなければならない。 +- シリアル化されたERC20許可署名を含む + +### 応答フォーマット + +#### サクセス・レスポンス (200) + +```javascript +{ + "message": "Request was successful", + "data": { + "_type": "TransactionReceipt", + "blockHash": "0x2a7ae196f6e7363fe3cfc79132c1d16292d159e231d73b4308f598a3222d1f57", + "blockNumber": 191523443, + "contractAddress": null, + "cumulativeGasUsed": "215000", + "from": "0x6C4ED74027ab609f506efCdd224041c9F5b5CDE1", + "gasPrice": "25000000000", + "gasUsed": "215000", + "hash": "0x0ca73736ceecf2dcf0ec2e1f65760d0b4f7348726cb9a0477710172b1dd44350", + "status": 1, + "to": "0x45bD04d5f14DD9AB908109cFEa816F758FaE6709", + "type": 49, + "feePayer": "0x1234567890abcdef1234567890abcdef12345678", + "feePayerSignatures": ["0x..."], + "logs": [ + { + "address": "0x...", + "topics": ["0x..."], + "data": "0x..." + } + ] + }, + "status": true, + "requestId": "req_abc123def456" +} +``` + +#### エラー応答 + +**400 Bad Request - Validation Errors:**」。 + +```javascript +{ + "message": "Bad request", + "data": "Permit deadline has expired", + "error": "BAD_REQUEST", + "status": false, + "requestId": "req_error_123" +} +``` + +**400 Bad Request - Transaction Revert:**. + +```javascript +{ + "message": "Bad request", + "data": "execution reverted: Permit already used", + "error": "BAD_REQUEST", + "status": false, + "requestId": "req_revert_456" +} +``` + +\*\*500内部サーバーエラー + +```javascript +{ + "message": "Internal server error", + "data": "Sending transaction was failed after 5 try, network is busy. Error message: Network timeout", + "error": "INTERNAL_ERROR", + "status": false, + "requestId": "req_error_789" +} +``` + +## エラー処理 + +### よくあるエラーのシナリオ + +| エラー | HTTPステータス | 説明 | ソリューション | +| -------------- | --------- | ---------------------------------- | -------------------------------------------------- | +| 必須フィールドの欠落 | 400 | _swap_または_permitSignature_が見つからない。 | 必要なパラメータをすべて含める | +| KAIAの残高 | 400 | KAIAの残高がゼロであること | KAIAの残高がゼロの方のみご利用いただけます。 | +| 無効な署名形式 | 400 | 許可署名が有効な16進文字列ではない | 有効な65バイトの16進数署名を提供する | +| 無効なアドレス | 400 | 不正なイーサリアムアドレス | アドレスが有効かどうかを検証する | +| サポートされていないトークン | 400 | トークンが許可リストにない | 設定されたトークンアドレスのみを使用する | +| 期限切れ | 400 | 過去の許可期限 | 未来のタイムスタンプを使う | +| 金額が大きすぎる | 400 | 契約の上限を超える | 契約書の\*maxUsdtAmount()\*をチェックする。 | +| 見積もり不足 | 400 | スリッページが厳しすぎる | スリップの許容範囲を広げるか、量を減らす | +| ガソリン価格が高すぎる | 400 | ネットワークの混雑 | ガソリン価格が下がるのを待つ | +| ネットワーク・タイムアウト | 500 | RPCプロバイダーの問題 | 遅延後の再試行要求 | + +## セキュリティへの配慮 + +### ガス料金保護 + +APIは過剰なコストを防ぐため、ガス価格が50gweiを超えると取引を拒否する。 ガス料金を監視し、混雑時には利用者に知らせる。 + +### 署名セキュリティ + +- 許可証の署名を再利用しない +- 常に妥当な期限を守る(5~30分) +- 署名前にすべてのパラメータを検証する +- すべてのAPI通信にHTTPSを使用する + +## スマート・コントラクトの詳細 + +### ガスレスERC20PermitSwap契約アドレス + + + + ``` + 0x45bD04d5f14DD9AB908109cFEa816F758FaE6709 + ``` + + + + ``` + 0xaaFe47636ACe87E2B8CAaFADb03E87090277Ff7B + ``` + + + +### 主な機能 + +**executeSwapWithPermit** - 許可署名を使用して、ガスなしスワップを実行する: + +- パーミットとスワップ・パラメーターの検証 +- 許可証を使用したトークンの移動 +- DEXスワップ実行 +- WKAIAをネイティブKAIAに変換 +- ネイティブのKAIAをユーザーに送信 + +**getExpectedOutput** - 期待出力量を取得するビュー関数: + +```javascript +function getExpectedOutput( + address tokenIn, + address tokenOut, + uint256 amountIn +) external view returns (uint256) +``` + +### 契約限度額 + +- 1スワップあたりの最大USDT1,000,000(1USDTで小数点以下6桁まで) +- 対応ペアUSDT → WKAIA → ネイティブKAIA +- シグネチャ追跡によるリプレイ防止 + +## その他のリソース + +- [ERC20 Permit Standard (EIP-2612)](https://eips.ethereum.org/EIPS/eip-2612) +- [カイア・イーサス・エクステンション](https://github.com/kaiachain/ethers-ext) + + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md new file mode 100644 index 000000000000..b804a6fd58da --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md @@ -0,0 +1,352 @@ +# カイアMEVオークションSDK検索ガイド + +[カイアv2.1.0](https://github.com/kaiachain/kaia/releases/tag/v2.1.0)はMEVオークションシステムを導入し、検索者がMEVの機会に対して公正で透明なオークションに参加できるようにした。 このガイドでは、Kaia MEV Auction SDK を使用したサーチャーワークフローの包括的なウォークスルーを提供します。 + +:::info + +このガイドでは、Kairosテストネットのエンドポイントと契約アドレスを使用しています。 メインネットの立ち上げは2025年12月中旬を予定している。 メインネットにデプロイする場合は、すべてのエンドポイントと契約アドレスを適宜更新してください。 + +::: + +サーチャーのワークフローは主に4つのステップからなる: + +![](/img/build/tutorials/searcher-guide-1.png) + +1. **デポジット**:オークション参加者はKAIAトークンを `AuctionDepositVault` に預け、入札資金を調達する。 +2. **入札**:オークショニアに入札書を提出し、バックランの枠を競う。 +3. \*\*落札価格を送信する:オークショニアは落札者を決定し、落札価格をコンセンサスノード(CN)に転送する。 +4. **落札取引の実行**:CNは`AuctionEntryPoint`契約を通じて落札取引を実行する。 + +詳細な技術的背景については、[KIP-249](https://kips.kaia.io/KIPs/kip-249)を参照のこと。 + +## 前提条件 + +開始する前に、以下を確認してください: + +- KAIAトークンが入金されたウォレット +- SDK サンプル用に [Go](https://golang.org/) をインストール (バージョン 1.25+) +- Kaiaネットワークエンドポイントへのアクセス(本ガイドではKairos testnetを使用) +- (オプション) [Foundry](https://getfoundry.sh/) インストール済み (`cast` コマンド用) + +**オークショニア・エンドポイント:**\*。 + +- カイロス(テストネット):https://auctioneer-kairos.kaia.io\` +- メインネットhttps://auctioneer.kaia.io\` + +\*\*エクスプローラー・エンドポイント + +- カイロス(テストネット):https://mev-kairos.kaia.io\` +- メインネットhttps://mev.kaia.io\` + +**ネットワーク・エンドポイント:**\*。 + +- カイロス(テストネット):https://public-en-kairos.node.kaia.io\` +- メインネットhttps://public-en.node.kaia.io\` + +**契約住所(カイロス):**\*。 + +- AuctionFeeVault: `0xE4e7d880786c53b6EA6cfA848Eb3a05eE97b2aCC` +- AuctionDepositVault: `0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc` +- AuctionEntryPoint: `0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480` + +メインネットの契約アドレス(メインネット開設後に利用可能)については、[契約アドレス](../../references/contract-addresses.md)を確認してください。 + +:::tip[Monitor MEVの機会]。 + +検索者は、以下の方法で有益な取引を特定することができる: + +- **オークショニアの保留中のトランザクションAPI**に加入すること:この API はコンセンサス・ノードから直接トランザクションをストリーミングするため、MEV の機会をリアルタイムで検出することができます。 以下の[未決済取引の登録](#step-3-subscribe-to-pending-transactions)のセクションを参照。 +- \*\*ネットワークメンプールを独立に監視する:独自の MEV 機会検出ロジックを実装する。 + +::: + +## ステップ1:資金の入金 + +![](/img/build/tutorials/searcher-guide-2.png) + +AuctionDepositVault\`には入札残高が保管されます。 手付金は、入札金額と入札執行にかかるガス料金の見積額の両方をカバーする必要があります。 + +### 預金要件を理解する + +預金残高でカバーすること: + +- **入札金額**:KAIA: 落札時にお支払いいただく金額です。 +- **見積ガス料金**:入札執行時のガス消費量(執行後に差し引かれ、ブロック提案者に送付される) + +:::warning[Always 十分な預金残高の維持] + +残高不足の場合、オークショニアは入札を却下します。 + +::: + +### 入金方法 + +この契約では、2つの入金方法が用意されている: + +**メソッド1: `deposit()`**. + +送金人の残高を使って入金する。 入金は送金人の口座に入金される。 + +```bash +# Deploy deposit of 200 KAIA +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "deposit()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 --value 200000000000000000000 +``` + +**メソッド2: `depositFor(アドレス検索者)`**。 + +他の口座の代理預金。 1つのソースから複数の検索者のアドレスに資金を供給するのに便利です。 + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "depositFor(address)" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 --value 200000000000000000000 +``` + +### 残高の確認 + +現在の預金残高を照会します: + +```bash +cast call 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "depositBalances(address)(uint256)" --rpc-url "https://public-en-kairos.node.kaia.io" +``` + +詳細な入金例については、[DEPOSIT.md ガイド](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/DEPOSIT.md) を参照のこと。 + +## ステップ2:入札書の提出 + +![](/img/build/tutorials/searcher-guide-3.png) + +有益な取引を見つけたら、オークショニアに入札を行う。 入札は封印され(オークションが終了するまで隠される)、入札額に基づいて競われる。 + +### 入札構成 + +入札は以下のフィールドで構成される([types.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/types.go)で定義されている): + +```go +type AuctionBid struct { + TargetTxRaw []byte // Raw transaction bytes of target tx + TargetTxHash common.Hash // Transaction to backrun + BlockNumber *big.Int // Target block number + Sender common.Address // Your searcher address + To common.Address // Contract to call + Nonce uint64 // Current nonce from AuctionEntryPoint + Bid *big.Int // Your bid in KAIA + CallGasLimit uint64 // Gas limit for your backrun logic + Data []byte // Encoded function call + SearcherSig []byte // EIP-712 signature from searcher +} +``` + +:::info + +オークショニアは、落札した入札をコンセンサスノードに転送する前に、入札の有効性を確認し、独自の署名 (`AuctioneerSignature`) を追加する。 必要なのは`SearcherSig`(あなたのEIP-712署名)のみです。 + +::: + +### 入札の提出 + +SDKは[`example/submitbid.go`](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go)で完全な動作例を提供しています。 この例はそれを示している: + +- オークショニアとの HTTPS 接続の確立 +- ENエンドポイントからの新しいブロックの検出 +- ターゲット取引と対応する入札の生成 +- オークショニアへの入札の提出 + +**Action Required**:実行する前に、コード内の秘密鍵を置き換えてください。 ソースコードの`TODO:`コメントをチェックする。 + +例題を実行する: + +```bash +# From repository root +go run example/submitbid.go +``` + +### 入札の検証 + +オークショニア、プロポーザ、スマートコントラクトは、それぞれ入札に対して特定の検証チェックを行う。 主な検証ルールは以下の通り: + +- **ブロック番号**:currentBlockNumber + 1 または currentBlockNumber + 2 でなければならない。 +- \*\*入札金額0より大きく、利用可能な預金残高以下でなければなりません。 +- **コールデータサイズ**:BidTxMaxDataSize\`(64KB)を超えてはならない。 +- **コールガス制限**:BidTxMaxCallGasLimit\`(10,000,000)を超えてはならない。 +- **nonce**:AuctionEntryPoint\` の現在の nonce と一致しなければならない。 と問い合わせる: + ```bash + cast call 0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480 "nonces(address)(uint256)" --rpc-url "https://public-en-kairos.node.kaia.io" + ``` +- **署名**:有効なEIP-712署名でなければならない(実装については[submitbid.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go)を参照のこと)。 +- **保証金の範囲**:入札金額+見積りガス料金\`をカバーする十分な保証金があること。 +- **独自性**:同じブロック内に他の落札者がいることはできません(同じ取引を対象としている場合を除く) +- **オークショニアの署名**:有効なもの(提出後にオークショニアが追加します) + +どのエンティティがどのチェックを行うかを示す完全なバリデーションマトリックスについては、[入札バリデーションガイド](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/bid_validation.md)を参照のこと。 + +## ステップ 3: 未決済取引の登録 + +![](/img/build/tutorials/searcher-guide-4.png) + +オークショニアは、保留中のトランザクションをコンセンサスノードから直接ストリーミングするWebSocketサブスクリプションサービスを提供する。 これにより、検索者はリアルタイムでMEVの機会を検出することができる。 + +SDKは[example/subscribe_pendingtx.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/subscribe_pendingtx.go)で完全な例を提供しています。 + +この例はそれを示している: + +- オークショニアへの WebSocket 接続の確立 +- 保留中のトランザクションストリームに加入する +- トランザクションを処理してMEVの機会を特定する + +例題を実行する: + +```bash +# From repository root +go run example/subscribe_pendingtx.go +``` + +サブスクリプションは、保留中のトランザクションが検出されると、トランザクショ ンハッシュを継続的に表示する。 この例を拡張して、独自の MEV 検出ロジックを実装することができます。 + +## ステップ4:実行を理解する + +あなたの入札が落札されると、Consensus Node は `AuctionEntryPoint` 契約を通じて入札を実行する: + +![](/img/build/tutorials/searcher-guide-1.png) + +### 実行フロー + +実行プロセスは3つのフェーズからなる: + +1. **検証段階**:契約は、ブロック番号、署名、ノンス、入札金額を検証する。 +2. \*\*入札支払段階入札金額が保証金から差し引かれ、エコシステム基金に送金される。 +3. **執行フェーズ**:あなたのバックランはエントリーポイント契約によって執行されます(執行結果に関係なく入札の支払いが行われます)。 + +**主要なセキュリティ機能:**\* + +- バリデーターが入札を代行(支払いを逃れるための入札取り消しを防止) +- ノンス・インクリメントがリプレイ攻撃を防ぐ +- 二重署名(サーチャー+オークショニア) 不正な入札の差し替えまたは操作 +- 入札代金はバックランの執行結果に関係なく発生する。 + +詳細な実行フローについては、[ENTRYPOINT.md ガイド](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/ENTRYPOINT.md) を参照。 + +## ステップ5:資金の引き出し + +![](/img/build/tutorials/searcher-guide-5.png) + +退会には、ロック期間付きの2段階の手続きが必要です: + +### 1. 積立金の取崩し + +引き出しを開始し、60秒のロック期間を開始する: + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "reserveWithdraw()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 +``` + +### 2. 完全脱退 + +60秒後、予約分を送金する: + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "withdraw()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 +``` + +:::info[Security 注]。 + +ロック期間付きの2段階引き出しプロセス: + +- オークション開催期間中のフラッシュ終了を防止 +- 検索者が入札を守るようにすることで、プロトコルの整合性を維持します。 +- 急激な資本操作攻撃からの保護 + +::: + +## APIリファレンス + +オークショニアは、検索者に2つの主要なAPIを提供する: + +**1. 入札API**の提出 + +- **エンドポイント**:POST/api/v1/auction/send\`。 +- \*\*目的MEVの機会に対する入札書の提出 + +\*\*2. 未決済取引のサブスクリプション + +- \*\*エンドポイントGET /api/v1/subscriber/pendingtx`: `GET /api/v1/subscriber/pendingtx\`. +- \*\*目的コンセンサスノードからの保留トランザクションのリアルタイムストリーム +- \*\*例subscribe_pendingtx.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/subscribe_pendingtx.go) の実装例を参照してください。 + +**完全なAPIドキュメンテーション:**。 + +- OpenAPI (Swagger)のスペックは下記で入手可能: + - **カイロス**: https://auctioneer-kairos.kaia.io/docs + - \*\*メインネットメインネット立ち上げ後に利用可能 +- APIの使い方:[APIドキュメント](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/api_doc.md) + +## トラブルシューティング + +### よくある問題 + +| 課題カテゴリー | 症状 | 原因 | ソリューション | +| ------------- | ------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| \*\*残高不足 | オークショニアによる入札拒否 | デポジット残高が入札額+ガス代の見積額をカバーしていない | depositBalances()\`で残高を確認し、さらにKAIAを入金する。 | +| \*\*ノンス・ミスマッチ | 入札が拒否された、または執行に失敗した | Nonce が `AuctionEntryPoint` の現在の nonce と一致しない。 | 各ビッドの前に `nonces()` で現在の nonce を問い合わせる。 注意:noncesは実行時にのみインクリメントされ、送信時にはインクリメントされない。 | +| \*\*ブロック番号の範囲 | オークショニアによる入札拒否 | 対象ブロックが許容範囲外 `[current+1, current+allowFutureBlock]`. | ブロック番号が範囲内であることを確認する(通常は+1または+2)。 二重提出戦略についてはFAQを参照 | +| \*\*無効な署名 | オークショニアによる入札拒否 | EIP-712シグネチャの作成が正しくない | ドメインセパレータとタイプハッシュを確認する。 正しい実装については、[submitbid.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go) を参照してください。 | +| \*\*ガス・リミット問題 | 不成立または入札拒否 | CallGasLimit\`が低すぎるか、最大値(10,000,000)を超えている。 | テストネットでバックランロジックをテストし、実際のガス消費量を測定する。 | + +## よくあるご質問 + +### サブスクリプション + +\*\*Q: 検索者一人当たり、いくつの同時接続が可能ですか? + +A: 1つの検索者アドレスにつき、保留中のトランザクションのサブスクリプション接続は1つのみ許可されます。 + +\*\*Q: 契約はいつまで有効ですか? + +A: 接続は24時間後に自動的に切断されます。 ローリングアップデートが進行中の場合、接続は24時間よりも早くクローズされることがある。 + +### APIのパフォーマンスとレイテンシー + +\*\*Q: 入札時のAPI待ち時間を最小限にするにはどうすればよいですか? + +A: オークショニアはHTTPSプロトコルのL7ロードバランサーを利用しています。 最初のハンドシェイクは、ネットワークの状態によって時間を消費する。 後続の入札APIを送信する際にこの最初の遅延を回避するために、キープアライブ接続を確立することを強く推奨する。 + +\*\*Q: APIレートの制限に注意すべきですか? + +A: Auctioneer API サーバーにブロックされるのを防ぐため、`ping` API を短期間に何度も送信しないでください。 + +\*\*Q:地理的な位置はレイテンシーに影響しますか? + +A:そうだ。 オークションサーバーはGCP KR(ソウル)リージョンで稼働しています。 遅延を最小限に抑え、地理的な遅延を減らすために、地理的に近い地域でインフラをホストすることをお勧めします。 + +### 入札タイミングとブロック・ターゲティング + +\*\*Q: なぜ私の入札は時々間違ったブロック番号をターゲットにするのですか? + +A: 入札のタイミングは、CN(コンセンサス・ノード)の採掘時間に大きく影響されます。 オークションの開始が遅い場合(採掘時間に近い場合)、入札取引は次のブロックの後に挿入される(ブロック番号は+1ではなく+2)。 つまり、ターゲット・ブロックの番号を+2に設定する必要がある。 + +\*\*Q: 入札倍率を上げるにはどうすればよいですか? + +A: ターゲットブロック番号はCNの採掘スケジュールに本質的に敏感です。もしあなたがブロック+2をターゲットにしていても、トランザクションが先の処理のためにブロック+1で挿入された場合、入札は失敗します。 そのため、ターゲットブロック番号を+1にして1回、ターゲットブロック番号を+2にして1回の計2回、入札取引を送信することで、包含確率を最大化することをお勧めします。 + +## ベストプラクティス + +- **預金残高の管理**:複数の入札をカバーするために十分な残高を維持する +- \*\*Nonceは慎重に扱ってください:入札前に常に最新のnonceを問い合わせること +- **検出の最適化**:MEV検出の高速化により競争優位性が向上 +- **カイロスでのテスト**:メインネット展開の前にテストネットで戦略を検証する +- **結果のモニター**:MEVエクスプローラーでオークションの結果を追跡し、入札戦略を練り直す +- **適切なガス制限**を設定します:十分なガス量とコスト効率のバランス + +## リソース + +- [SDKリポジトリ](https://github.com/kaiachain/auctioneer-sdk) +- [KIP-249仕様](https://kips.kaia.io/KIPs/kip-249) +- [コード例](https://github.com/kaiachain/auctioneer-sdk/tree/dev/example) +- APIドキュメント:[auctioneer-kairos.kaia.io/docs](https://auctioneer-kairos.kaia.io/docs) (Kairos), TBU (Mainnet) +- MEVエクスプローラー[mev-kairos.kaia.io](https://mev-kairos.kaia.io) (Kairos), TBU (メインネット) +- [よくある質問](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/FAQ.md) + +## ヘルプを得る + +問題や質問については + +- カイア・デブフォーラム](https://devforum.kaia.io)に投稿する +- SDKリポジトリ](https://github.com/kaiachain/auctioneer-sdk/issues)にissueを登録してください。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md new file mode 100644 index 000000000000..173958876efc --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md @@ -0,0 +1,325 @@ +# Pythを使ってカイアのリアルタイム価格を取得する方法 + +## はじめに + +Pythは分散型オラクルネットワークであり、プッシュ型オラクルが主流のエコシステムにおいて、独自のアプローチをとっている。 Pythは、一定間隔でデータを契約にプッシュする代わりに、オンデマンドで実世界のデータを引き出すことができます。 このモデルにより、開発者はよりコントロールしやすくなり、不必要なオンチェーン更新を避けることができる。 この統合により、開発者はリアルタイムのデータを取得し、更新が要求された場合にのみ料金が発生する従量課金モデルを使用することができる。 + +このガイドでは、Pythのリアルタイム価格フィードを使って、不換紙幣であるIDRの価値を読み取る方法を学びます。 Solidityスマートコントラクトは[pyth-sdk-solidity](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity)を使用してPythからUSD/IDR価格を取得し、[hermes-client](https://github.com/pyth-network/pyth-crosschain/tree/main/apps/hermes/client/js)を使用して最新の価格を更新して取得します。 + +手始めに、このチュートリアルの完全なコードを[GitHub](https://github.com/ayo-klaytn/pyth-kaia-hardhat-example)でご覧ください。 これは、すぐに使えるリファレンスを提供し、プロジェクトとインストールをより迅速にセットアップするのに役立ちます。 + +## 前提条件 + +作業を始める前に、以下のものが揃っていることを確認してください: + +- [Node.js と npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) + + 依存関係のインストールと開発ツールの実行に必要。 + +- KAIA testnetトークンで資金調達されたウォレット。 + + カイロス・テストネットの展開費用と取引ガス料金をKAIAに支払う必要があります。 KAIA蛇口](https://faucet.kaia.io/)から無料テストネットKAIAをリクエストすることができます。 + +## 開発環境の構築 + +このセクションでは、開発環境のセットアップ、オラクル・コントラクトのコンパイル、およびHardhatを使用したデプロイの準備を行います。 + +**1. ハードハット・プロジェクト**を作成する + +プロジェクト用に新しいディレクトリを作成し、Hardhatを初期化する: + +```bash +mkdir pyth-kaia-hardhat-example && cd pyth-kaia-hardhat-example +npm init -y +npx hardhat@next --init +``` + +プロンプトが表示されたら、デフォルトの応答を受け入れる。 このガイドでは、モカとイーサーのテンプレートを使用する。 + +Hardhatのバージョンを確認して、インストールを確認してください: + +```bash +npx hardhat --version +``` + +**2. 暗号化された秘密を設定**する + +これで、Hardhatの暗号化されたキーストアを使用して、RPC URLと秘密鍵が保存されます。 + +以下のコマンドを実行する: + +```bash +npx hardhat keystore set KAIROS_RPC_URL +npx hardhat keystore set PRIVATE_KEY +``` + +暗号化された状態を保つため、各変数には必ずパスワードと値を入力してください。 + +**3. コンフィギュレーション・ファイル**における参照秘密 + +hardhat.config.ts\`を開き、暗号化された秘密を参照するようにnetworksセクションを更新する。 異なるシークレット名を使用した場合は、それに応じてキーを更新する。 + +```typescript +import { configVariable } from "hardhat/config"; +module.exports = { + networks: { + kairos: { + url: configVariable("KAIROS_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + }, +}; +``` + +## 契約の作成とPythオラクルからの価格の取得 + +このセクションでは、[Pyth Solidity SDK](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity)をインストールし、PriceConsumerコントラクトを作成し、Hardhatを使用してデプロイします。 このコントラクトはPythの価格フィードを読み込み、後でエルメスから取得した価格データを使って更新する。 + +### Pyth SDKをインストールする + +PythはSolidity SDKを提供し、オンチェーンのPyth価格フィードコントラクトとやり取りすることができます。 SDKはIPythインターフェースと関連する構造体を公開しています。 + +SDKをnpmでインストールする: + +```bash +npm install --save-dev @pythnetwork/pyth-sdk-solidity +``` + +### PriceConsumerコントラクトの作成 + +contracts/PriceConsumer.sol\`に新しいファイルを作成し、以下のコードを追加する: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; +import "@pythnetwork/pyth-sdk-solidity/IPyth.sol"; +import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol"; +contract PriceConsumer { + IPyth public pyth; + constructor(address pythContract) { + pyth = IPyth(pythContract); + } + function updatePrice(bytes[] calldata priceUpdateData) + external + payable + { + // Pay the Pyth fee for receiving price updates + uint fee = pyth.getUpdateFee(priceUpdateData); + require(msg.value >= fee, "Not enough fee sent"); + // Update the Pyth price state + pyth.updatePriceFeeds{value: fee}(priceUpdateData); + // Can fetch the price and use it as well + //PythStructs.Price memory currentBasePrice = pyth.getPriceNoOlderThan(priceFeedId, 60); + } + function getLatestPrice(bytes32 priceFeedId) public view returns (int64, int32) { + // Read the current price from a price feed if it is less than 60 seconds old. + // Each price feed (e.g., USD/IDR) is identified by a price feed ID. + // The complete list of feed IDs is available at https://docs.pyth.network/price-feeds/price-feeds + PythStructs.Price memory currentBasePrice = pyth.getPriceNoOlderThan(priceFeedId, 60); + + // uint256 basePrice = PythUtils.convertToUint( + // currentBasePrice.price, + // currentBasePrice.expo, + // 18 + // ); + + return (currentBasePrice.price, currentBasePrice.expo); + } +} +``` + +\*\*ウォークスルー + +PriceConsumer契約: + +- Pyth のインターフェースと構造体を `@pythnetwork/pyth-sdk-solidity` からインポートします。 +- 店舗: + - Pythコントラクトのインスタンス(pyth)。 + - USD / IDR の価格フィード ID (usdIdrPriceId)。 +- updateAndGetUsdIdrPrice\` を公開する: + - IPyth.getUpdateFeeを使用して更新料を計算する。 + - IPyth.updatePriceFeedsに必要な料金を入力する。 + - IPyth.getPriceNoOlderThanを呼び出し、新しいUSD/IDR価格を読み込む。 + - 生の価格、指数、発行時間を返します。 + +後で、あなたのオフチェーンHermesクライアントはpriceUpdateバイト配列を構築し、あなたが新鮮な価格を必要とするときにこの関数にそれを渡します。 + +### 契約書をまとめる + +以下のコマンドを実行して、コントラクトをコンパイルする: + +``` +npx hardhat compile +``` + +## 契約の展開 + +PriceConsumerコントラクトをデプロイするには、Ignitionモジュールを作成し、デプロイコマンドを実行します。 + +\*\*イグニッションモジュールを作成する。 + +ignition/modules/PriceConsumer.ts\`に新しいファイルを作成する: + +```typescript +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const pythContractAddress = "0x2880ab155794e7179c9ee2e38200202908c17b43"; +export default buildModule("PriceConsumerModule", (m) => { + const priceConsumer = m.contract("PriceConsumer", [pythContractAddress]); + return { priceConsumer }; +}); +``` + +\*\*契約の展開 + +Ignitionモジュールを使用して、PriceConsumerコントラクトをKairos testnetにデプロイします: + +```bash +npx hardhat ignition deploy --network kairos ignition/modules/PriceConsumer.ts +``` + +プロンプトが表示されたら、暗号化された秘密のために先ほど設定したキーストアのパスワードを入力します。 + +これが完了すると、あなたの`PriceConsumer.sol`コントラクトはKairosテストネットにデプロイされ、PythからリアルタイムのUSD / IDR価格を消費する準備が整います。 + +## TypeScriptからの対話 + +この最後のステップでは、TypeScriptを使用して、デプロイしたPriceConsumerコントラクトと対話します。 このスクリプトは、Hermesクライアントを介してPyth価格更新データを要求し、それをオンチェインで送信することによって、最新のUSD/IDR価格を取得します。 + +\*\*依存関係のインストール + +必要なパッケージをインストールする: + +```bash +npm install --save-dev tsx @pythnetwork/hermes-client @dotenv +``` + +**.env**の設定 + +プロジェクトのルート・ディレクトリに.envファイルを作成し、秘密鍵を追加する: + +```bash +PRIVATE_KEY="0xDEAD....." // REPLACE WITH YOUR PRIVATE KEY +``` + +\*\*インタラクション・スクリプトを作成する。 + +scripts/interact.ts\*\*に新しいファイルを作成し、以下を追加する: + +```typescript +import { HermesClient } from "@pythnetwork/hermes-client"; +import { ethers } from "ethers"; +import 'dotenv/config' + +// 1. Setup +const hermes = new HermesClient("https://hermes.pyth.network"); +const provider = new ethers.JsonRpcProvider( + "https://public-en-kairos.node.kaia.io" +); + +const PK = process.env.PRIVATE_KEY; +const wallet = new ethers.Wallet(PK, provider); + + +// 2. Your deployed contract +const priceConsumerAddress = "0x91e89aa32224dEd5dA483a83a4de45bF4bE57caA"; // REPLACE WITH DEPLOYED PRICE CONSUMER CONTRACT + +const priceConsumerAbi = [ + "function updatePrice(bytes[] priceUpdateData) external payable", + "function getLatestPrice(bytes32 priceId) public view returns(int64, int32)", +]; + +const priceConsumer = new ethers.Contract( + priceConsumerAddress, + priceConsumerAbi, + wallet +); + +// 3. Price feed IDs +const priceId = + "0x6693afcd49878bbd622e46bd805e7177932cf6ab0b1c91b135d71151b9207433"; // FX.USD/IDR Beta Price Feed ID + +async function run() { + // Fetch Hermes price update binary + const update = await hermes.getLatestPriceUpdates([priceId], { + encoding: "hex", + }); + console.log(update); + + const priceUpdateData = ["0x" + update.binary.data]; // must be array of bytes + + console.log(priceUpdateData); + + // Estimate fee required by Pyth contract + // EVM Network Price Feed Contract Addresses: https://docs.pyth.network/price-feeds/core/contract-addresses/evm + + const pythContractAddress = "0x2880ab155794e7179c9ee2e38200202908c17b43"; + const pythAbi = [ + "function getUpdateFee(bytes[] calldata data) external view returns(uint)", + ]; + console.log("Pyth contract address:", pythContractAddress); + const pyth = new ethers.Contract(pythContractAddress, pythAbi, wallet); + const fee = await pyth.getUpdateFee(priceUpdateData); + console.log("Pyth fee:", fee.toString()); + + // Call your contract + const tx = await priceConsumer.updatePrice(priceUpdateData, { + value: fee, // pay the pyth update fee + gasLimit: 500000, + }); + console.log("Tx sent:", tx.hash); + const receipt = await tx.wait(); + console.log("Tx confirmed"); + console.log(receipt); + + // 4. Get latest price from contract + try { + console.log("=== Latest Price from Contract ==="); + const [price, expo] = await priceConsumer.getLatestPrice(priceId); + console.log("Price Value : " + price.toString()); + console.log("Exponent Value : " + expo.toString()); + } catch (error) { + console.log(error); + // @ts-ignore + console.error("\nError calling getLatestPrice:", error.message); + console.log( + "This usually means the price is older than 60 seconds or hasn't been updated yet." + ); + console.log("Make sure updatePrice() was called successfully first."); + } +} +run(); + +``` + +\*\*スクリプトの実行 + +でスクリプトを実行する: + +```bash +npx tsx scripts/interact.ts +``` + +\*\*出力例 + +```bash +Tx sent: 0x79c5dcb7abd9605b070bf9062ba2e2382272d23d58f7b50446c3107b7784fc8e +Tx confirmed +=== Latest Price from Contract === +Price Value : 1669784988 +Exponent Value : -5 +======== —— ========= +``` + +Kairos explorerの検索バーに取引ハッシュをペーストすることで、取引を確認することができます。 これにより、更新と読み取り操作が成功したことが確認される。 + +## 結論 + +このチュートリアルでは、Pythからリアルタイムの価格を読み取るSolidityコントラクトを作成し、Kairosテストネットにデプロイし、Hermesクライアントを使用して対話しました。 また、Pythのプルベースの設計が、価格更新のタイミングや方法をどのようにコントロールできるかを学びました。 + +詳しくは、こちらをご覧いただきたい: + +- [EVM契約リファレンス](https://api-reference.pyth.network/price-feeds/evm/getPriceNoOlderThan) for Pyth API +- [Pyth Oracle AMMの例](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/evm)完全なエンド・ツー・エンドの実装について + + + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md b/i18n/ja/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md index eae45b4bf57c..96bae4423860 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md @@ -190,33 +190,44 @@ Kaiaは1秒のブロック時間を維持することを目標としているの | TSTORE | 280 | | TLOAD | 220 | | MCOPY | 250 | +| シーエルゼット | 0 | ## Precompiled contracts computation cost table `Input` is a byte array input of a precompiled contract. -| Address | Precompiled contracts | Computation Cost | -| :------ | :-------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 0x01 | ecrecover | 113,150 | -| 0x02 | sha256hash | numOfWords(input) / 32 \* 100 + 1,000 | -| 0x03 | ripemd160hash | numOfWords(input) / 32 \* 10 + 100 | -| 0x04 | dataCopy | 0 | -| 0x05 | bigModExp | コードは[こちら](https://github.com/kaiachain/kaia/blob/75c149a464998eb946311f3a290d4b1ea339eaba/blockchain/vm/contracts.go#L340) | -| 0x06 | bn256Add | 8,000 | -| 0x07 | bn256ScalarMul | 100,000 | -| 0x08 | bn256Pairing | numOfPairings(input) \* 1,000,000 + 2,000,000 | -| 0x09 | blake2f | bigEndian(getRounds(input[0:4])) \* 10 + 10,000 | -| 0x0A | kzg | 2,200,000 | -| 0x3FD | vmLog | 10 | -| 0x3FE | feePayer | 10 | -| 0x3FF | validateSender | numOfSigs(input) \* 180,000 + 10,000 | +| Address | Precompiled contracts | Computation Cost | +| :------ | :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 0x01 | ecrecover | 113,150 | +| 0x02 | sha256hash | numOfWords(input) / 32 \* 100 + 1,000 | +| 0x03 | ripemd160hash | numOfWords(input) / 32 \* 10 + 100 | +| 0x04 | dataCopy | 0 | +| 0x05 | bigModExp | コードはこちら](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L586) | +| 0x06 | bn256Add | 8,000 | +| 0x07 | bn256ScalarMul | 100,000 | +| 0x08 | bn256Pairing | numOfPairings(input) \* 1,000,000 + 2,000,000 | +| 0x09 | blake2f | bigEndian(getRounds(input[0:4])) \* 10 + 10,000 | +| 0x0A | kzg | 2,200,000 | +| 0x3FD | vmLog | 10 | +| 0x3FE | feePayer | 10 | +| 0x3FF | validateSender | numOfSigs(input) \* 180,000 + 10,000 | +| 0x0b | bls12381G1Add | 18,750 | +| 0x0c | bls12381G1MultiExp | コードはこちら](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L1155) | +| 0x0d | bls12381G2Add | 30,000 | +| 0x0e | bls12381G2MultiExp | コードはこちら](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L1261) | +| 0x0f | bls12381ペアリング | numOfPairings(input) \* 1,630,000 + 1,885,000 | +| 0x10 | Bls12381MapG1 | 275,000 | +| 0x11 | Bls12381MapG2 | 1,190,000 | +| 0x100 | p256ベリファイ | 235,000 | ## Hardfork Changes -| Hardfork | New items | Changes | | | -| ------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | - | -| Cancun EVM | BLOBBASEFEE (0x49)
BLOBHASH (0x50)
TSTORE (0x5c) opcode
TLOAD (0x5d)
MCOPY (0x5e)
kzg (0x0a) precompiled contract | 計算コストの上限を引き上げる
100,000,000 から 150,000,000

いくつかのオペコードの計算コストを削減
CPU パフォーマンスの向上による
-Sdiv (0x05):739 -> 360
-Mod (0x06):812 -> 320
-Addmod (0x08):1410 -> 360
-Mulmod (0x09):1760 -> 700
-Exp (0x0A):5000 -> 720
-Sha3 (0x20): 2465 -> 560
-Mstore8 (0x53):5142 -> 230
-Log1、Log2、Log3、Log4 (0xA1-0xA4):
1000 -> 500

データベースサイズの増加により、いくつかのオペコードの計算コストが増加
-SLOAD (0x54):835 -> 2550
-SSTORE (0x55):1548 -> 2510 | | | -| Shanghai EVM | PUSH0 (0x5f) opcode | | | | -| Kore | | modExp (0x05) precompiled contract
新しいガス計算ロジックを使用。
計算コストも影響する。
より正確になる。 | | | -| London EVM | BaseFee (0x48) opcode | | | | -| Istanbul EVM | CHAINID (0x46) opcode
SELFBALANCE (0x47) opcode
blake2f (0x09) precompiled contract | 高価なオペコードの計算コストを削減
- ADDMOD (0x08):3349 -> 1410
- MULMOD (0x09):4757 -> 1760
- XOR (0x18):657 -> 454
- NOT (0x19):1289 -> 364
- SHL (0x1B): 1603 -> 478
- SHR (0x1C):1815 -> 834 | | | +| Hardfork | New items | Changes | +| ------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 大阪EVM | CLZ (0x1e) オペコード
p256Verify (0x100) コンパイル済み契約書 | modExp (0x05) precompiled contract
新しいガス計算ロジックを使用。
計算コストも影響する。
より正確になる。 | +| プラハEVM | bls12381G1Add (0x0b) コンパイル済み契約
bls12381G1MultiExp (0x0c) コンパイル済み契約
bls12381G2Add (0x0d) コンパイル済み契約
bls12381G2MultiExp(0x0e) コンパイル済み契約書
bls12381Pairing (0x0f) コンパイル済み契約書
bls12381MapG1 (0x10) コンパイル済み契約書
bls12381MapG2 (0x11) コンパイル済み契約書
| | +| Cancun EVM | BLOBBASEFEE (0x49) opcode
BLOBHASH (0x50) opcode
TSTORE (0x5c) opcode
TLOAD (0x5d) opcode
MCOPY (0x5e) opcode
kzg (0x0a) precompiled contract | 計算コストの上限を引き上げる
100,000,000 から 150,000,000

いくつかのオペコードの計算コストを削減
CPU パフォーマンスの向上による
-Sdiv (0x05):739 -> 360
-Mod (0x06):812 -> 320
-Addmod (0x08):1410 -> 360
-Mulmod (0x09):1760 -> 700
-Exp (0x0A):5000 -> 720
-Sha3 (0x20): 2465 -> 560
-Mstore8 (0x53):5142 -> 230
-Log1、Log2、Log3、Log4 (0xA1-0xA4):
1000 -> 500

データベースサイズの増加により、いくつかのオペコードの計算コストが増加
-SLOAD (0x54):835 -> 2550
-SSTORE (0x55):1548 -> 2510 | +| Shanghai EVM | PUSH0 (0x5f) opcode | | +| Kore | | modExp (0x05) precompiled contract
新しいガス計算ロジックを使用。
計算コストも影響する。
より正確になる。 | +| London EVM | BaseFee (0x48) opcode | | +| Istanbul EVM | CHAINID (0x46) opcode
SELFBALANCE (0x47) opcode
blake2f (0x09) precompiled contract | 高価なオペコードの計算コストを削減
- ADDMOD (0x08):3349 -> 1410
- MULMOD (0x09):4757 -> 1760
- XOR (0x18):657 -> 454
- NOT (0x19):1289 -> 364
- SHL (0x1B): 1603 -> 478
- SHR (0x1C):1815 -> 834 | diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md b/i18n/ja/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md index c5babdf81f8a..18ba6082e2ae 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md @@ -34,7 +34,7 @@ Kaiaの`callTracer`出力フォーマットは、以下を除いてgo-ethereumと同じである: -- Reverted取引では、両方のフィールドが提供される。 +- 逆取引の場合、両方のフィールドが提供される。 - `result.revertReason`: もしあれば、復帰理由の文字列。 - `result.reverted.contract`: 元に戻した契約のアドレス。 - `result.reverted.message`: revertReasonと同じ。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md b/i18n/ja/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md new file mode 100644 index 000000000000..e9fc0df50aa3 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md @@ -0,0 +1,107 @@ +# ストレージの最適化 + +カイア・ブロックチェーンが成長するにつれ、チェーン・データを保存するのに必要なストレージも増加する。 カイアは、この増大するストレージ要件を管理するために、主に2つのテクニックを実装している: + +## ステート・バッチ・プルーニング(ステート・マイグレーション) + +状態移行は、実行中のノードを中断することなく、既存のノードに適用できるバッチ刈り込み機能である。 + +### モチベーション + +ブロックステート(StateDB)は、オンチェーンアカウントとコントラクトをトライデータ構造に格納する。 Trieデータ構造は、古い状態と最近の状態の両方を保存するように設計されているので、Merkleハッシュを使って検証することができる。 トランザクションが状態変更を実行すると、状態トライは無限に成長する。 本稿執筆時点(2024年8月)では、カイア・メインネットのアーカイブ・ノード・サイズは20TBを超え、フル・ノードでも10TBを超えている。 + +### コンセプト + +ステート・マイグレーションは、新しいブロックの処理に必要のない古いブロック・ステートを削除する。 それは、"古い "から "新しい "へのステートトライをコピーする。 すべてのトライノードがコピーされるわけではない。 選択ブロックの状態根から到達可能なものがコピーされる。 コピー後、古いディレクトリは削除されるので、選択したブロックの状態だけが残る。 + +技術的な詳細については、以下のブログ記事をお読みください: +[ステート・マイグレーション:ノード・ストレージの節約](https://medium.com/klaytn/klaytn-v1-5-0-state-migration-saving-node-storage-1358d87e4a7a)、 +[カイア・ステート・マイグレーション:ブロックチェーン・データを削減する効率的な方法](https://medium.com/klaytn/klaytn-state-migration-an-efficient-way-to-reduce-blockchain-data-6615a3b36523) + +Batch Pruningの実行方法については、[State Migration Guide](../../misc/operation/node-pruning.md#how-to-perform-batch-pruning)を参照してください。 + +## 州ライブ剪定 + +ステート・ライブ・プルーニングは、増大するステート・データベースのサイズ問題に対する新しいソリューションである。 バッチ・プルーニング(ステート・マイグレーション)とは異なり、ライブ・プルーニングは、ノードのプロセスがブロックされると、古いステートを少しずつ自動的に削除する。 + +### モチベーション + +ブロックステート(StateDB)は、オンチェーンアカウントとコントラクトをトライデータ構造に格納する。 Trieデータ構造は、古い状態と最近の状態の両方を保存するように設計されているので、Merkleハッシュを使って検証することができる。 トランザクションが状態変更を実行すると、状態トライは無限に成長する。 本稿執筆時点(2025年8月)では、カイア・メインネットのアーカイブ・ノード・サイズは20TBを超え、フル・ノードでも10TBを超えている。 + +これまでの状態移行では、最近の状態を選択的にコピーして古い状態を削除し、残りを削除することでこの問題を軽減していた。 これにより、ノード全体のサイズを5TB未満に抑えることができる。 + +とはいえ、国家移民には欠点もある。 これは、数日かかる可能性のあるステートトライ全体を横断するという高いオーバーヘッドに悩まされる。 また、状態移行は手動でトリガーしなければならない。 これらの制限を克服するために、ライブ・プルーニング技術が導入された。 + +### コンセプト + +トライの刈り込みは、トライのノードが古いかどうかが不明なので難しい。 元のステートトライ構造では、トライノードは、それぞれが異なるブロックを構成する複数のトライの一部になることができる。 トライノード(口座残高など)が別の値に更新されても、他の親ノードがまだ必要としている可能性があるため、トライノードを削除することはできない。 この問題はハッシュ重複問題と呼ばれている。 + +ライブ・プルーニングは、同じ内容のトライノードを意図的に重複させる。 Live Pruningでは、トライノードはハッシュで参照されるのではなく、ExtHashで参照される。 ExtHashは、コンテンツの32バイトのハッシュと7バイトのシリアル・インデックスです。 直列インデックスは単調増加なので、すべてのトライノードは一意である。 + +``` +Hash: 32-byte Keccak256 +ExtHash: 32-byte Keccak256 + 7-byte Serial index +``` + +こうすることで、トライノードのコンテンツが変更されるたびに、そのトライノードは廃止されたと仮定しても問題ない。 Merkleハッシュは、直列インデックスを無視するだけで、同じように計算することができ、コンセンサスの点で非ライブ・プルーニング・ノードと互換性がある。 + +技術的な詳細については、このブログ記事をお読みください:[StateDB Live Pruningによるブロックチェーンデータ容量の効率的管理】(https://medium.com/klaytn/strong-efficient-management-of-blockchain-data-capacity-with-statedb-live-pruning-strong-6aaa09b05f91). + +ライブ・プルーニングを有効にする方法については、[ライブ・プルーニング・ガイド](../../misc/operation/node-pruning.md#how-to-perform-live-pruning)を参照してください。 + +## データ圧縮 + +データ圧縮は、LevelDB内蔵のSnappy圧縮アルゴリズムを選択したデータベーステーブルに適用することで、ブロックデータのストレージサイズを縮小します。 + +### モチベーション + +ヘッダ、トランザクションボディ、レシートからなるブロックデータは、EVMトランザクションのABIエンコーディング標準のため、多くの場合、非常に繰り返しの多いバイトシーケンスを含んでいる。 例えば、SolidityのABIエンコーディングでは、32バイトのワードアライメントを満たすためにゼロパディングが使用され、その結果、トランザクションコールデータに長いゼロが含まれることになります。 トランザクションの受信は、イベントログと戻り値に同様のパターンを示す。 + +このような自然な冗長性があるにもかかわらず、カイアの基盤となるLevelDBストレージ・エンジンはデフォルトで圧縮を利用していなかったため、反復的なデータが不必要にディスク容量を消費していた。 2025年7月現在、カイア・メインネットのフルノードは4.2TB以上のストレージを占有しており、約3.6TBが非圧縮ブロックデータに起因している。 + +### コンセプト + +Kaia v2.1.0は、LevelDBのSnappy圧縮アルゴリズムをデータベースのテーブルに選択的に適用します。 --db.leveldb.compression\`フラグを指定すると、きめ細かい制御が可能になる: + +- ヘッダー、ボディ、レシートを圧縮(冗長性が高く、大幅な節約になる) +- 州のトライデータを除外(ランダムに見える、圧縮効果は最小限) + +既存のノードでは、手動でデータベースの圧縮をトリガーすると、古い非圧縮データが圧縮形式に書き換えられる。 この "ハウスキーピング "プロセスは、SSTableをマージし、削除を調整し、副作用として圧縮を適用する。 + +\*\*結果:\*\*メインネットのフル・ノードでは、ストレージの総量が約50%削減され(~2TBの節約)、特にボディ・テーブルとレシート・テーブルで大きな効果が得られました。 この処理には約10時間かかり、通常のブロック処理と同時に実行できる。 + +技術的な詳細については、このブログ記事をお読みください:[カイアv2.1が圧縮によって2TBを取り戻すまで](https://blog.kaia.io/cutting-blockchain-storage-in-half/)。 + +圧縮を有効にする方法については、[ノードストレージの最適化ガイド](../../misc/operation/optimize-storage.md#database-compression)を参照してください。 + +## フラットトライ・ステート・スキーム(実験的) + +FlatTrieは、過去のアカウント状態の保存方法を再構築することで、アーカイブノードの状態データベースのサイズを大幅に削減する実験的な状態保存方式です。 + +### モチベーション + +アーカイブ・ノードは、すべてのブロックの高さですべてのアカウントの完全な履歴データを保持し、タイムトラベル・クエリーと包括的なブロックチェーン分析を可能にしなければならない。 2025年8月現在、カイア・メインネットのアーカイブ・ノードには35TB以上のディスク容量が必要で、そのうち31TB(89%)がステート・データベースに消費されている。 + +従来のMerkle Patricia Trie(MPT)構造は、アカウントデータ(リーフ)と、Merkleツリーを形成する中間ブランチノードの両方を格納する。 アーカイブノードはこれまで、複数のブロックの高さに対して完全なMPTを保持していたため、中間ノード(それ自身はアカウントデータを伝達しない)が無限に蓄積される原因となっていた。 + +State Migration](https://medium.com/klaytn/klaytn-v1-5-0-state-migration-saving-node-storage-1358d87e4a7a)(バッチ刈り込み)や[StateDB Live Pruning](https://medium.com/klaytn/strong-efficient-management-of-blockchain-data-capacity-with-statedb-live-pruning-strong-6aaa09b05f91)のような既存のストレージ最適化は、基本的に履歴データを削除する必要があるため、完全な履歴を保持する必要があるアーカイブノードには適用できない。 + +### コンセプト + +FlatTrieは、[Erigon Ethereumクライアント](https://github.com/erigontech/erigon/)から転用された実験的な状態保存スキームである。 それは、以下のような方法で状態記憶装置を再構築する: + +- フラットなキー・バリュー・テーブルに過去の口座状態を保存(単純な住所→口座データのマッピング) +- 最新のブロックの完全なMPTのみを、すべての中間ブランチノードで保持する。 +- 必要なブランチノードのみを一時的に構築することにより、オンデマンドで過去のMerkleルートを再構築する。 + +このアプローチでは、完全なアカウント状態の履歴とあらゆるブロックのMerkleルートを検証する能力を維持しながら、過去の中間ノードの永続的なストレージを排除する。 + +\*\*Erigonの実装はイーサリアムのアカウント構造を前提としている。 カイアは、人間が読めるアドレスや複数のキータイプといった独自の機能をサポートするため、異なるRLPエンコーディングを使用している。 この統合には、ErigonのMerkleハッシュモジュールをアカウントを不透明なバイト列として扱うように修正することと、KaiaのマルチスレッドTrieインターフェースとErigonのシングルスレッドMDBXデータベースの要件をブリッジするために3つのアダプターレイヤー(DomainsManager、WriteBuffer、DeferredContext)を作成することが必要でした。 + +**結果:** Kairosのテストネット実験では、FlatTrieアーカイブノードは、従来のアーカイブノードと比較して、総ストレージ消費量を約75%削減し、ステートデータベースのサイズを80%以上削減しました。 メインネットのアーカイブ・ノードについても、同様の節約効果が見込まれる(~35TBから~10TBへ)。 + +**制限事項:** 実験的な v2.1.0 の実装では、ブロックの巻き戻し (`debug_setHead` API) や Merkle 証明の生成 (`eth_getProof` API) や状態の刈り込み機能はサポートされていない。 これらの制限は、FlatTrieが過去のブランチノードを破棄するという設計上の選択に由来する。 + +技術的な詳細については、このブログ記事をお読みください:[カイアの実験的FlatTrie for Archive Nodes](https://blog.kaia.io/flatten-the-state-shrink-the-disk/). + +FlatTrieを有効にする方法については、[ノード・ストレージの最適化ガイド](../../misc/operation/optimize-storage.md#flattrie-state-scheme-experimental)を参照してください。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md b/i18n/ja/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md index 1a290c855613..133bef35de88 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md @@ -62,7 +62,7 @@ Magmaのハードフォーク以降、ネットワークはブロックごとに - UPPER_BOUND_BASE_FEE: The maximum value for the base fee (750 ston at the moment, can be changed later by governance) - LOWER_BOUND_BASE_FEE: The minimum value for the base fee (25 ston at the moment, can be changed later by governance) -以下は、基本料金の計算を簡略化したものである。 その本質において、基本料金の変化はGAS_TARGETとPREVIOUS_BLOCK_GAS_USEDの差に比例し、他のパラメータは基本料金の変化速度または境界を制御する。 正確な計算式は[KIP-71](https://github.com/kaiachain/kips/blob/main/KIPs/kip-71.md)を参照。 +以下は、基本料金の計算を簡略化したものである。 要するに、基本料金の変化はGAS_TARGETとPREVIOUS_BLOCK_GAS_USEDの差に比例し、他のパラメータは基本料金の変化速度や境界を制御する。 正確な計算式は[KIP-71](https://github.com/kaiachain/kips/blob/main/KIPs/kip-71.md)を参照。 ``` min(PREVIOUS_BLOCK_GAS_USED, MAX_BLOCK_GAS_USED_FOR_BASE_FEE) - GAS_TARGET diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/misc/faq.md b/i18n/ja/docusaurus-plugin-content-docs/current/misc/faq.md index d5e3172c20b3..c368ce54d894 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/misc/faq.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/misc/faq.md @@ -3,6 +3,7 @@ - [よくある質問](#faq) - [カイアとは? ](#what-is-kaia-) - [カイアはイーサリアムの等価性をどのようにサポートしていますか? ](#how-does-kaia-support-ethereum-equivalence-) + - [カイアのバージョン管理ポリシーは? ](#what-is-kaias-versioning-policy-) - [カイアのガス政策は? ](#what-is-kaias-gas-policy-) - [カイアの口座構成は特別ですか? ](#what-is-special-about-kaias-account-structure-) - [カイアのdApp開発はどこから始められますか? ](#where-can-i-start-dapp-development-with-kaia-) @@ -30,6 +31,10 @@ Kaiaは、特にアジアにおけるWeb3の大量導入のために設計され KaiaはEVM互換であり、EIP-4844 blobトランザクションを除くすべてのEthereum Cancun EVM機能をサポートしている。 これは `eth` 名前空間 RPC API を提供し、Ethereum SDK やツールをシームレスに使用できるようにします。 Kaia固有のトランザクションタイプはeth名前空間API内でタイプ0のレガシートランザクションとして表現されるため、イーサリアムSDKはそれらを認識する必要はない。 +## カイアのバージョン管理ポリシーは? + +github](https://github.com/kaiachain/kaia/blob/dev/CONTRIBUTING.md#versioning-policy)からチェックできる。 + ## カイアのガス政策とは? カイアは、通常のネットワーク状態では低料金を維持し、ネットワークの混雑状況に応じて料金を調整するダイナミックなガス料金モデルを採用している。 ガス料金はブロックごとに限られた範囲内で変更できるため、料金を予測可能に保ちながらネットワーク・スパムを防止するのに役立つ。 取引手数料の一部は自動的に焼却される。 このモデルは、ネットワークの安定性を維持しながら、ユーザーエクスペリエンスと企業にとっての利便性を優先している。 @@ -139,4 +144,4 @@ Kaiaでは、[アカウントアドレスをキーペアから切り離すこと - ethers-ext:[フィー委任による価値移転の例](https://docs.kaia.io/references/sdk/ethers-ext/v6/fee-delegated-transaction/value-transfer/) - web3js-ext:[料金委譲値転送の例](https://docs.kaia.io/references/sdk/web3js-ext/fee-delegated-transaction/value-transfer/) - web3j-ext:[料金委譲値転送の例](https://docs.kaia.io/references/sdk/web3j-ext/fee-delegated-transaction/value-transfer/) -- web3py-ext:[料金委任による価値移転の例](https://docs.kaia.io/references/sdk/web3py-ext/fee-delegated-transaction/value-transfer/) \ No newline at end of file +- web3py-ext:[料金委任による価値移転の例](https://docs.kaia.io/references/sdk/web3py-ext/fee-delegated-transaction/value-transfer/) diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md b/i18n/ja/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md index 3ba9709fe1f1..39d9c7513a68 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md @@ -43,7 +43,7 @@ ### クレイトンとフィンシャに何が起こったのか? -KlaytnとFinschiaは、両チェーンによるガバナンスの決定によって合併し、Kaiaとなった。 投票結果は[こちら](https://medium.com/kaiachain/klaytn-and-finschia-merge-proposal-passes-creating-asias-largest-blockchain-ecosystem-7af570eb069a)からご覧いただけます。 2つのチェーン(KLAYとFNSA)のユーティリティ・トークンはKAIAトークンに変換される。 両トークンの為替レートは[こちら](../../kaiatech/kaia-white-paper.md#fnsa-issuancedistribution-status)で確認できる。 +KlaytnとFinschiaは、両チェーンによるガバナンスの決定によって合併し、Kaiaとなった。 投票結果は[こちら](https://blog.kaia.io/klaytn-and-finschia-merge-proposal-passes-creating-asias-largest-blockchain-ecosystem/)からご覧いただけます。 2つのチェーン(KLAYとFNSA)のユーティリティ・トークンはKAIAトークンに変換される。 両トークンの為替レートは[こちら](../../kaiatech/kaia-white-paper.md#fnsa-issuancedistribution-status)で確認できる。 ### KLAYとFNSAはどうなるのか? @@ -142,8 +142,8 @@ KaiaはKlaytnチェーンのハードフォークであり、チェーンIDは チェーン・マージの主な情報源は以下の通り: - [ガバナンス提案](https://govforum.klaytn.foundation/t/kgp-25-klaytn-finschia-mainnet-merge/719) -- [合併に隠されたビジョン](https://medium.com/klaytn/finschia-klaytn-chain-merge-proposal-our-vision-for-asias-1-blockchain-ecosystem-7de1588e28c0) -- [カイア・デフィのコアを作る](https://medium.com/klaytn/crafting-the-core-of-project-dragons-defi-ecosystem-0fa561e02f56) -- [機関の需要に応える](https://medium.com/klaytn/project-dragon-responding-to-institutional-demand-bd36e2e1e2a6) -- [補足データと考察](https://medium.com/klaytn/project-dragon-supplementary-data-and-insights-d36abd25ca0f) -- [カイア・ブランド・ストーリー](https://medium.com/klaytn/say-hello-to-kaia-4182ccafe456) +- [合併に隠されたビジョン](https://blog.kaia.io/finschia-klaytn-chain-merge-proposal-our-vision-for-asias-no-1-blockchain-ecosystem/) +- [カイア・デフィのコアを作る](https://blog.kaia.io/crafting-the-core-of-project-dragons-defi-ecosystem/) +- [機関の需要に応える】(https://blog.kaia.io/project-dragon-responding-to-institutional-demand/) +- [補足データと考察](https://blog.kaia.io/project-dragon-supplementary-data-and-insights/) +- [カイア・ブランド・ストーリー](https://blog.kaia.io/say-hello-to-kaia/) diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md b/i18n/ja/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md index e2c2f3935a6f..4d4f1ee7195a 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md @@ -2,12 +2,160 @@ Finschiaユーザーは、Finshiaネットワーク上のFNSAトークンをKaiaネットワーク上のKAIAトークンに固定スワップレートでスワップすることができます。 スワップは、Kaiabridgeと総称される一連のスマートコントラクトとプログラムによって仲介される。 -トークンスワッププロセスは、Finschiaユーザーが`fwsap`モジュールにFNSAトークンを送信することから始まります。 トークンはまず `cony` デノミネーションから `kei` デノミネーションにスワップされ、次に `fbridge` モジュールに転送される。 `fbridge`からのイベントは信頼できる中継者によって認識され、カイアチェーン上のブリッジスマートコントラクトに提出される。 ブリッジング・リクエストは複数のステップで処理される: +オンラインツールキット](https://toolkit.kaia.io/kaiaBridge)でカイアブリッジにアクセスし、使用することができます。 -- Inflight:トークンはFinschiaの`fbridge`モジュールに到着したが、中継者はKaiaスマートコントラクトに報告しなかった。 -- Confirmed::中継者が契約書(「提供書」)に要望書を提出。 これでリクエストは30分のタイムロックに入った。 -- Claimed:タイムロックが切れた後、トークンはカイアチェーン上の譲渡先アカウントに譲渡(「クレーム」)されます。 +契約書のソースコードは[GitHub kaiachain/kaia リポジトリ](https://github.com/kaiachain/kaia/tree/dev/contracts/contracts/system_contracts/kaiabridge)に、デプロイされたアドレスは[契約書アドレス](https://docs.kaia.io/references/contract-addresses/)のページにあります。 -Kaiabridgeスマートコントラクトにはマルチシグ機能が組み込まれている。 例えば、リクエストが「確認」されるには、「オペレーター」アカウントからの複数の提供取引が必要です。 各オペレーターのアカウントは中継者によって保有され、中継者はカイア財団とフィンシャ財団によって管理されている。 +# カイアブリッジ ユーザーガイド -コントラクトのソースコードは[kaiachain GitHub](https://github.com/kaiachain/kaia/tree/dev/contracts/contracts/system_contracts/kaiabridge)に、デプロイされたアドレスは[コントラクトアドレス](https://docs.kaia.io/references/contract-addresses/)のページにあります。 \ No newline at end of file +## 前提条件 + +### 1. アカウントをMetaMaskまたはKaia Walletに移動する + +#### 生の秘密鍵 + +アカウントが生の秘密鍵としてエクスポートできる場合は、生の秘密鍵をコピーし、MetaMaskまたはKaiaウォレットにインポートします。 + +- [メタマスク](https://support.metamask.io/start/use-an-existing-wallet#import-using-a-private-key) +- [カイア・ウォレット](https://www.kaiawallet.io/en_US/faq/?id=25) + +#### リカバリーフレーズ + +アカウントが回復フレーズとしてのみエクスポートできる場合は、回復フレーズから生の秘密鍵を計算します。 BIP-39の派生パスをサポートするツールであれば、どのようなものでも使用できます。 そのようなツールには、[ethers.js](https://docs.ethers.org/v6/api/wallet/#HDNodeWallet)、[viem](https://viem.sh/docs/accounts/local/hdKeyToAccount)、[Foundry](https://getfoundry.sh/cast/reference/wallet/)、[BIP39ツール](https://github.com/iancoleman/bip39)などがある。 Finschiaウォレットは、デフォルトの派生パスとして「m/44'/438'/0'/0/0」パス([SLIP-044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)に基づく)を使用することがよくあります。 Finschiaウォレットに複数のアカウントがある場合、または異なる設定を使用している場合は、他の派生パスを使用する必要がある場合があります。 + +秘密鍵の計算が完了したら、上記の[生の秘密鍵を使用する場合](#with-raw-private-key)の指示に従ってください。 + +:::note[Example BIP39ツールを使って] + +秘密鍵はこのページで計算できます:[BIP39 - ニーモニックコード](https://iancoleman.io/bip39/)。 + +予防措置として、ページにある「オフラインでの使用」の説明に従い、プロセス中はインターネット接続を遮断することを強くお勧めします。 + +1. BIP39 Mnemonic」フィールドにリカバリーフレーズを貼り付ける。 +2. Coin "フィールドを "ETH - Ethereum "に設定する。 +3. 派生パス」を「BIP32」に設定する。 +4. クライアント」を「カスタム派生パス」に設定する。 +5. BIP32 Derivation Path」を「m/44'/438'/0'/0」に設定する。 +6. Derived Addresses "で、"Path "が "m/44'/438'/0'/0/0 "と表示されている最初の行を探す。 + +::: + +:::note[Example ファウンドリーツールを使って] + +1. Foundry](https://getfoundry.sh/)をインストールする。 +2. リカバリーのフレーズを `--mnemonic` に入れて、以下のコマンドを入力する。 生の秘密鍵が印刷される。 + ``` + cast wallet private-key --mnemonic "test test test test test test test junk" --mnemonic-derivation-path "m/44'/438'/0'/0/0" + ``` + +::: + +### 2. ネットワークのチェック + +MetaMaskを使用している場合、Kaia Mainnetを手動でネットワークに追加してください。 + +- [メタマスクとカイアの接続](https://docs.kaia.io/build/tutorials/connecting-metamask/) + +### 3. アカウントにガソリンを入れる + +スワップ取引を行うにはガソリンが必要です。 詳しくは「KAIA取得」(https://docs.kaia.io/build/get-started/getting-kaia/)を参照。 + +ガソリン代として最低でも0.1KAIAを用意することをお勧めする。 + +## フィンスキアをカイアに交換 + +:::warning[This スワップは不可逆的] + +提供および請求のリクエストは一度しか処理できず、取り消すことはできない。 +これらの指示に従う前に、よくお読みください。 + +::: + +### 1. 財布をつなぐ + +#### 1.1 メタマスクの接続 + +Connect MetaMask "ボタンをクリックする。 + +

Connect MetaMask

+ +アカウント」に自分の住所が表示されているか確認する。 +そうでない場合は、MetaMaskエクステンションを開き、ページに接続されていないと表示されるかどうかを確認する。 もしそうなら、"connect account "ボタンを押してください。 + +

Connect Account

+ +#### 1.2 カイアウォレットに接続する + +カイアウォレットを使用している場合、サイトがカイアウォレットとdApp(この場合はカイアオンラインツールキット)の接続を求めることがあります。 + +

Connect Kaia Wallet

+ +接続」をクリックし、カイアウォレットに接続します。 + +#### 2. カイア・メインネットに切り替える + +ネットワークを "Kaia Mainnet "または "Mainnet "に正しく設定したか確認してください。 そうでない場合は、カイア・メインネットに切り替えてください。 MetaMaskをご利用で、MetaMaskにKaia Mainnetのネットワークが追加されていない場合は、[ネットワークの確認](#2-check-your-network)をご参照ください。 + +#### 3. フィンシャのアドレスを導き出す + +Derive Finschia address "をクリックする。 メッセージへの署名を求められたら、"Confirm "または "Sign "をクリックする。 + +
+ Sign message in MetaMask + Sign message in Kaia Wallet +
+ +

+派生フィンシアアドレス」が元のフィンシアアドレスと一致し、「cony balance」がフィンシアネットワークの残高(CONYの場合)と一致するか確認してください。 + +
+ Address and CONY balance shown in the page + Address and CONY balance shown in your wallet +
+ +

+また、あなたの口座にガソリン代を支払うためのKAIAがあることを確認してください(財布の中で確認できます)。 + +
+ KAIA balance in MetaMask + KAIA balance in Kaia Wallet +
+ +

+アカウントにKAIAがない場合は、[Gas up your account](#3-gas-up-your-account)を参照してください。 + +#### 4. 要求条項 + +提供要請」をクリックする。 メッセージへの署名とトランザクションの送信を求められたら、"confirm "をクリックする。 + +
+ Confirm provision transaction request in MetaMask + Confirm provision transaction request in Kaia Wallet +
+ +

+処理には数秒かかるはずだ。 トランザクションが完了するまで待つ。 +結果はページで確認できる。 + +

Provision request successful

+ +
+表示されない場合は、更新して最初からやり直してください。 + +#### 5. 請求 + +請求する」をクリックします。 取引送信のプロンプトが表示されたら、"confirm "をクリックします。 + +
+ Confirm claim transaction request in MetaMask + Confirm claim transaction request in Kaia Wallet +
+ +

+処理には数秒かかるはずだ。 トランザクションが完了するまで待つ。 +結果はページで確認できる。 + +

Claim request successful

+ +
+最新の残高をご確認ください。 請求金額は、(あなたのコニー残高) * (換算レート、約148)を[kei](https://docs.kaia.io/learn/token-economics/kaia-native-token/#units-of-kaia-)単位で表したものです。 \ No newline at end of file diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md b/i18n/ja/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md index a66bf8d00655..4d626feeaa12 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md @@ -101,7 +101,7 @@ ## ダウンロード -効率化のため、バッチ・プルーニング(状態移行)またはライブ・プルーニングされたデータベースのみが提供される。 その概念については、[ストレージの最適化](../../learn/storage/state-pruning.md)を読んでほしい。 プルーニングもアーカイブデータもない完全なデータベースが必要な場合は、ジェネシスから新たに完全同期を実行してください。 +効率化のため、バッチ・プルーニング(状態移行)またはライブ・プルーニングされたデータベースのみが提供される。 その概念については、[ストレージの最適化](../../learn/storage/storage-optimization.md)を読んでほしい。 プルーニングもアーカイブデータもない完全なデータベースが必要な場合は、ジェネシスから新たに完全同期を実行してください。 | ネットワーク | 同期オプション | ダウンロード | | ------ | ------- | --------------------------------------------------------------------------------------------------- | diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md b/i18n/ja/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md index 7fcd87597874..a0a03213d73c 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md @@ -2,8 +2,8 @@ このページでは、過去のブロック状態を削除してストレージの必要量を減らす方法を説明します。 カイアはブロック状態を刈り込むために2つのアプローチを提供している: -- [ライブ・プルーニング](../../learn/storage/state-pruning.md#state-live-pruning):ライブ・プルーニング機能を有効にすると、一定の保存期間を超えたブロック状態は自動的に削除されます。 -- [バッチ・プルーニング:ステート・マイグレーション](../../learn/storage/state-pruning.md#state-batch-pruning-state-migration):あるブロック番号より前のブロック状態が利用可能になることを意味する。 +- [ライブ・プルーニング](../../learn/storage/storage-optimization.md#state-live-pruning):ライブ・プルーニング機能を有効にすると、一定の保存期間を超えたブロック状態は自動的に削除されます。 +- [バッチ・プルーニング:ステート・マイグレーション](../../learn/storage/storage-optimization.md#state-batch-pruning-state-migration):あるブロック番号より前のブロック状態が利用可能になることを意味する。 ## 剪定の影響を理解する diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md b/i18n/ja/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md new file mode 100644 index 000000000000..e6d5f5c47468 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md @@ -0,0 +1,293 @@ +# ノードストレージの最適化 + +[カイアv2.1.0](https://github.com/kaiachain/kaia/releases/tag/v2.1.0)は、ディスク容量を大幅に削減できる2つの補完的なストレージ最適化機能を導入しています: + +- **データベース圧縮**:繰り返しブロックデータを圧縮してストレージを削減 +- **FlatTrie State Scheme**:アーカイブ・ノードのステート・データベース・サイズを大幅に削減する実験的機能 + +このガイドでは、Kaiaノードにこれらの最適化を適用する方法を説明します。 + +## データベースの圧縮 + +データベース圧縮はLevelDBに内蔵されたSnappy圧縮を使用し、ブロックヘッダ、トランザクションボディ、レシートのサイズを縮小するもので、ABIエンコードされたトランザクションのゼロパディングのような繰り返しデータを含むことが多い。 + +**予想貯蓄額:**\*。 + +- フルノード:~2TB削減(メインネットの~4.2TBから~2TBへ) + +### 前提条件 + +- カイアv2.1.0以上 +- 手動コンパクションの場合:十分なディスク空き容量と持続的なディスクI/Oを受け入れる能力(以下の**リソースへの影響**セクションを参照) + +### 新規インストールで圧縮を有効にする + +v2.1.0から、圧縮はデフォルトで有効になりました。 ノードをスタートさせるだけだ: + +\*\*パッケージのインストール + +```bash +# Configure network in kend.conf +sudo vi /etc/kend/conf/kend.conf +# Set: NETWORK=mainnet or NETWORK=kairos + +# Start node (compression enabled by default in v2.1.0+) +kend start + +# Verify +kend status +tail -f /var/kend/logs/kend.out +``` + +新しく書き込まれたデータはすべて自動的に圧縮される。 + +### 既存のノードの圧縮を有効にする + +v2.1.0以前のバージョンからアップグレードする場合: + +**ステップ1:バージョンを確認する**。 + +```bash +ken version +``` + +**ステップ2: v2.1.0以降**の場合 + +圧縮はデフォルトで有効になっている。 新しいデータは自動的に圧縮される。 既存のデータを圧縮する場合は、ステップ4に進んでください。 + +**ステップ3:v2.1.0以前のバージョンのみ**。 + +設定に圧縮フラグを追加する: + +\*\*パッケージのインストール + +```bash +sudo vi /etc/kend/conf/kend.conf +# Add to ADDITIONAL variable: +ADDITIONAL="--db.leveldb.compression 2" +``` + +圧縮フラグの値は以下の通り: + +- `0`:圧縮しない +- `1`:レシートのみを圧縮する +- `2`:ヘッダ、ボディ、レシートを圧縮する(推奨) +- `3`:ステートトライを含む全てのテーブルを圧縮する (推奨されない) + +:::note + +ステートトライのデータはうまく圧縮されない(ランダムに見える)ので、オプション3を推奨する。 + +::: + +それから再スタートする: + +```bash +kend stop +kend start +``` + +**ステップ4:既存のデータを圧縮する(オプションだが推奨)**\*。 + +RPC経由でデータベースのコンパクションをトリガーする。 ノードコンソールに取り付ける: + +```bash +ken attach --datadir /var/kend/data +``` + +コンソールで、"allbutstate "プリセットを使ってコンパクションをトリガーする: + +```javascript +> debug.chaindbCompact({ "preset": "allbutstate" }) +null +``` + +**利用可能なプリセット:**\*。 + +- デフォルト"\`:すべてのデータベースコンポーネントのフルレンジコンパクション +- allbutstate"\`:状態のトライを除いた選択的な圧縮 (圧縮に推奨) +- custom"\`:特定のデータベーステーブルのカスタム範囲を定義する + +コンパクションはバックグラウンドで実行される。 ノードのログで進捗状況を監視する: + +```bash +tail -f /var/kend/logs/kend.out | grep -i Compact +``` + +というようなログ・エントリーが表示されるはずだ: + +``` +INFO[07/25,12:50:17 Z] [3] Compacting database started range=0x48-0x49 +INFO[07/25,12:55:17 Z] [3] Compacting database completed range=0x48-0x49 elapsed=5m0.085s +``` + +ノードはコンパクション中もブロックの処理を続ける。 + +**予想所要時間:** メインネットのフルノードで約10時間(~4TBのデータでSSDの場合)。 所要時間はハードウェアとデータサイズによって異なる。 + +\*\*資源への影響 + +- 高いディスクI/O(ピーク時:読み取り400MiB/秒以上、書き込み300MiB/秒以上) +- 高いディスクIOPS(しばしば>2000オペレーション/秒) +- ノードは稼働を続け、ブロックの同期を続ける + +:::note + +コンパクション中もノードは稼動しているが、I/Oのピーク時にはクエリのパフォーマンスに影響が出る可能性がある。 本番用RPCノードの場合は、メンテナンス・ウィンドウまたはトラフィックの少ない時間帯にコンパクションのスケジュールを設定します。 + +::: + +### 事前圧縮されたChaindataスナップショットを使用する(未定) + +事前圧縮されたチェーンデータのスナップショットは、将来のリリースで計画されていますが、まだ利用できません。 入手可能になれば、[Chaindataスナップショットページ](https://docs.kaia.io/misc/operation/chaindata-snapshot/)に掲載されます。 + +現在、あなたはどちらかでなければならない: + +- v2.1.0+の新規インストールで圧縮を有効にする(新規データは自動圧縮) +- 既存のノードで手動コンパクションを実行する(上記参照) + +圧縮スナップショットの可用性に関する更新については、スナップショットページを定期的にチェックしてください。 + +### 圧縮が有効であることを確認する + +ノードの起動ログに圧縮設定がないか確認してください: + +```bash +grep "compressionType" /var/kend/logs/kend.out +``` + +state-trie以外のテーブルで`compressionType=snappy`を示すログ・エントリを探します。 + +### モニタリングとトラブルシューティング + +\*\*ディスク使用量の削減をチェックする。 + +```bash +du -h --max-depth=1 /var/kend/data/klay/chaindata +``` + +圧縮前と圧縮後を比較する。 ブロック本体とレシートを含むディレクトリのストレージが大幅に削減されるはずだ。 + +\*\*よくある問題 + +1. \*\*コンパクションに失敗しました:十分なディスク容量を確保してください。 コンパクションは、一時的にデータを書き換えるための追加スペースを必要とする。 +2. \*\*FlatTrieが起動しません:FlatTrie は空のデータベースを必要とします。 既存のデータに関するエラーが表示された場合は、chaindataディレクトリを削除し、genesisから同期してください。 +3. **メルクル証明 API エラー**:FlatTrieは `eth_getProof` をサポートしていません。 このAPIが必要な場合は、従来のノードを使用する。 + +## フラットトライ・ステート・スキーム(実験的) + +FlatTrieは、Erigonイーサリアムクライアントから転用された実験的な状態保存スキームである。 アカウントの状態をフラットな構造で保存し、最新のブロックの完全なMerkle Patricia Trie(MPT)のみを保持し、オンデマンドで過去のトライを再構築する。 + +**予想貯蓄額:**\*。 + +- 総収納量:~75%削減(カイロス・テストネットの結果から予測) +- カイロス・テストネット4.3TB → 1TB +- メインネット~35TB → ~10TB(比例削減による見積もり) + +:::warning + +FlatTrieはv2.1.0の実験的機能です。 本番での使用は推奨されていない。 今後のリリースでは、潜在的な安定性の問題、パフォーマンスのボトルネック、破壊的な変更が予想されます。 テストおよび開発環境でのみ使用する。 + +::: + +### 前提条件 + +- カイアv2.1.0以上 +- \*\*ジェネシスからの同期が必要です。 +- 空のデータ・ディレクトリ + +### 現在の制限 + +FlatTrieを有効にする前に、これらの制限を理解してください: + +**サポートされない機能:**\*。 + +- バッチ剪定とライブ剪定 +- ブロックの巻き戻し (`--start-block-number` フラグと `debug_setHead` API) +- Merkle 証明生成 (`eth_getProof` API) + +**非適合性:**\*。 + +- 既存のデータベースから移行できない(ジェネシスから始める必要がある) +- FlatTrieモードと非FlatTrieモードの切り替えができない +- FlatTrieを使用するデータベースと使用しないデータベースに互換性はありません。 + +### FlatTrieを有効にする + +**ステップ1:空のデータディレクトリを用意する**。 + +```bash +# Ensure clean data directory +sudo rm -rf /var/kend/data +sudo mkdir -p /var/kend/data +``` + +**ステップ2:FlatTrieフラグでノードを起動し、genesisから同期する**。 + +```bash +# Mainnet +ken --state.experimental-flat-trie + +# Kairos testnet +ken --state.experimental-flat-trie --kairos +``` + +:::note + +FlatTrieが有効な場合、アーカイブモードは `--gcmode` と `--state.block-interval` フラグに関係なく、自動的に有効になる。 FlatTrieを使用する場合、これらのフラグは無視される。 + +::: + +**ステップ3:完全な同期を待つ**。 + +ノードはジェネシスからすべてのブロックを同期させる。 ハードウェアやネットワークによっては数週間かかる場合もあります。 + +### FlatTrieがアクティブであることを確認する + +ノードの起動ログをチェックして、FlatTrieモードを確認します: + +```bash +grep -i "flat" /var/kend/logs/kend.out | head -20 +``` + +エクスペリメンタル・フラット・トライがアクティブであることがわかるはずだ。 + +### FlatTrieのパフォーマンスをモニターする + +FlatTrieは、従来のステート・ストレージとは異なるリソース・プロファイルを使用する: + +\*\*期待される特性 + +- CPU使用率の低下 +- メモリ使用量が多い(~30GB) +- 高いゴルーチン数(~900~1000) +- ブロック確定時間の短縮 + +ノードのPrometheusメトリクスエンドポイントまたはGrafanaダッシュボードでこれらのメトリクスを監視します。 + +### FlatTrieのトラブルシューティング + +**Cannot start FlatTrie on existing database:** +FlatTrie cannot be enabled on non-empty data を示すエラーが表示された場合は、genesis から起動する必要があります。 chaindataディレクトリを削除し、`--state.experimental-flat-trie`フラグで完全同期を行う。 + +**Merkle proof API fails:** +FlatTrieは`eth_getProof`と関連するMerkle proof APIをサポートしていません。 アプリケーションにこれらのAPIが必要な場合は、代わりに従来のノードを使用してください。 + +**High memory usage:** +同期中のFlatTrieノードのメモリ使用量は約30GBと予想されます。 システムに十分なRAMがあることを確認してください。 チームは将来のバージョンでこれを減らすための最適化に取り組んでいる。 + +**遅い同期速度:** +FlatTrieの初期同期は、従来のノードと同等です。 同期が著しく遅い場合は、確認してください: + +- ディスクI/O性能(SSDを強く推奨) +- ネットワーク帯域幅 +- CPU使用率 + +## ベストプラクティス + +1. **大きな変更の前には必ずバックアップを取ってください**:特に手動コンパクションを実行する前に。 +2. \*\*ディスクの空き容量を監視してください:コンパクションの前に十分な空き容量があることを確認してください。 コンパクションは一時的にデータベース・ファイルを書き換えるための追加領域を必要とする。 +3. \*\*トラフィックの少ない時間帯にコンパクションをスケジュールする:パブリックRPCエンドポイントを実行している場合。 +4. **本番ノードにはSSDを使用してください**:圧縮もFlatTrieも、高速なランダムI/Oから恩恵を受けます。 +5. **実験的機能の計画**:FlatTrieはv2.1.xでは実験的な機能です。 本番使用前に十分にテストすること。 +6. **常にアップデート**してください:今後の最適化とFlatTrieが実験的ステータスを卒業する時期については、リリースノートをご確認ください。 \ No newline at end of file diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md b/i18n/ja/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md index de0835086bb3..f2e1fc43e857 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md @@ -10,14 +10,22 @@ ### ベアメタルサーバー -| カテゴリー | Specification | -| :---- | :---------------------------------------------------------------------------------------------------------------------------------------------- | -| サーバー | インテル® サーバー・システム [M50CYP1UR212](https://www.intel.sg/content/www/xa/en/products/sku/214842/intel-server-system-m50cyp1ur212/specifications.html) | -| CPU | Intel® Xeon 8358 2.60 GHz (32-core/64-thread) | -| メモリー | 128GB (32GB \* 4) | -| ストレージ | 4TB(またはそれ以上のサイズ)のSSD(チェーンデータのサイズによって、望ましいストレージのサイズと構成は異なる可能性があります。 詳しくはカイア・チームにご相談ください)。 | +#### 一般要件(すべてのノードタイプ) -これはCNとPNの推奨ハードウェア仕様であり、厳密な要件ではないことに注意。 同様のハードウェア構成を持つ物理的なマシンであれば、CNやPNを操作するのに十分だろう。 +| カテゴリー | 仕様 | +| :---- | :------------------------------------------------------------------------------------------- | +| CPU | 2.6 GHzベース - 最大周波数3.4 GHz以上(第3世代インテル® Xeon® スケーラブル・プロセッサーなど) | +| ストレージ | ≥ 4 TB SSD (チェーンのデータサイズに応じて調整。カイアチームにご相談ください) | + +同様のハードウェア構成を持つ物理的なマシンであれば、CNやPNを操作するのに十分だろう。 + +#### ノードタイプ別推奨仕様 + +| Node Type | コア/スレッド | メモリー | +| :------------------------------------------- | :---------- | :---- | +| CN | 16コア/32スレッド | 128GB | +| PN | 8コア/16スレッド | 64 GB | +| PN (with Live Pruning DB) | 4コア/8スレッド | 32 GB | ライブ刈り込みDBを使用するには、ライブ刈り込みオプションを使用し、適用することができます。 詳細はhttps://docs.kaia.io/learn/storage/live-pruning/。 ただし、ライブ・プルーニング仕様はCNには推奨されていないが、将来的には変更される可能性がある。 @@ -37,11 +45,11 @@ #### アジュール推奨仕様 -| Node Type | Model | vCPU | Memory (GiB) | Storage type (GiB) | Storage speed (IOPS) | Price (Korea Central, USD/h) | -| :------------------------------------------: | :-----: | :--: | :-----------------------------: | :-----------------------------------: | :-------------------------------------: | :---------------------------------------------: | -| CN | D32s v5 | 32 | 128 | P50 (4096) | 7500 | 1.888 | -| PN | D16s v5 | 16 | 64 | P50 (4096) | 7500 | 0.944 | -| PN (with Live Pruning DB) | D8s v5 | 8 | 32 | P50 (4096) | 7500 | 0.472 | +| ノードタイプ | Model | vCPU | Memory (GiB) | Storage type (GiB) | Storage speed (IOPS) | Price (Korea Central, USD/h) | +| :-----------: | :-----: | :--: | :-----------------------------: | :-----------------------------------: | :-------------------------------------: | :---------------------------------------------: | +| CN | D32s v5 | 32 | 128 | P50 (4096) | 7500 | 1.888 | +| 名詞 | D16s v5 | 16 | 64 | P50 (4096) | 7500 | 0.944 | +| PN(ライブ剪定DB付き) | D8s v5 | 8 | 32 | P50 (4096) | 7500 | 0.472 | このストレージ仕様は、Azure Premium Disk仕様から派生したものである。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/references/contract-addresses.md b/i18n/ja/docusaurus-plugin-content-docs/current/references/contract-addresses.md index bd0a135418b2..0a7b85f9bfdf 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/references/contract-addresses.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/references/contract-addresses.md @@ -15,6 +15,7 @@ | KIP-113 SimpleBlsRegistry | proxy 0x3e80e75975bdb8e04B800485DD28BebeC6d97679
logic 0xb5ed8d6edd437a0d6ae828580c0aef5678d87f1a | proxy 0x4BEed0651C46aE5a7CB3b7737345d2ee733789e6
logic 0x6751096fe72d835307d7e635aed51296948b93c5 | | KIP-247 ガスレススワップルーター | 0xCf658F786bf4AC62D66d70Dd26B5c1395dA22c63 | 0x4b41783732810b731569E4d944F59372F411BEa2 | | KIP-226 CLレジストリ | 0x25F4044c655Fc7B23c62bbC78ceF3B4EBFb4e478 | 0x25F4044c655Fc7B23c62bbC78ceF3B4EBFb4e478 | +| KIP-249 AuctionEntryPoint | 0xFc5c1C92d8DE06F7143f71FeA209e04042dcff82 | 0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480 | いくつかのコントラクトはKaiaノードによって直接読み取られることはないが、Kaiaブロックチェーンとそのエコシステムの運用において重要な役割を果たしている。 これらには、財務、ガバナンス、KAIAトークンのブリッジ契約などが含まれる。 @@ -33,7 +34,9 @@ | Kaiabridge Judge | 0x64c91d6517b8f2fd7f4157c32DE4acfe1AeA2611 | 0x3735Ba95cca5DEd47Fa5b202a2Bbda4c63c0B1DD | | Kaiabridge Guardian | 0xE49D152E5FA576caFC18D2775AF4E58C135a6851 | 0xc9e8342C1da4c89A423258d9030414331b4761Cf | | KIP-163 PublicDelegationFactory | 0x29C8cc53d22F79D4024ecB67DB1a09b37bCdE415 | 0x98c47c2cda854cbb025d47de72149a7ec238ec33 | -| KIP-226 CLDEXFactory | 0x2A4C5eCaafB26460F17d509EA4d15741AF5F5f0a | 0x537D58BdBC98c690bE5d3e3F638d4B93754B15Fd | -| KIP-226 CLDEXルーター | 0x21d3c567058277b19324FE22c8e4Bb3D2AE0D4C3 | 0x41F135a084897e4145CC2032e8701726af795e3a | +| KIP-226 CLDEXFactory | 0x93fa0E1deE99ac4158a617a6EC79cB941bD9a39F | 0x666a9a72D2f708062a20e7Ca94f6dd5Ce6B33eA4 | +| KIP-226 CLDEXルーター | 0x5086273d9C8a79B7d2466aaCc52a6E43E22152A5 | 0x2871e95eaBFF0E71e4e4b706D7F1F3D24811673b | | KIP-226 ステーキングトラッカーV2 | 0xF45c37c265f148894D6d9A4c066aFaAB00557c9c | 0x9b015Ab5916EE53e52Ef60f31E978b4001908c43 | | [カノニカルWKAIA](../build/smart-contracts/token-development/canonical-wkaia.md) | 0x19Aac5f612f524B754CA7e7c41cbFa2E981A4432 | 0x043c471bEe060e00A56CcD02c0Ca286808a5A436 | +| KIP-249 オークション・デポジット・ボールト | 0x0E66b62273Cc99BC519DD4dD0C0Cf689dd7b9876 | 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc | +| KIP-249 オークション料金保管庫 | 0x303BB9c9FF4Aa656ac4c8e9f99F8E4C133FDa665 | 0xE4e7d880786c53b6EA6cfA848Eb3a05eE97b2aCC | \ No newline at end of file diff --git a/i18n/ja/docusaurus-theme-classic/footer.json b/i18n/ja/docusaurus-theme-classic/footer.json index 04e7ab94474b..47d8335a0675 100644 --- a/i18n/ja/docusaurus-theme-classic/footer.json +++ b/i18n/ja/docusaurus-theme-classic/footer.json @@ -56,7 +56,11 @@ "description": "The label of footer link with label=Open Source linking to https://docs.kaia.io/misc/opensource/" }, "copyright": { - "message": "© Kaia DLT Foundation 2025. All rights reserved.", + "message": "", "description": "The footer copyright" + }, + "link.item.label.Blog": { + "message": "ブログ", + "description": "The label of footer link with label=Blog linking to https://blog.kaia.io/" } } diff --git a/i18n/ko/docusaurus-plugin-content-docs/current.json b/i18n/ko/docusaurus-plugin-content-docs/current.json index 0626ab6a2827..aede4793b5b1 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current.json +++ b/i18n/ko/docusaurus-plugin-content-docs/current.json @@ -5,23 +5,23 @@ }, "sidebar.buildSidebar.category.Get Started": { "message": "시작하기", - "description": "The label for category Get Started in sidebar buildSidebar" + "description": "The label for category 'Get Started' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Smart Contracts": { "message": "스마트 컨트랙트", - "description": "The label for category Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Deploy Smart Contracts": { "message": "스마트 컨트랙트 배포", - "description": "The label for category Deploy Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Deploy Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Sample Contracts": { "message": "샘플 컨트랙트", - "description": "The label for category Sample Contracts in sidebar buildSidebar" + "description": "The label for category 'Sample Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Tutorials": { "message": "튜토리얼", - "description": "The label for category Tutorials in sidebar buildSidebar" + "description": "The label for category 'Tutorials' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Tools": { "message": "도구", @@ -29,51 +29,51 @@ }, "sidebar.buildSidebar.category.Wallets": { "message": "지갑", - "description": "The label for category Wallets in sidebar buildSidebar" + "description": "The label for category 'Wallets' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Wallet Libraries": { "message": "지갑 라이브러리", - "description": "The label for category Wallet Libraries in sidebar buildSidebar" + "description": "The label for category 'Wallet Libraries' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Oracles": { "message": "오라클", - "description": "The label for category Oracles in sidebar buildSidebar" + "description": "The label for category 'Oracles' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Indexers": { "message": "인덱서", - "description": "The label for category Indexers in sidebar buildSidebar" + "description": "The label for category 'Indexers' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Cross-chain": { "message": "크로스 체인", - "description": "The label for category Cross-chain in sidebar buildSidebar" + "description": "The label for category 'Cross-chain' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Block Explorers": { "message": "블록 탐색기", - "description": "The label for category Block Explorers in sidebar buildSidebar" + "description": "The label for category 'Block Explorers' in sidebar 'buildSidebar'" }, "sidebar.nodeSidebar.category.Endpoint Node": { "message": "엔드포인트 노드", - "description": "The label for category Endpoint Node in sidebar nodeSidebar" + "description": "The label for category 'Endpoint Node' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Core Cell": { "message": "코어 셀", - "description": "The label for category Core Cell in sidebar nodeSidebar" + "description": "The label for category 'Core Cell' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Install Core Cell": { "message": "코어 셀 설치", - "description": "The label for category Install Core Cell in sidebar nodeSidebar" + "description": "The label for category 'Install Core Cell' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Service Chain": { "message": "서비스 체인", - "description": "The label for category Service Chain in sidebar nodeSidebar" + "description": "The label for category 'Service Chain' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Quick Start": { "message": "빠른 시작", - "description": "The label for category Quick Start in sidebar nodeSidebar" + "description": "The label for category 'Quick Start' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Configure Service Chain": { "message": "서비스 체인 구성", - "description": "The label for category Configure Service Chain in sidebar nodeSidebar" + "description": "The label for category 'Configure Service Chain' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Node Package Downloads": { "message": "노드 패키지 다운로드", @@ -81,11 +81,11 @@ }, "sidebar.refSidebar.category.RPC API Reference": { "message": "RPC API 레퍼런스", - "description": "The label for category RPC API Reference in sidebar refSidebar" + "description": "The label for category 'RPC API Reference' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.SDKs and Libraries": { "message": "SDK 및 라이브러리", - "description": "The label for category SDKs and Libraries in sidebar refSidebar" + "description": "The label for category 'SDKs and Libraries' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.API References": { "message": "API 레퍼런스", @@ -97,31 +97,31 @@ }, "sidebar.learnSidebar.category.Transaction Fees": { "message": "트랜잭션 수수료", - "description": "The label for category Transaction Fees in sidebar learnSidebar" + "description": "The label for category 'Transaction Fees' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Verify Smart Contracts": { "message": "스마트 컨트랙트 검증", - "description": "The label for category Verify Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Verify Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.learnSidebar.category.Data Management": { "message": "데이터 관리", - "description": "The label for category Data Management in sidebar learnSidebar" + "description": "The label for category 'Data Management' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Governance": { "message": "거버넌스", - "description": "The label for category Governance in sidebar learnSidebar" + "description": "The label for category 'Governance' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Node Quick Reference": { "message": "노드 퀵 레퍼런스", - "description": "The label for category Node Quick Reference in sidebar learnSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Kaia Safe": { "message": "Kaia 세이프", - "description": "The label for category Kaia Safe in sidebar buildSidebar" + "description": "The label for category 'Kaia Safe' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Node Quick Reference": { "message": "노드 퀵 레퍼런스", - "description": "The label for category Node Quick Reference in sidebar buildSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.link.KaiaScan": { "message": "KaiaScan", @@ -129,47 +129,47 @@ }, "sidebar.nodeSidebar.category.Node Quick Reference": { "message": "노드 퀵 레퍼런스", - "description": "The label for category Node Quick Reference in sidebar nodeSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'nodeSidebar'" }, "sidebar.refSidebar.category.ethers-ext < v1.0.1": { "message": "ethers-ext < v1.0.1", - "description": "The label for category ethers-ext < v1.0.1 in sidebar refSidebar" + "description": "The label for category 'ethers-ext < v1.0.1' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore": { "message": "키스토어", - "description": "The label for category keystore in sidebar refSidebar" + "description": "The label for category 'keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.ethers-ext": { "message": "ethers-ext", - "description": "The label for category ethers-ext in sidebar refSidebar" + "description": "The label for category 'ethers-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.v5": { "message": "v5", - "description": "The label for category v5 in sidebar refSidebar" + "description": "The label for category 'v5' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.v6": { "message": "v6", - "description": "The label for category v6 in sidebar refSidebar" + "description": "The label for category 'v6' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3js-ext": { "message": "web3js-ext", - "description": "The label for category web3js-ext in sidebar refSidebar" + "description": "The label for category 'web3js-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3j-ext": { "message": "web3j-ext", - "description": "The label for category web3j-ext in sidebar refSidebar" + "description": "The label for category 'web3j-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3py-ext": { "message": "web3py-ext", - "description": "The label for category web3py-ext in sidebar refSidebar" + "description": "The label for category 'web3py-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.Node Quick Reference": { "message": "노드 퀵 레퍼런스", - "description": "The label for category Node Quick Reference in sidebar refSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'refSidebar'" }, "sidebar.buildSidebar.category.Hardware Wallets": { "message": "하드웨어 지갑", - "description": "The label for category Hardware Wallets in sidebar buildSidebar" + "description": "The label for category 'Hardware Wallets' in sidebar 'buildSidebar'" }, "sidebar.miniDappSidebar.category.Build Mini dApps on LINE with Unity": { "message": "Unity로 만드는 LINE 미니 디앱", @@ -177,107 +177,107 @@ }, "sidebar.miniDappSidebar.category.Node Quick Reference": { "message": "노드 퀵 레퍼런스", - "description": "The label for category Node Quick Reference in sidebar miniDappSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'miniDappSidebar'" }, "sidebar.learnSidebar.category.Core Concepts": { "message": "핵심 개념", - "description": "The label for category Core Concepts in sidebar learnSidebar" + "description": "The label for category 'Core Concepts' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Smart Contracts": { "message": "스마트 컨트랙트", - "description": "The label for category Smart Contracts in sidebar learnSidebar" + "description": "The label for category 'Smart Contracts' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Advanced Topics": { "message": "고급 주제", - "description": "The label for category Advanced Topics in sidebar learnSidebar" + "description": "The label for category 'Advanced Topics' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Transaction Execution": { "message": "트랜잭션 실행", - "description": "The label for category Transaction Execution in sidebar learnSidebar" + "description": "The label for category 'Transaction Execution' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Token Economics": { "message": "토큰 경제학", - "description": "The label for category Token Economics in sidebar learnSidebar" + "description": "The label for category 'Token Economics' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Transactions": { "message": "트랜잭션", - "description": "The label for category Transactions in sidebar buildSidebar" + "description": "The label for category 'Transactions' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Token Management": { "message": "토큰 관리", - "description": "The label for category Token Management in sidebar buildSidebar" + "description": "The label for category 'Token Management' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Team Finance": { "message": "Team Finance", - "description": "The label for category Team Finance in sidebar buildSidebar" + "description": "The label for category 'Team Finance' in sidebar 'buildSidebar'" }, "sidebar.miniDappSidebar.category.LINE Mini DApp with Unity": { "message": "유니티와 함께하는 LINE 미니 디앱", - "description": "The label for category LINE Mini DApp with Unity in sidebar miniDappSidebar" + "description": "The label for category 'LINE Mini DApp with Unity' in sidebar 'miniDappSidebar'" }, "sidebar.miniDappSidebar.category.LINE Mini DApp with Cocos": { "message": "Cocos와 함께하는 LINE 미니 디앱", - "description": "The label for category LINE Mini DApp with Cocos in sidebar miniDappSidebar" + "description": "The label for category 'LINE Mini DApp with Cocos' in sidebar 'miniDappSidebar'" }, "sidebar.miniDappSidebar.category.Survey Mini DApp": { "message": "설문조사 미니 디앱", - "description": "The label for category Survey Mini DApp in sidebar miniDappSidebar" + "description": "The label for category 'Survey Mini DApp' in sidebar 'miniDappSidebar'" }, "sidebar.learnSidebar.link.Docs Updates": { "message": "문서 업데이트", - "description": "The label for link Docs Updates in sidebar learnSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'learnSidebar', linking to '/misc/updates'" }, "sidebar.buildSidebar.link.Docs Updates": { "message": "문서 업데이트", - "description": "The label for link Docs Updates in sidebar buildSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'buildSidebar', linking to '/misc/updates'" }, "sidebar.nodeSidebar.category.Debugging and Diagnostics": { "message": "디버깅 및 진단", - "description": "The label for category Debugging and Diagnostics in sidebar nodeSidebar" + "description": "The label for category 'Debugging and Diagnostics' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.link.Docs Updates": { "message": "문서 업데이트", - "description": "The label for link Docs Updates in sidebar nodeSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'nodeSidebar', linking to '/misc/updates'" }, "sidebar.refSidebar.link.Docs Updates": { "message": "문서 업데이트", - "description": "The label for link Docs Updates in sidebar refSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'refSidebar', linking to '/misc/updates'" }, "sidebar.miniDappSidebar.link.Docs Updates": { "message": "문서 업데이트", - "description": "The label for link Docs Updates in sidebar miniDappSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'miniDappSidebar', linking to '/misc/updates'" }, "sidebar.learnSidebar.category.Finschia to Kaia": { "message": "핀시아에서 Kaia로 옮기기", - "description": "The label for category Finschia to Kaia in sidebar learnSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Finschia to Kaia": { "message": "핀시아에서 Kaia로 옮기기", - "description": "The label for category Finschia to Kaia in sidebar buildSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'buildSidebar'" }, "sidebar.nodeSidebar.category.Finschia to Kaia": { "message": "핀시아에서 Kaia로 옮기기", - "description": "The label for category Finschia to Kaia in sidebar nodeSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'nodeSidebar'" }, "sidebar.refSidebar.category.Finschia to Kaia": { "message": "핀시아에서 Kaia로 옮기기", - "description": "The label for category Finschia to Kaia in sidebar refSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'refSidebar'" }, "sidebar.miniDappSidebar.category.Finschia to Kaia": { "message": "핀시아에서 Kaia로 옮기기", - "description": "The label for category Finschia to Kaia in sidebar miniDappSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'miniDappSidebar'" }, "sidebar.buildSidebar.category.Wallet Configuration": { "message": "월렛 구성", - "description": "The label for category Wallet Configuration in sidebar buildSidebar" + "description": "The label for category 'Wallet Configuration' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Wallet Operations": { "message": "월렛 운영", - "description": "The label for category Wallet Operations in sidebar buildSidebar" + "description": "The label for category 'Wallet Operations' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.dApp Integration": { "message": "dApp 통합", - "description": "The label for category dApp Integration in sidebar buildSidebar" + "description": "The label for category 'dApp Integration' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Implementing Transactions": { "message": "트랜잭션 구현", @@ -285,27 +285,27 @@ }, "sidebar.buildSidebar.category.Cookbooks": { "message": "쿡북", - "description": "The label for category Cookbooks in sidebar buildSidebar" + "description": "The label for category 'Cookbooks' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Fundamentals": { "message": "기본 사항", - "description": "The label for category Fundamentals in sidebar buildSidebar" + "description": "The label for category 'Fundamentals' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Token Development": { "message": "토큰 개발", - "description": "The label for category Token Development in sidebar buildSidebar" + "description": "The label for category 'Token Development' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Deployment & Verification": { "message": "배포 및 검증", - "description": "The label for category Deployment & Verification in sidebar buildSidebar" + "description": "The label for category 'Deployment & Verification' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Integrate Gas Abstraction (GA)": { "message": "가스 추상화(GA) 구현하기", - "description": "The label for category Integrate Gas Abstraction (GA) in sidebar buildSidebar" + "description": "The label for category 'Integrate Gas Abstraction (GA)' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Kaia Agent Kit": { "message": "카이아 에이전트 키트", - "description": "The label for category Kaia Agent Kit in sidebar buildSidebar" + "description": "The label for category 'Kaia Agent Kit' in sidebar 'buildSidebar'" }, "sidebar.refSidebar.category.Gas Abstraction": { "message": "가스 추상화", @@ -313,306 +313,306 @@ }, "sidebar.refSidebar.category.viem-ext": { "message": "viem-ext", - "description": "The label for category viem-ext in sidebar refSidebar" + "description": "The label for category 'viem-ext' in sidebar 'refSidebar'" }, "sidebar.buildSidebar.doc.Step 1: Foundation Setup": { "message": "1단계: 기초 설정", - "description": "The label for the doc item Step 1: Foundation Setup in sidebar buildSidebar, linking to the doc build/get-started/foundation-setup" + "description": "The label for the doc item 'Step 1: Foundation Setup' in sidebar 'buildSidebar', linking to the doc build/get-started/foundation-setup" }, "sidebar.buildSidebar.doc.Step 2: Set up Account and Networks": { "message": "2단계: 계정 및 네트워크 설정", - "description": "The label for the doc item Step 2: Set up Account and Networks in sidebar buildSidebar, linking to the doc build/get-started/wallet-config-get-started" + "description": "The label for the doc item 'Step 2: Set up Account and Networks' in sidebar 'buildSidebar', linking to the doc build/get-started/wallet-config-get-started" }, "sidebar.buildSidebar.doc.Step 3: Get KAIA": { "message": "3단계: KAIA 받기", - "description": "The label for the doc item Step 3: Get KAIA in sidebar buildSidebar, linking to the doc build/get-started/getting-kaia" + "description": "The label for the doc item 'Step 3: Get KAIA' in sidebar 'buildSidebar', linking to the doc build/get-started/getting-kaia" }, "sidebar.buildSidebar.doc.Step 4: Deploy Hello World Contract": { "message": "4단계: Hello World 계약 배포", - "description": "The label for the doc item Step 4: Deploy Hello World Contract in sidebar buildSidebar, linking to the doc build/get-started/kaiagreeter-get-started" + "description": "The label for the doc item 'Step 4: Deploy Hello World Contract' in sidebar 'buildSidebar', linking to the doc build/get-started/kaiagreeter-get-started" }, "sidebar.buildSidebar.doc.Step 5: Deploy your First Token Contract": { "message": "5단계: 첫 토큰 컨트랙트 배포", - "description": "The label for the doc item Step 5: Deploy your First Token Contract in sidebar buildSidebar, linking to the doc build/get-started/hardhat" + "description": "The label for the doc item 'Step 5: Deploy your First Token Contract' in sidebar 'buildSidebar', linking to the doc build/get-started/hardhat" }, "sidebar.buildSidebar.doc.Step 6: Build your First dApp on Kaia": { "message": "6단계: 카이아에서 첫 번째 dApp 구축하기", - "description": "The label for the doc item Step 6: Build your First dApp on Kaia in sidebar buildSidebar, linking to the doc build/get-started/scaffold-eth-get-started" + "description": "The label for the doc item 'Step 6: Build your First dApp on Kaia' in sidebar 'buildSidebar', linking to the doc build/get-started/scaffold-eth-get-started" }, "sidebar.buildSidebar.doc.Step 7: Build your Mini dApp on Kaia": { "message": "7단계: 카이아에서 미니 디앱 구축하기", - "description": "The label for the doc item Step 7: Build your Mini dApp on Kaia in sidebar buildSidebar, linking to the doc minidapps/minidapps" + "description": "The label for the doc item 'Step 7: Build your Mini dApp on Kaia' in sidebar 'buildSidebar', linking to the doc minidapps/minidapps" }, "sidebar.buildSidebar.category.smart-contract-tools": { "message": "도구", - "description": "The label for category Tools in sidebar buildSidebar" + "description": "The label for category 'Tools' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Best Practices": { "message": "모범 사례", - "description": "The label for category Best Practices in sidebar buildSidebar" + "description": "The label for category 'Best Practices' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.build-tools": { "message": "도구", - "description": "The label for category Tools in sidebar buildSidebar" + "description": "The label for category 'Tools' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Gaming SDKs": { "message": "게임 SDK", - "description": "The label for category Gaming SDKs in sidebar buildSidebar" + "description": "The label for category 'Gaming SDKs' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.doc.Proof of Play vRNG": { "message": "플레이 증명 vRNG", - "description": "The label for the doc item Proof of Play vRNG in sidebar buildSidebar, linking to the doc build/tools/oracles/vrng-pop" + "description": "The label for the doc item 'Proof of Play vRNG' in sidebar 'buildSidebar', linking to the doc build/tools/oracles/vrng-pop" }, "sidebar.refSidebar.category.account-management-v5": { "message": "계정 관리", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v5": { "message": "계정 키", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v5": { "message": "거래 서명", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v5": { "message": "서명 메시지", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-v5": { "message": "키스토어", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v5": { "message": "기본 거래", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v5": { "message": "수수료 위임 거래", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v5": { "message": "스마트 계약", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-v5": { "message": "Utils", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-v6": { "message": "계정 관리", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v6": { "message": "계정 키", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v6": { "message": "거래 서명", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v6": { "message": "서명 메시지", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-v6": { "message": "키스토어", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v6": { "message": "기본 거래", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v6": { "message": "수수료 위임 거래", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.gas-abstraction-ethers": { "message": "가스 추상화", - "description": "The label for category Gas Abstraction in sidebar refSidebar" + "description": "The label for category 'Gas Abstraction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v6": { "message": "스마트 계약", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-v6": { "message": "Utils", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-v1": { "message": "계정 관리", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v1": { "message": "계정 키", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v1": { "message": "거래 서명", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v1": { "message": "서명 메시지", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v1": { "message": "기본 거래", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v1": { "message": "수수료 위임 거래", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v1": { "message": "스마트 계약", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3js": { "message": "계정 관리", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3js": { "message": "계정 키", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3js": { "message": "거래 서명", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3js": { "message": "서명 메시지", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3js": { "message": "키스토어", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3js": { "message": "기본 거래", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3js": { "message": "수수료 위임 거래", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.gas-abstraction-web3js": { "message": "가스 추상화", - "description": "The label for category Gas Abstraction in sidebar refSidebar" + "description": "The label for category 'Gas Abstraction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3js": { "message": "스마트 계약", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3js": { "message": "Utils", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-viem": { "message": "기본 거래", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-viem": { "message": "수수료 위임 거래", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-viem": { "message": "스마트 계약", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3j": { "message": "계정 관리", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3j": { "message": "계정 키", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3j": { "message": "거래 서명", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3j": { "message": "서명 메시지", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3j": { "message": "키스토어", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3j": { "message": "기본 거래", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3j": { "message": "수수료 위임 거래", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3j": { "message": "스마트 계약", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3j": { "message": "Utils", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3py": { "message": "계정 관리", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3py": { "message": "계정 키", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3py": { "message": "거래 서명", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3py": { "message": "서명 메시지", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3py": { "message": "키스토어", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3py": { "message": "기본 거래", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3py": { "message": "수수료 위임 거래", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3py": { "message": "스마트 계약", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3py": { "message": "Utils", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.doc.getting-started-ethers": { "message": "시작하기", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/ethers-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/ethers-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-ethers-v1": { "message": "시작하기", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/ethers-ext-prior-v1-0-1/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/ethers-ext-prior-v1-0-1/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3js": { "message": "시작하기", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3js-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3js-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-viem": { "message": "시작하기", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/viem-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/viem-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3j": { "message": "시작하기", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3j-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3j-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3py": { "message": "시작하기", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3py-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3py-ext/getting-started" } } diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md b/i18n/ko/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md index cf95f8146132..aad41b53c51d 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md @@ -10,5 +10,5 @@ Web3.unity SDK는 현재 카이아 메인넷과 카이로스 테스트넷을 모두 지원합니다. 카이아에서 블록체인 지원 게임 개발을 시작하려면 다음 가이드를 확인하세요: -- [카이아를 활용한 유니티 게임 개발: 체인세이프를 통한 대체 가능한 토큰 발행](https://medium.com/kaiachain/unity-game-development-on-kaia-minting-fungible-tokens-with-chainsafe-beea9022c42d) -- [카이아에서 체인세이프와 써드웹을 사용하여 유니티 게임을 토큰 게이트하는 방법](https://medium.com/kaiachain/how-to-token-gate-a-unity-game-using-chainsafe-and-thirdweb-on-kaia-93c574519da2) +- [카이아를 활용한 유니티 게임 개발: 체인세이프를 통한 대체 가능한 토큰 발행](https://blog.kaia.io/unity-game-development-on-kaia-minting-fungible-tokens-with-chainsafe/) +- [카이아에서 체인세이프와 써드웹을 사용하여 유니티 게임을 토큰 게이트하는 방법](https://blog.kaia.io/how-to-token-gate-a-unity-game-using-chainsafe-and-thirdweb-on-kaia/) diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md index 7abf1644515f..a93a0a60a033 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md @@ -886,4 +886,4 @@ Fleek은 IPFS에서 최신 사이트와 앱을 구축할 수 있는 인프라입 여기에서 프런트엔드에서 정적으로 1 KAIA를 보내는 것 외에 커피 양을 입력하는 새로운 입력 필드를 추가하는 등 다른 옵션도 살펴볼 수 있습니다. 전체 코드베이스는 [github](https://github.com/ayo-klaytn/buy-me-a-coffee)에서 확인할 수 있으며, 이 [링크](https://spring-fog-0605.on.fleek.co/)를 사용하여 웹사이트를 테스트할 수도 있습니다. -더 자세한 내용은 [Kaia 문서](https://docs.klaytn.foundation/), [Web3Onbaord 문서](https://onboard.blocknative.com/docs/modules/react), [Fleek 문서](https://docs.fleek.co/tutorials/hosting/)를 참고하시기 바랍니다. If you have any questions, visit [Kaia Forum](https://devforum.kaia.io/). +자세한 내용은 [Kaia 문서](https://docs.kaia.io), [Web3Onboard 문서](https://onboard.blocknative.com/docs/modules/react), [Fleek 문서](https://docs.fleek.co/tutorials/hosting/)를 참조하세요. If you have any questions, visit [Kaia Forum](https://devforum.kaia.io/). diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md new file mode 100644 index 000000000000..56593ad6e5fb --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md @@ -0,0 +1,748 @@ +# 체인링크 CCIP로 카이아에서 크로스체인 NFT 구축하기: 실무 가이드 + +## 소개 + +대체 불가능한 토큰은 블록체인 기술의 가장 잘 알려진 사용 사례 중 하나가 되었으며, 고유하고 검증 가능한 디지털 자산을 생성할 수 있게 해줍니다. 그러나 기존의 NFT 구현은 단일 블록체인에 묶여 있습니다. 이러한 제한은 유연성을 떨어뜨리고 커뮤니티, 유동성, 유틸리티가 다를 수 있는 생태계에서 자산을 자유롭게 이동하지 못하게 합니다. + +크로스체인 NFT는 NFT가 고유성과 출처를 유지하면서 블록체인 간에 원활하게 이동할 수 있게 함으로써 이러한 문제를 해결합니다. 개발자는 체인링크의 체인 간 상호운용성 프로토콜(CCIP)을 통해 표준화된 보안 메시징 프레임워크를 사용하여 체인 간에 신뢰할 수 있는 연결고리를 구축할 수 있습니다. + +이 가이드에서는 번 앤 민트 모델을 사용해 크로스체인 NFT를 빌드하고 배포하는 방법을 설명합니다. NFT는 소스 체인에서 소각되고 동일한 토큰아이디와 메타데이터로 대상 체인에서 다시 발행되어, 주어진 시간에 유효한 사본이 하나만 존재하도록 보장합니다. + +## 전제 조건 + +시작하기 전에 다음 설정이 완료되었는지 확인하세요: + +- [Node.js](https://nodejs.org/) 및 [npm](https://www.npmjs.com/) +- 안전모 + - 설치합니다: `npm 설치 --save-dev 하드햇` + - 프로젝트 초기화: `npx hardhat --init` +- [메타마스크](https://metamask.io/en-GB/download) 지갑 + - 개발 지갑을 만들거나 설정합니다. + - 카이아 카이로스 테스트넷과 이더리움 세폴리아 네트워크를 모두 메타마스크에 추가하세요. +- 수도꼭지에서 토큰 테스트 + - [카이아](https://faucet.kaia.io/): 컨트랙트를 배포하거나 트랜잭션을 전송할 때 카이아에서 가스 수수료를 지불합니다. + - [LINK](https://faucets.chain.link/kaia-testnet) (테스트넷): LINK로 결제할 때 CCIP 수수료를 부담합니다. + - [세폴리아 이더](https://faucets.chain.link/sepolia): 세폴리아에서 가스 요금을 지불하며, 선택 시 기본 이더로 CCIP 수수료를 충당할 수도 있습니다. +- [파일베이스](https://filebase.com/) 계정 + - NFT 메타데이터(IPFS 스토리지)를 업로드하고 검색하는 데 필요합니다. + +## 크로스 체인 NFT는 어떻게 작동하나요? + +대체 불가능한 토큰은 단일 블록체인에 기록된 고유한 디지털 토큰입니다. 발행, 전송, 소유권 등 핵심 동작은 해당 체인에 연결된 스마트 컨트랙트에 의해 정의됩니다. 이 때문에 NFT는 추가 메커니즘 없이는 자연스럽게 블록체인을 이동할 수 없습니다. 상호 운용성을 위해 개발자는 여러 체인에 컴패니언 컨트랙트를 배포하고 크로스체인 메시징을 통해 이를 연결합니다. 그 결과 크로스체인 NFT는 여러 블록체인에 존재하는 동등한 토큰이지만 주어진 시간에 하나의 사본만 활성화되는 토큰입니다. + +크로스 체인 NFT는 일반적으로 다음 세 가지 방법 중 하나로 구현됩니다: + +- **소각 및 민트**: 소스 체인에서 NFT를 소각한 다음, 대상 체인에서 이에 상응하는 NFT를 발행합니다. + +- **잠금 및 민트**: NFT가 소스 체인에 잠기고 대상 체인에 복제본이 발행됩니다. 반환하려면 사본을 소각하여 원본의 잠금을 해제해야 합니다. + +- **잠금 및 잠금 해제**: 동일한 컬렉션이 여러 체인에 배포됩니다. 소유자는 한 체인에서 NFT를 잠그면 다른 체인에서 해당 NFT의 잠금을 해제하여 한 번에 하나의 사본만 사용할 수 있도록 합니다. + +이 가이드에서는 크로스체인 NFT에 번 앤 민트 모델을 사용하겠습니다. NFT는 한 체인에서 제거되고 다른 체인에서 다시 생성되며, 전체 프로세스는 체인링크 CCIP에 의해 구동됩니다. + +## 시작하기 + +이 가이드에서는 체인링크 CCIP를 사용하여 카이아 카이로스 테스트넷과 이더리움 세폴리아 간에 크로스체인 NFT를 발행하고 전송하는 방법을 설명합니다. + +결국에는 할 수 있게 될 것입니다: + +- 카이로스 테스트넷과 이더리움 세폴리아 모두에 대해 구성된 하드햇 프로젝트를 초기화합니다. +- 종속성으로 체인링크 CCIP 컨트랙트 및 인터페이스 추가하기 +- 크로스 체인 전송을 위한 번 앤 민트 메커니즘으로 크로스 체인 NFT 컨트랙트를 구현합니다. +- 두 네트워크에 컨트랙트를 배포하고 체인 간에 NFT를 전송합니다. + +### 하드햇 프로젝트 만들기 + +이 튜토리얼에서는 [하드햇 3](https://hardhat.org/docs/getting-started#getting-started-with-hardhat-3)을 사용하여 컨트랙트를 배포하고 상호 작용합니다. Hardhat 3는 암호화된 키 저장소에 대한 기본 지원, Solidity에서 테스트 작성 기능, 향상된 프로젝트 툴링과 같은 새로운 기능을 제공합니다. + +아래 단계에 따라 프로젝트를 설정하세요: + +1. Node.js 및 npm 설치 확인 + + 다음 명령을 실행하여 Node.js 및 npm이 설치되었는지 확인합니다: + +```bash +node -v +npm -v +``` + +2. 새 프로젝트 디렉터리 초기화 + + 새 폴더를 만들고, 그 폴더로 이동하여 Node.js 프로젝트를 초기화합니다: + +```bash +mkdir ccip-nft-kaia-hardhat-example +cd ccip-nft-kaia-hardhat-example +npm init -y +``` + +3. 하드햇 프로젝트 만들기 + + 실행: + +```bash +npx hardhat --init +``` + +메시지가 표시되면 Node.js 테스트 러너와 에테르가 포함된 샘플 프로젝트를 선택합니다. 현재 디렉터리에서 초기화하고 필요한 모든 종속성을 설치합니다. + +### 필수 계약 설치 + +체인링크 CCIP 컨트랙트를 설치합니다: + +```bash +npm i @chainlink/contracts-ccip --save-dev +``` + +표준 체인링크 컨트랙트를 설치합니다: + +```bash +npm i @chainlink/contracts --save-dev +``` + +오픈제플린 컨트랙트를 설치합니다(ERC-721 및 기타 기본 구현 제공): + +```bash +npm i @openzeppelin/contracts --save-dev +``` + +## NFT 메타데이터 구성 + +컨트랙트를 작성하기 전에 발행할 NFT의 사양을 정의해 보겠습니다. 각 NFT에는 이름, 설명, 이미지를 설명하는 메타데이터가 필요하며, 이는 JSON 파일에 저장되고 IPFS에서 호스팅됩니다. + +이 가이드에서는 이미지와 메타데이터를 모두 저장하기 위해 Filebase를 사용하겠습니다. 나만의 NFT를 만들려면 Filebase를 통해 이미지와 메타데이터 JSON 파일을 IPFS에 업로드하세요. 업로드 후 파일 탭에서 파일 이름을 클릭하고 IPFS URL을 복사합니다. 이와 비슷하게 보일 것입니다: + +```bash +https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmY1LZF8JHo2r3h4X5VzLLXtJujqnBFGTyo2aqR9joXnt8 +``` + +다음은 사용할 수 있는 샘플 메타데이터 파일입니다: + +```json +{ + "name": "Kairos NFT", + "description": "gkaia frens! gazuaaaaa!!!", + "image": "https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmRvQc4wZCp6NF7dFL4ywiWTG7FSH3KKGUAkXGgsdYfcKi" +} +``` + +## 스마트 컨트랙트 작성 + +이 섹션에서는 체인링크 CCIP로 구동되는 번 앤 민트 모델을 사용하여 블록체인 간 NFT 전송을 가능하게 하는 콘트랙트를 구현합니다. + +프로젝트의 컨트랙트 디렉토리에 'CrosschainNFT.sol'이라는 새 파일을 생성하고 다음 코드를 붙여넣습니다: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; +import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import {ERC721URIStorage} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; +import {ERC721Burnable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; +import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import {Client} from "@chainlink/contracts-ccip/contracts/libraries/Client.sol"; +import {IRouterClient} from "@chainlink/contracts-ccip/contracts/interfaces/IRouterClient.sol"; +import {IAny2EVMMessageReceiver} from "@chainlink/contracts-ccip/contracts/interfaces/IAny2EVMMessageReceiver.sol"; +import {OwnerIsCreator} from "@chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol"; +import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; +/** + * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. + * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. + * DO NOT USE THIS CODE IN PRODUCTION. + */ + // Source chain is Ethereum Sepolia + // Destination chain is Kairos Testnet +contract CrosschainNFT is ERC721, ERC721URIStorage, ERC721Burnable, IAny2EVMMessageReceiver, ReentrancyGuard, OwnerIsCreator { + using SafeERC20 for IERC20; + enum PayFeesIn { + Native, + LINK + } + error InvalidRouter(address router); + error OnlyOnEthereumSepolia(); + error NotEnoughBalanceForFees(uint256 currentBalance, uint256 calculatedFees); + error NothingToWithdraw(); + error FailedToWithdrawEth(address owner, address target, uint256 value); + error ChainNotEnabled(uint64 chainSelector); + error SenderNotEnabled(address sender); + error OperationNotAllowedOnCurrentChain(uint64 chainSelector); + struct crosschainNFTDetails { + address crosschainNFTAddress; + bytes ccipExtraArgsBytes; + } + uint256 constant ETHEREUM_SEPOLIA_CHAIN_ID = 11155111; + string tokenNFTURI = "https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmY1LZF8JHo2r3h4X5VzLLXtJujqnBFGTyo2aqR9joXnt8"; + IRouterClient internal immutable i_ccipRouter; + LinkTokenInterface internal immutable i_linkToken; + uint64 private immutable i_currentChainSelector; + uint256 private _nextTokenId; + mapping(uint64 destChainSelector => crosschainNFTDetails crosschainNFTPerChain) public s_chains; + event ChainEnabled(uint64 chainSelector, address xNftAddress, bytes ccipExtraArgs); + event ChainDisabled(uint64 chainSelector); + event CrossChainSent( + address from, address to, uint256 tokenId, uint64 sourceChainSelector, uint64 destinationChainSelector + ); + event CrossChainReceived( + address from, address to, uint256 tokenId, uint64 sourceChainSelector, uint64 destinationChainSelector + ); + modifier onlyRouter() { + if (msg.sender != address(i_ccipRouter)) { + revert InvalidRouter(msg.sender); + } + _; + } + modifier onlyOnEthereumSepolia() { + if (block.chainid != ETHEREUM_SEPOLIA_CHAIN_ID) { + revert OnlyOnEthereumSepolia(); + } + _; + } + modifier onlyEnabledChain(uint64 _chainSelector) { + if (s_chains[_chainSelector].crosschainNFTAddress == address(0)) { + revert ChainNotEnabled(_chainSelector); + } + _; + } + modifier onlyEnabledSender(uint64 _chainSelector, address _sender) { + if (s_chains[_chainSelector].crosschainNFTAddress != _sender) { + revert SenderNotEnabled(_sender); + } + _; + } + modifier onlyOtherChains(uint64 _chainSelector) { + if (_chainSelector == i_currentChainSelector) { + revert OperationNotAllowedOnCurrentChain(_chainSelector); + } + _; + } + constructor(address ccipRouterAddress, address linkTokenAddress, uint64 currentChainSelector) + ERC721("Cross Chain NFT", "XNFT") + { + if (ccipRouterAddress == address(0)) revert InvalidRouter(address(0)); + i_ccipRouter = IRouterClient(ccipRouterAddress); + i_linkToken = LinkTokenInterface(linkTokenAddress); + i_currentChainSelector = currentChainSelector; + } + function mint() external onlyOnEthereumSepolia { + uint256 tokenId = _nextTokenId++; + _safeMint(msg.sender, tokenId); + _setTokenURI(tokenId, tokenNFTURI); + } + function enableChain(uint64 chainSelector, address crosschainNFTAddress, bytes memory ccipExtraArgs) + external + onlyOwner + onlyOtherChains(chainSelector) + { + s_chains[chainSelector] = crosschainNFTDetails({crosschainNFTAddress: crosschainNFTAddress, ccipExtraArgsBytes: ccipExtraArgs}); + emit ChainEnabled(chainSelector, crosschainNFTAddress, ccipExtraArgs); + } + function disableChain(uint64 chainSelector) external onlyOwner onlyOtherChains(chainSelector) { + delete s_chains[chainSelector]; + emit ChainDisabled(chainSelector); + } + function crossChainTransferFrom( + address from, + address to, + uint256 tokenId, + uint64 destinationChainSelector, + PayFeesIn payFeesIn + ) external nonReentrant onlyEnabledChain(destinationChainSelector) returns (bytes32 messageId) { + string memory tokenUri = tokenURI(tokenId); + _burn(tokenId); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(s_chains[destinationChainSelector].crosschainNFTAddress), + data: abi.encode(from, to, tokenId, tokenUri), + tokenAmounts: new Client.EVMTokenAmount[](0), + extraArgs: s_chains[destinationChainSelector].ccipExtraArgsBytes, + feeToken: payFeesIn == PayFeesIn.LINK ? address(i_linkToken) : address(0) + }); + // Get the fee required to send the CCIP message + uint256 fees = i_ccipRouter.getFee(destinationChainSelector, message); + if (payFeesIn == PayFeesIn.LINK) { + if (fees > i_linkToken.balanceOf(address(this))) { + revert NotEnoughBalanceForFees(i_linkToken.balanceOf(address(this)), fees); + } + // Approve the Router to transfer LINK tokens on contract's behalf. It will spend the fees in LINK + i_linkToken.approve(address(i_ccipRouter), fees); + // Send the message through the router and store the returned message ID + messageId = i_ccipRouter.ccipSend(destinationChainSelector, message); + } else { + if (fees > address(this).balance) { + revert NotEnoughBalanceForFees(address(this).balance, fees); + } + // Send the message through the router and store the returned message ID + messageId = i_ccipRouter.ccipSend{value: fees}(destinationChainSelector, message); + } + emit CrossChainSent(from, to, tokenId, i_currentChainSelector, destinationChainSelector); + } + /// @inheritdoc IAny2EVMMessageReceiver + function ccipReceive(Client.Any2EVMMessage calldata message) + external + virtual + override + onlyRouter + nonReentrant + onlyEnabledChain(message.sourceChainSelector) + onlyEnabledSender(message.sourceChainSelector, abi.decode(message.sender, (address))) + { + uint64 sourceChainSelector = message.sourceChainSelector; + (address from, address to, uint256 tokenId, string memory tokenUri) = + abi.decode(message.data, (address, address, uint256, string)); + _safeMint(to, tokenId); + _setTokenURI(tokenId, tokenUri); + emit CrossChainReceived(from, to, tokenId, sourceChainSelector, i_currentChainSelector); + } + function withdraw(address _beneficiary) public onlyOwner { + uint256 amount = address(this).balance; + if (amount == 0) revert NothingToWithdraw(); + (bool sent,) = _beneficiary.call{value: amount}(""); + if (!sent) revert FailedToWithdrawEth(msg.sender, _beneficiary, amount); + } + function withdrawToken(address _beneficiary, address _token) public onlyOwner { + uint256 amount = IERC20(_token).balanceOf(address(this)); + if (amount == 0) revert NothingToWithdraw(); + IERC20(_token).safeTransfer(_beneficiary, amount); + } + function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) { + return super.tokenURI(tokenId); + } + function getCCIPRouter() public view returns (address) { + return address(i_ccipRouter); + } + function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721URIStorage) returns (bool) { + return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || super.supportsInterface(interfaceId); + } +} +``` + +### 코드 연습 + +크로스체인NFT는 블록체인 간에 NFT를 전송하기 위해 체인링크 CCIP를 통합하는 ERC-721 콘트랙트입니다. 소스 체인에서 NFT를 소각하고 동일한 토큰아이디와 토큰URI를 사용하여 대상에서 다시 채굴합니다. 이 콘트랙트는 enableChain을 통해 승인된 대상 체인 레지스트리를 유지하고, 크로스체인 메시징을 위해 체인링크 라우터(IRouterClient)에 의존하며, 네이티브 가스 토큰 또는 LINK로 수수료 지불을 지원합니다. + +주요 기능 + +- enableChain + +컨트랙트 소유자가 대상 블록체인을 등록할 수 있습니다. 대응하는 NFT 컨트랙트 주소와 CCIP 인수를 s_chains 매핑에 저장하여 해당 체인을 유효한 전송 대상으로 화이트리스트에 올립니다. 설정이 완료되면 체인 활성화 이벤트가 발생합니다. + +- 교차 체인 전송 + +체인 간 NFT 전송을 실행합니다. 먼저 대상 체인이 활성화되어 있는지 확인한 다음 NFT 메타데이터(tokenURI)를 검색하고 소스 체인에서 토큰을 소각합니다. 그런 다음 송금 세부 정보가 포함된 CCIP 메시지를 작성하고 필요한 수수료를 계산한 후 LINK 또는 네이티브 가스로 결제합니다. 라우터를 통해 메시지가 전송되면 전송을 기록하기 위해 CrossChainSent 이벤트가 발생합니다. + +이제 '크로스체인NFT.sol'의 핵심 흐름이 명확해졌으니, 다음 단계로 넘어가 보겠습니다. + +## 스마트 컨트랙트 컴파일하기 + +스마트 컨트랙트를 컴파일하려면 실행하세요: + +```bash +npx hardhat build +``` + +## 스마트 컨트랙트 배포 + +이 섹션에서는 필요한 변수를 설정한 다음 이더리움 세폴리아(소스 체인)와 카이로스 테스트넷(대상 체인) 모두에 `CrosschainNFT.sol` 컨트랙트를 배포하겠습니다. + +### 암호화된 키 저장소 사용 + +Hardhat 3의 장점 중 하나는 일반 텍스트 파일 대신 암호화된 키 저장소에 개인 키 및 RPC URL과 같은 민감한 값을 저장할 수 있다는 점입니다. 이 가이드에서는 세폴리아 및 카이로스의 _PRIVATE_KEY_와 _RPC URL_을 암호화합니다. + +**개인 키 추가** + +```bash +npx hardhat keystore set PRIVATE_KEY +``` + +이 명령을 처음 실행하면 Hardhat에서 키 저장소에 대한 비밀번호를 만들라는 메시지가 표시됩니다. 값을 추가하거나 업데이트할 때마다 이 비밀번호가 필요합니다. + +**각 네트워크에 대한 RPC URL 추가** + +```bash +npx hardhat keystore set KAIROS_RPC_URL +npx hardhat keystore set SEPOLIA_RPC_URL +``` + +마지막으로 `hardhat.config.ts` 파일을 편집하여 이러한 암호화된 값을 로드하고 두 네트워크를 구성합니다. + +```typescript +import type { HardhatUserConfig } from "hardhat/config"; +import hardhatToolboxMochaEthersPlugin from "@nomicfoundation/hardhat-toolbox-mocha-ethers"; +import { configVariable } from "hardhat/config"; +const config: HardhatUserConfig = { + plugins: [hardhatToolboxMochaEthersPlugin], + solidity: { + profiles: { + default: { + version: "0.8.28", + }, + production: { + version: "0.8.28", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + }, + }, + networks: { + hardhatMainnet: { + type: "edr-simulated", + chainType: "l1", + }, + hardhatOp: { + type: "edr-simulated", + chainType: "op", + }, + kairosTestnet: { + type: "http", + chainType: "l1", + url: configVariable("KAIROS_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + ethereumSepolia: { + type: "http", + chainType: "l1", + url: configVariable("SEPOLIA_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + }, +}; +export default config; +``` + +다음 단계는 이더리움 세폴리아 및 카이로스 테스트넷에 각각 크로스체인NFT 스마트 컨트랙트를 배포하는 것입니다. + +### 이더리움 세폴리아에 크로스체인NFT.sol 배포하기 + +배포하기 전에 [체인링크 CCIP 디렉토리](https://docs.chain.link/ccip/directory/testnet/chain/ethereum-testnet-sepolia)에서 이더리움 세폴리아에 대한 다음 값을 가져옵니다: + +- 체인 선택기 +- CCIP 라우터 주소 +- 링크 토큰 주소 + +이러한 값은 배포 스크립트에 필요합니다. 다음으로, 프로젝트의 _ignition/modules_ 폴더로 이동하여 'deployEthereumSepolia.ts'라는 새 파일을 생성하고 다음 코드를 붙여넣습니다: + +```typescript +// This setup uses Hardhat Ignition to manage smart contract deployments. +// Learn more about it at https://hardhat.org/ignition +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const ETHEREUM_SEPOLIA_ROUTER_ADDRESS = `0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59`; +const ETHEREUM_SEPOLIA_LINK_TOKEN_ADDRESS = `0x779877A7B0D9E8603169DdbD7836e478b4624789`; +const ETHEREUM_SEPOLIA_CHAIN_SELECTOR = `16015286601757825753`; +const CrosschainNFTSepoliaModule = buildModule("CrosschainNFTSepoliaModule", (m) => { + const crosschainNFTSepolia = m.contract("CrosschainNFT", [ETHEREUM_SEPOLIA_ROUTER_ADDRESS, ETHEREUM_SEPOLIA_LINK_TOKEN_ADDRESS, ETHEREUM_SEPOLIA_CHAIN_SELECTOR], { + }); + return { crosschainNFTSepolia }; +}); +export default CrosschainNFTSepoliaModule; +``` + +배포 스크립트를 실행합니다: + +```bash +npx hardhat ignition deploy ignition/modules/deployEthereumSepolia.ts --network ethereumSepolia +``` + +### 카이로스 테스트넷에 크로스체인NFT.sol 배포하기 + +배포하기 전에 [체인링크 CCIP 디렉토리](https://docs.chain.link/ccip/directory/testnet/chain/kaia-testnet-kairos)에서 카이로스 테스트넷의 다음 값을 가져옵니다: + +- 체인 선택기 +- CCIP 라우터 주소 +- 링크 토큰 주소 + +이러한 값은 배포 스크립트에 필요합니다. 그런 다음 프로젝트의 _ignition/modules_ 폴더로 이동하여 '배포카이로스테스트넷.ts'라는 새 파일을 생성하고 다음 코드를 붙여넣습니다: + +```typescript +// This setup uses Hardhat Ignition to manage smart contract deployments. +// Learn more about it at https://hardhat.org/ignition + +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const KAIROS_TESTNET_ROUTER_ADDRESS = `0x41477416677843fCE577748D2e762B6638492755`; +const KAIROS_TESTNET_LINK_TOKEN_ADDRESS = `0xAF3243f975afe2269Da8Ffa835CA3A8F8B6A5A36`; +const KAIROS_TESTNET_CHAIN_SELECTOR = `2624132734533621656`; +const CrosschainNFTKairosModule = buildModule("CrosschainNFTKairosModule", (m) => { + const crosschainNFTKairos = m.contract("CrosschainNFT", [KAIROS_TESTNET_ROUTER_ADDRESS, KAIROS_TESTNET_LINK_TOKEN_ADDRESS, KAIROS_TESTNET_CHAIN_SELECTOR], { + }); + return { crosschainNFTKairos }; +}); +export default CrosschainNFTKairosModule; +``` + +배포 스크립트를 실행합니다: + +```bash +npx hardhat ignition deploy ignition/modules/deployKairosTestnet.ts --network kairosTestnet +``` + +## 스마트 컨트랙트와 상호작용하기 + +이 섹션에서는 배포된 크로스체인NFT 스마트 컨트랙트와 상호작용하기 위해 각각 enableChain, mint, crosschainTransfer 함수를 실행해 보겠습니다. + +### 1단계: 이더리움 세폴리아에서 enableChain을 호출합니다. + +enableChain을 호출하기 전에 다음 값을 준비합니다: + +- **세폴리아 컨트랙트 주소**: 이더리움 세폴리아에 배포된 크로스체인NFT.sol 컨트랙트의 주소입니다. +- **카이로스 컨트랙트 주소**: 카이로스 테스트넷에 배포된 크로스체인NFT.sol 컨트랙트의 주소입니다. +- **체인 선택기**: 2624132734533621656 (카이로스 테스트넷의 CCIP 체인 선택기). +- **CCIP extraArgs**: 0x97a657c9000000000000000000000000000000000000000000000000000000000007A120(가스 제한이 500,000으로 설정된 extraArgs의 기본 인코딩 값입니다). + +그런 다음 스크립트 폴더에 새 타입스크립트 파일을 생성하고 이름을 'enableChainSepolia.ts'로 지정한 다음 다음 코드를 붙여넣습니다: + +```typescript +// scripts/enableChainSepolia.ts +import { network } from "hardhat"; +async function main() { + const connection = await network.connect({ + network: "ethereumSepolia" + }); + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory by name + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + // Contract addresses and parameters + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + const crosschainNFTAddressKairosTestnet = `0x8c464Bb9Bf364F68b898ed0708b8f5F66EF6Cfb1`; + const chainSelectorKairosTestnet = `2624132734533621656`; + const ccipExtraArgs = `0x97a657c9000000000000000000000000000000000000000000000000000000000007A120`; + // Attach to the deployed contract + const crosschainNFTSepolia = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + console.log(`Enabling chain for Kairos Testnet...`); + const tx = await crosschainNFTSepolia.enableChain( + chainSelectorKairosTestnet, + crosschainNFTAddressKairosTestnet, + ccipExtraArgs + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Chain enabled successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +다음 명령을 실행하여 함수를 호출합니다: + +```bash +npx hardhat run scripts/enableChainSepolia.ts --network ethereumSepolia +``` + +### 2단계: 카이로스 테스트넷에서 enableChain을 호출합니다. + +enableChain을 호출하기 전에 다음 값을 준비합니다: + +- **카이로스 컨트랙트 주소**: 카이로스 테스트넷에 배포된 크로스체인NFT.sol 컨트랙트의 주소입니다. +- **세폴리아 컨트랙트 주소**: 이더리움 세폴리아에 배포된 크로스체인NFT.sol 컨트랙트의 주소입니다. +- **체인 선택기**: 16015286601757825753 (카이로스 테스트넷의 CCIP 체인 선택기) +- **CCIP extraArgs**: 0x97a657c9000000000000000000000000000000000000000000000000000000000007A120(가스 제한이 500,000으로 설정된 extraArgs의 기본 인코딩 값입니다.) + +그런 다음 스크립트 폴더에 새 TypeScript 파일을 만들고 이름을 `enableChainKairos.ts`로 지정한 다음 다음 코드를 붙여넣습니다: + +```typescript +// scripts/enableChainKairos.ts +import { network } from "hardhat"; +async function main() { + const connection = await network.connect({ + network: "kairosTestnet" + }); + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory by name + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + // Contract addresses and parameters + const crosschainNFTAddressKairosTestnet = `0x8c464Bb9Bf364F68b898ed0708b8f5F66EF6Cfb1`; + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + const chainSelectorEthereumSepolia = `16015286601757825753`; + const ccipExtraArgs = `0x97a657c9000000000000000000000000000000000000000000000000000000000007A120`; + // Attach to the deployed contract on Kairos + const crosschainNFTKairos = CrosschainNFT.attach(crosschainNFTAddressKairosTestnet); + console.log(`Enabling chain for Ethereum Sepolia...`); + const tx = await crosschainNFTKairos.enableChain( + chainSelectorEthereumSepolia, + crosschainNFTAddressEthereumSepolia, + ccipExtraArgs + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Chain enabled successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +다음 명령을 실행하여 함수를 호출합니다: + +```bash +npx hardhat run scripts/enableChainKairos.ts --network KairosTestnet +``` + +### 3단계: 이더리움 세폴리아에서 LINK로 계약 자금 조달하기 + +CCIP 수수료를 충당하려면 이더리움 세폴리아에 배포된 크로스체인NFT 컨트랙트(crosschainNFTAddressEthereumSepolia)에 LINK로 자금을 조달하세요. 제공된 [수도꼭지](https://faucets.chain.link/sepolia)에서 테스트 링크를 받을 수 있습니다. 이 가이드에서는 LINK 3개를 보내면 충분합니다. + +![](/img/build/tutorials/cc-ccip-fund-link.png) + +### 4단계: 이더리움 세폴리아에서 새로운 크로스체인NFT를 발행하기 + +다음으로, 이더리움 세폴리아에 배포된 크로스체인NFT 콘트랙트에서 새로운 NFT를 발행합니다. + +스크립트 폴더에 새 TypeScript 파일을 만들고 이름을 `mint.ts`로 지정한 다음 다음 코드를 붙여넣습니다: + +```typescript +// scripts/mint.ts +import { network } from "hardhat"; +async function main() { + // Connect to the network + const connection = await network.connect({ + network: "ethereumSepolia" + }); +if (connection.networkName !== "ethereumSepolia") { + console.error(`Must be called from Ethereum Sepolia`); + process.exitCode = 1; + return; + } + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22` + // Attach to the deployed contract + const crosschainNFT = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + console.log(`Minting NFT...`); + const tx = await crosschainNFT.mint(); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`NFT minted successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +이 스크립트는 채굴 과정을 처리하고 교차 체인 전송을 위해 NFT를 준비합니다. + +다음 명령을 실행하여 함수를 호출합니다: + +```bash +npx hardhat run scripts/mint.ts --network ethereumSepolia +``` + +### 5단계: 체인 간 NFT 전송하기 + +이더리움 세폴리아에서는 크로스체인 트랜스퍼 프롬 함수를 호출하여 NFT를 카이로스 테스트넷으로 전송합니다. + +다음 값을 입력합니다: + +- **보낸 사람**: 이더리움 세폴리아의 EOA 주소 +- **받는 사람**: 카이로스 테스트넷에서 수신자의 EOA 주소(본인의 주소일 수도 있음) +- **토큰아이디**: 전송하려는 NFT의 ID입니다. +- **대상체인선택자**: 2624132734533621656 (카이로스 테스트넷의 CCIP 체인 선택기) +- **payFeesIn**: 1 (CCIP 수수료가 LINK로 결제됨을 나타냄) + +전송 스크립트 실행 + +스크립트 폴더에 새 타입스크립트 파일을 만들고 이름을 `crossChainTransferNFT.ts`로 지정한 다음 다음 코드를 붙여넣습니다: + +```typescript +// scripts/crossChainTransferNFT.ts +import { network } from "hardhat"; +async function main() { + // Connect to the network + const connection = await network.connect({ + network: "ethereumSepolia" + }); + // Check if we're on the correct network + if (connection.networkName !== "ethereumSepolia") { + console.error(`Must be called from Ethereum Sepolia`); + process.exitCode = 1; + return; + } + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + // Transfer parameters + const from = `0x7b467A6962bE0ac80784F131049A25CDE27d62Fb`; + const to = `0x7b467A6962bE0ac80784F131049A25CDE27d62Fb`; + const tokenId = 0; // Put NFT token id here + const destinationChainSelector = "2624132734533621656"; // Kairos Testnet + const payFeesIn = 1; // 0 - Native, 1 - LINK + // Attach to the deployed contract + const crosschainNFT = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + const tx = await crosschainNFT.crossChainTransferFrom( + from, + to, + tokenId, + destinationChainSelector, + payFeesIn + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Cross-chain transfer initiated successfully!`); + console.log(`Note: The NFT will arrive on Kairos Testnet after CCIP processes the message.`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +그런 다음 스크립트를 실행합니다: + +```bash +npx hardhat run scripts/crossChainTransferNFT.ts --network ethereumSepolia +``` + +전송 확인 + +CCIP Explorer](https://ccip.chain.link/#/side-drawer/msg/0x2a43cf8076ed6290dd0bf8bdbbc87abe2d238da43b6bf514e70909dd0f35c9db)에서 크로스체인 전송을 모니터링하고, [Kaiascan](https://kairos.kaiascan.io/nft/0x7dcdaa882603b1cfeee42d1c382a1ecba595d87c/0?tabId=nftTokenTransfer&page=1)에서 트랜잭션을 확인할 수 있습니다. + +![](/img/build/tutorials/cc-nft-ccip-explorer.png) + +![](/img/build/tutorials/cc-nft-ccip-kaiascan.png) + +NFT가 카이로스 테스트넷에 도착하면 메타마스크 지갑에 추가합니다: + +1. 메타마스크에서 NFT 탭을 엽니다. +2. NFT 가져오기를 클릭합니다. +3. 카이로스 테스트넷의 크로스체인NFT 컨트랙트 주소와 받은 토큰아이디를 입력합니다(예: 0). + +이제 NFT가 메타마스크 지갑에 표시됩니다. + +![](/img/build/tutorials/cc-ccip-mm-view-nft.png) + +## 결론 + +이 튜토리얼에서는 체인링크 CCIP를 사용해 번 앤 민트 모델을 사용해 카이아 카이로스 테스트넷과 이더리움 세폴리아 간에 NFT를 전송하는 방법을 배웠습니다. + +CCIP에 대해 자세히 알아보고 추가 사용 사례를 살펴보려면 공식 [체인링크 CCIP 문서](https://docs.chain.link/ccip)를 참조하시기 바랍니다. + + + + diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md index c481398d203a..b887a896db47 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md @@ -79,5 +79,5 @@ Kairos 테스트넷 익스플로러에서 볼 수 있습니다. 다음 블록들 **교육 콘텐츠:** -- [스테이블코인으로 가스비 지불이 가능하다면?](https://medium.com/kaiachain/pay-for-gas-fees-with-any-token-a-deep-dive-into-kaias-trustless-gas-abstraction-d670355a096b) -- [Kaia Consensus Liquidity 발표](https://medium.com/kaiachain/%EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8-%EC%9C%A0%EB%8F%99%EC%84%B1-%EA%B3%B5%EA%B8%89%EC%9D%98-%EC%83%88%EB%A1%9C%EC%9A%B4-%ED%8C%A8%EB%9F%AC%EB%8B%A4%EC%9E%84%EC%9D%84-%EC%A0%9C%EC%8B%9C%ED%95%A9%EB%8B%88%EB%8B%A4-kaia-consensus-liquidity-ff6ed20a155f) \ No newline at end of file +- [스테이블코인으로 가스 요금을 지불할 수 있다면 어떨까요?](https://blog.kaia.io/pay-for-gas-fees-with-any-token-a-deep-dive-into-kaias-trustless-gas-abstraction/) +- [카이아 컨센서스 유동성 발표](https://blog.kaia.io/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity/) \ No newline at end of file diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md index 89be0788196f..a8904ab082ca 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md @@ -45,4 +45,4 @@ Kaia 신규 사용자들은 다음과 같은 상황에서 어려움을 겪는 ## 1.4 컨센서스 리퀴디티(CL)와의 관계 -GA는 원래 [컨센서스 리퀴디티 토큰](https://medium.com/kaiachain/%EB%B8%94%EB%A1%9D%EC%B2%B4%EC%9D%B8-%EC%9C%A0%EB%8F%99%EC%84%B1-%EA%B3%B5%EA%B8%89%EC%9D%98-%EC%83%88%EB%A1%9C%EC%9A%B4-%ED%8C%A8%EB%9F%AC%EB%8B%A4%EC%9E%84%EC%9D%84-%EC%A0%9C%EC%8B%9C%ED%95%A9%EB%8B%88%EB%8B%A4-kaia-consensus-liquidity-ff6ed20a155f)의 활용을 촉진시키기 위해 설계되었고, 이 때 가스비 지불은 CL 토큰(예: BORA, Swapscanner)으로 가능했습니다. 하지만 이 기능은 스테이블코인을 포함한 다른 ERC-20 토큰도 지원할 수 있습니다. \ No newline at end of file +GA는 원래 [컨센서스 유동성 토큰](https://blog.kaia.io/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity/)의 활용도를 높이기 위해 설계되었으며, 사용자가 CL 토큰(예: BORA, 스왑스캐너)으로 가스를 결제할 수 있도록 합니다. 하지만 이 기능은 스테이블코인을 포함한 다른 ERC-20 토큰도 지원할 수 있습니다. \ No newline at end of file diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md new file mode 100644 index 000000000000..7a0cd140b63b --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md @@ -0,0 +1,479 @@ +--- +id: integrate-gas-free-usdt-kaia-swap +title: 가스 없는 USDT와 KAIA 스왑 통합 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# 가스 없는 USDT와 KAIA 스왑 통합 + +이 가이드는 목적, 전제 조건, 통합 단계, API 참조 등 가스 없는 USDT에서 KAIA로 스왑 기능에 대한 개요를 제공합니다. 개발자가 가스 프리 스왑 기능을 카이아 네트워크의 탈중앙화 애플리케이션(DApp)에 통합할 수 있도록 설계되었습니다. + +## 소개 + +사용자가 가스 수수료를 위해 카이아 토큰을 보유할 필요 없이 또는 사용자를 대신하여 거래 비용을 충당할 때에도 카이아 네트워크에서 가스 없는 ERC20 토큰 스왑(현재는 USDT로 제한됨)을 수행할 수 있도록 '가스 프리 스왑 카이아' API가 도입되었습니다. 이 API는 특히 완전한 가스 없는 사용자 경험을 위해 ERC20 허가 서명을 사용하여 USDT를 KAIA로 교환하는 것을 지원합니다. + +### 혜택 + +- **100% 가스 없는 경험**: 사용자는 스왑을 수행하기 위해 KAIA 토큰이 필요하지 않습니다. +- **향상된 사용자 온보딩**: 신규 사용자는 KAIA를 획득하지 않고도 즉시 토큰 스왑을 시작할 수 있습니다. +- **ERC20 권한 통합**: 안전한 가스 없는 토큰 승인을 위해 표준 ERC20 허가 서명을 사용합니다. + +### 작동 방식 + +- **사용자가 스왑을 시작합니다**: 사용자가 KAIA로 스왑할 USDT 금액을 선택합니다. +- **프론트엔드에서 퍼밋을 생성합니다**: DApp은 사용자가 서명할 수 있도록 ERC20 허가 서명을 생성합니다. +- **사용자가 허가에 서명**합니다: 사용자가 허가 메시지에 서명합니다(가스 필요 없음). +- **앱이 API를 호출합니다**: 프론트엔드에서 스왑 파라미터와 권한 서명을 API로 전송합니다. +- **백엔드 실행**: API가 허가를 검증하고 스왑을 실행하며 모든 가스 요금을 지불합니다. +- **사용자가 KAIA를 받음**: 네이티브 KAIA 토큰이 사용자의 지갑으로 직접 전송됩니다. + +## 사전 요구 사항 및 지원되는 환경 + +**서비스 엔드포인트** + + + + https://fee-delegation.kaia.io + + + + https://fee-delegation-kairos.kaia.io + + + +**지원되는 토큰 쌍** + +API는 현재 단일 거래 쌍만 지원합니다: + + + + 토큰 입력: USDT (`0xd077a400968890eacc75cdc901f0356c943e4fdb`) + +``` +Token Out: WKAIA (`0x19aac5f612f524b754ca7e7c41cbfa2e981a4432`) +``` + + + + + 토큰 입력: TEST (`0xcb00ba2cab67a3771f9ca1fa48fda8881b457750`) + +``` +Token Out: WKAIA (`0x043c471bEe060e00A56CcD02c0Ca286808a5A436`) +``` + + + + +**테스트 토큰 받기** + +카이로스 테스트넷용 TEST 토큰을 받으려면: + +- 카이아스캔에서 [ERC20 수도꼭지](https://kairos.kaiascan.io/address/0x78a6cacfe5d34e0566e56710c8789d207411001a?tabId=contract&page=1)를 엽니다. +- 계약 탭으로 이동한 다음 _계약서 작성_을 선택합니다. +- 클레임(토큰) 함수 찾기 +- 카이로스에서 지원되는 GA 토큰의 주소를 붙여넣습니다(이 가이드에서는 TEST 주소를 사용). +- 요청을 제출하려면 _조회_를 클릭합니다. 곧 테스트 토큰을 받게 될 것입니다. + +![](/img/build/tutorials/test-tokens-faucet.png) + +**스마트 계약 요건** + +이 API는 가스리스ERC20퍼밋스왑 스마트 컨트랙트와 상호작용합니다: + +- ERC20 권한 기반 승인 지원 +- 유니스왑 V2 호환 DEX와 통합 +- WKAIA를 기본 KAIA로 자동 변환합니다. +- 보안을 위한 최대 스왑 한도 적용 + +**사용자 요구 사항** + +메인넷에서 이 가스 없는 스왑 서비스를 이용하려면 KAIA 잔액이 0이어야 합니다. 이 요건은 온보딩 목적으로 가스 없는 거래가 꼭 필요한 사용자만 서비스를 사용하도록 보장합니다. 테스트넷에서는 테스트 목적으로 이 제한이 완화됩니다. + +최대 스왑 금액은 메인넷과 테스트넷 모두에서 1 USDT로 제한됩니다. 이 기능은 사용자가 카이아 체인에서 경험을 시작하기에 충분한 카이아를 받을 수 있도록 설계되었습니다. + +## 통합 단계 + +### 전체 통합 예시 + +```javascript +const { JsonRpcProvider, Wallet } = require('@kaiachain/ethers-ext/v6'); +const { Contract, parseUnits, formatUnits, Signature } = require('ethers'); + +async function fetchJson(url, init) { + if (typeof fetch !== 'undefined') { + return fetch(url, init); + } + const { default: nodeFetch } = await import('node-fetch'); + return nodeFetch(url, init); +} + +const GASLESS_SWAP_ABI = [ + 'function usdtToken() view returns (address)', + 'function wkaiaToken() view returns (address)', + 'function maxUsdtAmount() view returns (uint256)', + 'function getExpectedOutput(address tokenIn, address tokenOut, uint256 amountIn) view returns (uint256)', + 'function executeSwapWithPermit(address user, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOutMin, uint256 deadline, uint8 v, bytes32 r, bytes32 s)', +]; + +const ERC20_METADATA_ABI = [ + 'function decimals() view returns (uint8)', + 'function symbol() view returns (string)', + 'function name() view returns (string)', + 'function nonces(address owner) view returns (uint256)', + 'function balanceOf(address owner) view returns (uint256)', +]; + +async function buildPermitSignature({ token, owner, spender, value, deadline, domainVersion = '1' }) { + const [name, version, network, verifyingContract, nonce] = await Promise.all([ + token.name(), + Promise.resolve(domainVersion), + owner.provider.getNetwork(), + token.getAddress(), + token.nonces(owner.address), + ]); + + const domain = { + name, + version, + chainId: Number(network.chainId), + verifyingContract, + }; + + const types = { + Permit: [ + { name: 'owner', type: 'address' }, + { name: 'spender', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'nonce', type: 'uint256' }, + { name: 'deadline', type: 'uint256' }, + ], + }; + + const message = { + owner: owner.address, + spender, + value, + nonce, + deadline, + }; + + return Signature.from(await owner.signTypedData(domain, types, message)); +} + +async function executeGaslessSwap({ + rpcUrl, + serverUrl, + userWallet, + contractAddress, + amountIn = '0.01', // Amount in USDT + slippageBps = 50, // 0.5% slippage + permitDeadlineSeconds = 600 // 10 minutes +}) { + console.log('🚀 Starting gasless swap'); + + const provider = new JsonRpcProvider(rpcUrl); + const wallet = userWallet.connect(provider); + const swap = new Contract(contractAddress, GASLESS_SWAP_ABI, provider); + + // Get token addresses from contract + const [tokenInAddress, tokenOutAddress, maxUsdtAmount] = await Promise.all([ + swap.usdtToken(), + swap.wkaiaToken(), + swap.maxUsdtAmount(), + ]); + + const tokenIn = new Contract(tokenInAddress, ERC20_METADATA_ABI, provider); + const tokenOut = new Contract(tokenOutAddress, ERC20_METADATA_ABI, provider); + + const [tokenInDecimals, tokenOutDecimals, tokenInSymbol, tokenOutSymbol] = await Promise.all([ + tokenIn.decimals(), + tokenOut.decimals(), + tokenIn.symbol(), + tokenOut.symbol(), + ]); + + const amountInWei = parseUnits(amountIn, tokenInDecimals); + + // Check if amount exceeds contract maximum + if (amountInWei > maxUsdtAmount) { + throw new Error(`Amount (${amountIn} ${tokenInSymbol}) exceeds contract cap (${formatUnits(maxUsdtAmount, tokenInDecimals)} ${tokenInSymbol})`); + } + + // Get expected output and calculate minimum with slippage + const expectedOut = await swap.getExpectedOutput(tokenInAddress, tokenOutAddress, amountInWei); + const amountOutMin = (expectedOut * BigInt(10_000 - slippageBps)) / 10_000n; + + // Create permit signature + const deadline = BigInt(Math.floor(Date.now() / 1000) + permitDeadlineSeconds); + const signature = await buildPermitSignature({ + token: tokenIn, + owner: wallet, + spender: contractAddress, + value: amountInWei, + deadline, + }); + + // Prepare API payload + const payload = { + swap: { + user: wallet.address, + tokenIn: tokenInAddress, + tokenOut: tokenOutAddress, + amountIn: amountInWei.toString(), + amountOutMin: amountOutMin.toString(), + deadline: deadline.toString(), + }, +permitSignature: signature.serialized, + }; + + console.log('From:', wallet.address); + console.log('Swap amount:', formatUnits(amountInWei, tokenInDecimals), tokenInSymbol); + console.log('Minimum out:', formatUnits(amountOutMin, tokenOutDecimals), tokenOutSymbol); + + // Check balance before swap + const balanceBefore = await provider.getBalance(wallet.address); + + // Call the API + const response = await fetchJson(`${serverUrl}/api/gasFreeSwapKaia`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + + const result = await response.json().catch(() => ({})); + console.log('HTTP status:', response.status); + console.log('Response:', JSON.stringify(result, null, 2)); + + if (response.ok && result.status) { + console.log('🎉 Gasless swap request succeeded'); + + // Check balance after swap + const balanceAfter = await provider.getBalance(wallet.address); + console.log('Balance before:', formatUnits(balanceBefore, 18), 'KAIA'); + console.log('Balance after:', formatUnits(balanceAfter, 18), 'KAIA'); + console.log('Balance difference:', formatUnits(balanceAfter - balanceBefore, 18), 'KAIA'); + + return result; + } else { + console.error('❌ Gasless swap request failed'); + throw new Error(`Swap failed: ${result.data || result.message || 'Unknown error'}`); + } +} + +// Usage example +async function main() { + try { + const userWallet = new Wallet('your_private_key'); + + const result = await executeGaslessSwap({ + rpcUrl: 'https://public-en-kairos.node.kaia.io', + serverUrl: 'https://fee-delegation-kairos.kaia.io', + userWallet: userWallet, + contractAddress: '0xaaFe47636ACe87E2B8CAaFADb03E87090277Ff7B', + amountIn: '0.002', + slippageBps: 50, + }); + + console.log('Transaction hash:', result.data.hash); + } catch (error) { + console.error('💥 Swap failed:', error.message); + } +} + +main(); +``` + +## API 참조 엔드포인트 + +- URL: `/api/gasFreeSwapKaia` +- 방법: POST +- 콘텐츠 유형: 애플리케이션/json + +### 요청 본문 + +```javascript +{ + "swap": { + "user": "0x742d35Cc6635C0532925a3b8D400e6D2A4b8E0bb", + "tokenIn": "0xcb00ba2cab67a3771f9ca1fa48fda8881b457750", + "tokenOut": "0x043c471bEe060e00A56CcD02c0Ca286808a5A436", + "amountIn": "1000000", + "amountOutMin": "950000000000000000", + "deadline": "1699123456" + }, + "permitSignature": "0x…65-byte signature string…" +} +``` + +### 매개변수 + +**스왑** (객체, 필수): + +- 사용자(문자열): 권한에 서명한 토큰 소유자의 주소입니다. +- 토큰인(문자열): 입력 토큰의 주소(설정된 USDT 주소와 일치해야 함) +- 토큰아웃(문자열): 출력 토큰의 주소(구성된 WKAIA 주소와 일치해야 함). +- amountIn (문자열): 입력 토큰의 양을 문자열로 표시합니다(위/최소 단위). +- amountOutMin (문자열): 예상되는 최소 출력 토큰(미끄러짐 방지) +- 기한(문자열): 권한 및 스왑 만료를 위한 유닉스 타임스탬프(초) + +**퍼밋서명**(문자열, 필수): + +- 65바이트의 유효한 16진수 문자열이어야 합니다. +- 일련화된 ERC20 권한 서명이 포함되어 있습니다. + +### 응답 형식 + +#### 성공 응답 (200) + +```javascript +{ + "message": "Request was successful", + "data": { + "_type": "TransactionReceipt", + "blockHash": "0x2a7ae196f6e7363fe3cfc79132c1d16292d159e231d73b4308f598a3222d1f57", + "blockNumber": 191523443, + "contractAddress": null, + "cumulativeGasUsed": "215000", + "from": "0x6C4ED74027ab609f506efCdd224041c9F5b5CDE1", + "gasPrice": "25000000000", + "gasUsed": "215000", + "hash": "0x0ca73736ceecf2dcf0ec2e1f65760d0b4f7348726cb9a0477710172b1dd44350", + "status": 1, + "to": "0x45bD04d5f14DD9AB908109cFEa816F758FaE6709", + "type": 49, + "feePayer": "0x1234567890abcdef1234567890abcdef12345678", + "feePayerSignatures": ["0x..."], + "logs": [ + { + "address": "0x...", + "topics": ["0x..."], + "data": "0x..." + } + ] + }, + "status": true, + "requestId": "req_abc123def456" +} +``` + +#### 오류 응답 + +**400 잘못된 요청 - 유효성 검사 오류:** + +```javascript +{ + "message": "Bad request", + "data": "Permit deadline has expired", + "error": "BAD_REQUEST", + "status": false, + "requestId": "req_error_123" +} +``` + +**400 잘못된 요청 - 트랜잭션 되돌리기:** + +```javascript +{ + "message": "Bad request", + "data": "execution reverted: Permit already used", + "error": "BAD_REQUEST", + "status": false, + "requestId": "req_revert_456" +} +``` + +**500 내부 서버 오류:** + +```javascript +{ + "message": "Internal server error", + "data": "Sending transaction was failed after 5 try, network is busy. Error message: Network timeout", + "error": "INTERNAL_ERROR", + "status": false, + "requestId": "req_error_789" +} +``` + +## 오류 처리 + +### 일반적인 오류 시나리오 + +| 오류 | HTTP 상태 | 설명 | 솔루션 | +| ------------------------------------ | ------- | ------------------------------------------ | ---------------------------------------------------- | +| 누락된 필수 필드 | 400 | _스왑_ 또는 _퍼밋서명_ 누락 | 모든 필수 매개변수 포함 | +| 사용자에게 KAIA 잔액이 있습니다. | 400 | 사용자의 KAIA 잔액이 0이어야 합니다. | KAIA 잔액이 0원인 사용자만 이 서비스를 이용할 수 있습니다. | +| 잘못된 서명 형식 | 400 | 권한 서명이 유효한 16진수 문자열이 아닙니다. | 유효한 65바이트 16진수 서명을 제공하세요. | +| 잘못된 주소 | 400 | 잘못된 이더리움 주소 | 주소가 유효한지 확인 | +| 지원되지 않는 토큰 | 400 | 허용 목록에 없는 토큰 | 구성된 토큰 주소만 사용 | +| 만료된 마감일 | 400 | 과거 허가 마감일 | 향후 타임스탬프 사용 | +| 금액이 너무 큼 | 400 | 계약 한도 초과 | 계약에서 _최대사용금액()_ 확인 | +| 견적 불충분 | 400 | 너무 엄격한 미끄러짐 | 미끄러짐 허용 오차를 늘리거나 양을 줄입니다. | +| 가스 가격이 너무 높음 | 400 | 네트워크 혼잡 | 유가 하락을 기다리기 | +| 네트워크 시간 초과 | 500 | RPC 공급자 문제 | 지연 후 재시도 요청 | + +## 보안 고려 사항 + +### 가스 가격 보호 + +API는 과도한 비용을 방지하기 위해 가스 가격이 50GWI를 초과하면 거래를 거부합니다. 가스 가격을 모니터링하고 혼잡한 시간대에 사용자에게 정보를 제공합니다. + +### 서명 보안 + +- 허가 서명을 재사용하지 마십시오. +- 항상 합리적인 마감 시간(5-30분)을 사용하세요. +- 서명하기 전에 모든 매개변수 유효성 검사 +- 모든 API 통신에 HTTPS 사용 + +## 스마트 계약 세부 정보 + +### 가스리스ERC20퍼밋스왑 컨트랙트 주소 + + + + ``` + 0x45bD04d5f14DD9AB908109cFEa816F758FaE6709 + ``` + + + + ``` + 0xaaFe47636ACe87E2B8CAaFADb03E87090277Ff7B + ``` + + + +### 주요 기능 + +**executeSwapWithPermit** - 허가 서명을 사용하여 가스 없는 스왑을 실행합니다: + +- 허가 및 스왑 매개변수 유효성 검사 +- 허가를 사용하여 토큰 전송 +- DEX 스왑 실행 +- WKAIA를 기본 KAIA로 변환합니다. +- 사용자에게 네이티브 KAIA 전송 + +**겟익스펙티드아웃풋** - 예상 출력량을 조회하는 함수입니다: + +```javascript +function getExpectedOutput( + address tokenIn, + address tokenOut, + uint256 amountIn +) external view returns (uint256) +``` + +### 계약 한도 + +- 스왑당 최대 USDT: 1,000,000 (소수점 6자리 1 USDT) +- 지원되는 페어: USDT → WKAIA → 네이티브 KAIA +- 서명 추적을 통한 재생 방지 보호 + +## 추가 리소스 + +- [ERC20 허가 표준(EIP-2612)](https://eips.ethereum.org/EIPS/eip-2612) +- [카이아 이더 확장](https://github.com/kaiachain/ethers-ext) + + diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md new file mode 100644 index 000000000000..13017acffc2b --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md @@ -0,0 +1,352 @@ +# 검색자를 위한 Kaia MEV 경매 SDK 가이드 + +[Kaia v2.1.0](https://github.com/kaiachain/kaia/releases/tag/v2.1.0)에서는 MEV 경매 시스템을 도입하여 검색자가 공정하고 투명한 경매에 참여하여 MEV 기회를 얻을 수 있도록 했습니다. 이 가이드는 Kaia MEV 경매 SDK를 사용하는 검색자 워크플로우에 대한 포괄적인 안내를 제공합니다. + +:::info + +이 가이드는 카이로스 테스트넷 엔드포인트와 컨트랙트 주소를 사용합니다. 메인넷 출시는 2025년 12월 중순으로 예정되어 있습니다. 메인넷에 배포할 때는 모든 엔드포인트와 컨트랙트 주소를 적절히 업데이트하세요. + +::: + +검색기 워크플로는 네 가지 주요 단계로 구성됩니다: + +![](/img/build/tutorials/searcher-guide-1.png) + +1. **예치**: 검색자는 입찰 활동 자금을 조달하기 위해 '경매예치금고'에 KAIA 토큰을 예치합니다. +2. **입찰**: 검색자는 백런 슬롯에 대해 경매인에게 봉인된 입찰을 제출하여 경쟁합니다. +3. **낙찰 입찰 제출**을 클릭합니다: 경매인이 낙찰자를 선정하고 낙찰 입찰을 합의 노드(CN)에 전달합니다. +4. **입찰 거래 실행**: CN은 '경매 진입점' 컨트랙트를 통해 낙찰된 입찰 거래를 실행합니다. + +자세한 기술적 배경은 [KIP-249](https://kips.kaia.io/KIPs/kip-249)를 참조하세요. + +## 전제 조건 + +시작하기 전에 다음 사항을 확인하세요: + +- 예치금을 위한 KAIA 토큰이 있는 자금 지갑 +- [이동](https://golang.org/)을 설치(버전 1.25 이상)하여 SDK 예제를 확인합니다. +- Kaia 네트워크 엔드포인트에 액세스(이 가이드에서는 카이로스 테스트넷 사용) +- (선택 사항) [파운드리](https://getfoundry.sh/) 설치(`cast` 명령용) + +**경매인 엔드포인트:** + +- 카이로스(테스트넷): `https://auctioneer-kairos.kaia.io` +- 메인넷: `https://auctioneer.kaia.io` + +**익스플로러 엔드포인트:** + +- 카이로스(테스트넷): `https://mev-kairos.kaia.io` +- 메인넷: `https://mev.kaia.io` + +**네트워크 엔드포인트:** + +- 카이로스(테스트넷): `https://public-en-kairos.node.kaia.io` +- 메인넷: `https://public-en.node.kaia.io` + +**계약 주소(카이로스):** + +- AuctionFeeVault: `0xE4e7d880786c53b6EA6cfA848Eb3a05eE97b2aCC` +- AuctionDepositVault: `0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc` +- AuctionEntryPoint: `0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480` + +메인넷 컨트랙트 주소(메인넷 출시 후 사용 가능)는 [컨트랙트 주소](../../references/contract-addresses.md)를 확인하세요. + +:::tip[Monitor MEV 기회] + +검색자는 수익성 있는 거래를 식별할 수 있습니다: + +- **경매인의 보류 중인 트랜잭션 API 구독하기**: 이 API는 컨센서스 노드에서 직접 트랜잭션을 스트리밍하여 실시간으로 MEV 기회를 감지할 수 있습니다. 아래의 [보류 중인 거래 구독](#step-3-subscribe-to-pending-transactions) 섹션을 참조하세요. +- **네트워크 멤풀을 독립적으로 모니터링**: 대기 중인 tx를 구독하여 자체 MEV 기회 감지 로직을 구현하세요. + +::: + +## 1단계: 자금 입금 + +![](/img/build/tutorials/searcher-guide-2.png) + +'경매예치금'은 입찰 잔액을 보관합니다. 보증금은 입찰 금액과 입찰 실행을 위한 예상 가스 요금에 모두 포함되어야 합니다. + +### 보증금 요건 이해 + +보증금 잔액이 있어야 합니다: + +- **입찰 금액**: 경매 낙찰을 위해 지불할 의향이 있는 KAIA입니다. +- **예상 가스 요금**: 입찰 실행 중 소비된 가스(실행 후 차감되어 블록 제안자에게 전송됨) + +:::warning[Always 충분한 예금 잔액 유지] + +잔액이 입찰 금액에 예상 가스 수수료를 더한 금액을 충당하기에 부족한 경우, 유효성 검사 중에 경매인이 입찰을 거부합니다. + +::: + +### 입금 방법 + +계약서에는 두 가지 입금 방법이 제공됩니다: + +**방법 1: `deposit()`** + +발신자의 잔액을 사용하여 입금합니다. 입금액은 발신자의 계좌로 입금됩니다. + +```bash +# Deploy deposit of 200 KAIA +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "deposit()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 --value 200000000000000000000 +``` + +**방법 2: `depitFor(주소 검색자)`** + +다른 계좌를 대신하여 입금합니다. 단일 소스에서 여러 검색자 주소에 자금을 지원하는 데 유용합니다. + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "depositFor(address)" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 --value 200000000000000000000 +``` + +### 잔액 확인 + +현재 입금 잔액을 조회합니다: + +```bash +cast call 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "depositBalances(address)(uint256)" --rpc-url "https://public-en-kairos.node.kaia.io" +``` + +자세한 입금 예시는 [DEPOSIT.md 가이드](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/DEPOSIT.md)를 참조하세요. + +## 2단계: 입찰 제출 + +![](/img/build/tutorials/searcher-guide-3.png) + +수익성 있는 거래를 확인했다면 경매인에게 입찰을 제출하세요. 입찰은 봉인되며(경매가 종료될 때까지 숨겨집니다) 입찰 금액에 따라 경쟁합니다. + +### 입찰 구조 + +입찰은 다음 필드로 구성됩니다([types.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/types.go)에 정의된 대로): + +```go +type AuctionBid struct { + TargetTxRaw []byte // Raw transaction bytes of target tx + TargetTxHash common.Hash // Transaction to backrun + BlockNumber *big.Int // Target block number + Sender common.Address // Your searcher address + To common.Address // Contract to call + Nonce uint64 // Current nonce from AuctionEntryPoint + Bid *big.Int // Your bid in KAIA + CallGasLimit uint64 // Gas limit for your backrun logic + Data []byte // Encoded function call + SearcherSig []byte // EIP-712 signature from searcher +} +``` + +:::info + +입찰을 제출하면 경매인은 낙찰된 입찰을 합의 노드로 전달하기 전에 자신의 서명('경매인 서명')을 검증하고 추가합니다. '검색자 서명'(EIP-712 서명)만 제공하면 됩니다. + +::: + +### 입찰 제출 + +SDK는 [`example/submitbid.go`](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go)에서 전체 작동 예제를 제공합니다. 이 예제에서 확인할 수 있습니다: + +- 경매사와 HTTPS 연결 설정하기 +- EN 엔드포인트에서 새로운 블록 감지하기 +- 타겟 거래 및 해당 입찰가 생성하기 +- 경매인에게 입찰 제출하기 + +**작업 필요**: 실행하기 전에 코드에서 개인 키를 교체하세요. 소스 코드의 `TODO:` 주석을 확인하세요. + +예제를 실행합니다: + +```bash +# From repository root +go run example/submitbid.go +``` + +### 입찰 유효성 검사 + +경매인, 제안자, 스마트 컨트랙트는 각각 입찰에 대한 특정 유효성 검사를 수행합니다. 주요 유효성 검사 규칙은 다음과 같습니다: + +- **블록 번호**: 현재블록번호 + 1 또는 현재블록번호 + 2여야 합니다. +- **입찰 금액**: 0보다 크고 사용 가능한 예금 잔액보다 작아야 합니다. +- **호출 데이터 크기**: 입찰 데이터 크기\`(64KB)를 초과하지 않아야 합니다. +- **콜 가스 한도**: 입찰가 제한\`(10,000,000)을 초과하지 않아야 합니다. +- **논스**: 경매 진입점\`의 현재 논스와 일치해야 합니다. 로 쿼리하세요: + ```bash + cast call 0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480 "nonces(address)(uint256)" --rpc-url "https://public-en-kairos.node.kaia.io" + ``` +- **서명**: 유효한 EIP-712 서명이어야 합니다(구현 방법은 [submitbid.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go) 참조). +- **보증금 범위**: '입찰 금액 + 예상 가스 요금'을 충당할 수 있는 충분한 보증금이 있어야 합니다. +- **고유성**: 동일한 블록에 다른 낙찰이 있을 수 없습니다(동일한 거래를 대상으로 하지 않는 한). +- **경매인 서명**: 유효해야 합니다(제출 후 경매사가 추가). + +어떤 주체가 어떤 검사를 수행하는지 보여주는 전체 유효성 검사 매트릭스는 [입찰 검증 가이드](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/bid_validation.md)를 참조하세요. + +## 3단계: 보류 중인 거래 구독하기 + +![](/img/build/tutorials/searcher-guide-4.png) + +경매자는 컨센서스 노드에서 직접 보류 중인 트랜잭션을 스트리밍하는 웹소켓 구독 서비스를 제공합니다. 이를 통해 검색자는 MEV 기회를 실시간으로 감지할 수 있습니다. + +SDK는 [example/subscribe_pendingtx.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/subscribe_pendingtx.go)에서 전체 예제를 제공합니다. + +이 예제에서 확인할 수 있습니다: + +- 옥션에 웹소켓 연결 설정하기 +- 보류 중인 트랜잭션 스트림 구독하기 +- 들어오는 트랜잭션을 처리하여 MEV 기회 식별 + +예제를 실행합니다: + +```bash +# From repository root +go run example/subscribe_pendingtx.go +``` + +구독은 보류 중인 트랜잭션이 감지되면 트랜잭션 해시를 계속 인쇄합니다. 이 예제를 확장하여 자신만의 MEV 감지 로직을 구현할 수 있습니다. + +## 4단계: 실행 이해 + +입찰이 낙찰되면 컨센서스 노드는 '경매 진입점' 컨트랙트를 통해 이를 실행합니다: + +![](/img/build/tutorials/searcher-guide-1.png) + +### 실행 흐름 + +실행 프로세스는 세 단계로 구성됩니다: + +1. **검증 단계**: 컨트랙트는 블록 번호, 서명, 논스 및 입찰 금액을 검증합니다. +2. **입찰 결제 단계**: 입찰 금액이 보증금에서 차감되어 에코시스템 펀드로 송금됩니다. +3. **실행 단계**: 엔트리포인트 계약에 의해 백런이 실행됩니다(실행 결과와 관계없이 입찰 대금 지불이 이루어짐). + +**주요 보안 기능:** + +- 검증자가 사용자를 대신하여 입찰을 실행합니다(결제를 회피하기 위해 입찰을 되돌릴 수 없음). +- 논스 증가로 리플레이 공격 방지 +- 이중 서명(검색자+경매인) 무단 입찰 교체 또는 조작 +- 백런 실행 결과와 관계없이 입찰 대금이 지급됩니다. + +자세한 실행 흐름은 [ENTRYPOINT.md 가이드](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/ENTRYPOINT.md)를 참조하세요. + +## 5단계: 자금 인출 + +![](/img/build/tutorials/searcher-guide-5.png) + +출금하려면 잠금 기간이 있는 2단계 절차를 거쳐야 합니다: + +### 1. 예약 출금 + +출금을 시작하고 60초의 잠금 기간을 시작합니다: + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "reserveWithdraw()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 +``` + +### 2. 출금 완료 + +60초 후에 예약 금액을 이체합니다: + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "withdraw()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 +``` + +:::info[Security 참고] + +잠금 기간이 있는 2단계 출금 절차: + +- 활성 경매 기간 동안 플래시 종료 방지 +- 검색자가 입찰가를 준수하도록 보장하여 프로토콜 무결성 유지 +- 빠른 자본 조작 공격으로부터 보호 + +::: + +## API 참조 + +옥션은 검색자를 위해 두 가지 기본 API를 제공합니다: + +**1. 입찰 API 제출** + +- **엔드포인트**: `POST /api/v1/auction/send` +- **목적**: MEV 기회에 대한 밀봉 입찰 제출 + +**2. 보류 중인 거래 구독** + +- **엔드포인트**: `GET /api/v1/subscriber/pendingtx` +- **목적**: 컨센서스 노드에서 보류 중인 트랜잭션의 실시간 스트림 +- **예제**: subscribe_pendingtx.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/subscribe_pendingtx.go)에서 구현 예시를 참조하세요. + +**전체 API 문서:** + +- OpenAPI(Swagger) 사양은 다음에서 확인할 수 있습니다: + - **카이로스**: https://auctioneer-kairos.kaia.io/docs + - **메인넷**: 메인넷 출시 후 사용 가능 +- API 사용법: [API 문서](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/api_doc.md) + +## 문제 해결 + +### 일반적인 문제 + +| 이슈 카테고리 | 증상 | 원인 | 솔루션 | +| -------------- | ------------------------------------ | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **잔액 부족** | 경매사에 의해 입찰이 거부됨 | 보증금 잔액은 입찰 금액 + 예상 가스 요금에 포함되지 않습니다. | 입금잔액()\`으로 잔액을 확인하고 더 많은 KAIA를 입금하세요. | +| **불일치 없음** | 입찰이 거부되거나 실행이 실패합니다. | 논스가 `AuctionEntryPoint`의 현재 논스와 일치하지 않습니다. | 각 입찰 전에 `nonces()`로 현재 논스를 쿼리합니다. 기억하세요: 논스는 제출이 아닌 실행 시에만 증가합니다. | +| **블록 번호 범위** | 경매사에 의해 입찰이 거부됨 | 허용 범위를 벗어난 타겟 블록 `[현재+1, 현재+allowFutureBlock]` | 블록 번호가 범위 내에 있는지 확인합니다(일반적으로 +1 또는 +2). 이중 제출 전략에 대한 FAQ 참조 | +| **유효하지 않은 서명** | 경매사에 의해 입찰이 거부됨 | 잘못된 EIP-712 서명 구성 | 도메인 구분 기호를 확인하고 해시를 입력합니다. 올바른 구현을 위해 [submitbid.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go)를 참조하세요. | +| **가스 한도 문제** | 실행 실패 또는 입찰이 거부됨 | 콜가스한도\`가 너무 낮거나 최대치(10,000,000)를 초과합니다. | 테스트넷에서 백런 로직을 테스트하여 실제 가스 소비량 측정하기 | + +## 자주 묻는 질문 + +### 구독 + +\*\*Q: 검색자당 몇 개의 동시 연결이 허용되나요? + +A: 검색자 주소당 보류 중인 거래 구독 연결은 하나만 허용됩니다. + +\*\*Q: 구독 연결은 얼마나 오랫동안 활성 상태로 유지되나요? + +A: 연결은 24시간이 지나면 자동으로 종료됩니다. 롤링 업데이트가 진행 중인 경우 연결이 24시간보다 일찍 종료될 수 있습니다. + +### API 성능 및 지연 시간 + +\*\*Q: 입찰을 제출할 때 API 지연 시간을 최소화하려면 어떻게 해야 하나요? + +A: 옥션은 HTTPS 프로토콜을 사용하는 L7 로드 밸런서를 사용합니다. 초기 핸드셰이크는 네트워크 상태에 따라 시간이 소요됩니다. 후속 입찰 API를 전송할 때 이러한 초기 지연을 우회하려면 연결 유지 연결을 설정하는 것이 좋습니다. + +\*\*Q: API 요금 제한에 주의해야 하나요? + +A: 경매사 API 서버에 의해 차단되는 것을 방지하려면 짧은 시간 내에 `ping` API를 너무 많이 보내지 마세요. + +\*\*Q: 지리적 위치가 지연 시간에 영향을 주나요? + +A: 예. 경매 서버는 GCP KR(서울) 리전에서 운영 중입니다. 지연 시간을 최소화하고 지리적 지연을 줄이려면 지리적으로 가까운 지역에서 인프라를 호스팅하는 것이 좋습니다. + +### 입찰 타이밍 및 블록 타겟팅 + +\*\*Q: 입찰이 가끔 잘못된 블록 번호를 타겟팅하는 이유는 무엇인가요? + +답변: 입찰 제출 시기는 CN(컨센서스 노드) 채굴 시간에 매우 민감합니다. 경매가 늦게 시작되면(채굴 시간에 가까워지면) 입찰 거래는 다음 블록에 삽입됩니다(블록 번호 +1이 아닌 +2). 즉, 목표 블록 번호를 +2로 설정해야 합니다. + +\*\*Q: 입찰 포함률을 높이려면 어떻게 해야 하나요? + +A: 목표 블록 번호는 본질적으로 CN 채굴 일정에 민감합니다. 즉, +2 블록을 목표로 하지만 이전 처리로 인해 거래가 +1 블록에 삽입되면 입찰이 실패하게 됩니다. 따라서 입찰 트랜잭션을 목표 블록 번호 +1과 목표 블록 번호 +2로 두 번 전송하여 포함 확률을 극대화하는 것이 좋습니다. + +## 모범 사례 + +- **예치금 잔액 모니터링**: 여러 입찰을 감당할 수 있는 충분한 잔액 유지 +- **논스를 주의 깊게 다루기**: 입찰하기 전에 항상 최신 논스를 조회하세요. +- **탐지 최적화**: 더 빠른 MEV 감지로 경쟁 우위 향상 +- **카이로스에서 테스트**: 메인넷 배포 전 테스트넷에서 전략을 검증하세요. +- **결과 모니터링**: MEV Explorer를 통해 경매 결과를 추적하여 입찰 전략을 구체화하세요. +- **적절한 가스 한도 설정**: 충분한 가스와 비용 효율성 사이의 균형 + +## 리소스 + +- [SDK 리포지토리](https://github.com/kaiachain/auctioneer-sdk) +- [KIP-249 사양](https://kips.kaia.io/KIPs/kip-249) +- [예제 코드](https://github.com/kaiachain/auctioneer-sdk/tree/dev/example) +- API 문서: [auctioneer-kaia.io/docs](https://auctioneer-kairos.kaia.io/docs) (카이로스), TBU (메인넷) +- MEV 탐색기: [메브카이로스](https://mev-kairos.kaia.io) (카이로스), TBU (메인넷) +- [FAQ](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/FAQ.md) + +## 도움 받기 + +문제나 질문이 있는 경우 + +- 카이아 개발자 포럼](https://devforum.kaia.io)에 게시하세요. +- SDK 리포지토리](https://github.com/kaiachain/auctioneer-sdk/issues)에서 이슈를 엽니다. diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md new file mode 100644 index 000000000000..42d21b01977c --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md @@ -0,0 +1,325 @@ +# Pyth를 사용하여 Kaia에서 실시간 가격 가져오기 방법 + +## 소개 + +Pyth는 주로 푸시 기반 오라클로 구동되는 생태계에서 독특한 접근 방식을 취하는 탈중앙화 오라클 네트워크입니다. 고정된 간격으로 데이터를 계약에 푸시하는 대신 Pyth를 사용하면 필요에 따라 실제 데이터를 가져올 수 있습니다. 이 모델은 개발자에게 더 많은 제어권을 부여하고 불필요한 온체인 업데이트를 방지하는 데 도움이 됩니다. 이 통합을 통해 개발자는 실시간 데이터를 가져오고 업데이트가 요청된 경우에만 요금이 적용되는 사용량 기반 유료 모델을 사용할 수 있습니다. + +이 가이드에서는 Pyth의 실시간 가격 피드를 사용하여 법정 화폐인 IDR의 가치를 읽는 방법을 알아보세요. 솔리디티 스마트 컨트랙트는 [pyth-sdk-solidity](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity)를 사용하여 Pyth에서 USD/IDR 가격을 검색하고, [hermes-client](https://github.com/pyth-network/pyth-crosschain/tree/main/apps/hermes/client/js)를 사용하여 최신 가격을 업데이트하고 가져옵니다. + +빠르게 시작하려면 이 튜토리얼의 전체 코드를 [GitHub](https://github.com/ayo-klaytn/pyth-kaia-hardhat-example)에서 확인할 수 있습니다. 이는 바로 사용할 수 있는 참조를 제공하며 프로젝트와 설치를 더 빠르게 설정하는 데 도움이 됩니다. + +## 전제 조건 + +시작하기 전에 다음 사항이 준비되어 있는지 확인하세요: + +- [Node.js 및 npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) + + 종속성을 설치하고 개발 도구를 실행하는 데 필요합니다. + +- KAIA 테스트넷 토큰으로 자금을 조달한 지갑입니다. + + 카이로스 테스트넷의 배포 및 트랜잭션 가스 수수료를 지불하려면 KAIA가 필요합니다. 카이아 수도꼭지](https://faucet.kaia.io/)에서 무료 테스트넷 KAIA를 신청할 수 있습니다. + +## 개발 환경 설정 + +이 섹션에서는 개발 환경을 설정하고, 오라클 컨트랙트를 컴파일하고, Hardhat을 사용하여 배포할 수 있도록 준비합니다. + +**1. 하드햇 프로젝트 만들기** + +프로젝트의 새 디렉터리를 만들고 하드햇을 초기화합니다: + +```bash +mkdir pyth-kaia-hardhat-example && cd pyth-kaia-hardhat-example +npm init -y +npx hardhat@next --init +``` + +메시지가 표시되면 기본 응답을 수락합니다. 이 가이드에서는 모카 및 이더 템플릿을 사용합니다. + +하드햇 버전을 확인하여 설치를 확인합니다: + +```bash +npx hardhat --version +``` + +**2. 암호화된 비밀 설정** + +이제 하드햇의 암호화된 키 저장소를 사용하여 RPC URL과 개인 키를 저장합니다. + +다음 명령을 실행합니다: + +```bash +npx hardhat keystore set KAIROS_RPC_URL +npx hardhat keystore set PRIVATE_KEY +``` + +각 변수에 대한 비밀번호와 값을 입력하여 암호화된 상태로 유지하세요. + +**3. 구성 파일의 참조 비밀** + +hardhat.config.ts\`를 열고 네트워크 섹션을 업데이트하여 암호화된 비밀번호를 참조하세요. 다른 비밀 이름을 사용했다면 그에 따라 키를 업데이트하세요. + +```typescript +import { configVariable } from "hardhat/config"; +module.exports = { + networks: { + kairos: { + url: configVariable("KAIROS_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + }, +}; +``` + +## 계약 생성 및 파이썬 오라클에서 가격 가져오기 + +이 섹션에서는 [파이스 솔리디티 SDK](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity)를 설치하고, PriceConsumer 컨트랙트를 생성한 후, 하드햇을 사용하여 배포합니다. 계약은 나중에 Hermes에서 가져온 가격 데이터를 사용하여 업데이트할 Pyth 가격 피드를 읽습니다. + +### Pyth SDK 설치 + +파이스는 온체인 파이스 가격 피드 콘트랙트와 상호작용할 수 있는 솔리디티 SDK를 제공합니다. SDK는 IPyth 인터페이스와 관련 구조를 노출합니다. + +npm으로 SDK를 설치합니다: + +```bash +npm install --save-dev @pythnetwork/pyth-sdk-solidity +``` + +### PriceConsumer 컨트랙트 생성 + +계약/가격소비자.sol\`에 새 파일을 만들고 다음 코드를 추가합니다: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; +import "@pythnetwork/pyth-sdk-solidity/IPyth.sol"; +import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol"; +contract PriceConsumer { + IPyth public pyth; + constructor(address pythContract) { + pyth = IPyth(pythContract); + } + function updatePrice(bytes[] calldata priceUpdateData) + external + payable + { + // Pay the Pyth fee for receiving price updates + uint fee = pyth.getUpdateFee(priceUpdateData); + require(msg.value >= fee, "Not enough fee sent"); + // Update the Pyth price state + pyth.updatePriceFeeds{value: fee}(priceUpdateData); + // Can fetch the price and use it as well + //PythStructs.Price memory currentBasePrice = pyth.getPriceNoOlderThan(priceFeedId, 60); + } + function getLatestPrice(bytes32 priceFeedId) public view returns (int64, int32) { + // Read the current price from a price feed if it is less than 60 seconds old. + // Each price feed (e.g., USD/IDR) is identified by a price feed ID. + // The complete list of feed IDs is available at https://docs.pyth.network/price-feeds/price-feeds + PythStructs.Price memory currentBasePrice = pyth.getPriceNoOlderThan(priceFeedId, 60); + + // uint256 basePrice = PythUtils.convertToUint( + // currentBasePrice.price, + // currentBasePrice.expo, + // 18 + // ); + + return (currentBasePrice.price, currentBasePrice.expo); + } +} +``` + +**워크스루** + +PriceConsumer 계약: + +- Pyth 인터페이스와 구조체를 `@pythnetwork/pyth-sdk-solidity`에서 가져옵니다. +- 스토어: + - 파이스 컨트랙트 인스턴스(pyth)입니다. + - USD/IDR의 가격 피드 ID(usdIdrPriceId)입니다. +- updateAndGetUsdIdrPrice\`를 노출합니다: + - IPyth.getUpdateFee를 사용하여 업데이트 수수료를 계산합니다. + - 필요한 수수료와 함께 IPyth.updatePriceFeeds를 호출합니다. + - 새로운 USD/IDR 가격을 확인하려면 IPyth.getPriceNoOlderThan을 호출하세요. + - 원시 가격, 지수, 게시 시간을 반환합니다. + +나중에 오프체인 헤르메스 클라이언트는 가격 업데이트 바이트 배열을 생성하고 새로운 가격이 필요할 때 이 함수에 전달합니다. + +### 계약서 컴파일 + +다음 명령을 실행하여 컨트랙트를 컴파일합니다: + +``` +npx hardhat compile +``` + +## 컨트랙트 배포 + +PriceConsumer 컨트랙트를 배포하려면 Ignition 모듈을 생성한 다음 배포 명령을 실행합니다. + +**이그니션 모듈 만들기** + +'ignition/modules/PriceConsumer.ts'에 새 파일을 생성합니다: + +```typescript +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const pythContractAddress = "0x2880ab155794e7179c9ee2e38200202908c17b43"; +export default buildModule("PriceConsumerModule", (m) => { + const priceConsumer = m.contract("PriceConsumer", [pythContractAddress]); + return { priceConsumer }; +}); +``` + +**계약 배포** + +이그니션 모듈을 사용하여 PriceConsumer 컨트랙트를 카이로스 테스트넷에 배포합니다: + +```bash +npx hardhat ignition deploy --network kairos ignition/modules/PriceConsumer.ts +``` + +메시지가 표시되면 앞서 암호화된 비밀에 대해 구성한 키 저장소 비밀번호를 입력합니다. + +이 작업이 완료되면 `PriceConsumer.sol` 컨트랙트가 카이로스 테스트넷에 배포되고 파이스로부터 실시간 USD/IDR 가격을 사용할 준비가 된 것입니다. + +## 타입스크립트에서 상호 작용 + +이 마지막 단계에서는 TypeScript를 사용하여 배포된 PriceConsumer 컨트랙트와 상호 작용합니다. 이 스크립트는 헤르메스 클라이언트를 통해 파이스 가격 업데이트 데이터를 요청하고 이를 온체인으로 전송하여 최신 USD/IDR 가격을 가져옵니다. + +**종속성 설치** + +필요한 패키지를 설치합니다: + +```bash +npm install --save-dev tsx @pythnetwork/hermes-client @dotenv +``` + +**.env 설정** + +프로젝트의 루트 디렉터리에 .env 파일을 만들고 개인 키를 추가합니다: + +```bash +PRIVATE_KEY="0xDEAD....." // REPLACE WITH YOUR PRIVATE KEY +``` + +**인터랙션 스크립트 만들기** + +스크립트/인터랙트.ts\*\*에 새 파일을 만들고 다음을 추가합니다: + +```typescript +import { HermesClient } from "@pythnetwork/hermes-client"; +import { ethers } from "ethers"; +import 'dotenv/config' + +// 1. Setup +const hermes = new HermesClient("https://hermes.pyth.network"); +const provider = new ethers.JsonRpcProvider( + "https://public-en-kairos.node.kaia.io" +); + +const PK = process.env.PRIVATE_KEY; +const wallet = new ethers.Wallet(PK, provider); + + +// 2. Your deployed contract +const priceConsumerAddress = "0x91e89aa32224dEd5dA483a83a4de45bF4bE57caA"; // REPLACE WITH DEPLOYED PRICE CONSUMER CONTRACT + +const priceConsumerAbi = [ + "function updatePrice(bytes[] priceUpdateData) external payable", + "function getLatestPrice(bytes32 priceId) public view returns(int64, int32)", +]; + +const priceConsumer = new ethers.Contract( + priceConsumerAddress, + priceConsumerAbi, + wallet +); + +// 3. Price feed IDs +const priceId = + "0x6693afcd49878bbd622e46bd805e7177932cf6ab0b1c91b135d71151b9207433"; // FX.USD/IDR Beta Price Feed ID + +async function run() { + // Fetch Hermes price update binary + const update = await hermes.getLatestPriceUpdates([priceId], { + encoding: "hex", + }); + console.log(update); + + const priceUpdateData = ["0x" + update.binary.data]; // must be array of bytes + + console.log(priceUpdateData); + + // Estimate fee required by Pyth contract + // EVM Network Price Feed Contract Addresses: https://docs.pyth.network/price-feeds/core/contract-addresses/evm + + const pythContractAddress = "0x2880ab155794e7179c9ee2e38200202908c17b43"; + const pythAbi = [ + "function getUpdateFee(bytes[] calldata data) external view returns(uint)", + ]; + console.log("Pyth contract address:", pythContractAddress); + const pyth = new ethers.Contract(pythContractAddress, pythAbi, wallet); + const fee = await pyth.getUpdateFee(priceUpdateData); + console.log("Pyth fee:", fee.toString()); + + // Call your contract + const tx = await priceConsumer.updatePrice(priceUpdateData, { + value: fee, // pay the pyth update fee + gasLimit: 500000, + }); + console.log("Tx sent:", tx.hash); + const receipt = await tx.wait(); + console.log("Tx confirmed"); + console.log(receipt); + + // 4. Get latest price from contract + try { + console.log("=== Latest Price from Contract ==="); + const [price, expo] = await priceConsumer.getLatestPrice(priceId); + console.log("Price Value : " + price.toString()); + console.log("Exponent Value : " + expo.toString()); + } catch (error) { + console.log(error); + // @ts-ignore + console.error("\nError calling getLatestPrice:", error.message); + console.log( + "This usually means the price is older than 60 seconds or hasn't been updated yet." + ); + console.log("Make sure updatePrice() was called successfully first."); + } +} +run(); + +``` + +**스크립트 실행** + +스크립트를 실행합니다: + +```bash +npx tsx scripts/interact.ts +``` + +**출력 예시** + +```bash +Tx sent: 0x79c5dcb7abd9605b070bf9062ba2e2382272d23d58f7b50446c3107b7784fc8e +Tx confirmed +=== Latest Price from Contract === +Price Value : 1669784988 +Exponent Value : -5 +======== —— ========= +``` + +거래 해시를 검색창에 붙여넣어 카이로스 탐색기에서 거래를 확인할 수 있습니다. 이렇게 하면 업데이트 및 읽기 작업이 성공했음을 확인할 수 있습니다. + +## 결론 + +이 튜토리얼에서는 파이스에서 실시간 가격을 읽는 솔리디티 컨트랙트를 생성하고, 이를 카이로스 테스트넷에 배포한 다음, 헤르메스 클라이언트를 사용해 상호작용했습니다. 또한 Pyth의 풀 기반 설계를 통해 가격 업데이트 시기와 방법을 제어하는 방법도 배웠습니다. + +자세한 내용은 탐색하기에서 확인하세요: + +- Pyth API용 [EVM 계약 참조](https://api-reference.pyth.network/price-feeds/evm/getPriceNoOlderThan) +- 완전한 엔드투엔드 구현을 위한 [Pyth Oracle AMM 예제](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/evm)를 확인하세요. + + + diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md b/i18n/ko/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md index 6d871978b860..48c4fac94c75 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md @@ -190,33 +190,44 @@ Kaia에는 검증되지 않은 블록 실행 시간 제한이 있습니다. 유 | TSTORE | 280 | | TLOAD | 220 | | MCOPY | 250 | +| CLZ | 0 | ## 미리 컴파일된 컨트랙트 계산 비용 표 `Input`은 미리 컴파일된 컨트랙트의 바이트 배열 입력입니다. -| 주소 | 미리 컴파일된 컨트랙트 | 계산 비용 | -| :---- | :------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 0x01 | ecrecover | 113,150 | -| 0x02 | sha256hash | numOfWords(input) / 32 \* 100 + 1,000 | -| 0x03 | ripemd160hash | numOfWords(input) / 32 \* 10 + 100 | -| 0x04 | dataCopy | 0 | -| 0x05 | bigModExp | see the code [here](https://github.com/kaiachain/kaia/blob/75c149a464998eb946311f3a290d4b1ea339eaba/blockchain/vm/contracts.go#L340) | -| 0x06 | bn256Add | 8,000 | -| 0x07 | bn256ScalarMul | 100,000 | -| 0x08 | bn256Pairing | numOfPairings(input) \* 1,000,000 + 2,000,000 | -| 0x09 | blake2f | bigEndian(getRounds(input[0:4])) \* 10 + 10,000 | -| 0x0A | kzg | 2,200,000 | -| 0x3FD | vmLog | 10 | -| 0x3FE | feePayer | 10 | -| 0x3FF | validateSender | numOfSigs(input) \* 180,000 + 10,000 | +| 주소 | 미리 컴파일된 컨트랙트 | 계산 비용 | +| :---- | :----------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 0x01 | ecrecover | 113,150 | +| 0x02 | sha256hash | numOfWords(input) / 32 \* 100 + 1,000 | +| 0x03 | ripemd160hash | numOfWords(input) / 32 \* 10 + 100 | +| 0x04 | dataCopy | 0 | +| 0x05 | bigModExp | 코드 참조 [여기](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L586) | +| 0x06 | bn256Add | 8,000 | +| 0x07 | bn256ScalarMul | 100,000 | +| 0x08 | bn256Pairing | numOfPairings(input) \* 1,000,000 + 2,000,000 | +| 0x09 | blake2f | bigEndian(getRounds(input[0:4])) \* 10 + 10,000 | +| 0x0A | kzg | 2,200,000 | +| 0x3FD | vmLog | 10 | +| 0x3FE | feePayer | 10 | +| 0x3FF | validateSender | numOfSigs(input) \* 180,000 + 10,000 | +| 0x0b | bls12381G1Add | 18,750 | +| 0x0c | bls12381G1MultiExp | 코드 참조 [여기](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L1155) | +| 0x0d | bls12381G2Add | 30,000 | +| 0x0e | bls12381G2MultiExp | 코드 참조 [여기](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L1261) | +| 0x0f | bls12381페어링 | numOfPairings(입력) \* 1,630,000 + 1,885,000 | +| 0x10 | bls12381MapG1 | 275,000 | +| 0x11 | bls12381MapG2 | 1,190,000 | +| 0x100 | p256확인 | 235,000 | ## 하드포크 변경 사항 -| 하드포크 | 신규 항목 | 변경 사항 | | | -| ------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | - | -| Cancun EVM | BLOBBASEFEE (0x49)
BLOBHASH (0x50)
TSTORE (0x5c) opcode
TLOAD (0x5d)
MCOPY (0x5e)
kzg (0x0a) precompiled contract | increase the computation cost limit
from 100,000,000 to 150,000,000

reduce the computation cost of some opcodes
due to cpu performance increase
-Sdiv (0x05): 739 -> 360
-Mod (0x06): 812 -> 320
-Addmod (0x08): 1410 -> 360
-Mulmod (0x09): 1760 -> 700
-Exp (0x0A): 5000 -> 720
-Sha3 (0x20): 2465 -> 560
-Mstore8 (0x53): 5142 -> 230
-Log1, Log2, Log3, Log4 (0xA1-0xA4): 1000 -> 500

increase the computation cost of some opcodes
due to increased database size
-SLOAD (0x54): 835 -> 2550
-SSTORE (0x55): 1548 -> 2510 | | | -| Shanghai EVM | PUSH0 (0x5f) opcode | | | | -| Kore | | modExp (0x05) precompiled contract
use new gas calculation logic.
Computation cost also affected.
Become more accurate. | | | -| London EVM | BaseFee (0x48) opcode | | | | -| Istanbul EVM | CHAINID (0x46) opcode
SELFBALANCE (0x47) opcode
blake2f (0x09) precompiled contract | reduce the computation cost of over-priced opcodes
- ADDMOD (0x08): 3349 -> 1410
- MULMOD (0x09): 4757 -> 1760
- XOR (0x18): 657 -> 454
- NOT (0x19): 1289 -> 364
- SHL (0x1B): 1603 -> 478
- SHR (0x1C): 1815 -> 834 | | | +| 하드포크 | 신규 항목 | 변경 사항 | +| ------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 오사카 EVM | CLZ (0x1e) opcode
p256검증 (0x100) 사전 컴파일된 컨트랙트 | modExp (0x05) precompiled contract
use new gas calculation logic.
Computation cost also affected.
Become more accurate. | +| 프라하 EVM | bls12381G1Add (0x0b) 사전 컴파일된 컨트랙트
bls12381G1MultiExp (0x0c) 사전 컴파일된 컨트랙트
bls12381G2Add (0x0d) 사전 컴파일된 컨트랙트
bls12381G2MultiExp (0x0e) 미리 컴파일된 컨트랙트
bls12381Pairing (0x0f) 미리 컴파일된 컨트랙트
bls12381MapG1 (0x10) 미리 컴파일된 컨트랙트
bls12381MapG2 (0x11) 미리 컴파일된 컨트랙트
| | +| Cancun EVM | BLOBBASEFEE (0x49) opcode
BLOBHASH (0x50) opcode
TSTORE (0x5c) opcode
TLOAD (0x5d) opcode
MCOPY (0x5e) opcode
kzg (0x0a) precom파일된 컨트랙트 | increase the computation cost limit
from 100,000,000 to 150,000,000

reduce the computation cost of some opcodes
due to cpu performance increase
-Sdiv (0x05): 739 -> 360
-Mod (0x06): 812 -> 320
-Addmod (0x08): 1410 -> 360
-Mulmod (0x09): 1760 -> 700
-Exp (0x0A): 5000 -> 720
-Sha3 (0x20): 2465 -> 560
-Mstore8 (0x53): 5142 -> 230
-Log1, Log2, Log3, Log4 (0xA1-0xA4): 1000 -> 500

increase the computation cost of some opcodes
due to increased database size
-SLOAD (0x54): 835 -> 2550
-SSTORE (0x55): 1548 -> 2510 | +| Shanghai EVM | PUSH0 (0x5f) opcode | | +| Kore | | modExp (0x05) 사전 컴파일된 컨트랙트
새로운 가스 계산 로직을 사용합니다.
계산 비용도 영향을 받았습니다.
더 정확해지세요. | +| London EVM | BaseFee (0x48) opcode | | +| Istanbul EVM | CHAINID (0x46) opcode
SELFBALANCE (0x47) opcode
blake2f (0x09) precompiled contract | reduce the computation cost of over-priced opcodes
- ADDMOD (0x08): 3349 -> 1410
- MULMOD (0x09): 4757 -> 1760
- XOR (0x18): 657 -> 454
- NOT (0x19): 1289 -> 364
- SHL (0x1B): 1603 -> 478
- SHR (0x1C): 1815 -> 834 | diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md b/i18n/ko/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md index 8ccca785f6cb..0523a8a8010b 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md @@ -34,7 +34,7 @@ To get traces with the debug API, you first need to decide what kind of informat Kaia's `callTracer` output format is identical to go-ethereum except for following: -- For revered transactions, both fields are provided. +- 역방향 트랜잭션의 경우 두 필드가 모두 제공됩니다. - `result.revertReason`: revert reason string, if any. - `result.reverted.contract`: the address of the reverted contract. - `result.reverted.message`: same as revertReason diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md b/i18n/ko/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md new file mode 100644 index 000000000000..8a8652c0ccfb --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md @@ -0,0 +1,107 @@ +# 스토리지 최적화 + +카이아 블록체인이 성장함에 따라 체인 데이터를 저장하는 데 필요한 스토리지도 증가하고 있습니다. Kaia는 증가하는 스토리지 요구 사항을 관리하기 위해 두 가지 주요 기술을 구현합니다: + +## 상태 일괄 가지치기(상태 마이그레이션) + +상태 마이그레이션은 실행 중인 노드를 중단하지 않고 기존 노드에 적용할 수 있는 일괄 가지치기 기능입니다. + +### 동기 부여 + +블록 상태 또는 스테이트DB는 온체인 계정과 컨트랙트를 트라이 데이터 구조에 저장합니다. 트라이 데이터 구조는 사용되지 않는 상태와 최근 상태를 모두 저장하도록 설계되어 머클 해시를 사용하여 확인할 수 있습니다. 트랜잭션이 상태 변경을 수행하면 상태 트라이가 무한정 증가합니다. 현재(2024년 8월) 카이아 메인넷 아카이브 노드 크기는 20TB가 넘고, 풀 노드도 10TB가 넘습니다. + +### 개념 + +상태 마이그레이션은 새 블록을 처리하는 데 필요하지 않은 이전 블록 상태를 삭제합니다. 상태 트라이를 "이전"에서 "새"로 복사합니다. 모든 트라이 노드가 복사되는 것은 아닙니다. 선택적 블록의 상태 루트에서 도달할 수 있는 블록이 복사됩니다. 복사 후에는 이전 디렉터리가 삭제되므로 선택한 블록의 상태만 남게 됩니다. + +더 자세한 기술적인 내용은 다음 블로그 글을 참조하세요: +[상태 마이그레이션: 노드 스토리지 절약](https://medium.com/klaytn/klaytn-v1-5-0-state-migration-saving-node-storage-1358d87e4a7a), +[카이아 상태 마이그레이션: 블록체인 데이터를 줄이는 효율적인 방법](https://medium.com/klaytn/klaytn-state-migration-an-efficient-way-to-reduce-blockchain-data-6615a3b36523) + +일괄 가지치기를 수행하는 방법은 [상태 마이그레이션 가이드](../../misc/operation/node-pruning.md#how-to-perform-batch-pruning)를 참조하세요. + +## 상태 라이브 가지치기 + +상태 라이브 가지치기는 증가하는 상태 데이터베이스 크기 문제에 대한 새로운 솔루션입니다. 배치 가지치기(상태 마이그레이션)와 달리 라이브 가지치기는 노드 프로세스가 블록화되면서 오래된 상태를 조금씩 자동으로 삭제합니다. + +### 동기 부여 + +블록 상태 또는 스테이트DB는 온체인 계정과 컨트랙트를 트라이 데이터 구조에 저장합니다. 트라이 데이터 구조는 사용되지 않는 상태와 최근 상태를 모두 저장하도록 설계되어 머클 해시를 사용하여 확인할 수 있습니다. 트랜잭션이 상태 변경을 수행하면 상태 트라이가 무한정 증가합니다. 현재(2025년 8월) 카이아 메인넷 아카이브 노드 크기는 20TB가 넘고, 풀 노드도 10TB가 넘습니다. + +이전에는 상태 마이그레이션을 통해 최근 상태만 선택적으로 복사하고 나머지는 삭제하여 이전 상태를 삭제함으로써 이 문제를 완화했습니다. 이렇게 하면 전체 노드 크기를 5TB 미만으로 줄일 수 있습니다. + +그럼에도 불구하고 상태 마이그레이션에는 단점이 있습니다. 전체 주 트라이를 통과하는 데 며칠이 걸릴 수 있는 높은 오버헤드가 발생합니다. 또한 상태 마이그레이션은 수동으로 트리거해야 합니다. 이러한 한계를 극복하기 위해 라이브 가지치기 기법이 도입되었습니다. + +### 개념 + +트라이 노드가 오래되었는지 여부를 알 수 없기 때문에 트라이 가지치기가 어렵습니다. 원래 상태 트라이 구조에서 트라이 노드는 각각 다른 블록을 구성하는 여러 트라이의 일부가 될 수 있습니다. 트라이 노드(예: 계정 잔액)가 다른 값으로 업데이트되더라도 다른 부모 노드에서 여전히 필요할 수 있으므로 트라이 노드를 삭제할 수 없습니다. 이 문제를 해시 중복 문제라고 합니다. + +라이브 가지치기는 동일한 콘텐츠를 가진 트라이 노드를 의도적으로 복제합니다. 라이브 가지치기에서 트라이 노드는 해시로 참조되지 않고, 그 대신 ExtHash로 참조됩니다. ExtHash는 콘텐츠의 32바이트 해시에 7바이트 직렬 인덱스를 더한 값입니다. 직렬 인덱스는 단조롭게 증가하므로 모든 트라이 노드는 고유합니다. + +``` +Hash: 32-byte Keccak256 +ExtHash: 32-byte Keccak256 + 7-byte Serial index +``` + +이렇게 하면 트라이 노드의 콘텐츠가 변경될 때마다 해당 트라이 노드가 더 이상 사용되지 않는다고 가정해도 안전합니다. 머클 해시는 직렬 인덱스를 무시하는 것만으로도 동일한 방식으로 계산할 수 있으며, 합의 측면에서 비라이브 프루닝 노드와 호환됩니다. + +자세한 기술적인 내용은 이 블로그 글을 참조하세요: [StateDB 라이브 프루닝을 통한 블록체인 데이터 용량의 효율적인 관리](https://medium.com/klaytn/strong-efficient-management-of-blockchain-data-capacity-with-statedb-live-pruning-strong-6aaa09b05f91). + +실시간 가지치기를 활성화하는 방법은 [실시간 가지치기 가이드](../../misc/operation/node-pruning.md#how-to-perform-live-pruning)를 참조하세요. + +## 데이터 압축 + +데이터 압축은 선택한 데이터베이스 테이블에 LevelDB의 내장된 Snappy 압축 알고리즘을 적용하여 블록 데이터의 저장 크기를 줄입니다. + +### 동기 부여 + +헤더, 트랜잭션 본문, 영수증으로 구성된 블록 데이터는 EVM 트랜잭션의 ABI 인코딩 표준으로 인해 매우 반복적인 바이트 시퀀스를 포함하는 경우가 많습니다. 예를 들어 솔리디티의 ABI 인코딩은 32바이트 단어 정렬을 충족하기 위해 제로 패딩을 사용하므로 트랜잭션 호출 데이터에 0이 길게 나열되는 결과를 초래합니다. 트랜잭션 영수증은 이벤트 로그와 반환 값에서 비슷한 패턴을 보입니다. + +이러한 자연스러운 중복성에도 불구하고 Kaia의 기본 LevelDB 스토리지 엔진은 기본적으로 압축을 활용하지 않아 반복적인 데이터가 불필요하게 디스크 공간을 소비하게 했습니다. 2025년 7월 기준, 카이아 메인넷의 전체 노드는 4.2TB 이상의 스토리지를 차지했으며, 이 중 약 3.6TB가 압축되지 않은 블록 데이터에 할당되었습니다. + +### 개념 + +Kaia v2.1.0은 데이터베이스 테이블에 선택적으로 적용하여 LevelDB의 Snappy 압축 알고리즘을 활성화합니다. db.leveldb.compression\` 플래그를 사용하면 세분화된 제어가 가능합니다: + +- 헤더, 본문 및 영수증 압축(높은 중복성, 상당한 비용 절감) +- 상태 테스트 데이터는 제외됨(무작위로 표시, 최소한의 압축 혜택) + +기존 노드의 경우 데이터베이스 압축을 수동으로 트리거하면 압축되지 않은 오래된 데이터가 압축된 형식으로 다시 작성됩니다. 이 '하우스키핑' 프로세스는 SSTables를 병합하고, 삭제를 조정하고, 부작용으로 압축을 적용합니다. + +\*\*결과: 메인넷 전체 노드에서 총 스토리지가 약 50% 감소(약 2TB 절감)했으며, 본체와 영수증 테이블에서 대부분 증가했습니다. 이 프로세스는 약 10시간이 소요되며 일반 블록 처리와 동시에 실행할 수 있습니다. + +자세한 기술적인 내용은 이 블로그 글을 참조하세요: [Kaia v2.1이 압축을 통해 2TB를 회수한 방법](https://blog.kaia.io/cutting-blockchain-storage-in-half/). + +압축을 활성화하는 방법은 [노드 스토리지 최적화 가이드](../../misc/operation/optimize-storage.md#database-compression)를 참조하세요. + +## 플랫트리 상태 체계(실험적) + +FlatTrie는 과거 계정 상태 저장 방식을 재구성하여 아카이브 노드 상태 데이터베이스 크기를 대폭 줄이는 실험적인 상태 저장 방식입니다. + +### 동기 부여 + +아카이브 노드는 모든 블록 높이의 모든 계정에 대한 완전한 기록 상태 데이터를 보유하여 시간 여행 쿼리와 포괄적인 블록체인 분석을 가능하게 해야 합니다. 2025년 8월 현재 카이아 메인넷 아카이브 노드에는 35TB 이상의 디스크 공간이 필요하며, 이 중 31TB(89%)는 스테이트 데이터베이스가 차지합니다. + +기존의 머클 패트리샤 트리(MPT) 구조는 계정 데이터(리프)와 머클 트리를 구성하는 중간 지점 노드를 모두 저장합니다. 아카이브 노드는 역사적으로 여러 블록 높이에 대해 완전한 MPT를 유지했기 때문에 계정 데이터 자체를 전달하지 않는 중간 노드가 무한정 누적되는 문제가 발생했습니다. + +상태 마이그레이션](https://medium.com/klaytn/klaytn-v1-5-0-state-migration-saving-node-storage-1358d87e4a7a)(일괄 가지치기)과 [상태DB 라이브 가지치기](https://medium.com/klaytn/strong-efficient-management-of-blockchain-data-capacity-with-statedb-live-pruning-strong-6aaa09b05f91)와 같은 기존 스토리지 최적화는 기본적으로 기록 데이터를 삭제해야 하므로 전체 기록을 보존해야 하는 아카이브 노드에는 적용이 불가능합니다. + +### 개념 + +플랫트리는 [에리곤 이더리움 클라이언트](https://github.com/erigontech/erigon/)에서 채택한 실험적인 상태 저장 방식입니다. 상태 저장소를 재구성하는 기준은 다음과 같습니다: + +- 플랫 키-값 테이블에 과거 계정 상태 저장(단순 주소 → 계정 데이터 매핑) +- 모든 중간 지점 노드와 함께 최신 블록의 전체 MPT만 유지 관리 +- 필요한 분기 노드만 임시로 구축하여 온디맨드 방식으로 과거 머클 루트를 재구성합니다. + +이 접근 방식은 전체 계정 상태 기록과 모든 블록에 대한 머클 루트를 확인할 수 있는 기능을 보존하면서 과거 중간 노드의 영구적인 저장을 제거합니다. + +**적응 과제:** 에리곤의 구현은 이더리움의 계정 구조를 가정합니다. Kaia는 사람이 읽을 수 있는 주소 및 여러 키 유형과 같은 고유한 기능을 지원하기 위해 다른 RLP 인코딩을 사용합니다. 통합을 위해서는 계정을 불투명한 바이트 문자열로 처리하도록 Erigon의 Merkle 해싱 모듈을 수정하고, Kaia의 멀티스레드 Trie 인터페이스와 Erigon의 싱글스레드 MDBX 데이터베이스 요구 사항을 연결하기 위해 3개의 어댑터 계층(DomainsManager, WriteBuffer, DeferredContext)을 만들어야 했습니다. + +**결과:** 카이로스 테스트넷 실험에서 FlatTrie 아카이브 노드는 기존 아카이브 노드보다 총 스토리지 사용량이 약 75% 적었으며, 상태 데이터베이스 크기는 80% 이상 감소했습니다. 메인넷 아카이브 노드에서도 비슷한 절감 효과가 있을 것으로 예상됩니다(~35TB에서 ~10TB). + +**제한 사항:** 실험적인 v2.1.0 구현은 블록 되돌리기(`debug_setHead` API), 머클 증명 생성(`eth_getProof` API), 상태 가지치기 기능을 지원하지 않습니다. 이러한 제한은 과거 브랜치 노드를 버리기로 한 FlatTrie의 설계 선택에서 비롯된 것입니다. + +자세한 기술적 내용은 이 블로그 글을 참조하세요: [카이아의 아카이브 노드를 위한 실험적 FlatTrie](https://blog.kaia.io/flatten-the-state-shrink-the-disk/). + +FlatTrie를 활성화하는 방법은 [노드 스토리지 최적화 가이드](../../misc/operation/optimize-storage.md#flattrie-state-scheme-experimental)를 참조하세요. diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/misc/faq.md b/i18n/ko/docusaurus-plugin-content-docs/current/misc/faq.md index 1da25eecea5d..2ab91cd99834 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/misc/faq.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/misc/faq.md @@ -3,6 +3,7 @@ - [FAQ](#faq) - [Kaia란 무엇인가요? ](#what-is-kaia-) - [Kaia는 어떻게 이더리움 동등성을 지원하나요? ](#how-does-kaia-support-ethereum-equivalence-) + - [카이아의 버전 관리 정책은 무엇인가요? ](#what-is-kaias-versioning-policy-) - [Kaia의 가스 정책은 무엇인가요? ](#what-is-kaias-gas-policy-) - [Kaia 계정 구조의 특별한 점은 무엇인가요? ](#what-is-special-about-kaias-account-structure-) - [Kaia로 디앱 개발은 어디서 시작할 수 있나요? ](#where-can-i-start-dapp-development-with-kaia-) @@ -30,6 +31,10 @@ Kaia is a high-performance Layer 1 blockchain designed for the mass adoption of Kaia is EVM-compatible and supports all Ethereum Cancun EVM features except EIP-4844 blob transactions. It provides the `eth` namespace RPC API, allowing seamless use of Ethereum SDKs and tools. Kaia-specific transaction types are represented as Type 0 legacy transactions within the eth namespace APIs, so Ethereum SDKs do not need to be aware of them. +## Kaia의 버전 관리 정책은 무엇인가요? + +github](https://github.com/kaiachain/kaia/blob/dev/CONTRIBUTING.md#versioning-policy)에서 확인할 수 있습니다. + ## Kaia의 가스 정책은 무엇인가요? Kaia uses a dynamic gas fee model that maintains low fees during normal network conditions but adjusts fees based on network congestion. The gas fee can change within a limited range per block, helping prevent network spam while keeping fees predictable. A portion of every transaction fee is automatically burned. The model prioritizes user experience and enterprise-friendliness while maintaining network stability. @@ -139,4 +144,4 @@ You can find complete working examples of fee delegation using several different - ethers-ext: [fee delegated value transfer example](https://docs.kaia.io/references/sdk/ethers-ext/v6/fee-delegated-transaction/value-transfer/) - web3js-ext: [fee delegated value transfer example](https://docs.kaia.io/references/sdk/web3js-ext/fee-delegated-transaction/value-transfer/) - web3j-ext: [fee delegated value transfer example](https://docs.kaia.io/references/sdk/web3j-ext/fee-delegated-transaction/value-transfer/) -- web3py-ext: [fee delegated value transfer example](https://docs.kaia.io/references/sdk/web3py-ext/fee-delegated-transaction/value-transfer/) \ No newline at end of file +- web3py-ext: [fee delegated value transfer example](https://docs.kaia.io/references/sdk/web3py-ext/fee-delegated-transaction/value-transfer/) diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md b/i18n/ko/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md index 80139e80ba1d..b3bdedc43899 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md @@ -43,7 +43,7 @@ This FAQ addresses common questions and concerns for CEXs, node providers, walle ### What happened to Klaytn and Finschia? -Klaytn and Finschia merged to form Kaia through governance decisions made by both chains. You can view the voting results [here](https://medium.com/kaiachain/klaytn-and-finschia-merge-proposal-passes-creating-asias-largest-blockchain-ecosystem-7af570eb069a). The utility tokens of the two chains (KLAY and FNSA) are converted to the KAIA token. You can find the exchange rates for both tokens [here](../../kaiatech/kaia-white-paper.md#fnsa-issuancedistribution-status). +Klaytn and Finschia merged to form Kaia through governance decisions made by both chains. 투표 결과는 여기에서 확인할 수 있습니다(https://blog.kaia.io/klaytn-and-finschia-merge-proposal-passes-creating-asias-largest-blockchain-ecosystem/). The utility tokens of the two chains (KLAY and FNSA) are converted to the KAIA token. You can find the exchange rates for both tokens [here](../../kaiatech/kaia-white-paper.md#fnsa-issuancedistribution-status). ### What happens to KLAY and FNSA? @@ -142,8 +142,8 @@ Kaia is a hard fork of the Klaytn chain, and the chain ID remains unchanged. The Here are the main information sources for the chain merge: - [Governance proposal](https://govforum.klaytn.foundation/t/kgp-25-klaytn-finschia-mainnet-merge/719) -- [Our vision behind the merge](https://medium.com/klaytn/finschia-klaytn-chain-merge-proposal-our-vision-for-asias-1-blockchain-ecosystem-7de1588e28c0) -- [Crafting the core of Kaia DeFi](https://medium.com/klaytn/crafting-the-core-of-project-dragons-defi-ecosystem-0fa561e02f56) -- [Responding to institutional demand](https://medium.com/klaytn/project-dragon-responding-to-institutional-demand-bd36e2e1e2a6) -- [Supplementary data and insights](https://medium.com/klaytn/project-dragon-supplementary-data-and-insights-d36abd25ca0f) -- [The Kaia brand story](https://medium.com/klaytn/say-hello-to-kaia-4182ccafe456) +- [합병의 비전](https://blog.kaia.io/finschia-klaytn-chain-merge-proposal-our-vision-for-asias-no-1-blockchain-ecosystem/) +- [카이아 디파이의 핵심 만들기](https://blog.kaia.io/crafting-the-core-of-project-dragons-defi-ecosystem/) +- [기관 수요에 대한 대응](https://blog.kaia.io/project-dragon-responding-to-institutional-demand/) +- [보충 데이터 및 인사이트](https://blog.kaia.io/project-dragon-supplementary-data-and-insights/) +- [카이아 브랜드 스토리](https://blog.kaia.io/say-hello-to-kaia/) diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md b/i18n/ko/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md index 730484f46516..c79b5cb7aa35 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md @@ -2,12 +2,160 @@ Finschia users can swap their FNSA tokens on Finshia network to KAIA tokens on Kaia network at a fixed swap rate. The swap is mediated by a set of smart contract and programs, collectively called Kaiabridge. -A token swap process begins with the Finschia user sending the FNSA token to the `fwsap` module. The token is first swapped from `cony` to `kei` denomination, then transferred to `fbridge` module. The event from `fbridge` is recognized by the trusted relayers and submitted to bridge smart contracts on Kaia chain. The bridging request is handled in multiple steps: +온라인 툴킷](https://toolkit.kaia.io/kaiaBridge)에서 카이아브리지에 액세스하여 사용할 수 있습니다. -- Inflight: The token arrived in Finschia's `fbridge` module, but the relayers did not report to the Kaia smart contracts. -- Confirmed: The relayers submitted the request to the contracts ("provision"). Now the request enters a 30 minute timelock. -- Claimed: After the timelock has expired, the token has been transferred ("claim") to the destination account on Kaia chain. +컨트랙트 소스 코드는 [깃허브 카이아체인/카이아 저장소](https://github.com/kaiachain/kaia/tree/dev/contracts/contracts/system_contracts/kaiabridge)에서, 배포된 주소는 [컨트랙트 주소](https://docs.kaia.io/references/contract-addresses/) 페이지에서 확인할 수 있습니다. -Kaiabridge smart contracts has built-in multisig features. For instance, it takes multiple provision transactions from the Operator accounts for a request to be Confirmed. Each Operator account is held by a relayer, and the relayers are managed by Kaia Foundation and Finschia Foundation. +# 카이아브리지 사용자 가이드 -You can find the contract source codes in [kaiachain GitHub](https://github.com/kaiachain/kaia/tree/dev/contracts/contracts/system_contracts/kaiabridge) and deployed addresses in the [contract addresses](https://docs.kaia.io/references/contract-addresses/) page. \ No newline at end of file +## 전제 조건 + +### 1. 계정을 메타마스크 또는 카이아 월렛으로 옮기기 + +#### 원시 개인 키 사용 + +계정을 원시 개인키로 내보낼 수 있는 경우, 원시 개인키를 복사하여 메타마스크 또는 Kaia 지갑에서 가져옵니다. + +- [메타마스크](https://support.metamask.io/start/use-an-existing-wallet#import-using-a-private-key) +- [카이아 월렛](https://www.kaiawallet.io/en_US/faq/?id=25) + +#### 복구 문구 포함 + +계정을 복구 문구로만 내보낼 수 있는 경우, 복구 문구에서 원시 개인 키를 계산하세요. BIP-39 파생 경로를 지원하는 모든 도구를 사용할 수 있습니다. 이러한 도구에는 [ethers.js](https://docs.ethers.org/v6/api/wallet/#HDNodeWallet), [viem](https://viem.sh/docs/accounts/local/hdKeyToAccount), [Foundry](https://getfoundry.sh/cast/reference/wallet/), [BIP39 도구](https://github.com/iancoleman/bip39) 등이 있습니다. 핀키아 지갑은 기본 파생 경로로 "m/44'/438'/0'/0/0" 경로([SLIP-044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)에 따름)를 사용하는 경우가 많습니다. 핀키아 지갑에 여러 개의 계정이 있거나 다른 구성을 사용하는 경우 다른 파생 경로를 사용해야 할 수도 있습니다. + +개인키를 계산했으면 위 섹션 [원시 개인키 사용](#with-raw-private-key)의 지침을 따릅니다. + +:::note[Example BIP39 도구 사용] + +이 페이지에서 개인 키를 계산할 수 있습니다: [BIP39 - 니모닉 코드](https://iancoleman.io/bip39/). + +예방을 위해 페이지의 '오프라인 사용' 지침을 따르고 이 과정에서 인터넷 연결을 차단하는 것이 좋습니다. + +1. "BIP39 니모닉" 필드에 복구 문구를 붙여넣습니다. +2. "코인" 필드를 "ETH - 이더리움"으로 설정합니다. +3. "파생 경로"를 "BIP32"로 설정합니다. +4. "클라이언트"를 "사용자 지정 파생 경로"로 설정합니다. +5. "BIP32 파생 경로"를 "m/44'/438'/0'/0"으로 설정합니다. +6. "파생 주소"에서 "경로"에 "m/44'/438'/0'/0/0"이 표시된 첫 번째 행을 찾으면 "개인 키" 필드에 원시 개인 키가 표시됩니다. + +::: + +:::note[Example 파운드리 도구 사용] + +1. 파운드리](https://getfoundry.sh/)를 설치합니다. +2. 니모닉\`에 복구 구문과 함께 다음 명령을 입력합니다. 원시 개인 키가 인쇄됩니다. + ``` + 캐스트 지갑 개인 키 --m니모닉 "테스트 테스트 테스트 테스트 테스트 테스트 테스트 테스트 테스트 테스트 정크" --m니모닉 파생 경로 "m/44'/438'/0'/0/0" + ``` + +::: + +### 2. 네트워크 확인 + +메타마스크를 사용하는 경우, 아직 추가하지 않았다면 네트워크에 카이아 메인넷을 수동으로 추가하세요. + +- [메타마스크와 카이아 연결하기](https://docs.kaia.io/build/tutorials/connecting-metamask/) + +### 3. 계정 충전 + +스왑을 위해 트랜잭션을 전송하려면 가스가 필요합니다. 자세한 안내는 [KAIA 받기](https://docs.kaia.io/build/get-started/getting-kaia/)를 참조하세요. + +가스 요금은 최소 0.1 KAIA를 사용하는 것이 좋습니다. + +## 핀치아를 카이아로 교환 + +:::warning[This 스왑은 되돌릴 수 없습니다] + +제공 및 청구 요청은 한 번만 처리할 수 있으며 되돌릴 수 없습니다. +이 지침을 따르기 전에 주의 깊게 읽어보세요. + +::: + +### 1. 지갑 연결 + +#### 1.1 메타마스크 연결 + +"메타마스크 연결" 버튼을 클릭합니다. + +

Connect MetaMask

+ +'계정'에 주소가 표시되는지 확인합니다. +그렇지 않은 경우 메타마스크 확장 프로그램을 열고 페이지에 연결되지 않았다는 메시지가 표시되는지 확인하세요. 그렇다면 '계정 연결' 버튼을 누릅니다. + +

Connect Account

+ +#### 1.2 카이아 지갑 연결 + +카이아 지갑을 사용하는 경우, 사이트에서 카이아 지갑을 dApp(이 경우 카이아 온라인 툴킷)에 연결하도록 요청할 수 있습니다. + +

Connect Kaia Wallet

+ +"연결"을 클릭하여 Kaia 지갑을 연결합니다. + +#### 2. 카이아 메인넷으로 전환 + +네트워크를 '카이아 메인넷' 또는 '메인넷'으로 올바르게 설정했는지 확인하세요. 그렇지 않은 경우 카이아 메인넷으로 전환하세요. 메타마스크를 사용 중이고 메타마스크에 Kaia 메인넷 네트워크를 추가하지 않은 경우, [네트워크 확인](#2-check-your-network)을 참조하세요. + +#### 3. 핀치아 주소 도출 + +"핀키아 주소 도출"을 클릭합니다. 메시지에 서명하라는 메시지가 표시되면 '확인' 또는 '서명'을 클릭합니다. + +
+ Sign message in MetaMask + Sign message in Kaia Wallet +
+ +

+'파생된 핀키아 주소'가 원래 핀키아 주소와 일치하는지, '코니 잔액'이 핀키아 네트워크(CONY)의 잔액과 일치하는지 확인합니다. + +
+ Address and CONY balance shown in the page + Address and CONY balance shown in your wallet +
+ +

+또한 계정에 가스 요금을 결제할 수 있는 KAIA가 있는지 확인하세요(지갑에서 확인할 수 있습니다). + +
+ KAIA balance in MetaMask + KAIA balance in Kaia Wallet +
+ +

+계정에 KAIA가 없는 경우 [계정 충전하기](#3-gas-up-your-account)를 참조하세요. + +#### 4. 프로비저닝 요청 + +"제공 요청"을 클릭합니다. 메시지에 서명하고 트랜잭션을 보내라는 메시지가 표시되면 '확인'을 클릭합니다. + +
+ Confirm provision transaction request in MetaMask + Confirm provision transaction request in Kaia Wallet +
+ +

+이 과정은 몇 초 정도 소요됩니다. 거래가 완료될 때까지 기다립니다. +페이지에서 결과를 확인할 수 있습니다. + +

Provision request successful

+ +
+그렇지 않은 경우 새로 고침하고 처음부터 다시 시작하세요. + +#### 5. 클레임 요청 + +'청구 요청'을 클릭합니다. 트랜잭션을 전송하라는 메시지가 표시되면 '확인'을 클릭합니다. + +
+ Confirm claim transaction request in MetaMask + Confirm claim transaction request in Kaia Wallet +
+ +

+이 과정은 몇 초 정도 소요됩니다. 거래가 완료될 때까지 기다립니다. +페이지에서 결과를 확인할 수 있습니다. + +

Claim request successful

+ +
+업데이트된 잔액을 확인하세요. 청구 금액은 (코니 잔액) * (전환율, 약 148)을 [kei](https://docs.kaia.io/learn/token-economics/kaia-native-token/#units-of-kaia-)로 계산해야 합니다. \ No newline at end of file diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md b/i18n/ko/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md index 36ec97d26642..c3ca2711baa5 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md @@ -101,7 +101,7 @@ Download a compressed file to the new directory. URLs can be found at the bottom ## Downloads -For efficiency, only batch pruned (state migrated) or live pruned database are provided. Read [Storage Optimization](../../learn/storage/state-pruning.md) for their concepts. If you want a full database without neither pruning, or even archive data, perform a fresh full sync from genesis. +For efficiency, only batch pruned (state migrated) or live pruned database are provided. 스토리지 최적화](../../learn/storage/storage-optimization.md)를 참조하여 개념을 알아보세요. If you want a full database without neither pruning, or even archive data, perform a fresh full sync from genesis. | network | sync options | download | | ------- | -------------- | --------------------------------------------------------------------------------------------------- | diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md b/i18n/ko/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md index b7e7824a7c44..7aff376179b1 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md @@ -2,8 +2,8 @@ This page explains how to delete historical block states to reduce the storage requirement. Kaia offers two approaches for pruning block states: -- [Live Pruning](../../learn/storage/state-pruning.md#state-live-pruning): With the live pruning feature enabled, the block states beyond a certain retention period will be automatically deleted. -- [Batch Pruning: State Migration](../../learn/storage/state-pruning.md#state-batch-pruning-state-migration): The block states can be state-migrated, meaning the block states before a certain block number become available. +- [실시간 정리](../../learn/storage/storage-optimization.md#state-live-pruning): 실시간 가지치기 기능을 활성화하면 특정 보존 기간이 지난 블록 상태는 자동으로 삭제됩니다. +- [일괄 정리: 상태 마이그레이션](../../learn/storage/storage-optimization.md#state-batch-pruning-state-migration)을 참조하세요: 블록 상태를 상태 마이그레이션할 수 있습니다. 즉, 특정 블록 번호 이전의 블록 상태를 사용할 수 있게 됩니다. ## Understanding Pruning Impacts diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md b/i18n/ko/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md new file mode 100644 index 000000000000..6df4db3f0de3 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md @@ -0,0 +1,293 @@ +# 노드 스토리지 최적화 + +[Kaia v2.1.0](https://github.com/kaiachain/kaia/releases/tag/v2.1.0)은 디스크 공간 요구 사항을 크게 줄일 수 있는 두 가지 보완적인 스토리지 최적화 기능을 도입했습니다: + +- **데이터베이스 압축**: 반복적인 블록 데이터를 압축하여 저장 공간을 줄입니다. +- **플랫트리 상태 체계**: 아카이브 노드 상태 데이터베이스 크기를 대폭 줄여주는 실험적 기능 + +이 가이드에서는 이러한 최적화를 Kaia 노드에 적용하는 방법을 설명합니다. + +## 데이터베이스 압축 + +데이터베이스 압축은 LevelDB의 내장된 Snappy 압축을 사용하여 블록 헤더, 트랜잭션 본문 및 영수증의 크기를 줄이며, 이는 종종 ABI 인코딩 트랜잭션에서 제로 패딩과 같은 반복적인 데이터를 포함합니다. + +**예상 절감액:** + +- 전체 노드: ~2TB 감소(메인넷에서 ~4.2TB에서 ~2TB로) + +### 전제 조건 + +- Kaia v2.1.0 이상 +- 수동 압축의 경우: 충분한 디스크 여유 공간과 지속적인 디스크 I/O 수용 능력(아래 **리소스 영향** 섹션 참조) + +### 새 설치에 압축 사용 + +v2.1.0부터는 압축이 기본적으로 활성화됩니다. 노드를 시작하기만 하면 됩니다: + +**패키지 설치:** + +```bash +# Configure network in kend.conf +sudo vi /etc/kend/conf/kend.conf +# Set: NETWORK=mainnet or NETWORK=kairos + +# Start node (compression enabled by default in v2.1.0+) +kend start + +# Verify +kend status +tail -f /var/kend/logs/kend.out +``` + +새로 작성된 모든 데이터는 자동으로 압축됩니다. + +### 기존 노드에 압축 사용 + +v2.1.0 이전 버전에서 업그레이드하는 경우: + +**1단계: 버전 확인** + +```bash +ken version +``` + +**2단계: v2.1.0 이상**\*\* + +압축은 이미 기본적으로 활성화되어 있습니다. 새 데이터는 자동으로 압축됩니다. 기존 데이터를 압축하려면 4단계로 건너뜁니다. + +3단계: v2.1.0 이전 버전만 해당\*\*\*\* + +구성에 압축 플래그를 추가합니다: + +**패키지 설치:** + +```bash +sudo vi /etc/kend/conf/kend.conf +# Add to ADDITIONAL variable: +ADDITIONAL="--db.leveldb.compression 2" +``` + +압축 플래그 값은 다음과 같습니다: + +- `0`: 압축 없음 +- `1`: 영수증만 압축 +- `2`: 헤더, 본문 및 영수증 압축(권장) +- `3`: 상태 트라이를 포함한 모든 테이블 압축(권장하지 않음) + +:::note + +옵션 2는 상태 테스트 데이터가 잘 압축되지 않으므로(무작위로 표시됨) 옵션 3은 최소한의 추가 이점을 제공하므로 권장됩니다. + +::: + +그런 다음 다시 시작합니다: + +```bash +kend stop +kend start +``` + +**4단계: 기존 데이터 압축(선택 사항이지만 권장)** + +RPC를 통해 데이터베이스 압축을 트리거합니다. 노드 콘솔에 연결합니다: + +```bash +ken attach --datadir /var/kend/data +``` + +콘솔에서 "allbutstate" 프리셋을 사용하여 압축을 트리거합니다: + +```javascript +> debug.chaindbCompact({ "preset": "allbutstate" }) +null +``` + +**사용 가능한 프리셋:** + +- `"기본값"`: 모든 데이터베이스 구성 요소의 전체 범위 압축 +- `"allbutstate"`: 상태 트라이를 제외한 선택적 압축(압축에 권장) +- "custom"\`: 특정 데이터베이스 테이블에 대한 사용자 지정 범위 정의 + +압축은 백그라운드에서 실행됩니다. 노드 로그에서 진행 상황을 모니터링하세요: + +```bash +tail -f /var/kend/logs/kend.out | grep -i Compact +``` + +다음과 같은 로그 항목이 표시되어야 합니다: + +``` +INFO[07/25,12:50:17 Z] [3] Compacting database started range=0x48-0x49 +INFO[07/25,12:55:17 Z] [3] Compacting database completed range=0x48-0x49 elapsed=5m0.085s +``` + +노드는 압축하는 동안 블록을 계속 처리합니다. + +\*\*예상 소요 시간: 메인넷 풀 노드의 경우 약 10시간(최대 4TB 데이터의 SSD 사용 시). 기간은 하드웨어 및 데이터 크기에 따라 다릅니다. + +**리소스 영향:** + +- 높은 디스크 I/O(피크 >400 MiB/s 읽기, >300 MiB/s 쓰기) +- 높은 디스크 IOPS(종종 초당 2000개 이상의 작업) +- 노드는 계속 작동하며 블록을 계속 동기화합니다. + +:::note + +압축하는 동안 노드는 계속 작동하지만, I/O가 집중되는 기간에는 쿼리 성능이 영향을 받을 수 있습니다. 프로덕션 RPC 노드의 경우 유지보수 기간이나 트래픽이 적은 기간에 압축을 예약하세요. + +::: + +### 사전 압축된 체인데이터 스냅샷 사용(미정) + +사전 압축된 체인데이터 스냅샷은 향후 릴리스에서 제공될 예정이지만 아직 제공되지 않습니다. 사용 가능한 경우 [체인데이터 스냅샷 페이지](https://docs.kaia.io/misc/operation/chaindata-snapshot/)에 나열됩니다. + +현재로서는 둘 중 하나를 선택해야 합니다: + +- 새 v2.1.0 이상 설치 시 압축 사용(새 데이터의 경우 자동) +- 기존 노드에서 수동 압축 실행(위 참조) + +스냅샷 페이지에서 압축 스냅샷 가용성에 대한 업데이트를 주기적으로 확인하세요. + +### 압축이 활성 상태인지 확인 + +노드 시작 로그에서 압축 구성을 확인하세요: + +```bash +grep "compressionType" /var/kend/logs/kend.out +``` + +상태 트리가 아닌 테이블에 대해 '압축 유형=스나피'를 나타내는 로그 항목을 찾습니다. + +### 모니터링 및 문제 해결 + +**디스크 사용량 감소 확인:** + +```bash +du -h --max-depth=1 /var/kend/data/klay/chaindata +``` + +압축 전과 후를 비교하세요. 블록 본문과 영수증이 포함된 디렉터리에서 저장 공간이 크게 줄어든 것을 확인할 수 있습니다. + +**일반적인 문제:** + +1. **압축 실패**: 충분한 디스크 공간을 확보하세요. 압축은 일시적으로 데이터 재작성을 위한 추가 공간이 필요합니다. +2. **FlatTrie가 시작되지 않았습니다**: FlatTrie에는 빈 데이터베이스가 필요합니다. 기존 데이터에 대한 오류가 표시되면 체인데이터 디렉터리를 삭제하고 제네시스에서 동기화하세요. +3. **메르클 증명 API 오류**: FlatTrie는 `eth_getProof`를 지원하지 않습니다. 이 API가 필요한 경우 기존 노드를 사용하세요. + +## 플랫트리 상태 체계(실험적) + +플랫트리는 에리곤 이더리움 클라이언트에서 채택한 실험적인 상태 저장 방식입니다. 플랫 구조로 계정 상태를 저장하고 최신 블록의 완전한 머클 패트리샤 트리(MPT)만 유지하며, 필요에 따라 과거 시도를 재구성합니다. + +**예상 절감액:** + +- 총 저장 공간: ~최대 75% 감소(카이로스 테스트넷 결과에서 예상) +- 카이로스 테스트넷: 4.3TB → 1TB +- 메인넷: ~35TB → ~10TB(비례적 감소에 따른 추정치) + +:::warning + +FlatTrie는 v2.1.0의 실험적 기능입니다. 프로덕션용으로는 권장하지 않습니다. 향후 릴리스에서는 잠재적인 안정성 문제, 성능 병목 현상 및 획기적인 변경 사항이 발생할 수 있습니다. 테스트 및 개발 환경에서만 사용하세요. + +::: + +### 전제 조건 + +- Kaia v2.1.0 이상 +- **제네시스에서 동기화해야 함**(기존 데이터베이스를 변환할 수 없음) +- 빈 데이터 디렉터리 + +### 현재 제한 사항 + +FlatTrie를 활성화하기 전에 이러한 제한 사항을 이해하세요: + +**지원되지 않는 기능:** + +- 일괄 가지 치기 및 라이브 가지 치기 +- 블록 되감기(`--start-block-number` 플래그 및 `debug_setHead` API) +- 머클 증명 생성(`eth_getProof` API) + +**비호환성:** + +- 기존 데이터베이스에서 마이그레이션할 수 없습니다(제네시스부터 시작해야 함). +- 플랫트리 모드와 비플랫트리 모드 간에 전환할 수 없습니다. +- FlatTrie가 있는 데이터베이스와 없는 데이터베이스는 호환되지 않습니다. + +### 플랫트리 사용 + +**1단계: 빈 데이터 디렉터리 준비** + +```bash +# Ensure clean data directory +sudo rm -rf /var/kend/data +sudo mkdir -p /var/kend/data +``` + +**2단계: FlatTrie 플래그로 노드를 시작하고 제네시스로부터 동기화** + +```bash +# Mainnet +ken --state.experimental-flat-trie + +# Kairos testnet +ken --state.experimental-flat-trie --kairos +``` + +:::note + +FlatTrie가 활성화되면 `--gcmode` 및 `--state.block-interval` 플래그에 관계없이 아카이브 모드가 자동으로 활성화됩니다. 플랫트리를 사용할 때는 이러한 플래그가 무시됩니다. + +::: + +**3단계: 전체 동기화 대기** + +노드는 제네시스의 모든 블록을 동기화합니다. 하드웨어와 네트워크에 따라 몇 주가 소요될 수 있습니다. + +### 플랫트리가 활성 상태인지 확인 + +노드 시작 로그를 확인하여 FlatTrie 모드를 확인하세요: + +```bash +grep -i "flat" /var/kend/logs/kend.out | head -20 +``` + +실험적인 플랫 트라이가 활성화되어 있다는 표시가 나타납니다. + +### 플랫트리 성능 모니터링 + +FlatTrie는 기존 상태 스토리지와 다른 리소스 프로필을 사용합니다: + +**예상되는 특성:** + +- CPU 사용량 감소 +- 더 높은 메모리 사용량(~30GB) +- 더 많은 고루틴 횟수(~900-1000) +- 블록 확정 시간 단축 + +노드의 Prometheus 메트릭 엔드포인트 또는 Grafana 대시보드를 통해 이러한 메트릭을 모니터링하세요. + +### 플랫트리 문제 해결 + +**기존 데이터베이스에서 FlatTrie를 시작할 수 없음:** +비어 있지 않은 데이터에서 FlatTrie를 활성화할 수 없다는 오류가 표시되면 제네시스부터 시작해야 합니다. 체인데이터 디렉토리를 삭제하고 `--state.experimental-flat-trie` 플래그를 사용하여 전체 동기화를 수행합니다. + +**머클 증명 API 오류:** +FlatTrie는 `eth_getProof` 및 관련 머클 증명 API를 지원하지 않습니다. 애플리케이션에 이러한 API가 필요한 경우 기존 노드를 대신 사용하세요. + +**높은 메모리 사용량:** +동기화 중 FlatTrie 노드에 약 30GB의 메모리 사용량이 예상됩니다. 시스템에 충분한 RAM이 있는지 확인합니다. 팀은 향후 버전에서 이 문제를 줄이기 위해 최적화 작업을 진행 중입니다. + +**느린 동기화 속도:** +FlatTrie를 사용한 초기 동기화는 기존 노드와 비슷합니다. 동기화 속도가 현저히 느리다면 확인해 보세요: + +- 디스크 I/O 성능(SSD 적극 권장) +- 네트워크 대역폭 +- CPU 사용률 + +## 모범 사례 + +1. **주요 변경 전에는 항상 백업하세요**: 특히 수동 압축을 실행하기 전에. +2. **디스크 공간 모니터링**: 압축하기 전에 충분한 여유 공간이 있는지 확인합니다. 압축은 일시적으로 데이터베이스 파일을 다시 쓰기 위한 추가 공간을 필요로 합니다. +3. **트래픽이 적은 시간대에 압축을 예약하세요**: 퍼블릭 RPC 엔드포인트를 실행하는 경우. +4. **프로덕션 노드에 SSD 사용**: 압축과 FlatTrie 모두 빠른 랜덤 I/O의 이점을 누릴 수 있습니다. +5. **실험적 기능 계획**: FlatTrie는 v2.1.x에서 실험 중입니다. 프로덕션 사용 전에 철저히 테스트하세요. +6. **계속 업데이트**: 향후 최적화에 대한 릴리스 노트와 FlatTrie가 실험적 상태를 졸업하는 시기를 확인하세요. \ No newline at end of file diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md index 43b6bca7bb1d..04fcf975e6a8 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md @@ -159,7 +159,7 @@ REWARDBASE="d13f7da0032b1204f77029dc1ecbf4dae2f04241" ### (Optional) Download Chaindata Snapshot -Synching from the genesis block is time-consuming. You may use [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../../learn/storage/block-sync.md#full-sync) process. +제네시스 블록에서 동기화하는 데는 시간이 많이 걸립니다. You may use [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../../learn/storage/block-sync.md#full-sync) process. ## CN 시작하기 diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md index 6750190000a0..d86add2d8476 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md @@ -146,7 +146,7 @@ DATA_DIR=/var/kpnd/data ### (Optional) Download Chaindata Snapshot -Synching from the genesis block is time-consuming. You may use [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../../learn/storage/block-sync.md#full-sync) process. +제네시스 블록에서 동기화하는 데는 시간이 많이 걸립니다. You may use [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../../learn/storage/block-sync.md#full-sync) process. ## PN 시작하기 diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md index 223329c9537e..e5cf42141536 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md @@ -10,14 +10,22 @@ ### 베어메탈 머신 -| 카테고리 | 사양 | -| :--- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 서버 | 인텔® 서버 시스템 [M50CYP1UR212](https://www.intel.sg/content/www/xa/en/products/sku/214842/intel-server-system-m50cyp1ur212/specifications.html) | -| CPU | 인텔® 제온 8358 2.60GHz (32코어/64스레드) | -| 메모리 | 128GB (32GB \* 4) | -| 스토리지 | 4TB (or larger size) SSD (The preferred storage size and configuration could differ depending on the chain data size. 자세한 내용은 Kaia 팀에 문의하시기 바랍니다.) | +#### 일반 요구 사항(모든 노드 유형) -이는 CN과 PN에 권장되는 하드웨어 사양이며, 정확한 요구 사항은 아닙니다. 유사한 하드웨어 구성을 가진 모든 물리적 컴퓨터는 CN 또는 PN을 작동하기에 충분합니다. +| 카테고리 | 사양 | +| :--- | :------------------------------------------------------------------------------------------------------------------------- | +| CPU | 2.6GHz 기본 - 3.4GHz 최대 주파수 이상(예: 3세대 인텔® 제온® 스케일러블 프로세서) | +| 스토리지 | ≥ 4TB 이상의 SSD(체인 데이터 크기에 따라 조정, 지침은 Kaia 팀에 문의) | + +유사한 하드웨어 구성을 가진 모든 물리적 컴퓨터는 CN 또는 PN을 작동하기에 충분합니다. + +#### 노드 유형별 권장 사양 + +| Node Type | 코어/스레드 | 메모리 | +| :------------------------------------------- | :--------- | :---- | +| CN | 16코어/32스레드 | 128GB | +| PN | 8코어/16스레드 | 64GB | +| PN (with Live Pruning DB) | 4코어/8스레드 | 32GB | You can use and apply a live-pruning option to use live-pruning DB. For more details, please refer https://docs.kaia.io/learn/storage/live-pruning/. However, note that live-pruning spec is not recommended for CNs but this may change in the future. @@ -25,7 +33,7 @@ You can use and apply a live-pruning option to use live-pruning DB. For more det #### 권장 사양 -| Node Type | Model | vCPU | 네트워크 대역폭(Gbps) | 디스크 대역폭(Mbps) | Storage speed (IOPS) | 가격 (서울 지역, USD/h) | +| 노드 유형 | Model | vCPU | 네트워크 대역폭(Gbps) | 디스크 대역폭(Mbps) | Storage speed (IOPS) | 가격 (서울 지역, USD/h) | | :------------------------------------------: | :-------------------------: | :--: | :-------------------------------: | :--------------------------------: | :-------------------------------------: | :----------------------------------: | | CN | m6i.8xlarge | 32 | 128 | 4,000 (Minimum) | 9,000 | 1.888 | | PN | m6i.4xlarge | 16 | 64 | 4,000 (Minimum) | 9,000 | 0.944 | @@ -49,11 +57,11 @@ You can use and apply a live-pruning option to use live-pruning DB. For more det #### EN의 경우 다음 사양을 권장합니다. -| 노드 유형 | 모델 | vCPU | 메모리(GiB) | 스토리지(GiB) | 스토리지 속도 (IOPS) | Price (asia-northeast3, USD/h) | -| :------------------------------------------: | :------------: | :--: | :-------------------------: | :--------------------------------: | :-------------------------------: | :-----------------------------------------------: | -| CN | c4-standard-32 | 32 | 120 | > 4,000 | 7500 | 2.03078256 | -| PN | n2-standard-16 | 16 | 64 | 4,000 (Minimum) | 7500 | 1.016243 | -| PN (with Live Pruning DB) | n2-standard-8 | 8 | 32 | 3,500 (Minimum) | 7500 | 0.508121 | +| 노드 유형 | 모델 | vCPU | 메모리(GiB) | 스토리지(GiB) | 스토리지 속도 (IOPS) | Price (asia-northeast3, USD/h) | +| :-----------------------------------: | :------------: | :--: | :-------------------------: | :--------------------------------: | :-------------------------------: | :-----------------------------------------------: | +| CN | c4-standard-32 | 32 | 120 | > 4,000 | 7500 | 2.03078256 | +| PN | n2-standard-16 | 16 | 64 | 4,000 (Minimum) | 7500 | 1.016243 | +| PN(라이브 가지치기 DB 포함) | n2-standard-8 | 8 | 32 | 3,500 (Minimum) | 7500 | 0.508121 | The information above is from [https://cloud.google.com/compute/vm-instance-pricing#general-purpose_machine_type_family/](https://cloud.google.com/compute/vm-instance-pricing#general-purpose_machine_type_family/) and [https://cloud.google.com/storage/pricing#asia](https://cloud.google.com/storage/pricing#asia) and may be changed by Google. diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md index 27027948a9fd..c1bb9446c9e3 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md @@ -27,7 +27,7 @@ echo "LOG_DIR=/var/kend/logs" >> conf/kend.conf ### (Optional) Download Chaindata Snapshot -제네시스 블록에서 동기화하는 것은 시간이 많이 걸립니다. You may use [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../learn/storage/block-sync.md#full-sync) process. Download and decompress the chaindata snapshot. Then mount the decompressed directory to the container. +제네시스 블록에서 동기화하는 데는 시간이 많이 걸립니다. You may use [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../learn/storage/block-sync.md#full-sync) process. Download and decompress the chaindata snapshot. Then mount the decompressed directory to the container. ## 컨테이너 시작 diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md index 3f4c60481407..20593c1095e0 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md @@ -115,7 +115,7 @@ DATA_DIR=/var/kend/data ### (Optional) Download Chaindata Snapshot -Synching from the genesis block is time-consuming. You may use [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../learn/storage/block-sync.md#full-sync) process. +제네시스 블록에서 동기화하는 데는 시간이 많이 걸립니다. You may use [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../learn/storage/block-sync.md#full-sync) process. ## EN 시작하기 diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/endpoint-node/json-rpc-apis.md b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/endpoint-node/json-rpc-apis.md index da9f5800bf61..271e159a4147 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/endpoint-node/json-rpc-apis.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/endpoint-node/json-rpc-apis.md @@ -85,7 +85,7 @@ $ curl -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"rp 활성화된 API는 다음과 같습니다: -- [VM Tracing](../.../../references/json-rpc/debug/trace-bad-block) API를 사용할 수 있지만 기능이 제한되어 있습니다([사전 정의된 tracer](../.../references/json-rpc/debug/trace-bad-block)만 허용됩니다. params/tracingOptions을 참고하세요.) +- [VM Tracing](../../../references/json-rpc/debug/trace-bad-block) API를 사용할 수 있지만 기능이 제한되어 있습니다([사전 정의된 tracer](../../references/json-rpc/debug/trace-bad-block)만 허용됩니다. params/tracingOptions을 참고하세요.) - debug_dumpBlock, debug_dumpStateTrie, debug_getBlockRlp, debug_getModifiedAccountsByHash, debug_getModifiedAccountsByNumber, debug_getBadBlocks, debug_getModifiedStorageNodesByNumber - debug_metrics diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/service-chain/configure/anchoring.md b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/service-chain/configure/anchoring.md index 520239af4a1c..8fc13e66679b 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/nodes/service-chain/configure/anchoring.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/nodes/service-chain/configure/anchoring.md @@ -43,7 +43,7 @@ KLAY를 전송한 후 아래와 같이 잔액을 확인할 수 있습니다. ``` 이후 아래와 같이 RPC API인 `subbridge.anchoring`을 통해 앵커링을 활성화할 수 있습니다. -자세한 내용은 [subbridge API](../.../../references/json-rpc/subbridge/anchoring)를 참조하세요. +자세한 내용은 [subbridge API](../../../references/json-rpc/subbridge/anchoring)를 참조하세요. ``` > subbridge.anchoring(true) @@ -58,7 +58,7 @@ true ### 하위 브리지 서브 브리지에서는 아래와 같이 최신 앵커 블록 번호를 확인할 수 있습니다. -자세한 내용은 [subbridge API](../.../../references/json-rpc/subbridge/latest-anchored-block-number)를 참조하세요. +자세한 내용은 [subbridge API](../../../references/json-rpc/subbridge/latest-anchored-block-number)를 참조하세요. ```javascript > subbridge.latestAnchoredBlockNumber diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/references/contract-addresses.md b/i18n/ko/docusaurus-plugin-content-docs/current/references/contract-addresses.md index 5320bf1a002d..cb5a64131d82 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/references/contract-addresses.md +++ b/i18n/ko/docusaurus-plugin-content-docs/current/references/contract-addresses.md @@ -15,6 +15,7 @@ Some Kaia features rely on the special smart contracts called _system contracts_ | KIP-113 SimpleBlsRegistry | proxy 0x3e80e75975bdb8e04B800485DD28BebeC6d97679
logic 0xb5ed8d6edd437a0d6ae828580c0aef5678d87f1a | proxy 0x4BEed0651C46aE5a7CB3b7737345d2ee733789e6
logic 0x6751096fe72d835307d7e635aed51296948b93c5 | | KIP-247 가스리스스왑 라우터 | 0xCf658F786bf4AC62D66d70Dd26B5c1395dA22c63 | 0x4b41783732810b731569E4d944F59372F411BEa2 | | KIP-226 CL레지스트리 | 0x25F4044c655Fc7B23c62bbC78ceF3B4EBFb4e478 | 0x25F4044c655Fc7B23c62bbC78ceF3B4EBFb4e478 | +| KIP-249 경매 엔트리포인트 | 0xFc5c1C92d8DE06F7143f71FeA209e04042dcff82 | 0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480 | Some contracts are not directly read by Kaia nodes but play crucial roles in operating the Kaia blockchain and its ecosystem. They include treasury, governance, and KAIA token bridge contracts. @@ -33,7 +34,9 @@ Some contracts are not directly read by Kaia nodes but play crucial roles in ope | Kaiabridge Judge | 0x64c91d6517b8f2fd7f4157c32DE4acfe1AeA2611 | 0x3735Ba95cca5DEd47Fa5b202a2Bbda4c63c0B1DD | | Kaiabridge Guardian | 0xE49D152E5FA576caFC18D2775AF4E58C135a6851 | 0xc9e8342C1da4c89A423258d9030414331b4761Cf | | KIP-163 PublicDelegationFactory | 0x29C8cc53d22F79D4024ecB67DB1a09b37bCdE415 | 0x98c47c2cda854cbb025d47de72149a7ec238ec33 | -| KIP-226 CLDEXFactory | 0x2A4C5eCaafB26460F17d509EA4d15741AF5F5f0a | 0x537D58BdBC98c690bE5d3e3F638d4B93754B15Fd | -| KIP-226 CLDEX라우터 | 0x21d3c567058277b19324FE22c8e4Bb3D2AE0D4C3 | 0x41F135a084897e4145CC2032e8701726af795e3a | +| KIP-226 CLDEXFactory | 0x93fa0E1deE99ac4158a617a6EC79cB941bD9a39F | 0x666a9a72D2f708062a20e7Ca94f6dd5Ce6B33eA4 | +| KIP-226 CLDEX라우터 | 0x5086273d9C8a79B7d2466aaCc52a6E43E22152A5 | 0x2871e95eaBFF0E71e4e4b706D7F1F3D24811673b | | KIP-226 스테이킹트래커V2 | 0xF45c37c265f148894D6d9A4c066aFaAB00557c9c | 0x9b015Ab5916EE53e52Ef60f31E978b4001908c43 | | [정식 WKAIA](../build/smart-contracts/token-development/canonical-wkaia.md) | 0x19Aac5f612f524B754CA7e7c41cbFa2E981A4432 | 0x043c471bEe060e00A56CcD02c0Ca286808a5A436 | +| KIP-249 경매예치금 보관소 | 0x0E66b62273Cc99BC519DD4dD0C0Cf689dd7b9876 | 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc | +| KIP-249 경매 수수료 보관소 | 0x303BB9c9FF4Aa656ac4c8e9f99F8E4C133FDa665 | 0xE4e7d880786c53b6EA6cfA848Eb3a05eE97b2aCC | \ No newline at end of file diff --git a/i18n/ko/docusaurus-theme-classic/footer.json b/i18n/ko/docusaurus-theme-classic/footer.json index 6d5029de70eb..57260a2a9a74 100644 --- a/i18n/ko/docusaurus-theme-classic/footer.json +++ b/i18n/ko/docusaurus-theme-classic/footer.json @@ -56,7 +56,11 @@ "description": "The label of footer link with label=Open Source linking to https://docs.kaia.io/misc/opensource/" }, "copyright": { - "message": "© Kaia DLT Foundation 2025. All rights reserved.", + "message": "", "description": "The footer copyright" + }, + "link.item.label.Blog": { + "message": "블로그", + "description": "The label of footer link with label=Blog linking to https://blog.kaia.io/" } } diff --git a/i18n/vi/docusaurus-plugin-content-docs/current.json b/i18n/vi/docusaurus-plugin-content-docs/current.json index 23a968d121f1..8725a300e215 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current.json +++ b/i18n/vi/docusaurus-plugin-content-docs/current.json @@ -5,23 +5,23 @@ }, "sidebar.buildSidebar.category.Get Started": { "message": "Tổng quan", - "description": "The label for category Get Started in sidebar buildSidebar" + "description": "The label for category 'Get Started' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Smart Contracts": { "message": "Hợp đồng thông minh", - "description": "The label for category Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Deploy Smart Contracts": { "message": "Hướng dẫn triển khai", - "description": "The label for category Deploy Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Deploy Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Sample Contracts": { "message": "Hợp đồng mẫu", - "description": "The label for category Sample Contracts in sidebar buildSidebar" + "description": "The label for category 'Sample Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Tutorials": { "message": "Hướng dẫn", - "description": "The label for category Tutorials in sidebar buildSidebar" + "description": "The label for category 'Tutorials' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Tools": { "message": "Dụng Cụ", @@ -29,51 +29,51 @@ }, "sidebar.buildSidebar.category.Wallets": { "message": "Ví", - "description": "The label for category Wallets in sidebar buildSidebar" + "description": "The label for category 'Wallets' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Wallet Libraries": { "message": "Thư viện ví", - "description": "The label for category Wallet Libraries in sidebar buildSidebar" + "description": "The label for category 'Wallet Libraries' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Oracles": { "message": "Oracles", - "description": "The label for category Oracles in sidebar buildSidebar" + "description": "The label for category 'Oracles' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Indexers": { "message": "Indexers", - "description": "The label for category Indexers in sidebar buildSidebar" + "description": "The label for category 'Indexers' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Cross-chain": { "message": "Cross-chain", - "description": "The label for category Cross-chain in sidebar buildSidebar" + "description": "The label for category 'Cross-chain' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Block Explorers": { "message": "Trình duyệt khối", - "description": "The label for category Block Explorers in sidebar buildSidebar" + "description": "The label for category 'Block Explorers' in sidebar 'buildSidebar'" }, "sidebar.nodeSidebar.category.Endpoint Node": { "message": "Nút điểm cuối", - "description": "The label for category Endpoint Node in sidebar nodeSidebar" + "description": "The label for category 'Endpoint Node' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Core Cell": { "message": "Core Cell", - "description": "The label for category Core Cell in sidebar nodeSidebar" + "description": "The label for category 'Core Cell' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Install Core Cell": { "message": "Hướng dẫn cài đặt", - "description": "The label for category Install Core Cell in sidebar nodeSidebar" + "description": "The label for category 'Install Core Cell' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Service Chain": { "message": "Chuỗi dịch vụ", - "description": "The label for category Service Chain in sidebar nodeSidebar" + "description": "The label for category 'Service Chain' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Quick Start": { "message": "Bắt đầu nhanh", - "description": "The label for category Quick Start in sidebar nodeSidebar" + "description": "The label for category 'Quick Start' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Configure Service Chain": { "message": "Cấu hình Chuỗi Dịch vụ", - "description": "The label for category Configure Service Chain in sidebar nodeSidebar" + "description": "The label for category 'Configure Service Chain' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Node Package Downloads": { "message": "Tải xuống gói nút", @@ -81,11 +81,11 @@ }, "sidebar.refSidebar.category.RPC API Reference": { "message": "Tham chiếu API RPC", - "description": "The label for category RPC API Reference in sidebar refSidebar" + "description": "The label for category 'RPC API Reference' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.SDKs and Libraries": { "message": "Dịch vụ RPC", - "description": "The label for category SDKs and Libraries in sidebar refSidebar" + "description": "The label for category 'SDKs and Libraries' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.API References": { "message": "Tham khảo API", @@ -97,31 +97,31 @@ }, "sidebar.learnSidebar.category.Transaction Fees": { "message": "Phí giao dịch", - "description": "The label for category Transaction Fees in sidebar learnSidebar" + "description": "The label for category 'Transaction Fees' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Verify Smart Contracts": { "message": "Xác minh hợp đồng thông minh", - "description": "The label for category Verify Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Verify Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.learnSidebar.category.Data Management": { "message": "Data Management", - "description": "The label for category Data Management in sidebar learnSidebar" + "description": "The label for category 'Data Management' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Governance": { "message": "Governance", - "description": "The label for category Governance in sidebar learnSidebar" + "description": "The label for category 'Governance' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Node Quick Reference": { "message": "Node Quick Reference", - "description": "The label for category Node Quick Reference in sidebar learnSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Kaia Safe": { "message": "Kaia Safe", - "description": "The label for category Kaia Safe in sidebar buildSidebar" + "description": "The label for category 'Kaia Safe' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Node Quick Reference": { "message": "Node Quick Reference", - "description": "The label for category Node Quick Reference in sidebar buildSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.link.KaiaScan": { "message": "KaiaScan", @@ -129,47 +129,47 @@ }, "sidebar.nodeSidebar.category.Node Quick Reference": { "message": "Node Quick Reference", - "description": "The label for category Node Quick Reference in sidebar nodeSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'nodeSidebar'" }, "sidebar.refSidebar.category.ethers-ext < v1.0.1": { "message": "ethers-ext < v1.0.1", - "description": "The label for category ethers-ext < v1.0.1 in sidebar refSidebar" + "description": "The label for category 'ethers-ext < v1.0.1' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore": { "message": "keystore", - "description": "The label for category keystore in sidebar refSidebar" + "description": "The label for category 'keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.ethers-ext": { "message": "ethers-ext", - "description": "The label for category ethers-ext in sidebar refSidebar" + "description": "The label for category 'ethers-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.v5": { "message": "v5", - "description": "The label for category v5 in sidebar refSidebar" + "description": "The label for category 'v5' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.v6": { "message": "v6", - "description": "The label for category v6 in sidebar refSidebar" + "description": "The label for category 'v6' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3js-ext": { "message": "web3js-ext", - "description": "The label for category web3js-ext in sidebar refSidebar" + "description": "The label for category 'web3js-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3j-ext": { "message": "web3j-ext", - "description": "The label for category web3j-ext in sidebar refSidebar" + "description": "The label for category 'web3j-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3py-ext": { "message": "web3py-ext", - "description": "The label for category web3py-ext in sidebar refSidebar" + "description": "The label for category 'web3py-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.Node Quick Reference": { "message": "Node Quick Reference", - "description": "The label for category Node Quick Reference in sidebar refSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'refSidebar'" }, "sidebar.buildSidebar.category.Hardware Wallets": { "message": "Hardware Wallets", - "description": "The label for category Hardware Wallets in sidebar buildSidebar" + "description": "The label for category 'Hardware Wallets' in sidebar 'buildSidebar'" }, "sidebar.miniDappSidebar.category.Build Mini dApps on LINE with Unity": { "message": "Build Mini dApps on LINE with Unity", @@ -177,107 +177,107 @@ }, "sidebar.miniDappSidebar.category.Node Quick Reference": { "message": "Node Quick Reference", - "description": "The label for category Node Quick Reference in sidebar miniDappSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'miniDappSidebar'" }, "sidebar.learnSidebar.category.Core Concepts": { "message": "Các khái niệm cốt lõi", - "description": "The label for category Core Concepts in sidebar learnSidebar" + "description": "The label for category 'Core Concepts' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Smart Contracts": { "message": "Hợp đồng thông minh", - "description": "The label for category Smart Contracts in sidebar learnSidebar" + "description": "The label for category 'Smart Contracts' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Advanced Topics": { "message": "Chủ đề nâng cao", - "description": "The label for category Advanced Topics in sidebar learnSidebar" + "description": "The label for category 'Advanced Topics' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Transaction Execution": { "message": "Thực hiện giao dịch", - "description": "The label for category Transaction Execution in sidebar learnSidebar" + "description": "The label for category 'Transaction Execution' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Token Economics": { "message": "Kinh tế Token", - "description": "The label for category Token Economics in sidebar learnSidebar" + "description": "The label for category 'Token Economics' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Transactions": { "message": "Giao dịch", - "description": "The label for category Transactions in sidebar buildSidebar" + "description": "The label for category 'Transactions' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Token Management": { "message": "Quản lý mã thông báo", - "description": "The label for category Token Management in sidebar buildSidebar" + "description": "The label for category 'Token Management' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Team Finance": { "message": "Tài chính nhóm", - "description": "The label for category Team Finance in sidebar buildSidebar" + "description": "The label for category 'Team Finance' in sidebar 'buildSidebar'" }, "sidebar.miniDappSidebar.category.LINE Mini DApp with Unity": { "message": "LINE Mini DApp với Unity", - "description": "The label for category LINE Mini DApp with Unity in sidebar miniDappSidebar" + "description": "The label for category 'LINE Mini DApp with Unity' in sidebar 'miniDappSidebar'" }, "sidebar.miniDappSidebar.category.LINE Mini DApp with Cocos": { "message": "LINE Mini DApp với Cocos", - "description": "The label for category LINE Mini DApp with Cocos in sidebar miniDappSidebar" + "description": "The label for category 'LINE Mini DApp with Cocos' in sidebar 'miniDappSidebar'" }, "sidebar.miniDappSidebar.category.Survey Mini DApp": { "message": "Khảo sát Mini DApp", - "description": "The label for category Survey Mini DApp in sidebar miniDappSidebar" + "description": "The label for category 'Survey Mini DApp' in sidebar 'miniDappSidebar'" }, "sidebar.learnSidebar.link.Docs Updates": { "message": "Cập nhật tài liệu", - "description": "The label for link Docs Updates in sidebar learnSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'learnSidebar', linking to '/misc/updates'" }, "sidebar.buildSidebar.link.Docs Updates": { "message": "Cập nhật tài liệu", - "description": "The label for link Docs Updates in sidebar buildSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'buildSidebar', linking to '/misc/updates'" }, "sidebar.nodeSidebar.category.Debugging and Diagnostics": { "message": "Gỡ lỗi và chẩn đoán", - "description": "The label for category Debugging and Diagnostics in sidebar nodeSidebar" + "description": "The label for category 'Debugging and Diagnostics' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.link.Docs Updates": { "message": "Cập nhật tài liệu", - "description": "The label for link Docs Updates in sidebar nodeSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'nodeSidebar', linking to '/misc/updates'" }, "sidebar.refSidebar.link.Docs Updates": { "message": "Cập nhật tài liệu", - "description": "The label for link Docs Updates in sidebar refSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'refSidebar', linking to '/misc/updates'" }, "sidebar.miniDappSidebar.link.Docs Updates": { "message": "Cập nhật tài liệu", - "description": "The label for link Docs Updates in sidebar miniDappSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'miniDappSidebar', linking to '/misc/updates'" }, "sidebar.learnSidebar.category.Finschia to Kaia": { "message": "Finschia đến Kaia", - "description": "The label for category Finschia to Kaia in sidebar learnSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Finschia to Kaia": { "message": "Finschia đến Kaia", - "description": "The label for category Finschia to Kaia in sidebar buildSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'buildSidebar'" }, "sidebar.nodeSidebar.category.Finschia to Kaia": { "message": "Finschia đến Kaia", - "description": "The label for category Finschia to Kaia in sidebar nodeSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'nodeSidebar'" }, "sidebar.refSidebar.category.Finschia to Kaia": { "message": "Finschia đến Kaia", - "description": "The label for category Finschia to Kaia in sidebar refSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'refSidebar'" }, "sidebar.miniDappSidebar.category.Finschia to Kaia": { "message": "Finschia đến Kaia", - "description": "The label for category Finschia to Kaia in sidebar miniDappSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'miniDappSidebar'" }, "sidebar.buildSidebar.category.Wallet Configuration": { "message": "Cấu hình ví", - "description": "The label for category Wallet Configuration in sidebar buildSidebar" + "description": "The label for category 'Wallet Configuration' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Wallet Operations": { "message": "Hoạt động ví", - "description": "The label for category Wallet Operations in sidebar buildSidebar" + "description": "The label for category 'Wallet Operations' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.dApp Integration": { "message": "Tích hợp ứng dụng phi tập trung (dApp)", - "description": "The label for category dApp Integration in sidebar buildSidebar" + "description": "The label for category 'dApp Integration' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Implementing Transactions": { "message": "Thực hiện giao dịch", @@ -285,27 +285,27 @@ }, "sidebar.buildSidebar.category.Cookbooks": { "message": "Sách nấu ăn", - "description": "The label for category Cookbooks in sidebar buildSidebar" + "description": "The label for category 'Cookbooks' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Fundamentals": { "message": "Cơ bản", - "description": "The label for category Fundamentals in sidebar buildSidebar" + "description": "The label for category 'Fundamentals' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Token Development": { "message": "Phát triển token", - "description": "The label for category Token Development in sidebar buildSidebar" + "description": "The label for category 'Token Development' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Deployment & Verification": { "message": "Triển khai & Xác minh", - "description": "The label for category Deployment & Verification in sidebar buildSidebar" + "description": "The label for category 'Deployment & Verification' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Integrate Gas Abstraction (GA)": { "message": "Tích hợp Hệ thống Chiết xuất Khí (GA)", - "description": "The label for category Integrate Gas Abstraction (GA) in sidebar buildSidebar" + "description": "The label for category 'Integrate Gas Abstraction (GA)' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Kaia Agent Kit": { "message": "Bộ dụng cụ Kaia Agent", - "description": "The label for category Kaia Agent Kit in sidebar buildSidebar" + "description": "The label for category 'Kaia Agent Kit' in sidebar 'buildSidebar'" }, "sidebar.refSidebar.category.Gas Abstraction": { "message": "Chiết xuất khí", @@ -313,306 +313,306 @@ }, "sidebar.refSidebar.category.viem-ext": { "message": "viêm-ext", - "description": "The label for category viem-ext in sidebar refSidebar" + "description": "The label for category 'viem-ext' in sidebar 'refSidebar'" }, "sidebar.buildSidebar.doc.Step 1: Foundation Setup": { "message": "Bước 1: Thiết lập nền tảng", - "description": "The label for the doc item Step 1: Foundation Setup in sidebar buildSidebar, linking to the doc build/get-started/foundation-setup" + "description": "The label for the doc item 'Step 1: Foundation Setup' in sidebar 'buildSidebar', linking to the doc build/get-started/foundation-setup" }, "sidebar.buildSidebar.doc.Step 2: Set up Account and Networks": { "message": "Bước 2: Thiết lập tài khoản và mạng", - "description": "The label for the doc item Step 2: Set up Account and Networks in sidebar buildSidebar, linking to the doc build/get-started/wallet-config-get-started" + "description": "The label for the doc item 'Step 2: Set up Account and Networks' in sidebar 'buildSidebar', linking to the doc build/get-started/wallet-config-get-started" }, "sidebar.buildSidebar.doc.Step 3: Get KAIA": { "message": "Bước 3: Nhận KAIA", - "description": "The label for the doc item Step 3: Get KAIA in sidebar buildSidebar, linking to the doc build/get-started/getting-kaia" + "description": "The label for the doc item 'Step 3: Get KAIA' in sidebar 'buildSidebar', linking to the doc build/get-started/getting-kaia" }, "sidebar.buildSidebar.doc.Step 4: Deploy Hello World Contract": { "message": "Bước 4: Triển khai hợp đồng Hello World", - "description": "The label for the doc item Step 4: Deploy Hello World Contract in sidebar buildSidebar, linking to the doc build/get-started/kaiagreeter-get-started" + "description": "The label for the doc item 'Step 4: Deploy Hello World Contract' in sidebar 'buildSidebar', linking to the doc build/get-started/kaiagreeter-get-started" }, "sidebar.buildSidebar.doc.Step 5: Deploy your First Token Contract": { "message": "Bước 5: Triển khai hợp đồng token đầu tiên của bạn", - "description": "The label for the doc item Step 5: Deploy your First Token Contract in sidebar buildSidebar, linking to the doc build/get-started/hardhat" + "description": "The label for the doc item 'Step 5: Deploy your First Token Contract' in sidebar 'buildSidebar', linking to the doc build/get-started/hardhat" }, "sidebar.buildSidebar.doc.Step 6: Build your First dApp on Kaia": { "message": "Bước 6: Xây dựng ứng dụng phi tập trung (dApp) đầu tiên của bạn trên Kaia", - "description": "The label for the doc item Step 6: Build your First dApp on Kaia in sidebar buildSidebar, linking to the doc build/get-started/scaffold-eth-get-started" + "description": "The label for the doc item 'Step 6: Build your First dApp on Kaia' in sidebar 'buildSidebar', linking to the doc build/get-started/scaffold-eth-get-started" }, "sidebar.buildSidebar.doc.Step 7: Build your Mini dApp on Kaia": { "message": "Bước 7: Xây dựng ứng dụng dApp mini của bạn trên Kaia", - "description": "The label for the doc item Step 7: Build your Mini dApp on Kaia in sidebar buildSidebar, linking to the doc minidapps/minidapps" + "description": "The label for the doc item 'Step 7: Build your Mini dApp on Kaia' in sidebar 'buildSidebar', linking to the doc minidapps/minidapps" }, "sidebar.buildSidebar.category.smart-contract-tools": { "message": "Công cụ", - "description": "The label for category Tools in sidebar buildSidebar" + "description": "The label for category 'Tools' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Best Practices": { "message": "Các phương pháp tốt nhất", - "description": "The label for category Best Practices in sidebar buildSidebar" + "description": "The label for category 'Best Practices' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.build-tools": { "message": "Công cụ", - "description": "The label for category Tools in sidebar buildSidebar" + "description": "The label for category 'Tools' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Gaming SDKs": { "message": "Bộ công cụ phát triển phần mềm (SDK) cho trò chơi", - "description": "The label for category Gaming SDKs in sidebar buildSidebar" + "description": "The label for category 'Gaming SDKs' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.doc.Proof of Play vRNG": { "message": "Chứng minh quá trình chơi vRNG", - "description": "The label for the doc item Proof of Play vRNG in sidebar buildSidebar, linking to the doc build/tools/oracles/vrng-pop" + "description": "The label for the doc item 'Proof of Play vRNG' in sidebar 'buildSidebar', linking to the doc build/tools/oracles/vrng-pop" }, "sidebar.refSidebar.category.account-management-v5": { "message": "Quản lý tài khoản", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v5": { "message": "Khóa tài khoản", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v5": { "message": "Ký giao dịch", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v5": { "message": "Thông điệp ký tên", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-v5": { "message": "Kho khóa", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v5": { "message": "Giao dịch cơ bản", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v5": { "message": "Phí giao dịch ủy quyền", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v5": { "message": "Hợp đồng thông minh", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-v5": { "message": "Công cụ", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-v6": { "message": "Quản lý tài khoản", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v6": { "message": "Khóa tài khoản", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v6": { "message": "Ký giao dịch", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v6": { "message": "Thông điệp ký tên", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-v6": { "message": "Kho khóa", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v6": { "message": "Giao dịch cơ bản", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v6": { "message": "Phí giao dịch ủy quyền", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.gas-abstraction-ethers": { "message": "Chiết xuất khí", - "description": "The label for category Gas Abstraction in sidebar refSidebar" + "description": "The label for category 'Gas Abstraction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v6": { "message": "Hợp đồng thông minh", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-v6": { "message": "Công cụ", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-v1": { "message": "Quản lý tài khoản", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v1": { "message": "Khóa tài khoản", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v1": { "message": "Ký giao dịch", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v1": { "message": "Thông điệp ký tên", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v1": { "message": "Giao dịch cơ bản", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v1": { "message": "Phí giao dịch ủy quyền", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v1": { "message": "Hợp đồng thông minh", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3js": { "message": "Quản lý tài khoản", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3js": { "message": "Khóa tài khoản", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3js": { "message": "Ký giao dịch", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3js": { "message": "Thông điệp ký tên", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3js": { "message": "Kho khóa", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3js": { "message": "Giao dịch cơ bản", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3js": { "message": "Phí giao dịch ủy quyền", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.gas-abstraction-web3js": { "message": "Chiết xuất khí", - "description": "The label for category Gas Abstraction in sidebar refSidebar" + "description": "The label for category 'Gas Abstraction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3js": { "message": "Hợp đồng thông minh", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3js": { "message": "Công cụ", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-viem": { "message": "Giao dịch cơ bản", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-viem": { "message": "Phí giao dịch ủy quyền", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-viem": { "message": "Hợp đồng thông minh", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3j": { "message": "Quản lý tài khoản", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3j": { "message": "Khóa tài khoản", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3j": { "message": "Ký giao dịch", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3j": { "message": "Thông điệp ký tên", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3j": { "message": "Kho khóa", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3j": { "message": "Giao dịch cơ bản", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3j": { "message": "Phí giao dịch ủy quyền", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3j": { "message": "Hợp đồng thông minh", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3j": { "message": "Công cụ", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3py": { "message": "Quản lý tài khoản", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3py": { "message": "Khóa tài khoản", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3py": { "message": "Ký giao dịch", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3py": { "message": "Thông điệp ký tên", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3py": { "message": "Kho khóa", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3py": { "message": "Giao dịch cơ bản", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3py": { "message": "Phí giao dịch ủy quyền", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3py": { "message": "Hợp đồng thông minh", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3py": { "message": "Công cụ", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.doc.getting-started-ethers": { "message": "Bắt đầu", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/ethers-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/ethers-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-ethers-v1": { "message": "Bắt đầu", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/ethers-ext-prior-v1-0-1/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/ethers-ext-prior-v1-0-1/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3js": { "message": "Bắt đầu", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3js-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3js-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-viem": { "message": "Bắt đầu", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/viem-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/viem-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3j": { "message": "Bắt đầu", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3j-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3j-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3py": { "message": "Bắt đầu", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3py-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3py-ext/getting-started" } } diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md b/i18n/vi/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md index 256dbd2d0d7e..284255909ebb 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md @@ -10,5 +10,5 @@ Với SDK Web3.unity, các nhà phát triển có thể dễ dàng xây dựng c SDK Web3.unity hiện tại hỗ trợ cả mạng chính Kaia (Kaia Mainnet) và mạng thử nghiệm Kairos (Kairos Testnet). Để bắt đầu phát triển các trò chơi tích hợp blockchain trên Kaia, hãy tham khảo các hướng dẫn sau: -- [Phát triển trò chơi Unity trên Kaia: Tạo token có thể thay thế (Fungible Tokens) với ChainSafe](https://medium.com/kaiachain/unity-game-development-on-kaia-minting-fungible-tokens-with-chainsafe-beea9022c42d) -- [Cách áp dụng cơ chế Token-Gate cho trò chơi Unity bằng Chainsafe và Thirdweb trên Kaia](https://medium.com/kaiachain/how-to-token-gate-a-unity-game-using-chainsafe-and-thirdweb-on-kaia-93c574519da2) +- [Phát triển trò chơi Unity trên Kaia: Tạo token có thể thay thế (Fungible Tokens) với ChainSafe](https://blog.kaia.io/unity-game-development-on-kaia-minting-fungible-tokens-with-chainsafe/) +- [Cách áp dụng cơ chế Token-Gate cho trò chơi Unity bằng Chainsafe và Thirdweb trên Kaia](https://blog.kaia.io/how-to-token-gate-a-unity-game-using-chainsafe-and-thirdweb-on-kaia/) diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md index f7d65b4a7dfe..c91f7aa64c0d 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md @@ -887,4 +887,4 @@ If you’ve made it this far, congratulations! In this tutorial, you have learne From here, you could also explore some other options in your frontend like adding a new input field for the amount of coffee to be sent other than sending 1 KAIA statically. You can have access to the full codebase here on [github](https://github.com/ayo-klaytn/buy-me-a-coffee) and also test the website using this [link](https://spring-fog-0605.on.fleek.co/). -If you want more information, visit [Kaia Docs](https://docs.klaytn.foundation/), [Web3Onboard Docs](https://onboard.blocknative.com/docs/modules/react), and [Fleek Docs](https://docs.fleek.co/tutorials/hosting/). If you have any questions, visit [Kaia Forum](https://devforum.kaia.io/). +Nếu bạn muốn biết thêm thông tin, hãy truy cập [Kaia Docs](https://docs.kaia.io), [Web3Onboard Docs](https://onboard.blocknative.com/docs/modules/react) và [Fleek Docs](https://docs.fleek.co/tutorials/hosting/). If you have any questions, visit [Kaia Forum](https://devforum.kaia.io/). diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md new file mode 100644 index 000000000000..f59e5cd3fe71 --- /dev/null +++ b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md @@ -0,0 +1,748 @@ +# Xây dựng NFT đa chuỗi trên Kaia với Chainlink CCIP: Hướng dẫn thực hành + +## Giới thiệu + +NFT đã trở thành một trong những ứng dụng nổi bật nhất của công nghệ blockchain, cho phép tạo ra các tài sản kỹ thuật số duy nhất và có thể xác minh. Tuy nhiên, các triển khai NFT truyền thống bị giới hạn trong một blockchain duy nhất. Hạn chế này làm giảm tính linh hoạt và ngăn cản tài sản di chuyển tự do giữa các hệ sinh thái, nơi các cộng đồng, thanh khoản và tính hữu dụng có thể khác nhau. + +NFTs xuyên chuỗi giải quyết thách thức này bằng cách cho phép NFTs di chuyển một cách liền mạch giữa các chuỗi khối trong khi vẫn giữ nguyên tính duy nhất và nguồn gốc của chúng. Với giao thức tương tác chuỗi chéo (CCIP) của Chainlink, các nhà phát triển có thể xây dựng các cầu nối đáng tin cậy giữa các chuỗi bằng cách sử dụng một khung làm việc tin nhắn tiêu chuẩn và an toàn. + +Trong hướng dẫn này, bạn sẽ tạo và triển khai một NFT Crosschain sử dụng mô hình đốt và đúc. Một NFT sẽ được đốt trên chuỗi nguồn và đúc lại trên chuỗi đích với cùng tokenId và metadata, đảm bảo rằng chỉ có một bản sao hợp lệ tồn tại tại bất kỳ thời điểm nào. + +## Điều kiện tiên quyết + +Trước khi bắt đầu, hãy đảm bảo rằng bạn đã có các thiết lập sau: + +- [Node.js](https://nodejs.org/) và [npm](https://www.npmjs.com/) +- Mũ bảo hộ + - Cài đặt: `npm install --save-dev hardhat` + - Khởi tạo dự án: `npx hardhat --init` +- [MetaMask](https://metamask.io/en-GB/download) ví + - Tạo hoặc thiết lập ví phát triển. + - Thêm cả mạng thử nghiệm Kaia Kairos Testnet và mạng Ethereum Sepolia vào MetaMask. +- Kiểm tra token từ các vòi nước + - [KAIA](https://faucet.kaia.io/): Thanh toán phí gas trên Kaia khi triển khai hợp đồng hoặc gửi giao dịch. + - [LINK](https://faucets.chain.link/kaia-testnet) (testnet): Miễn phí CCIP khi thanh toán bằng LINK. + - [Sepolia ETH](https://faucets.chain.link/sepolia): thanh toán phí gas trên Sepolia và cũng có thể thanh toán phí CCIP bằng ETH gốc nếu được chọn. +- Tài khoản [Filebase](https://filebase.com/) + - Cần tải lên và truy xuất metadata của NFT (lưu trữ IPFS). + +## Các NFT xuyên chuỗi hoạt động như thế nào? + +Một NFT là một token kỹ thuật số duy nhất được ghi lại trên một blockchain duy nhất. Hành vi cốt lõi của nó, bao gồm việc đúc, chuyển nhượng và quyền sở hữu, được xác định bởi một hợp đồng thông minh liên kết với chuỗi đó. Do đó, một NFT không thể tự nhiên di chuyển giữa các blockchain mà không có các cơ chế bổ sung. Để đảm bảo khả năng tương tác, các nhà phát triển triển khai các hợp đồng phụ trợ trên nhiều chuỗi khối và kết nối chúng thông qua tin nhắn xuyên chuỗi. Kết quả là một NFT xuyên chuỗi: các token tương đương tồn tại trên nhiều blockchain, nhưng chỉ có một bản sao hoạt động tại bất kỳ thời điểm nào. + +NFT xuyên chuỗi thường được triển khai theo một trong ba cách sau: + +- **Đốt và đúc**: NFT được đốt trên chuỗi nguồn, sau đó một bản sao tương đương được đúc trên chuỗi đích. + +- **Khóa và đúc**: NFT được khóa trên chuỗi nguồn và một bản sao được đúc trên chuỗi đích. Để khôi phục, bạn cần xóa bản sao để mở khóa bản gốc. + +- **Khóa và mở khóa**: Các bộ sưu tập giống hệt nhau được triển khai trên nhiều chuỗi. Chủ sở hữu khóa NFT trên một chuỗi để mở khóa phiên bản tương ứng trên chuỗi khác, đảm bảo chỉ có một bản sao có thể được sử dụng tại một thời điểm. + +Trong hướng dẫn này, chúng ta sẽ sử dụng mô hình burn and mint cho NFT Crosschain của mình. NFT sẽ được gỡ bỏ khỏi một chuỗi khối và tạo lại trên một chuỗi khối khác, với toàn bộ quá trình được hỗ trợ bởi Chainlink CCIP. + +## Bắt đầu + +Trong hướng dẫn này, bạn sẽ tạo và chuyển NFT chuỗi chéo giữa Kaia Kairos Testnet và Ethereum Sepolia bằng cách sử dụng Chainlink CCIP. + +Cuối cùng, bạn sẽ có thể: + +- Khởi tạo một dự án Hardhat được cấu hình cho cả mạng thử nghiệm Kairos và Ethereum Sepolia. +- Thêm các hợp đồng và giao diện Chainlink CCIP làm phụ thuộc. +- Triển khai hợp đồng NFT đa chuỗi có cơ chế đốt và đúc để hỗ trợ chuyển giao giữa các chuỗi khối. +- Triển khai hợp đồng thông minh lên cả hai mạng lưới và chuyển NFT qua các chuỗi khối. + +### Tạo dự án Hardhat + +Trong hướng dẫn này, chúng ta sẽ sử dụng [Hardhat 3](https://hardhat.org/docs/getting-started#getting-started-with-hardhat-3) để triển khai và tương tác với hợp đồng của mình. Hardhat 3 cung cấp các tính năng mới như hỗ trợ tích hợp cho kho khóa mã hóa, khả năng viết thử nghiệm bằng Solidity và cải tiến công cụ quản lý dự án. + +Thực hiện các bước sau để thiết lập dự án của bạn: + +1. Kiểm tra cài đặt Node.js và npm + + Chạy các lệnh sau để kiểm tra xem Node.js và npm đã được cài đặt hay chưa: + +```bash +node -v +npm -v +``` + +2. Tạo một thư mục dự án mới + + Tạo một thư mục mới, truy cập vào thư mục đó và khởi tạo một dự án Node.js: + +```bash +mkdir ccip-nft-kaia-hardhat-example +cd ccip-nft-kaia-hardhat-example +npm init -y +``` + +3. Tạo dự án Hardhat + + Chạy: + +```bash +npx hardhat --init +``` + +Khi được yêu cầu, hãy chọn dự án mẫu bao gồm trình chạy thử nghiệm Node.js và ethers. Khởi tạo nó trong thư mục hiện tại và cài đặt tất cả các phụ thuộc cần thiết. + +### Cài đặt các hợp đồng bắt buộc + +Cài đặt các hợp đồng Chainlink CCIP: + +```bash +npm i @chainlink/contracts-ccip --save-dev +``` + +Cài đặt các hợp đồng Chainlink tiêu chuẩn: + +```bash +npm i @chainlink/contracts --save-dev +``` + +Cài đặt các hợp đồng OpenZeppelin (cung cấp các triển khai cơ bản như ERC-721 và các tiêu chuẩn khác): + +```bash +npm i @openzeppelin/contracts --save-dev +``` + +## Cấu hình metadata NFT + +Trước khi soạn thảo hợp đồng, hãy xác định các thông số kỹ thuật của NFT mà chúng ta sẽ đúc. Mỗi NFT cần có metadata mô tả tên, mô tả và hình ảnh của nó, được lưu trữ trong một tệp JSON và lưu trữ trên IPFS. + +Trong hướng dẫn này, chúng ta sẽ sử dụng Filebase để lưu trữ cả hình ảnh và metadata. Nếu bạn muốn tạo NFT của riêng mình, hãy tải lên hình ảnh và tệp JSON metadata của bạn lên IPFS thông qua Filebase. Sau khi tải lên, nhấp vào tên tệp trong tab Tệp và sao chép URL IPFS. Nó sẽ trông tương tự như sau: + +```bash +https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmY1LZF8JHo2r3h4X5VzLLXtJujqnBFGTyo2aqR9joXnt8 +``` + +Dưới đây là một tệp metadata mẫu mà bạn có thể sử dụng: + +```json +{ + "name": "Kairos NFT", + "description": "gkaia frens! gazuaaaaa!!!", + "image": "https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmRvQc4wZCp6NF7dFL4ywiWTG7FSH3KKGUAkXGgsdYfcKi" +} +``` + +## Viết Hợp đồng thông minh + +Trong phần này, bạn sẽ triển khai hợp đồng cho phép chuyển nhượng NFT giữa các blockchain bằng mô hình đốt và đúc (burn-and-mint) được hỗ trợ bởi Chainlink CCIP. + +Tạo một tệp mới trong thư mục hợp đồng của dự án có tên `CrosschainNFT.sol`, và dán mã sau vào tệp đó: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; +import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import {ERC721URIStorage} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; +import {ERC721Burnable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; +import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import {Client} from "@chainlink/contracts-ccip/contracts/libraries/Client.sol"; +import {IRouterClient} from "@chainlink/contracts-ccip/contracts/interfaces/IRouterClient.sol"; +import {IAny2EVMMessageReceiver} from "@chainlink/contracts-ccip/contracts/interfaces/IAny2EVMMessageReceiver.sol"; +import {OwnerIsCreator} from "@chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol"; +import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; +/** + * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. + * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. + * DO NOT USE THIS CODE IN PRODUCTION. + */ + // Source chain is Ethereum Sepolia + // Destination chain is Kairos Testnet +contract CrosschainNFT is ERC721, ERC721URIStorage, ERC721Burnable, IAny2EVMMessageReceiver, ReentrancyGuard, OwnerIsCreator { + using SafeERC20 for IERC20; + enum PayFeesIn { + Native, + LINK + } + error InvalidRouter(address router); + error OnlyOnEthereumSepolia(); + error NotEnoughBalanceForFees(uint256 currentBalance, uint256 calculatedFees); + error NothingToWithdraw(); + error FailedToWithdrawEth(address owner, address target, uint256 value); + error ChainNotEnabled(uint64 chainSelector); + error SenderNotEnabled(address sender); + error OperationNotAllowedOnCurrentChain(uint64 chainSelector); + struct crosschainNFTDetails { + address crosschainNFTAddress; + bytes ccipExtraArgsBytes; + } + uint256 constant ETHEREUM_SEPOLIA_CHAIN_ID = 11155111; + string tokenNFTURI = "https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmY1LZF8JHo2r3h4X5VzLLXtJujqnBFGTyo2aqR9joXnt8"; + IRouterClient internal immutable i_ccipRouter; + LinkTokenInterface internal immutable i_linkToken; + uint64 private immutable i_currentChainSelector; + uint256 private _nextTokenId; + mapping(uint64 destChainSelector => crosschainNFTDetails crosschainNFTPerChain) public s_chains; + event ChainEnabled(uint64 chainSelector, address xNftAddress, bytes ccipExtraArgs); + event ChainDisabled(uint64 chainSelector); + event CrossChainSent( + address from, address to, uint256 tokenId, uint64 sourceChainSelector, uint64 destinationChainSelector + ); + event CrossChainReceived( + address from, address to, uint256 tokenId, uint64 sourceChainSelector, uint64 destinationChainSelector + ); + modifier onlyRouter() { + if (msg.sender != address(i_ccipRouter)) { + revert InvalidRouter(msg.sender); + } + _; + } + modifier onlyOnEthereumSepolia() { + if (block.chainid != ETHEREUM_SEPOLIA_CHAIN_ID) { + revert OnlyOnEthereumSepolia(); + } + _; + } + modifier onlyEnabledChain(uint64 _chainSelector) { + if (s_chains[_chainSelector].crosschainNFTAddress == address(0)) { + revert ChainNotEnabled(_chainSelector); + } + _; + } + modifier onlyEnabledSender(uint64 _chainSelector, address _sender) { + if (s_chains[_chainSelector].crosschainNFTAddress != _sender) { + revert SenderNotEnabled(_sender); + } + _; + } + modifier onlyOtherChains(uint64 _chainSelector) { + if (_chainSelector == i_currentChainSelector) { + revert OperationNotAllowedOnCurrentChain(_chainSelector); + } + _; + } + constructor(address ccipRouterAddress, address linkTokenAddress, uint64 currentChainSelector) + ERC721("Cross Chain NFT", "XNFT") + { + if (ccipRouterAddress == address(0)) revert InvalidRouter(address(0)); + i_ccipRouter = IRouterClient(ccipRouterAddress); + i_linkToken = LinkTokenInterface(linkTokenAddress); + i_currentChainSelector = currentChainSelector; + } + function mint() external onlyOnEthereumSepolia { + uint256 tokenId = _nextTokenId++; + _safeMint(msg.sender, tokenId); + _setTokenURI(tokenId, tokenNFTURI); + } + function enableChain(uint64 chainSelector, address crosschainNFTAddress, bytes memory ccipExtraArgs) + external + onlyOwner + onlyOtherChains(chainSelector) + { + s_chains[chainSelector] = crosschainNFTDetails({crosschainNFTAddress: crosschainNFTAddress, ccipExtraArgsBytes: ccipExtraArgs}); + emit ChainEnabled(chainSelector, crosschainNFTAddress, ccipExtraArgs); + } + function disableChain(uint64 chainSelector) external onlyOwner onlyOtherChains(chainSelector) { + delete s_chains[chainSelector]; + emit ChainDisabled(chainSelector); + } + function crossChainTransferFrom( + address from, + address to, + uint256 tokenId, + uint64 destinationChainSelector, + PayFeesIn payFeesIn + ) external nonReentrant onlyEnabledChain(destinationChainSelector) returns (bytes32 messageId) { + string memory tokenUri = tokenURI(tokenId); + _burn(tokenId); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(s_chains[destinationChainSelector].crosschainNFTAddress), + data: abi.encode(from, to, tokenId, tokenUri), + tokenAmounts: new Client.EVMTokenAmount[](0), + extraArgs: s_chains[destinationChainSelector].ccipExtraArgsBytes, + feeToken: payFeesIn == PayFeesIn.LINK ? address(i_linkToken) : address(0) + }); + // Get the fee required to send the CCIP message + uint256 fees = i_ccipRouter.getFee(destinationChainSelector, message); + if (payFeesIn == PayFeesIn.LINK) { + if (fees > i_linkToken.balanceOf(address(this))) { + revert NotEnoughBalanceForFees(i_linkToken.balanceOf(address(this)), fees); + } + // Approve the Router to transfer LINK tokens on contract's behalf. It will spend the fees in LINK + i_linkToken.approve(address(i_ccipRouter), fees); + // Send the message through the router and store the returned message ID + messageId = i_ccipRouter.ccipSend(destinationChainSelector, message); + } else { + if (fees > address(this).balance) { + revert NotEnoughBalanceForFees(address(this).balance, fees); + } + // Send the message through the router and store the returned message ID + messageId = i_ccipRouter.ccipSend{value: fees}(destinationChainSelector, message); + } + emit CrossChainSent(from, to, tokenId, i_currentChainSelector, destinationChainSelector); + } + /// @inheritdoc IAny2EVMMessageReceiver + function ccipReceive(Client.Any2EVMMessage calldata message) + external + virtual + override + onlyRouter + nonReentrant + onlyEnabledChain(message.sourceChainSelector) + onlyEnabledSender(message.sourceChainSelector, abi.decode(message.sender, (address))) + { + uint64 sourceChainSelector = message.sourceChainSelector; + (address from, address to, uint256 tokenId, string memory tokenUri) = + abi.decode(message.data, (address, address, uint256, string)); + _safeMint(to, tokenId); + _setTokenURI(tokenId, tokenUri); + emit CrossChainReceived(from, to, tokenId, sourceChainSelector, i_currentChainSelector); + } + function withdraw(address _beneficiary) public onlyOwner { + uint256 amount = address(this).balance; + if (amount == 0) revert NothingToWithdraw(); + (bool sent,) = _beneficiary.call{value: amount}(""); + if (!sent) revert FailedToWithdrawEth(msg.sender, _beneficiary, amount); + } + function withdrawToken(address _beneficiary, address _token) public onlyOwner { + uint256 amount = IERC20(_token).balanceOf(address(this)); + if (amount == 0) revert NothingToWithdraw(); + IERC20(_token).safeTransfer(_beneficiary, amount); + } + function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) { + return super.tokenURI(tokenId); + } + function getCCIPRouter() public view returns (address) { + return address(i_ccipRouter); + } + function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721URIStorage) returns (bool) { + return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || super.supportsInterface(interfaceId); + } +} +``` + +### Hướng dẫn chi tiết về mã nguồn + +CrosschainNFT là một hợp đồng ERC-721 tích hợp Chainlink CCIP để chuyển NFT giữa các blockchain. Nó đốt NFT trên chuỗi nguồn và đúc lại nó trên chuỗi đích với cùng tokenId và tokenURI. Hợp đồng duy trì một danh sách các chuỗi đích được phê duyệt thông qua enableChain, sử dụng Chainlink Router (IRouterClient) cho việc truyền tin giữa các chuỗi, và hỗ trợ thanh toán phí bằng cả token gas gốc hoặc LINK. + +Các chức năng chính + +- Kích hoạt chuỗi + +Cho phép chủ sở hữu hợp đồng đăng ký một blockchain đích. Nó lưu trữ địa chỉ hợp đồng NFT đối tác và các tham số CCIP trong bản đồ s_chains, cho phép chuỗi đó là mục tiêu chuyển nhượng hợp lệ. Sự kiện ChainEnabled được phát ra khi quá trình thiết lập hoàn tất. + +- Chuyển giao chuỗi chéo từ + +Thực hiện việc chuyển giao NFT giữa các chuỗi khối. Nó trước tiên kiểm tra xem chuỗi đích đã được kích hoạt hay chưa, sau đó lấy metadata của NFT (tokenURI) và đốt token trên chuỗi nguồn. Tiếp theo, nó tạo một tin nhắn CCIP chứa thông tin chuyển khoản, tính toán phí cần thiết và thanh toán bằng LINK hoặc gas gốc. Khi tin nhắn được gửi qua router, sự kiện CrossChainSent được phát ra để ghi lại giao dịch. + +Bây giờ khi đã hiểu rõ luồng chính của `CrosschainNFT.sol`, chúng ta hãy tiếp tục sang bước tiếp theo. + +## Biên dịch các hợp đồng thông minh + +Để biên dịch các hợp đồng thông minh của bạn, hãy chạy: + +```bash +npx hardhat build +``` + +## Triển khai Hợp đồng thông minh + +Trong phần này, chúng ta sẽ cấu hình các biến cần thiết và sau đó triển khai hợp đồng `CrosschainNFT.sol` trên cả Ethereum Sepolia (chuỗi nguồn) và Kairos Testnet (chuỗi đích). + +### Sử dụng Kho khóa được mã hóa + +Một trong những lợi ích của Hardhat 3 là khả năng lưu trữ các giá trị nhạy cảm, chẳng hạn như khóa riêng tư và URL RPC, trong một kho khóa được mã hóa thay vì các tệp văn bản thuần túy. Trong hướng dẫn này, chúng ta sẽ mã hóa _PRIVATE_KEY_ và _RPC URLs_ cho Sepolia và Kairos. + +**Thêm khóa riêng của bạn** + +```bash +npx hardhat keystore set PRIVATE_KEY +``` + +Lần đầu tiên bạn chạy lệnh này, Hardhat sẽ yêu cầu bạn tạo mật khẩu cho kho khóa. Bạn sẽ cần mật khẩu này mỗi khi thêm hoặc cập nhật giá trị. + +**Thêm URL RPC cho từng mạng** + +```bash +npx hardhat keystore set KAIROS_RPC_URL +npx hardhat keystore set SEPOLIA_RPC_URL +``` + +Cuối cùng, chỉnh sửa tệp `hardhat.config.ts` của bạn để tải các giá trị đã được mã hóa này và cấu hình hai mạng. + +```typescript +import type { HardhatUserConfig } from "hardhat/config"; +import hardhatToolboxMochaEthersPlugin from "@nomicfoundation/hardhat-toolbox-mocha-ethers"; +import { configVariable } from "hardhat/config"; +const config: HardhatUserConfig = { + plugins: [hardhatToolboxMochaEthersPlugin], + solidity: { + profiles: { + default: { + version: "0.8.28", + }, + production: { + version: "0.8.28", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + }, + }, + networks: { + hardhatMainnet: { + type: "edr-simulated", + chainType: "l1", + }, + hardhatOp: { + type: "edr-simulated", + chainType: "op", + }, + kairosTestnet: { + type: "http", + chainType: "l1", + url: configVariable("KAIROS_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + ethereumSepolia: { + type: "http", + chainType: "l1", + url: configVariable("SEPOLIA_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + }, +}; +export default config; +``` + +Bước tiếp theo là triển khai hợp đồng thông minh CrosschainNFT lên Ethereum Sepolia và Kairos Testnet tương ứng. + +### Triển khai CrosschainNFT.sol lên Ethereum Sepolia + +Trước khi triển khai, hãy lấy các giá trị sau cho Ethereum Sepolia từ [Chainlink CCIP Directory](https://docs.chain.link/ccip/directory/testnet/chain/ethereum-testnet-sepolia): + +- Chọn chuỗi +- Địa chỉ router CCIP +- Địa chỉ token LINK + +Các giá trị này sẽ được yêu cầu trong kịch bản triển khai của bạn. Tiếp theo, truy cập vào thư mục _ignition/modules_ trong dự án của bạn và tạo một tệp mới có tên: `deployEthereumSepolia.ts`, sau đó dán mã sau vào tệp đó: + +```typescript +// This setup uses Hardhat Ignition to manage smart contract deployments. +// Learn more about it at https://hardhat.org/ignition +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const ETHEREUM_SEPOLIA_ROUTER_ADDRESS = `0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59`; +const ETHEREUM_SEPOLIA_LINK_TOKEN_ADDRESS = `0x779877A7B0D9E8603169DdbD7836e478b4624789`; +const ETHEREUM_SEPOLIA_CHAIN_SELECTOR = `16015286601757825753`; +const CrosschainNFTSepoliaModule = buildModule("CrosschainNFTSepoliaModule", (m) => { + const crosschainNFTSepolia = m.contract("CrosschainNFT", [ETHEREUM_SEPOLIA_ROUTER_ADDRESS, ETHEREUM_SEPOLIA_LINK_TOKEN_ADDRESS, ETHEREUM_SEPOLIA_CHAIN_SELECTOR], { + }); + return { crosschainNFTSepolia }; +}); +export default CrosschainNFTSepoliaModule; +``` + +Chạy kịch bản triển khai: + +```bash +npx hardhat ignition deploy ignition/modules/deployEthereumSepolia.ts --network ethereumSepolia +``` + +### Triển khai CrosschainNFT.sol lên mạng thử nghiệm Kairos. + +Trước khi triển khai, hãy lấy các giá trị sau cho Kairos Testnet từ [Chainlink CCIP Directory](https://docs.chain.link/ccip/directory/testnet/chain/kaia-testnet-kairos): + +- Chọn chuỗi +- Địa chỉ router CCIP +- Địa chỉ token LINK + +Các giá trị này sẽ được yêu cầu trong kịch bản triển khai của bạn. Tiếp theo, truy cập vào thư mục _ignition/modules_ trong dự án của bạn và tạo một tệp mới có tên: `deployKairosTestnet.ts`, sau đó dán mã sau vào tệp đó: + +```typescript +// This setup uses Hardhat Ignition to manage smart contract deployments. +// Learn more about it at https://hardhat.org/ignition + +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const KAIROS_TESTNET_ROUTER_ADDRESS = `0x41477416677843fCE577748D2e762B6638492755`; +const KAIROS_TESTNET_LINK_TOKEN_ADDRESS = `0xAF3243f975afe2269Da8Ffa835CA3A8F8B6A5A36`; +const KAIROS_TESTNET_CHAIN_SELECTOR = `2624132734533621656`; +const CrosschainNFTKairosModule = buildModule("CrosschainNFTKairosModule", (m) => { + const crosschainNFTKairos = m.contract("CrosschainNFT", [KAIROS_TESTNET_ROUTER_ADDRESS, KAIROS_TESTNET_LINK_TOKEN_ADDRESS, KAIROS_TESTNET_CHAIN_SELECTOR], { + }); + return { crosschainNFTKairos }; +}); +export default CrosschainNFTKairosModule; +``` + +Chạy kịch bản triển khai: + +```bash +npx hardhat ignition deploy ignition/modules/deployKairosTestnet.ts --network kairosTestnet +``` + +## Tương tác với Hợp đồng thông minh + +Trong phần này, chúng ta sẽ tương tác với hợp đồng thông minh CrosschainNFT đã được triển khai bằng cách thực thi các hàm enableChain, mint và crosschainTransfer tương ứng. + +### Bước 1: Trên Ethereum Sepolia, gọi hàm enableChain + +Chuẩn bị các giá trị sau đây trước khi gọi hàm enableChain: + +- **Địa chỉ hợp đồng Sepolia**: Địa chỉ của hợp đồng CrosschainNFT.sol được triển khai trên mạng Ethereum Sepolia. +- **Địa chỉ hợp đồng Kairos**: Địa chỉ của hợp đồng CrosschainNFT.sol được triển khai trên mạng thử nghiệm Kairos. +- **Chọn chuỗi**: 2624132734533621656 (mã chọn chuỗi CCIP cho mạng thử nghiệm Kairos). +- **CCIP extraArgs**: 0x97a657c9000000000000000000000000000000000000000000000000000000000007A120 (Đây là giá trị mã hóa mặc định của extraArgs với giới hạn gas được đặt là 500.000). + +Tiếp theo, tạo một tệp TypeScript mới trong thư mục scripts, đặt tên là: `enableChainSepolia.ts` và dán mã sau vào tệp đó: + +```typescript +// scripts/enableChainSepolia.ts +import { network } from "hardhat"; +async function main() { + const connection = await network.connect({ + network: "ethereumSepolia" + }); + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory by name + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + // Contract addresses and parameters + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + const crosschainNFTAddressKairosTestnet = `0x8c464Bb9Bf364F68b898ed0708b8f5F66EF6Cfb1`; + const chainSelectorKairosTestnet = `2624132734533621656`; + const ccipExtraArgs = `0x97a657c9000000000000000000000000000000000000000000000000000000000007A120`; + // Attach to the deployed contract + const crosschainNFTSepolia = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + console.log(`Enabling chain for Kairos Testnet...`); + const tx = await crosschainNFTSepolia.enableChain( + chainSelectorKairosTestnet, + crosschainNFTAddressKairosTestnet, + ccipExtraArgs + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Chain enabled successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +Gọi hàm bằng cách chạy lệnh sau: + +```bash +npx hardhat run scripts/enableChainSepolia.ts --network ethereumSepolia +``` + +### Bước 2: Trên mạng thử nghiệm Kairos, gọi hàm enableChain + +Chuẩn bị các giá trị sau đây trước khi gọi hàm enableChain: + +- **Địa chỉ hợp đồng Kairos**: Địa chỉ của hợp đồng CrosschainNFT.sol được triển khai trên mạng thử nghiệm Kairos. +- **Địa chỉ hợp đồng Sepolia**: Địa chỉ của hợp đồng CrosschainNFT.sol được triển khai trên mạng Ethereum Sepolia. +- **Chuỗi chọn**: 16015286601757825753 (chuỗi chọn CCIP cho mạng thử nghiệm Kairos) +- **CCIP extraArgs**: 0x97a657c9000000000000000000000000000000000000000000000000000000000007A120 (Đây là giá trị mã hóa mặc định của extraArgs với giới hạn gas được đặt là 500.000) + +Tiếp theo, tạo một tệp TypeScript mới trong thư mục scripts, đặt tên là: `enableChainKairos.ts` và dán mã sau vào tệp đó: + +```typescript +// scripts/enableChainKairos.ts +import { network } from "hardhat"; +async function main() { + const connection = await network.connect({ + network: "kairosTestnet" + }); + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory by name + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + // Contract addresses and parameters + const crosschainNFTAddressKairosTestnet = `0x8c464Bb9Bf364F68b898ed0708b8f5F66EF6Cfb1`; + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + const chainSelectorEthereumSepolia = `16015286601757825753`; + const ccipExtraArgs = `0x97a657c9000000000000000000000000000000000000000000000000000000000007A120`; + // Attach to the deployed contract on Kairos + const crosschainNFTKairos = CrosschainNFT.attach(crosschainNFTAddressKairosTestnet); + console.log(`Enabling chain for Ethereum Sepolia...`); + const tx = await crosschainNFTKairos.enableChain( + chainSelectorEthereumSepolia, + crosschainNFTAddressEthereumSepolia, + ccipExtraArgs + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Chain enabled successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +Gọi hàm bằng cách chạy lệnh sau: + +```bash +npx hardhat run scripts/enableChainKairos.ts --network KairosTestnet +``` + +### Bước 3: Tài trợ hợp đồng bằng LINK trên Ethereum Sepolia + +Để thanh toán phí CCIP, hãy nạp tiền vào hợp đồng CrosschainNFT được triển khai trên Ethereum Sepolia (crosschainNFTAddressEthereumSepolia) bằng LINK. Bạn có thể nhận mã thử nghiệm LINK từ [vòi nước](https://faucets.chain.link/sepolia) được cung cấp. Đối với hướng dẫn này, việc gửi 3 LINK là đủ. + +![](/img/build/tutorials/cc-ccip-fund-link.png) + +### Bước 4: Tạo một NFT chuỗi chéo mới trên Ethereum Sepolia + +Tiếp theo, tạo một NFT mới trên hợp đồng CrosschainNFT đã được triển khai trên Ethereum Sepolia. + +Tạo một tệp TypeScript mới trong thư mục scripts, đặt tên là `mint.ts` và dán mã sau vào tệp đó: + +```typescript +// scripts/mint.ts +import { network } from "hardhat"; +async function main() { + // Connect to the network + const connection = await network.connect({ + network: "ethereumSepolia" + }); +if (connection.networkName !== "ethereumSepolia") { + console.error(`Must be called from Ethereum Sepolia`); + process.exitCode = 1; + return; + } + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22` + // Attach to the deployed contract + const crosschainNFT = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + console.log(`Minting NFT...`); + const tx = await crosschainNFT.mint(); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`NFT minted successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +Kịch bản này sẽ xử lý quá trình đúc NFT và chuẩn bị NFT cho việc chuyển giao chuỗi chéo. + +Gọi hàm bằng cách chạy lệnh sau: + +```bash +npx hardhat run scripts/mint.ts --network ethereumSepolia +``` + +### Bước 5: Chuyển NFT giữa các chuỗi khối + +Trên Ethereum Sepolia, bạn sẽ gọi hàm crossChainTransferFrom để chuyển NFT của mình sang Kairos Testnet. + +Chuẩn bị các giá trị sau: + +- **Từ**: Địa chỉ EOA của bạn trên Ethereum Sepolia +- **đến**: địa chỉ EOA của người nhận trên mạng thử nghiệm Kairos (đây cũng có thể là địa chỉ của chính bạn) +- **tokenId**: ID của NFT mà bạn muốn chuyển nhượng +- **destinationChainSelector**: 2624132734533621656 (mã chọn chuỗi CCIP cho mạng thử nghiệm Kairos) +- **payFeesIn**: 1 (cho biết phí CCIP sẽ được thanh toán bằng LINK) + +Chạy skript chuyển đổi + +Tạo một tệp TypeScript mới trong thư mục scripts, đặt tên là `crossChainTransferNFT.ts` và dán mã sau vào tệp đó: + +```typescript +// scripts/crossChainTransferNFT.ts +import { network } from "hardhat"; +async function main() { + // Connect to the network + const connection = await network.connect({ + network: "ethereumSepolia" + }); + // Check if we're on the correct network + if (connection.networkName !== "ethereumSepolia") { + console.error(`Must be called from Ethereum Sepolia`); + process.exitCode = 1; + return; + } + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + // Transfer parameters + const from = `0x7b467A6962bE0ac80784F131049A25CDE27d62Fb`; + const to = `0x7b467A6962bE0ac80784F131049A25CDE27d62Fb`; + const tokenId = 0; // Put NFT token id here + const destinationChainSelector = "2624132734533621656"; // Kairos Testnet + const payFeesIn = 1; // 0 - Native, 1 - LINK + // Attach to the deployed contract + const crosschainNFT = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + const tx = await crosschainNFT.crossChainTransferFrom( + from, + to, + tokenId, + destinationChainSelector, + payFeesIn + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Cross-chain transfer initiated successfully!`); + console.log(`Note: The NFT will arrive on Kairos Testnet after CCIP processes the message.`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +Sau đó, thực thi kịch bản bằng cách: + +```bash +npx hardhat run scripts/crossChainTransferNFT.ts --network ethereumSepolia +``` + +Xác minh giao dịch chuyển khoản + +Bạn có thể theo dõi giao dịch chuyển chuỗi trên [CCIP Explorer](https://ccip.chain.link/#/side-drawer/msg/0x2a43cf8076ed6290dd0bf8bdbbc87abe2d238da43b6bf514e70909dd0f35c9db) và xác nhận giao dịch trên [Kaiascan](https://kairos.kaiascan.io/nft/0x7dcdaa882603b1cfeee42d1c382a1ecba595d87c/0?tabId=nftTokenTransfer&page=1). + +![](/img/build/tutorials/cc-nft-ccip-explorer.png) + +![](/img/build/tutorials/cc-nft-ccip-kaiascan.png) + +Khi NFT được đưa lên mạng thử nghiệm Kairos, hãy thêm nó vào ví MetaMask của bạn: + +1. Mở tab NFT trong MetaMask. +2. Nhấp vào "Nhập NFT". +3. Nhập địa chỉ hợp đồng CrosschainNFT trên mạng thử nghiệm Kairos và mã tokenId mà bạn đã nhận (ví dụ: 0). + +NFT của bạn hiện đã xuất hiện trong ví MetaMask của bạn. + +![](/img/build/tutorials/cc-ccip-mm-view-nft.png) + +## Kết luận + +Trong hướng dẫn này, bạn đã học cách sử dụng Chainlink CCIP để chuyển NFT giữa Kaia Kairos Testnet và Ethereum Sepolia bằng mô hình đốt và đúc. + +Để tìm hiểu sâu hơn về CCIP và khám phá các trường hợp sử dụng bổ sung, hãy truy cập tài liệu chính thức [Chainlink CCIP Documentation](https://docs.chain.link/ccip). + + + + diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md index 4b5e0da8dfbc..d2cf4e3d535d 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md @@ -79,5 +79,5 @@ Bạn có thể xem chúng trên trình khám phá mạng thử nghiệm Kairos. **Nội dung giáo dục:** -- [Nếu bạn có thể thanh toán phí gas bằng stablecoin thì sao?](https://medium.com/kaiachain/pay-for-gas-fees-with-any-token-a-deep-dive-into-kaias-trustless-gas-abstraction-d670355a096b) -- [Thông báo về tính thanh khoản của Kaia Consensus](https://medium.com/kaiachain/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity-7c8a7393cd19) \ No newline at end of file +- [Nếu bạn có thể thanh toán phí gas bằng stablecoin thì sao?](https://blog.kaia.io/pay-for-gas-fees-with-any-token-a-deep-dive-into-kaias-trustless-gas-abstraction/) +- [Thông báo về thanh khoản của Kaia Consensus](https://blog.kaia.io/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity/) \ No newline at end of file diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md index c103957433e4..0fb13f1ea872 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md @@ -45,4 +45,4 @@ Khác với các giải pháp dựa vào dịch vụ "người thanh toán trung ## 1.4 Mối quan hệ với Thanh khoản đồng thuận (CL) -GA ban đầu được thiết kế để tăng tính tiện ích cho [Consensus Liquidity tokens](https://medium.com/kaiachain/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity-7c8a7393cd19), cho phép người dùng thanh toán phí gas bằng CL tokens (ví dụ: BORA, Swapscanner). Tuy nhiên, tính năng này cũng hỗ trợ các token ERC-20 khác, bao gồm cả stablecoin. \ No newline at end of file +GA ban đầu được thiết kế để tăng tính tiện ích cho [Consensus Liquidity tokens](https://blog.kaia.io/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity/), cho phép người dùng thanh toán phí gas bằng các token CL (ví dụ: BORA, Swapscanner). Tuy nhiên, tính năng này cũng hỗ trợ các token ERC-20 khác, bao gồm cả stablecoin. \ No newline at end of file diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md new file mode 100644 index 000000000000..cf6a2a713a53 --- /dev/null +++ b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md @@ -0,0 +1,479 @@ +--- +id: integrate-gas-free-usdt-kaia-swap +title: Tích hợp USDT không cần gas vào KAIA Swaps +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Tích hợp USDT không cần gas vào KAIA Swaps + +Hướng dẫn này cung cấp tổng quan về tính năng Swap USDT sang KAIA không sử dụng gas, bao gồm mục đích, điều kiện tiên quyết, các bước tích hợp và tài liệu tham khảo API. Nó được thiết kế để giúp các nhà phát triển tích hợp khả năng hoán đổi không tốn gas vào các ứng dụng phi tập trung (DApps) của họ trên mạng Kaia. + +## Giới thiệu + +API `gasFreeSwapKaia` đã được giới thiệu để cho phép người dùng thực hiện các giao dịch hoán đổi token ERC20 không tốn phí gas (hiện tại chỉ hỗ trợ USDT) trên mạng lưới Kaia mà không cần phải nắm giữ token KAIA để thanh toán phí gas, hoặc thậm chí khi thanh toán phí giao dịch thay cho người dùng. API này hỗ trợ việc đổi USDT sang KAIA bằng cách sử dụng chữ ký cho phép ERC20, mang lại trải nghiệm người dùng hoàn toàn không tốn phí gas. + +### Lợi ích + +- **Trải nghiệm 100% không cần gas**: Người dùng không cần bất kỳ token KAIA nào để thực hiện các giao dịch hoán đổi. +- **Tối ưu hóa quy trình đăng ký người dùng**: Người dùng mới có thể bắt đầu giao dịch token ngay lập tức mà không cần mua KAIA. +- **Tích hợp ERC20 Permit**: Sử dụng chữ ký ERC20 Permit tiêu chuẩn để phê duyệt token an toàn và không tốn gas. + +### Cách thức hoạt động + +- **Người dùng khởi tạo giao dịch hoán đổi**: Người dùng chọn số lượng USDT để hoán đổi sang KAIA. +- **Frontend tạo giấy phép**: Ứng dụng phi tập trung (DApp) tạo chữ ký giấy phép ERC20 cho người dùng ký. +- **Người dùng ký giấy phép**: Người dùng ký vào thông báo giấy phép (không cần gas) +- **Gọi API của DApp**: Giao diện người dùng gửi các thông số giao dịch và chữ ký cho phép đến API. +- **Backend thực thi**: API xác thực giấy phép, thực hiện giao dịch hoán đổi và thanh toán tất cả phí gas. +- **Người dùng nhận KAIA**: Các token KAIA gốc được gửi trực tiếp vào ví của người dùng. + +## Điều kiện tiên quyết và Môi trường được hỗ trợ + +**Điểm cuối dịch vụ** + + + + https://fee-delegation.kaia.io + + + + https://fee-delegation-kairos.kaia.io + + + +**Cặp token được hỗ trợ** + +Hiện tại, API chỉ hỗ trợ một cặp giao dịch duy nhất: + + + + Token vào: USDT (`0xd077a400968890eacc75cdc901f0356c943e4fdb`) + +``` +Token Out: WKAIA (`0x19aac5f612f524b754ca7e7c41cbfa2e981a4432`) +``` + + + + + Token vào: TEST (`0xcb00ba2cab67a3771f9ca1fa48fda8881b457750`) + +``` +Token Out: WKAIA (`0x043c471bEe060e00A56CcD02c0Ca286808a5A436`) +``` + + + + +**Nhận mã thử nghiệm** + +Để nhận token TEST cho mạng thử nghiệm Kairos: + +- Mở [ERC20 Faucet](https://kairos.kaiascan.io/address/0x78a6cacfe5d34e0566e56710c8789d207411001a?tabId=contract&page=1) trên Kaiascan +- Đi đến tab Hợp đồng, sau đó chọn _Viết Hợp đồng_ +- Tìm chức năng yêu cầu (token) +- Dán địa chỉ của một token GA được hỗ trợ trên Kairos (đối với hướng dẫn này, hãy sử dụng địa chỉ cho TEST) +- Nhấp vào _Query_ để gửi yêu cầu. Bạn sẽ nhận được các token TEST của mình trong thời gian ngắn. + +![](/img/build/tutorials/test-tokens-faucet.png) + +**Yêu cầu của Hợp đồng thông minh** + +Giao diện lập trình ứng dụng (API) tương tác với hợp đồng thông minh GaslessERC20PermitSwap, hợp đồng này: + +- Hỗ trợ các phê duyệt dựa trên giấy phép theo tiêu chuẩn ERC20. +- Tích hợp với sàn giao dịch phi tập trung (DEX) tương thích với Uniswap V2. +- Chuyển đổi WKAIA sang KAIA gốc một cách tự động. +- Áp dụng giới hạn hoán đổi tối đa cho mục đích bảo mật. + +**Yêu cầu của người dùng** + +Trên mạng chính, người dùng phải có số dư KAIA bằng 0 để sử dụng dịch vụ hoán đổi không phí gas này. Yêu cầu này đảm bảo dịch vụ chỉ được sử dụng bởi những người dùng thực sự cần giao dịch không cần gas cho mục đích đăng ký. Trong môi trường testnet, hạn chế này được nới lỏng cho mục đích thử nghiệm. + +Số tiền hoán đổi tối đa được giới hạn ở mức 1 USDT trên cả mạng chính (mainnet) và mạng thử nghiệm (testnet). Tính năng này được thiết kế để người dùng có thể nhận đủ KAIA để bắt đầu trải nghiệm của họ trên Kaia Chain. + +## Các bước tích hợp + +### Ví dụ về tích hợp hoàn chỉnh + +```javascript +const { JsonRpcProvider, Wallet } = require('@kaiachain/ethers-ext/v6'); +const { Contract, parseUnits, formatUnits, Signature } = require('ethers'); + +async function fetchJson(url, init) { + if (typeof fetch !== 'undefined') { + return fetch(url, init); + } + const { default: nodeFetch } = await import('node-fetch'); + return nodeFetch(url, init); +} + +const GASLESS_SWAP_ABI = [ + 'function usdtToken() view returns (address)', + 'function wkaiaToken() view returns (address)', + 'function maxUsdtAmount() view returns (uint256)', + 'function getExpectedOutput(address tokenIn, address tokenOut, uint256 amountIn) view returns (uint256)', + 'function executeSwapWithPermit(address user, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOutMin, uint256 deadline, uint8 v, bytes32 r, bytes32 s)', +]; + +const ERC20_METADATA_ABI = [ + 'function decimals() view returns (uint8)', + 'function symbol() view returns (string)', + 'function name() view returns (string)', + 'function nonces(address owner) view returns (uint256)', + 'function balanceOf(address owner) view returns (uint256)', +]; + +async function buildPermitSignature({ token, owner, spender, value, deadline, domainVersion = '1' }) { + const [name, version, network, verifyingContract, nonce] = await Promise.all([ + token.name(), + Promise.resolve(domainVersion), + owner.provider.getNetwork(), + token.getAddress(), + token.nonces(owner.address), + ]); + + const domain = { + name, + version, + chainId: Number(network.chainId), + verifyingContract, + }; + + const types = { + Permit: [ + { name: 'owner', type: 'address' }, + { name: 'spender', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'nonce', type: 'uint256' }, + { name: 'deadline', type: 'uint256' }, + ], + }; + + const message = { + owner: owner.address, + spender, + value, + nonce, + deadline, + }; + + return Signature.from(await owner.signTypedData(domain, types, message)); +} + +async function executeGaslessSwap({ + rpcUrl, + serverUrl, + userWallet, + contractAddress, + amountIn = '0.01', // Amount in USDT + slippageBps = 50, // 0.5% slippage + permitDeadlineSeconds = 600 // 10 minutes +}) { + console.log('🚀 Starting gasless swap'); + + const provider = new JsonRpcProvider(rpcUrl); + const wallet = userWallet.connect(provider); + const swap = new Contract(contractAddress, GASLESS_SWAP_ABI, provider); + + // Get token addresses from contract + const [tokenInAddress, tokenOutAddress, maxUsdtAmount] = await Promise.all([ + swap.usdtToken(), + swap.wkaiaToken(), + swap.maxUsdtAmount(), + ]); + + const tokenIn = new Contract(tokenInAddress, ERC20_METADATA_ABI, provider); + const tokenOut = new Contract(tokenOutAddress, ERC20_METADATA_ABI, provider); + + const [tokenInDecimals, tokenOutDecimals, tokenInSymbol, tokenOutSymbol] = await Promise.all([ + tokenIn.decimals(), + tokenOut.decimals(), + tokenIn.symbol(), + tokenOut.symbol(), + ]); + + const amountInWei = parseUnits(amountIn, tokenInDecimals); + + // Check if amount exceeds contract maximum + if (amountInWei > maxUsdtAmount) { + throw new Error(`Amount (${amountIn} ${tokenInSymbol}) exceeds contract cap (${formatUnits(maxUsdtAmount, tokenInDecimals)} ${tokenInSymbol})`); + } + + // Get expected output and calculate minimum with slippage + const expectedOut = await swap.getExpectedOutput(tokenInAddress, tokenOutAddress, amountInWei); + const amountOutMin = (expectedOut * BigInt(10_000 - slippageBps)) / 10_000n; + + // Create permit signature + const deadline = BigInt(Math.floor(Date.now() / 1000) + permitDeadlineSeconds); + const signature = await buildPermitSignature({ + token: tokenIn, + owner: wallet, + spender: contractAddress, + value: amountInWei, + deadline, + }); + + // Prepare API payload + const payload = { + swap: { + user: wallet.address, + tokenIn: tokenInAddress, + tokenOut: tokenOutAddress, + amountIn: amountInWei.toString(), + amountOutMin: amountOutMin.toString(), + deadline: deadline.toString(), + }, +permitSignature: signature.serialized, + }; + + console.log('From:', wallet.address); + console.log('Swap amount:', formatUnits(amountInWei, tokenInDecimals), tokenInSymbol); + console.log('Minimum out:', formatUnits(amountOutMin, tokenOutDecimals), tokenOutSymbol); + + // Check balance before swap + const balanceBefore = await provider.getBalance(wallet.address); + + // Call the API + const response = await fetchJson(`${serverUrl}/api/gasFreeSwapKaia`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + + const result = await response.json().catch(() => ({})); + console.log('HTTP status:', response.status); + console.log('Response:', JSON.stringify(result, null, 2)); + + if (response.ok && result.status) { + console.log('🎉 Gasless swap request succeeded'); + + // Check balance after swap + const balanceAfter = await provider.getBalance(wallet.address); + console.log('Balance before:', formatUnits(balanceBefore, 18), 'KAIA'); + console.log('Balance after:', formatUnits(balanceAfter, 18), 'KAIA'); + console.log('Balance difference:', formatUnits(balanceAfter - balanceBefore, 18), 'KAIA'); + + return result; + } else { + console.error('❌ Gasless swap request failed'); + throw new Error(`Swap failed: ${result.data || result.message || 'Unknown error'}`); + } +} + +// Usage example +async function main() { + try { + const userWallet = new Wallet('your_private_key'); + + const result = await executeGaslessSwap({ + rpcUrl: 'https://public-en-kairos.node.kaia.io', + serverUrl: 'https://fee-delegation-kairos.kaia.io', + userWallet: userWallet, + contractAddress: '0xaaFe47636ACe87E2B8CAaFADb03E87090277Ff7B', + amountIn: '0.002', + slippageBps: 50, + }); + + console.log('Transaction hash:', result.data.hash); + } catch (error) { + console.error('💥 Swap failed:', error.message); + } +} + +main(); +``` + +## Điểm cuối tham chiếu API + +- URL: `/api/gasFreeSwapKaia` +- Phương thức: POST +- Loại nội dung: application/json + +### Nội dung yêu cầu + +```javascript +{ + "swap": { + "user": "0x742d35Cc6635C0532925a3b8D400e6D2A4b8E0bb", + "tokenIn": "0xcb00ba2cab67a3771f9ca1fa48fda8881b457750", + "tokenOut": "0x043c471bEe060e00A56CcD02c0Ca286808a5A436", + "amountIn": "1000000", + "amountOutMin": "950000000000000000", + "deadline": "1699123456" + }, + "permitSignature": "0x…65-byte signature string…" +} +``` + +### Tham số + +**đổi** (đối tượng, bắt buộc): + +- Người dùng (chuỗi): Địa chỉ của chủ sở hữu token đã ký giấy phép. +- tokenIn (chuỗi): Địa chỉ của token đầu vào (phải trùng khớp với địa chỉ USDT đã cấu hình) +- tokenOut (chuỗi): Địa chỉ của token đầu ra (phải trùng khớp với địa chỉ WKAIA đã cấu hình) +- amountIn (chuỗi): Số lượng token đầu vào dưới dạng chuỗi (đơn vị wei/đơn vị nhỏ nhất) +- amountOutMin (chuỗi): Số lượng token đầu ra tối thiểu dự kiến (bảo vệ trượt giá) +- Hạn chót (chuỗi): Dấu thời gian Unix (giây) cho thời hạn hết hiệu lực của giấy phép và trao đổi. + +**permitSignature** (chuỗi, bắt buộc): + +- Phải là chuỗi hex hợp lệ có độ dài 65 byte. +- Chứa chữ ký cho phép ERC20 đã được serial hóa. + +### Định dạng phản hồi + +#### Phản hồi thành công (200) + +```javascript +{ + "message": "Request was successful", + "data": { + "_type": "TransactionReceipt", + "blockHash": "0x2a7ae196f6e7363fe3cfc79132c1d16292d159e231d73b4308f598a3222d1f57", + "blockNumber": 191523443, + "contractAddress": null, + "cumulativeGasUsed": "215000", + "from": "0x6C4ED74027ab609f506efCdd224041c9F5b5CDE1", + "gasPrice": "25000000000", + "gasUsed": "215000", + "hash": "0x0ca73736ceecf2dcf0ec2e1f65760d0b4f7348726cb9a0477710172b1dd44350", + "status": 1, + "to": "0x45bD04d5f14DD9AB908109cFEa816F758FaE6709", + "type": 49, + "feePayer": "0x1234567890abcdef1234567890abcdef12345678", + "feePayerSignatures": ["0x..."], + "logs": [ + { + "address": "0x...", + "topics": ["0x..."], + "data": "0x..." + } + ] + }, + "status": true, + "requestId": "req_abc123def456" +} +``` + +#### Phản hồi lỗi + +**400 Yêu cầu không hợp lệ - Lỗi xác thực:** + +```javascript +{ + "message": "Bad request", + "data": "Permit deadline has expired", + "error": "BAD_REQUEST", + "status": false, + "requestId": "req_error_123" +} +``` + +**400 Yêu cầu không hợp lệ - Giao dịch bị hủy:** + +```javascript +{ + "message": "Bad request", + "data": "execution reverted: Permit already used", + "error": "BAD_REQUEST", + "status": false, + "requestId": "req_revert_456" +} +``` + +**Lỗi máy chủ nội bộ 500:** + +```javascript +{ + "message": "Internal server error", + "data": "Sending transaction was failed after 5 try, network is busy. Error message: Network timeout", + "error": "INTERNAL_ERROR", + "status": false, + "requestId": "req_error_789" +} +``` + +## Xử lý lỗi + +### Các tình huống lỗi thường gặp + +| Lỗi | Trạng thái HTTP | Mô tả | Giải pháp | +| ----------------------------- | --------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | +| Thiếu các trường bắt buộc | 400 | _swap_ hoặc _permitSignature_ bị thiếu | Ba gồm tất cả các tham số bắt buộc. | +| Người dùng có số dư KAIA | 400 | Người dùng phải có số dư KAIA bằng 0. | Chỉ những người dùng có số dư KAIA bằng 0 mới có thể sử dụng dịch vụ này. | +| Định dạng chữ ký không hợp lệ | 400 | Chữ ký giấy phép không phải là chuỗi hex hợp lệ. | Cung cấp một chữ ký hex hợp lệ có độ dài 65 byte. | +| Địa chỉ không hợp lệ | 400 | Địa chỉ Ethereum không hợp lệ | Kiểm tra xem các địa chỉ có hợp lệ hay không. | +| Token không được hỗ trợ | 400 | Token không có trong danh sách được phép. | Chỉ sử dụng các địa chỉ token đã được cấu hình. | +| Hạn chót đã hết hạn | 400 | Hạn chót cấp phép trong quá khứ | Sử dụng dấu thời gian trong tương lai | +| Số tiền quá lớn | 400 | Vượt quá giới hạn tối đa trong hợp đồng | Kiểm tra _maxUsdtAmount()_ từ hợp đồng | +| Báo giá không đủ | 400 | Độ trượt quá nghiêm ngặt | Tăng giới hạn trượt hoặc giảm lượng. | +| Giá xăng quá cao | 400 | Tắc nghẽn mạng | Chờ giá xăng dầu giảm. | +| Thời gian chờ mạng | 500 | Vấn đề liên quan đến nhà cung cấp RPC | Thử lại yêu cầu sau khi chờ đợi | + +## Các yếu tố bảo mật + +### Bảo vệ giá xăng + +API từ chối các giao dịch khi giá gas vượt quá 50 gwei để ngăn chặn chi phí quá cao. Theo dõi giá xăng dầu và thông báo cho người dùng trong các khoảng thời gian giao thông đông đúc. + +### Bảo mật chữ ký + +- Không bao giờ tái sử dụng chữ ký trên giấy phép. +- Luôn sử dụng thời hạn hợp lý (5-30 phút) +- Kiểm tra tất cả các thông số trước khi ký. +- Sử dụng HTTPS cho tất cả các giao tiếp API. + +## Chi tiết Hợp đồng thông minh + +### Địa chỉ hợp đồng GaslessERC20PermitSwap + + + + ``` + 0x45bD04d5f14DD9AB908109cFEa816F758FaE6709 + ``` + + + + ``` + 0xaaFe47636ACe87E2B8CAaFADb03E87090277Ff7B + ``` + + + +### Các chức năng chính + +**executeSwapWithPermit** - Thực hiện giao dịch hoán đổi không tiêu tốn gas bằng chữ ký cho phép: + +- Xác minh giấy phép và các thông số trao đổi. +- Chuyển giao token bằng giấy phép +- Thực hiện giao dịch hoán đổi trên sàn giao dịch phi tập trung (DEX) +- Chuyển đổi WKAIA sang định dạng gốc KAIA +- Gửi KAIA gốc cho người dùng + +**getExpectedOutput** - Chức năng hiển thị để lấy số lượng đầu ra dự kiến: + +```javascript +function getExpectedOutput( + address tokenIn, + address tokenOut, + uint256 amountIn +) external view returns (uint256) +``` + +### Giới hạn hợp đồng + +- Số USDT tối đa cho mỗi giao dịch hoán đổi: 1.000.000 (1 USDT với 6 chữ số thập phân) +- Cặp tiền được hỗ trợ: USDT → WKAIA → KAIA gốc +- Bảo vệ chống tái phát qua theo dõi chữ ký + +## Tài nguyên bổ sung + +- [Tiêu chuẩn cho phép ERC20 (EIP-2612)](https://eips.ethereum.org/EIPS/eip-2612) +- [Kaia Ethers Extension](https://github.com/kaiachain/ethers-ext) + + diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md new file mode 100644 index 000000000000..b0a5e0d5e019 --- /dev/null +++ b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md @@ -0,0 +1,352 @@ +# Hướng dẫn SDK đấu giá Kaia MEV cho người tìm kiếm + +[Kaia v2.1.0](https://github.com/kaiachain/kaia/releases/tag/v2.1.0) đã giới thiệu hệ thống đấu giá MEV, cho phép người dùng tham gia vào các cuộc đấu giá công bằng và minh bạch để tận dụng cơ hội MEV. Hướng dẫn này cung cấp một hướng dẫn chi tiết về quy trình làm việc của người tìm kiếm sử dụng SDK Kaia MEV Auction. + +:::info + +Hướng dẫn này sử dụng các điểm cuối và địa chỉ hợp đồng của mạng thử nghiệm Kairos. Việc ra mắt mạng chính (mainnet) dự kiến sẽ diễn ra vào giữa tháng 12 năm 2025. Khi triển khai lên mạng chính, hãy cập nhật tất cả các điểm cuối và địa chỉ hợp đồng tương ứng. + +::: + +Quy trình làm việc của người tìm kiếm bao gồm bốn bước chính: + +![](/img/build/tutorials/searcher-guide-1.png) + +1. **Khoản đặt cọc**: Người tham gia đặt cọc các token KAIA vào `AuctionDepositVault` để tài trợ cho hoạt động đấu giá. +2. **Đấu giá**: Các nhà thầu cạnh tranh bằng cách nộp các đề xuất đấu giá kín cho người điều hành đấu giá để giành các khung giờ phát sóng. +3. **Nộp đề xuất trúng thầu**: Người điều hành đấu giá chọn người trúng thầu và chuyển các đề xuất trúng thầu đến các nút đồng thuận (CNs). +4. **Thực hiện giao dịch đấu giá**: Các CN thực hiện các giao dịch đấu giá thắng cuộc thông qua hợp đồng `AuctionEntryPoint`. + +Để biết thêm chi tiết về nền tảng kỹ thuật, xem [KIP-249](https://kips.kaia.io/KIPs/kip-249). + +## Điều kiện tiên quyết + +Trước khi bắt đầu, hãy đảm bảo rằng bạn đã có: + +- Ví được nạp tiền bằng token KAIA để nạp tiền. +- [Go](https://golang.org/) đã được cài đặt (phiên bản 1.25+) cho các ví dụ SDK. +- Quyền truy cập vào các điểm cuối mạng Kaia (hướng dẫn này sử dụng mạng thử nghiệm Kairos) +- (Tùy chọn) [Foundry](https://getfoundry.sh/) đã được cài đặt (để sử dụng các lệnh `cast`) + +**Điểm cuối của người đấu giá:** + +- Kairos (mạng thử nghiệm): `https://auctioneer-kairos.kaia.io` +- Mainnet: `https://auctioneer.kaia.io` + +**Điểm cuối Explorer:** + +- Kairos (mạng thử nghiệm): `https://mev-kairos.kaia.io` +- Mainnet: `https://mev.kaia.io` + +**Điểm cuối mạng:** + +- Kairos (mạng thử nghiệm): `https://public-en-kairos.node.kaia.io` +- Mainnet: `https://public-en.node.kaia.io` + +**Địa chỉ hợp đồng (Kairos):** + +- AuctionFeeVault: `0xE4e7d880786c53b6EA6cfA848Eb3a05eE97b2aCC` +- AuctionDepositVault: `0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc` +- AuctionEntryPoint: `0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480` + +Đối với địa chỉ hợp đồng trên mạng chính (sẽ có sẵn sau khi mạng chính được ra mắt), vui lòng kiểm tra [Địa chỉ hợp đồng](../../references/contract-addresses.md). + +:::tip[Monitor Cơ hội MEV] + +Người tìm kiếm có thể xác định các giao dịch có lợi nhuận bằng cách: + +- **Đăng ký API giao dịch đang chờ xử lý của Nhà đấu giá**: API này truyền trực tiếp các giao dịch từ các nút đồng thuận, cho phép bạn phát hiện các cơ hội MEV theo thời gian thực. Xem phần [Giao dịch đang chờ xác nhận đăng ký](#step-3-subscribe-to-pending-transactions) bên dưới. +- **Theo dõi mempool mạng một cách độc lập**: Thực hiện logic phát hiện cơ hội MEV của riêng bạn bằng cách đăng ký các giao dịch đang chờ xử lý. + +::: + +## Bước 1: Nạp tiền + +![](/img/build/tutorials/searcher-guide-2.png) + +`AuctionDepositVault` lưu trữ số dư đặt cọc của bạn. Số tiền đặt cọc của bạn phải đủ để chi trả cả số tiền đặt cọc và phí gas dự kiến cho việc thực hiện đặt cọc. + +### Hiểu rõ các yêu cầu về tiền gửi + +Số dư tiền gửi của bạn phải đủ để: + +- **Số tiền đặt giá**: Số tiền KAIA mà bạn sẵn sàng trả để thắng cuộc đấu giá. +- **Phí gas ước tính**: Lượng gas tiêu thụ trong quá trình thực thi lệnh đặt giá (được trừ sau khi thực thi và chuyển cho các nhà đề xuất khối) + +:::warning[Always [duy trì số dư tiền gửi đủ mức] + +Nếu số dư tài khoản của bạn không đủ để thanh toán số tiền đặt giá thầu cộng với phí gas dự kiến, đề nghị đặt giá thầu của bạn sẽ bị từ chối bởi người điều hành đấu giá trong quá trình xác minh. + +::: + +### Phương thức nạp tiền + +Hợp đồng quy định hai phương thức đặt cọc: + +**Phương pháp 1: `deposit()`** + +Gửi tiền bằng số dư của người gửi. Số tiền đặt cọc được ghi có vào tài khoản của người gửi. + +```bash +# Deploy deposit of 200 KAIA +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "deposit()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 --value 200000000000000000000 +``` + +**Phương pháp 2: `depositFor(address searcher)`** + +Gửi tiền thay mặt cho tài khoản khác. Dùng để tài trợ cho nhiều địa chỉ tìm kiếm từ một nguồn duy nhất. + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "depositFor(address)" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 --value 200000000000000000000 +``` + +### Kiểm tra số dư tài khoản của bạn + +Tra cứu số dư tài khoản tiền gửi hiện tại của bạn: + +```bash +cast call 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "depositBalances(address)(uint256)" --rpc-url "https://public-en-kairos.node.kaia.io" +``` + +Để xem các ví dụ chi tiết về tiền gửi, vui lòng tham khảo hướng dẫn [DEPOSIT.md](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/DEPOSIT.md). + +## Bước 2: Nộp hồ sơ dự thầu + +![](/img/build/tutorials/searcher-guide-3.png) + +Sau khi xác định được một giao dịch có lợi nhuận, hãy nộp đơn đặt giá cho người đấu giá. Các đề xuất được niêm phong (giấu kín cho đến khi phiên đấu giá kết thúc) và cạnh tranh dựa trên giá thầu. + +### Cấu trúc đấu thầu + +Một đề xuất bao gồm các trường sau (như được định nghĩa trong [types.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/types.go)): + +```go +type AuctionBid struct { + TargetTxRaw []byte // Raw transaction bytes of target tx + TargetTxHash common.Hash // Transaction to backrun + BlockNumber *big.Int // Target block number + Sender common.Address // Your searcher address + To common.Address // Contract to call + Nonce uint64 // Current nonce from AuctionEntryPoint + Bid *big.Int // Your bid in KAIA + CallGasLimit uint64 // Gas limit for your backrun logic + Data []byte // Encoded function call + SearcherSig []byte // EIP-712 signature from searcher +} +``` + +:::info + +Sau khi bạn nộp đề xuất đấu giá, Người điều hành đấu giá sẽ xác minh và thêm chữ ký của mình (`AuctioneerSignature`) trước khi chuyển các đề xuất trúng thầu đến các Nút đồng thuận. Bạn chỉ cần cung cấp `SearcherSig` (chữ ký EIP-712 của bạn). + +::: + +### Nộp đề xuất + +SDK cung cấp một ví dụ hoàn chỉnh và hoạt động tại [`example/submitbid.go`](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go). Ví dụ minh họa: + +- Thiết lập kết nối HTTPS với người đấu giá +- Phát hiện các khối mới từ điểm cuối EN +- Tạo các giao dịch mục tiêu và các đề xuất tương ứng +- Nộp hồ sơ dự thầu cho Ban tổ chức đấu giá + +**Hành động cần thực hiện**: Thay thế khóa riêng tư của bạn trong mã trước khi chạy nó. Kiểm tra các bình luận `TODO:` trong mã nguồn. + +Chạy ví dụ: + +```bash +# From repository root +go run example/submitbid.go +``` + +### Xác minh đề xuất + +Người điều hành đấu giá, Người đề xuất và Hợp đồng thông minh mỗi bên thực hiện các kiểm tra xác thực cụ thể đối với các đề nghị đấu giá. Các quy tắc xác thực chính bao gồm: + +- **Số khối**: Phải là currentBlockNumber + 1 hoặc currentBlockNumber + 2 +- **Số tiền đặt cọc**: Phải lớn hơn 0 và nhỏ hơn hoặc bằng số dư tiền gửi khả dụng của bạn. +- **Kích thước dữ liệu giao dịch**: Không được vượt quá `BidTxMaxDataSize` (64KB) +- **Giới hạn gas cho giao dịch**: Không được vượt quá `BidTxMaxCallGasLimit` (10.000.000) +- **Nonce**: Phải khớp với nonce hiện tại của bạn trong `AuctionEntryPoint`. Hãy truy vấn bằng: + ```bash + cast call 0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480 "nonces(address)(uint256)" --rpc-url "https://public-en-kairos.node.kaia.io" + ``` +- **Chữ ký**: Phải là chữ ký hợp lệ theo tiêu chuẩn EIP-712 (xem [submitbid.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go) để biết cách triển khai) +- **Bảo đảm tiền gửi**: Phải có đủ tiền gửi để chi trả cho `bid_amount + estimated_gas_fee` +- **Độc đáo**: Không thể có một đề nghị trúng thầu khác trong cùng một khối (trừ khi nhắm mục tiêu vào cùng một giao dịch) +- **Chữ ký của người đấu giá**: Phải hợp lệ (được người đấu giá thêm sau khi bạn nộp) + +Để xem ma trận xác thực đầy đủ cho biết thực thể nào thực hiện các kiểm tra nào, vui lòng tham khảo [Hướng dẫn xác thực đề xuất](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/bid_validation.md). + +## Bước 3: Đăng ký theo dõi các giao dịch đang chờ xử lý + +![](/img/build/tutorials/searcher-guide-4.png) + +Nhà đấu giá cung cấp dịch vụ đăng ký WebSocket cho phép truyền trực tiếp các giao dịch đang chờ xử lý từ các nút đồng thuận. Điều này cho phép người tìm kiếm phát hiện các cơ hội MEV theo thời gian thực. + +SDK cung cấp một ví dụ hoàn chỉnh tại [example/subscribe_pendingtx.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/subscribe_pendingtx.go). + +Ví dụ minh họa: + +- Thiết lập kết nối WebSocket với Auctioneer +- Đăng ký theo dõi luồng giao dịch đang chờ xử lý +- Xử lý các giao dịch đến để xác định cơ hội MEV. + +Chạy ví dụ: + +```bash +# From repository root +go run example/subscribe_pendingtx.go +``` + +Dịch vụ đăng ký liên tục in các băm giao dịch khi phát hiện các giao dịch đang chờ xử lý. Bạn có thể mở rộng ví dụ này để triển khai logic phát hiện MEV của riêng mình. + +## Bước 4: Hiểu về quá trình thực thi + +Khi đề xuất của bạn trúng thầu, Nút Đồng thuận sẽ thực thi nó thông qua hợp đồng `AuctionEntryPoint`: + +![](/img/build/tutorials/searcher-guide-1.png) + +### Quy trình thực thi + +Quy trình thực thi bao gồm ba giai đoạn: + +1. **Giai đoạn xác thực**: Hợp đồng xác thực số khối, chữ ký, nonce và số tiền đặt cược. +2. **Giai đoạn thanh toán đấu thầu**: Số tiền đấu thầu được trừ từ khoản đặt cọc của bạn và chuyển vào quỹ hệ sinh thái. +3. **Giai đoạn thực thi**: Giao dịch của bạn được thực thi bởi hợp đồng EntryPoint (việc thanh toán đặt cược diễn ra bất kể kết quả thực thi). + +**Các tính năng bảo mật chính:** + +- Các trình xác thực thực hiện các đề xuất thay mặt bạn (ngăn chặn việc hủy bỏ đề xuất để tránh thanh toán). +- Sự gia tăng nonce ngăn chặn các cuộc tấn công tái phát. +- Chữ ký kép (người tìm kiếm + người đấu giá) không được phép thay thế hoặc thao túng giá thầu. +- Thanh toán thầu diễn ra bất kể kết quả thực thi backrun. + +Để xem chi tiết về luồng thực thi, hãy tham khảo hướng dẫn [ENTRYPOINT.md](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/ENTRYPOINT.md). + +## Bước 5: Rút tiền + +![](/img/build/tutorials/searcher-guide-5.png) + +Việc rút tiền yêu cầu một quy trình hai bước với thời gian khóa: + +### 1. Rút tiền từ tài khoản dự trữ + +Bắt đầu quá trình rút tiền và khởi động khoảng thời gian khóa 60 giây: + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "reserveWithdraw()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 +``` + +### 2. Rút lui hoàn toàn + +Sau 60 giây, chuyển số tiền đã dự trữ: + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "withdraw()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 +``` + +:::info[Security Lưu ý] + +Quy trình rút tiền hai bước có thời gian khóa: + +- Ngăn chặn việc thoát khỏi phiên đấu giá đột ngột trong các giai đoạn đấu giá đang diễn ra. +- Bảo đảm tính toàn vẹn của giao thức bằng cách đảm bảo các bên tham gia tuân thủ cam kết của mình. +- Bảo vệ chống lại các cuộc tấn công thao túng vốn nhanh chóng. + +::: + +## Tham chiếu API + +Nhà đấu giá cung cấp hai giao diện lập trình ứng dụng (API) chính cho người tìm kiếm: + +**1. Gửi đề xuất API** + +- **Điểm cuối**: `POST /api/v1/auction/send` +- **Mục đích**: Nộp hồ sơ dự thầu kín cho các cơ hội MEV. + +**2. Đăng ký giao dịch đang chờ xử lý** + +- **Điểm cuối**: `GET /api/v1/subscriber/pendingtx` +- **Mục đích**: Dòng dữ liệu thời gian thực về các giao dịch đang chờ xử lý từ các nút đồng thuận. +- **Ví dụ**: Xem ví dụ thực hiện trong [subscribe_pendingtx.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/subscribe_pendingtx.go) + +**Tài liệu API đầy đủ:** + +- Các thông số kỹ thuật OpenAPI (Swagger) có sẵn tại: + - **Kairos**: https://auctioneer-kairos.kaia.io/docs + - **Mainnet**: Có sẵn sau khi mainnet được ra mắt. +- Sử dụng API: [Tài liệu API](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/api_doc.md) + +## Khắc phục sự cố + +### Vấn đề thường gặp + +| Loại vấn đề | Triệu chứng | Nguyên nhân | Giải pháp | +| --------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Số dư không đủ** | Đề nghị đấu giá bị từ chối bởi người điều hành đấu giá. | Số dư tiền gửi không đủ để thanh toán số tiền đặt cọc + phí gas dự kiến. | Kiểm tra số dư bằng hàm `depositBalances()` và nạp thêm KAIA. | +| **Sự không khớp của nonce** | Đề xuất bị từ chối hoặc việc thực hiện không thành công | Nonce không khớp với nonce hiện tại trong `AuctionEntryPoint` | Kiểm tra giá trị nonce hiện tại bằng hàm `nonces()` trước mỗi lần đặt giá thầu. Lưu ý: Nonces chỉ tăng khi thực thi, không phải khi gửi. | +| **Phạm vi số khối** | Đề nghị đấu giá bị từ chối bởi người điều hành đấu giá. | Khối mục tiêu nằm ngoài phạm vi cho phép `[current+1, current+allowFutureBlock]` | Đảm bảo số khối nằm trong phạm vi (thường là +1 hoặc +2). Xem FAQ để biết chiến lược nộp đơn kép. | +| **Chữ ký không hợp lệ** | Đề nghị đấu giá bị từ chối bởi người điều hành đấu giá. | Cấu trúc chữ ký EIP-712 không chính xác | Xác minh dấu phân cách miền và nhập mã băm. Tham khảo [submitbid.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go) để thực hiện đúng cách. | +| **Vấn đề giới hạn gas** | Thực thi thất bại hoặc đề nghị bị từ chối | `CallGasLimit` quá thấp hoặc vượt quá giới hạn tối đa (10.000.000) | Kiểm tra logic chạy ngược trên mạng thử nghiệm để đo lường mức tiêu thụ gas thực tế. | + +## Câu hỏi thường gặp + +### Đăng ký + +**Câu hỏi: Số lượng kết nối đồng thời được phép cho mỗi người tìm kiếm là bao nhiêu?** + +A: Mỗi địa chỉ người tìm kiếm chỉ được phép có một kết nối đăng ký giao dịch đang chờ xử lý. + +**Câu hỏi: Kết nối đăng ký sẽ duy trì hoạt động trong bao lâu?** + +A: Các kết nối sẽ tự động đóng sau 24 giờ. Lưu ý rằng kết nối có thể bị đóng trước 24 giờ nếu đang thực hiện cập nhật liên tục. + +### Hiệu suất và độ trễ của API + +**Câu hỏi: Làm thế nào để giảm thiểu độ trễ API khi gửi đề xuất?** + +A: Người điều hành đấu giá sử dụng bộ cân bằng tải L7 với giao thức HTTPS. Quá trình bắt tay ban đầu mất thời gian tùy thuộc vào trạng thái mạng. Để tránh sự chậm trễ ban đầu khi gửi các API đặt giá tiếp theo, khuyến nghị mạnh mẽ là thiết lập kết nối keep-alive. + +**Câu hỏi: Tôi có cần lưu ý về giới hạn tốc độ API không?** + +A: Để tránh bị chặn bởi máy chủ API của Auctioneer, vui lòng không gửi yêu cầu `ping` API quá nhiều lần trong một khoảng thời gian ngắn. + +**Câu hỏi: Vị trí địa lý có ảnh hưởng đến độ trễ không?** + +A: Vâng. Máy chủ Auctioneer đang chạy trong khu vực GCP KR (Seoul). Bạn được khuyến nghị nên triển khai hạ tầng của mình tại một khu vực địa lý gần để giảm thiểu độ trễ và giảm thiểu sự chậm trễ do khoảng cách địa lý. + +### Thời điểm đặt giá thầu và mục tiêu khối + +**Câu hỏi: Tại sao đề xuất của tôi đôi khi nhắm mục tiêu vào số khối sai?** + +A: Thời điểm nộp đề xuất của bạn có ảnh hưởng lớn đến thời gian khai thác của CN (Consensus Node). Nếu phiên đấu giá bắt đầu muộn (gần thời gian khai thác), giao dịch đặt giá thầu sẽ được chèn vào khối tiếp theo (số khối +2 thay vì +1). Điều này có nghĩa là bạn nên đặt số khối mục tiêu của mình thành +2. + +**Câu hỏi: Làm thế nào để tôi có thể cải thiện tỷ lệ trúng thầu của mình?** + +A: Số khối mục tiêu có tính nhạy cảm cao với lịch trình khai thác CN: nếu bạn đặt mục tiêu là khối +2 nhưng giao dịch được chèn vào khối +1 do quá trình xử lý sớm hơn, đề xuất sẽ thất bại. Do đó, khuyến nghị nên tối đa hóa xác suất được chọn bằng cách gửi giao dịch đặt giá thầu hai lần: một lần với số khối mục tiêu là +1 và một lần với số khối mục tiêu là +2. + +## Các phương pháp tốt nhất + +- **Theo dõi số dư tài khoản**: Duy trì số dư đủ để đảm bảo có thể tham gia nhiều lượt đấu giá. +- **Xử lý Nonces cẩn thận**: Luôn kiểm tra nonce mới nhất trước khi đặt giá thầu. +- **Tối ưu hóa phát hiện**: Phát hiện MEV nhanh hơn giúp nâng cao lợi thế cạnh tranh. +- **Kiểm thử trên Kairos**: Kiểm tra chiến lược của bạn trên mạng thử nghiệm trước khi triển khai lên mạng chính. +- **Theo dõi kết quả**: Theo dõi kết quả đấu giá thông qua MEV Explorer để tối ưu hóa chiến lược đặt giá thầu của bạn. +- **Đặt giới hạn khí phù hợp**: Cân bằng giữa lượng khí đủ và hiệu quả chi phí. + +## Tài nguyên + +- [Kho SDK](https://github.com/kaiachain/auctioneer-sdk) +- [KIP-249 Specification](https://kips.kaia.io/KIPs/kip-249) +- [Ví dụ mã nguồn](https://github.com/kaiachain/auctioneer-sdk/tree/dev/example) +- Tài liệu API: [auctioneer-kairos.kaia.io/docs](https://auctioneer-kairos.kaia.io/docs) (Kairos), TBU (Mainnet) +- MEV Explorer: [mev-kairos.kaia.io](https://mev-kairos.kaia.io) (Kairos), TBU (Mainnet) +- [Câu hỏi thường gặp](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/FAQ.md) + +## Nhận trợ giúp + +Đối với các vấn đề hoặc câu hỏi: + +- Đăng bài trong [Kaia DevForum](https://devforum.kaia.io) +- Mở một vấn đề trong kho lưu trữ SDK (https://github.com/kaiachain/auctioneer-sdk/issues) diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md new file mode 100644 index 000000000000..8dee4964c731 --- /dev/null +++ b/i18n/vi/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md @@ -0,0 +1,325 @@ +# Cách lấy giá thời gian thực trên Kaia bằng Python + +## Giới thiệu + +Pyth là một mạng lưới oracle phi tập trung có cách tiếp cận độc đáo trong một hệ sinh thái chủ yếu được vận hành bởi các oracle dựa trên cơ chế đẩy. Thay vì đẩy dữ liệu đến hợp đồng của bạn theo các khoảng thời gian cố định, Pyth cho phép bạn kéo dữ liệu thực tế theo yêu cầu. Mô hình này cung cấp cho các nhà phát triển quyền kiểm soát nhiều hơn và giúp tránh các bản cập nhật không cần thiết trên chuỗi khối. Với tích hợp này, các nhà phát triển có thể truy xuất dữ liệu thời gian thực và sử dụng mô hình thanh toán theo nhu cầu, trong đó phí chỉ được áp dụng khi có yêu cầu cập nhật. + +Trong hướng dẫn này, bạn sẽ học cách sử dụng nguồn dữ liệu giá thời gian thực của Pyth để đọc giá trị của IDR, một loại tiền tệ fiat. Hợp đồng thông minh Solidity của bạn sẽ lấy giá USD/IDR từ Pyth bằng cách sử dụng [pyth-sdk-solidity](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity), và bạn sẽ cập nhật và lấy giá mới nhất bằng cách sử dụng [hermes-client](https://github.com/pyth-network/pyth-crosschain/tree/main/apps/hermes/client/js). + +Để bắt đầu nhanh chóng, bạn có thể tìm thấy mã nguồn đầy đủ cho hướng dẫn này trên [GitHub](https://github.com/ayo-klaytn/pyth-kaia-hardhat-example). Điều này cung cấp một tài liệu tham khảo sẵn sàng sử dụng và giúp bạn thiết lập dự án và cài đặt nhanh chóng hơn. + +## Điều kiện tiên quyết + +Trước khi bắt đầu, hãy đảm bảo bạn có các thứ sau: + +- [Node.js và npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) + + Yêu cầu cài đặt các gói phụ thuộc và chạy các công cụ phát triển. + +- Một ví được nạp bằng token KAIA trên mạng thử nghiệm. + + Bạn sẽ cần KAIA để thanh toán phí triển khai và phí giao dịch trên mạng thử nghiệm Kairos. Bạn có thể yêu cầu KAIA miễn phí trên mạng thử nghiệm (testnet) từ [Kaia Faucet](https://faucet.kaia.io/). + +## Cài đặt môi trường phát triển + +Trong phần này, bạn sẽ thiết lập môi trường phát triển, biên dịch hợp đồng Oracle của mình và chuẩn bị để triển khai bằng Hardhat. + +**1. Tạo Dự án Hardhat** + +Tạo một thư mục mới cho dự án của bạn và khởi tạo Hardhat: + +```bash +mkdir pyth-kaia-hardhat-example && cd pyth-kaia-hardhat-example +npm init -y +npx hardhat@next --init +``` + +Chấp nhận các phản hồi mặc định khi được yêu cầu. Trong hướng dẫn này, chúng ta sẽ sử dụng mẫu Mocha và Ethers. + +Kiểm tra phiên bản Hardhat để xác minh cài đặt của bạn: + +```bash +npx hardhat --version +``` + +**2. Đặt các bí mật được mã hóa** + +Bạn sẽ lưu trữ URL RPC và khóa riêng tư của mình bằng kho khóa được mã hóa của Hardhat. + +Chạy các lệnh sau: + +```bash +npx hardhat keystore set KAIROS_RPC_URL +npx hardhat keystore set PRIVATE_KEY +``` + +Hãy đảm bảo nhập mật khẩu và giá trị cho từng biến để giữ chúng được mã hóa. + +**3. Tham chiếu các bí mật trong tệp cấu hình của bạn** + +Mở tệp `hardhat.config.ts` và cập nhật phần `networks` để tham chiếu đến các bí mật đã được mã hóa. Nếu bạn đã sử dụng các tên bí mật khác nhau, hãy cập nhật các khóa tương ứng. + +```typescript +import { configVariable } from "hardhat/config"; +module.exports = { + networks: { + kairos: { + url: configVariable("KAIROS_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + }, +}; +``` + +## Tạo hợp đồng và lấy giá từ Pyth Oracles + +Trong phần này, bạn sẽ cài đặt [Pyth Solidity SDK](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity), tạo hợp đồng PriceConsumer và triển khai nó bằng Hardhat. Hợp đồng sẽ đọc dữ liệu giá từ Pyth, mà sau đó bạn sẽ cập nhật bằng dữ liệu giá lấy từ Hermes. + +### Cài đặt SDK Python + +Pyth cung cấp một SDK Solidity cho phép bạn tương tác với các hợp đồng cung cấp dữ liệu giá Pyth trên chuỗi khối. SDK cung cấp giao diện IPyth và các cấu trúc liên quan. + +Cài đặt SDK bằng npm: + +```bash +npm install --save-dev @pythnetwork/pyth-sdk-solidity +``` + +### Tạo hợp đồng PriceConsumer + +Tạo một tệp mới tại `contracts/PriceConsumer.sol` và thêm mã sau: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; +import "@pythnetwork/pyth-sdk-solidity/IPyth.sol"; +import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol"; +contract PriceConsumer { + IPyth public pyth; + constructor(address pythContract) { + pyth = IPyth(pythContract); + } + function updatePrice(bytes[] calldata priceUpdateData) + external + payable + { + // Pay the Pyth fee for receiving price updates + uint fee = pyth.getUpdateFee(priceUpdateData); + require(msg.value >= fee, "Not enough fee sent"); + // Update the Pyth price state + pyth.updatePriceFeeds{value: fee}(priceUpdateData); + // Can fetch the price and use it as well + //PythStructs.Price memory currentBasePrice = pyth.getPriceNoOlderThan(priceFeedId, 60); + } + function getLatestPrice(bytes32 priceFeedId) public view returns (int64, int32) { + // Read the current price from a price feed if it is less than 60 seconds old. + // Each price feed (e.g., USD/IDR) is identified by a price feed ID. + // The complete list of feed IDs is available at https://docs.pyth.network/price-feeds/price-feeds + PythStructs.Price memory currentBasePrice = pyth.getPriceNoOlderThan(priceFeedId, 60); + + // uint256 basePrice = PythUtils.convertToUint( + // currentBasePrice.price, + // currentBasePrice.expo, + // 18 + // ); + + return (currentBasePrice.price, currentBasePrice.expo); + } +} +``` + +**Hướng dẫn chi tiết** + +Hợp đồng Giá cả và Người tiêu dùng: + +- Nhập các giao diện và cấu trúc của Pyth từ `@pythnetwork/pyth-sdk-solidity`. +- Cửa hàng: + - Thực thể hợp đồng Pyth (pyth). + - Mã nguồn giá cho cặp tiền USD/IDR (usdIdrPriceId). +- Phơi bày phương thức `updateAndGetUsdIdrPrice`, có chức năng: + - Tính toán phí cập nhật bằng cách sử dụng hàm IPyth.getUpdateFee. + - Gọi hàm IPyth.updatePriceFeeds với phí yêu cầu. + - Gọi hàm IPyth.getPriceNoOlderThan để đọc giá USD / IDR mới nhất. + - Trả về giá gốc, hệ số mũ và thời gian công bố. + +Sau đó, client Hermes offchain của bạn sẽ xây dựng mảng bytes priceUpdate và truyền nó vào hàm này khi bạn cần cập nhật giá mới. + +### Soạn thảo hợp đồng + +Chạy lệnh sau để biên dịch các hợp đồng của bạn: + +``` +npx hardhat compile +``` + +## Triển khai Hợp đồng + +Để triển khai hợp đồng PriceConsumer, bạn sẽ tạo một mô-đun Ignition và sau đó chạy lệnh triển khai. + +**Tạo mô-đun Ignition** + +Tạo một tệp mới tại `ignition/modules/PriceConsumer.ts`: + +```typescript +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const pythContractAddress = "0x2880ab155794e7179c9ee2e38200202908c17b43"; +export default buildModule("PriceConsumerModule", (m) => { + const priceConsumer = m.contract("PriceConsumer", [pythContractAddress]); + return { priceConsumer }; +}); +``` + +**Triển khai hợp đồng** + +Triển khai hợp đồng PriceConsumer lên mạng thử nghiệm Kairos bằng mô-đun Ignition của bạn: + +```bash +npx hardhat ignition deploy --network kairos ignition/modules/PriceConsumer.ts +``` + +Khi được yêu cầu, hãy nhập mật khẩu keystore mà bạn đã cấu hình trước đó cho các bí mật được mã hóa của mình. + +Sau khi hoàn tất, hợp đồng `PriceConsumer.sol` của bạn sẽ được triển khai trên mạng thử nghiệm Kairos và sẵn sàng để lấy dữ liệu giá USD/IDR theo thời gian thực từ Pyth. + +## Tương tác từ TypeScript + +Trong bước cuối cùng này, bạn sẽ tương tác với hợp đồng PriceConsumer đã được triển khai bằng TypeScript. Kịch bản này sẽ lấy giá USD/IDR mới nhất bằng cách yêu cầu dữ liệu cập nhật giá từ Pyth thông qua client Hermes và gửi dữ liệu đó lên chuỗi khối. + +**Cài đặt các thành phần phụ thuộc** + +Cài đặt các gói phần mềm cần thiết: + +```bash +npm install --save-dev tsx @pythnetwork/hermes-client @dotenv +``` + +**Thiết lập tệp .env** + +Tạo một tệp .env trong thư mục gốc của dự án và thêm khóa riêng tư của bạn: + +```bash +PRIVATE_KEY="0xDEAD....." // REPLACE WITH YOUR PRIVATE KEY +``` + +**Tạo kịch bản tương tác** + +Tạo một tệp mới tại **scripts/interact.ts** và thêm nội dung sau: + +```typescript +import { HermesClient } from "@pythnetwork/hermes-client"; +import { ethers } from "ethers"; +import 'dotenv/config' + +// 1. Setup +const hermes = new HermesClient("https://hermes.pyth.network"); +const provider = new ethers.JsonRpcProvider( + "https://public-en-kairos.node.kaia.io" +); + +const PK = process.env.PRIVATE_KEY; +const wallet = new ethers.Wallet(PK, provider); + + +// 2. Your deployed contract +const priceConsumerAddress = "0x91e89aa32224dEd5dA483a83a4de45bF4bE57caA"; // REPLACE WITH DEPLOYED PRICE CONSUMER CONTRACT + +const priceConsumerAbi = [ + "function updatePrice(bytes[] priceUpdateData) external payable", + "function getLatestPrice(bytes32 priceId) public view returns(int64, int32)", +]; + +const priceConsumer = new ethers.Contract( + priceConsumerAddress, + priceConsumerAbi, + wallet +); + +// 3. Price feed IDs +const priceId = + "0x6693afcd49878bbd622e46bd805e7177932cf6ab0b1c91b135d71151b9207433"; // FX.USD/IDR Beta Price Feed ID + +async function run() { + // Fetch Hermes price update binary + const update = await hermes.getLatestPriceUpdates([priceId], { + encoding: "hex", + }); + console.log(update); + + const priceUpdateData = ["0x" + update.binary.data]; // must be array of bytes + + console.log(priceUpdateData); + + // Estimate fee required by Pyth contract + // EVM Network Price Feed Contract Addresses: https://docs.pyth.network/price-feeds/core/contract-addresses/evm + + const pythContractAddress = "0x2880ab155794e7179c9ee2e38200202908c17b43"; + const pythAbi = [ + "function getUpdateFee(bytes[] calldata data) external view returns(uint)", + ]; + console.log("Pyth contract address:", pythContractAddress); + const pyth = new ethers.Contract(pythContractAddress, pythAbi, wallet); + const fee = await pyth.getUpdateFee(priceUpdateData); + console.log("Pyth fee:", fee.toString()); + + // Call your contract + const tx = await priceConsumer.updatePrice(priceUpdateData, { + value: fee, // pay the pyth update fee + gasLimit: 500000, + }); + console.log("Tx sent:", tx.hash); + const receipt = await tx.wait(); + console.log("Tx confirmed"); + console.log(receipt); + + // 4. Get latest price from contract + try { + console.log("=== Latest Price from Contract ==="); + const [price, expo] = await priceConsumer.getLatestPrice(priceId); + console.log("Price Value : " + price.toString()); + console.log("Exponent Value : " + expo.toString()); + } catch (error) { + console.log(error); + // @ts-ignore + console.error("\nError calling getLatestPrice:", error.message); + console.log( + "This usually means the price is older than 60 seconds or hasn't been updated yet." + ); + console.log("Make sure updatePrice() was called successfully first."); + } +} +run(); + +``` + +**Chạy kịch bản** + +Chạy kịch bản bằng cách: + +```bash +npx tsx scripts/interact.ts +``` + +**Ví dụ về kết quả đầu ra** + +```bash +Tx sent: 0x79c5dcb7abd9605b070bf9062ba2e2382272d23d58f7b50446c3107b7784fc8e +Tx confirmed +=== Latest Price from Contract === +Price Value : 1669784988 +Exponent Value : -5 +======== —— ========= +``` + +Giao dịch của bạn có thể được xác minh trên Kairos Explorer bằng cách dán mã giao dịch vào thanh tìm kiếm. Điều này xác nhận rằng các thao tác cập nhật và đọc đã thành công. + +## Kết luận + +Trong hướng dẫn này, bạn đã tạo một hợp đồng Solidity đọc giá thời gian thực từ Pyth, triển khai nó lên mạng thử nghiệm Kairos và tương tác với nó thông qua client Hermes. Bạn cũng đã tìm hiểu cách thiết kế dựa trên kéo (pull-based design) của Pyth cho phép bạn kiểm soát thời điểm và cách thức cập nhật giá diễn ra. + +Để biết thêm thông tin, hãy khám phá: + +- [Tham chiếu hợp đồng EVM](https://api-reference.pyth.network/price-feeds/evm/getPriceNoOlderThan) cho API Pyth +- [Ví dụ về AMM của Pyth Oracle](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/evm) cho một triển khai hoàn chỉnh từ đầu đến cuối. + + + diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md b/i18n/vi/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md index 8d895efe1a8c..6c925bedd870 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md @@ -190,6 +190,7 @@ The below table shows the computation cost of EVM opcodes. The computation cost | TSTORE | 280 | | TLOAD | 220 | | MCOPY | 250 | +| CLZ | 0 | ## Precompiled contracts computation cost table @@ -201,7 +202,7 @@ The below table shows the computation cost of EVM opcodes. The computation cost | 0x02 | sha256hash | numOfWords(input) / 32 \* 100 + 1,000 | | 0x03 | ripemd160hash | numOfWords(input) / 32 \* 10 + 100 | | 0x04 | dataCopy | 0 | -| 0x05 | bigModExp | see the code [here](https://github.com/kaiachain/kaia/blob/75c149a464998eb946311f3a290d4b1ea339eaba/blockchain/vm/contracts.go#L340) | +| 0x05 | bigModExp | Xem mã nguồn [tại đây](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L586) | | 0x06 | bn256Add | 8,000 | | 0x07 | bn256ScalarMul | 100,000 | | 0x08 | bn256Pairing | numOfPairings(input) \* 1,000,000 + 2,000,000 | @@ -210,13 +211,23 @@ The below table shows the computation cost of EVM opcodes. The computation cost | 0x3FD | vmLog | 10 | | 0x3FE | feePayer | 10 | | 0x3FF | validateSender | numOfSigs(input) \* 180,000 + 10,000 | +| 0x0b | bls12381G1Thêm | 18.750 | +| 0x0c | bls12381G1Đa Năng | Xem mã nguồn [tại đây](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L1155) | +| 0x0d | bls12381G2Thêm | 30.000 | +| 0x0e | bls12381G2Đa Mở Rộng | Xem mã nguồn [tại đây](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L1261) | +| 0x0f | bls12381Kết hợp | Số cặp (input) \* 1.630.000 + 1.885.000 | +| 0x10 | bls12381Bản đồ G1 | 275.000 | +| 0x11 | bls12381Bản đồ G2 | 1.190.000 | +| 0x100 | p256Xác minh | 235.000 | ## Hardfork Changes -| Hardfork | New items | Changes | | | -| ------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | - | -| Cancun EVM | BLOBBASEFEE (0x49)
BLOBHASH (0x50)
TSTORE (0x5c) opcode
TLOAD (0x5d)
MCOPY (0x5e)
kzg (0x0a) precompiled contract | increase the computation cost limit
from 100,000,000 to 150,000,000

reduce the computation cost of some opcodes
due to cpu performance increase
-Sdiv (0x05): 739 -> 360
-Mod (0x06): 812 -> 320
-Addmod (0x08): 1410 -> 360
-Mulmod (0x09): 1760 -> 700
-Exp (0x0A): 5000 -> 720
-Sha3 (0x20): 2465 -> 560
-Mstore8 (0x53): 5142 -> 230
-Log1, Log2, Log3, Log4 (0xA1-0xA4): 1000 -> 500

increase the computation cost of some opcodes
due to increased database size
-SLOAD (0x54): 835 -> 2550
-SSTORE (0x55): 1548 -> 2510 | | | -| Shanghai EVM | PUSH0 (0x5f) opcode | | | | -| Kore | | modExp (0x05) precompiled contract
use new gas calculation logic.
Computation cost also affected.
Become more accurate. | | | -| London EVM | BaseFee (0x48) opcode | | | | -| Istanbul EVM | CHAINID (0x46) opcode
SELFBALANCE (0x47) opcode
blake2f (0x09) precompiled contract | reduce the computation cost of over-priced opcodes
- ADDMOD (0x08): 3349 -> 1410
- MULMOD (0x09): 4757 -> 1760
- XOR (0x18): 657 -> 454
- NOT (0x19): 1289 -> 364
- SHL (0x1B): 1603 -> 478
- SHR (0x1C): 1815 -> 834 | | | +| Hardfork | New items | Changes | +| ------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Osaka EVM | CLZ (0x1e) mã lệnh
p256Verify (0x100) hợp đồng đã được biên dịch sẵn | modExp (0x05) precompiled contract
use new gas calculation logic.
Computation cost also affected.
Become more accurate. | +| Prague EVM | bls12381G1Add (0x0b) hợp đồng đã biên dịch sẵn
bls12381G1MultiExp (0x0c) hợp đồng đã biên dịch sẵn
bls12381G2Add (0x0d) hợp đồng đã biên dịch sẵn
bls12381G2MultiExp (0x0e) hợp đồng đã biên dịch sẵn
bls12381Pairing (0x0f) hợp đồng đã biên dịch sẵn
bls12381MapG1 (0x10) hợp đồng đã biên dịch sẵn
bls12381MapG2 (0x11) hợp đồng đã biên dịch sẵn
| | +| Cancun EVM | BLOBBASEFEE (0x49) mã lệnh
BLOBHASH (0x50) mã lệnh
TSTORE (0x5c) mã lệnh
TLOAD (0x5d) mã lệnh
MCOPY (0x5e) mã lệnh
kzg (0x0a) hợp đồng đã biên dịch sẵn | increase the computation cost limit
from 100,000,000 to 150,000,000

reduce the computation cost of some opcodes
due to cpu performance increase
-Sdiv (0x05): 739 -> 360
-Mod (0x06): 812 -> 320
-Addmod (0x08): 1410 -> 360
-Mulmod (0x09): 1760 -> 700
-Exp (0x0A): 5000 -> 720
-Sha3 (0x20): 2465 -> 560
-Mstore8 (0x53): 5142 -> 230
-Log1, Log2, Log3, Log4 (0xA1-0xA4): 1000 -> 500

increase the computation cost of some opcodes
due to increased database size
-SLOAD (0x54): 835 -> 2550
-SSTORE (0x55): 1548 -> 2510 | +| Shanghai EVM | PUSH0 (0x5f) opcode | | +| Kore | | modExp (0x05) hợp đồng đã được biên dịch sẵn
sử dụng logic tính toán gas mới.
Chi phí tính toán cũng bị ảnh hưởng.
Trở nên chính xác hơn. | +| London EVM | BaseFee (0x48) opcode | | +| Istanbul EVM | CHAINID (0x46) opcode
SELFBALANCE (0x47) opcode
blake2f (0x09) precompiled contract | reduce the computation cost of over-priced opcodes
- ADDMOD (0x08): 3349 -> 1410
- MULMOD (0x09): 4757 -> 1760
- XOR (0x18): 657 -> 454
- NOT (0x19): 1289 -> 364
- SHL (0x1B): 1603 -> 478
- SHR (0x1C): 1815 -> 834 | diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md b/i18n/vi/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md index d2e7bf97d195..1b4f65d5dc4f 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md @@ -34,7 +34,7 @@ To get traces with the debug API, you first need to decide what kind of informat Kaia's `callTracer` output format is identical to go-ethereum except for following: -- For revered transactions, both fields are provided. +- Đối với các giao dịch đảo ngược, cả hai trường đều được cung cấp. - `result.revertReason`: revert reason string, if any. - `result.reverted.contract`: the address of the reverted contract. - `result.reverted.message`: same as revertReason diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md b/i18n/vi/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md new file mode 100644 index 000000000000..effcfabb264c --- /dev/null +++ b/i18n/vi/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md @@ -0,0 +1,107 @@ +# Tối ưu hóa lưu trữ + +Khi blockchain Kaia phát triển, nhu cầu lưu trữ dữ liệu chuỗi cũng tăng theo. Kaia áp dụng hai kỹ thuật chính để quản lý yêu cầu lưu trữ ngày càng tăng này: + +## Cắt bớt lô trạng thái (Di chuyển trạng thái) + +Chức năng State Migration là một tính năng cắt tỉa theo lô có thể được áp dụng cho các nút hiện có mà không làm gián đoạn hoạt động của các nút đang chạy. + +### Động lực + +Các trạng thái khối (Block states) hoặc StateDB lưu trữ các tài khoản và hợp đồng trên chuỗi trong cấu trúc dữ liệu trie. Cấu trúc dữ liệu trie được thiết kế để lưu trữ cả các trạng thái đã lỗi thời và các trạng thái mới nhất, để chúng có thể được xác minh bằng cách sử dụng hàm băm Merkle. Khi các giao dịch thực hiện thay đổi trạng thái, cây trạng thái (state trie) sẽ phát triển vô hạn. Tính đến thời điểm viết bài (tháng 8 năm 2024), kích thước của nút lưu trữ chính Kaia Mainnet đã vượt quá 20TB và ngay cả nút đầy đủ cũng đã vượt quá 10TB. + +### Khái niệm + +Hệ thống di chuyển trạng thái xóa các trạng thái khối cũ không còn cần thiết cho việc xử lý các khối mới. Nó sao chép cây trạng thái từ "cũ" sang "mới". Không phải tất cả các nút trie đều được sao chép. Các phần tử có thể truy cập từ các gốc của các khối chọn lọc được sao chép. Sau khi sao chép, thư mục cũ sẽ bị xóa, do đó bạn chỉ còn lại trạng thái của các khối đã chọn. + +Đọc các bài viết blog sau để biết thêm chi tiết kỹ thuật: +[Di chuyển trạng thái: Lưu trữ dữ liệu nút](https://medium.com/klaytn/klaytn-v1-5-0-state-migration-saving-node-storage-1358d87e4a7a), +[Di chuyển trạng thái Kaia: Cách hiệu quả để giảm dữ liệu blockchain](https://medium.com/klaytn/klaytn-state-migration-an-efficient-way-to-reduce-blockchain-data-6615a3b36523) + +Để biết cách thực hiện Batch Pruning, vui lòng tham khảo [Hướng dẫn Di chuyển Trạng thái](../../misc/operation/node-pruning.md#how-to-perform-batch-pruning). + +## Cắt tỉa cây sống theo quy định của nhà nước + +Cắt tỉa cơ sở dữ liệu theo thời gian thực là giải pháp mới cho vấn đề kích thước cơ sở dữ liệu nhà nước ngày càng tăng. Khác với Batch Pruning (Di chuyển trạng thái), Live Pruning tự động xóa các trạng thái cũ dần dần khi quá trình xử lý nút bị chặn. + +### Động lực + +Các trạng thái khối (Block states) hoặc StateDB lưu trữ các tài khoản và hợp đồng trên chuỗi trong cấu trúc dữ liệu trie. Cấu trúc dữ liệu trie được thiết kế để lưu trữ cả các trạng thái đã lỗi thời và các trạng thái mới nhất, để chúng có thể được xác minh bằng cách sử dụng hàm băm Merkle. Khi các giao dịch thực hiện thay đổi trạng thái, cây trạng thái (state trie) sẽ phát triển vô hạn. Tính đến thời điểm viết bài (tháng 8 năm 2025), kích thước của nút lưu trữ chính Kaia Mainnet đã vượt quá 20TB và ngay cả nút đầy đủ cũng đã vượt quá 10TB. + +Trước đây, Cơ quan Di trú Nhà nước đã giải quyết vấn đề này bằng cách xóa các trạng thái cũ bằng cách sao chép chọn lọc các trạng thái gần đây và xóa phần còn lại. Điều này có thể giảm kích thước của nút đầy đủ xuống dưới 5TB. + +Tuy nhiên, chính sách di trú của Nhà nước cũng có những nhược điểm riêng. Nó gặp phải chi phí xử lý cao khi duyệt qua toàn bộ cây trạng thái, quá trình này có thể mất vài ngày. Ngoài ra, quá trình di chuyển dữ liệu cũng phải được kích hoạt thủ công. Để khắc phục những hạn chế này, kỹ thuật Live Pruning đã được giới thiệu. + +### Khái niệm + +Việc cắt tỉa cây trie là khó khăn vì không thể xác định chắc chắn liệu một nút trong cây trie có bị lỗi thời hay không. Trong cấu trúc trie ban đầu, một nút trie có thể là một phần của nhiều trie khác nhau, mỗi trie đại diện cho một khối khác nhau. Ngay cả khi một nút trie (ví dụ: số dư tài khoản) được cập nhật thành một giá trị khác, nút trie đó không thể bị xóa vì nó vẫn có thể được các nút cha khác sử dụng. Vấn đề này được gọi là vấn đề trùng lặp hash. + +Quá trình cắt tỉa trực tiếp (Live Pruning) cố ý sao chép các nút trie có nội dung giống nhau. Trong chế độ Live Pruning, một nút trie không được tham chiếu bằng hash của nó, mà thay vào đó được tham chiếu bằng ExtHash của nó. ExtHash là hàm băm 32 byte của nội dung cộng với chỉ số seri 7 byte. Chỉ số chuỗi tăng đơn điệu, do đó mỗi nút trie là duy nhất. + +``` +Hash: 32-byte Keccak256 +ExtHash: 32-byte Keccak256 + 7-byte Serial index +``` + +Như vậy, mỗi khi nội dung của một nút trie thay đổi, có thể an toàn để giả định rằng nút trie đó hiện đã lỗi thời. Hàm băm Merkle có thể được tính toán theo cách tương tự bằng cách bỏ qua chỉ số seri, giúp nó tương thích với các nút không thực hiện cắt tỉa trực tiếp (non-live-pruning nodes) về mặt đồng thuận. + +Đọc bài viết blog này để biết thêm chi tiết kỹ thuật: [Quản lý hiệu quả dung lượng dữ liệu blockchain với StateDB Live Pruning](https://medium.com/klaytn/strong-efficient-management-of-blockchain-data-capacity-with-statedb-live-pruning-strong-6aaa09b05f91). + +Để biết cách kích hoạt Live Pruning, hãy tham khảo [Hướng dẫn Live Pruning](../../misc/operation/node-pruning.md#how-to-perform-live-pruning). + +## Nén dữ liệu + +Nén dữ liệu giảm kích thước lưu trữ của dữ liệu khối bằng cách áp dụng thuật toán nén Snappy tích hợp sẵn của LevelDB cho các bảng cơ sở dữ liệu được chọn. + +### Động lực + +Dữ liệu khối—gồm tiêu đề, nội dung giao dịch và biên lai—thường chứa các chuỗi byte lặp lại cao do tiêu chuẩn mã hóa ABI trong các giao dịch EVM. Ví dụ, mã hóa ABI của Solidity sử dụng phương pháp thêm số 0 để đảm bảo sự căn chỉnh theo đơn vị 32 byte, dẫn đến dữ liệu gọi giao dịch có các chuỗi số 0 kéo dài. Phiếu giao dịch có các mẫu tương tự trong nhật ký sự kiện và giá trị trả về. + +Mặc dù có sự dư thừa tự nhiên này, hệ thống lưu trữ LevelDB cơ bản của Kaia không sử dụng nén theo mặc định, khiến dữ liệu lặp lại chiếm dụng không gian đĩa một cách không cần thiết. Tính đến tháng 7 năm 2025, một nút chính Kaia Mainnet chiếm dụng hơn 4,2TB dung lượng lưu trữ, trong đó khoảng 3,6TB được quy cho dữ liệu khối chưa nén. + +### Khái niệm + +Kaia v2.1.0 kích hoạt thuật toán nén Snappy của LevelDB với việc áp dụng chọn lọc cho các bảng cơ sở dữ liệu. Tham số `--db.leveldb.compression` cho phép kiểm soát chi tiết: + +- Đầu đề, nội dung và biên lai được nén (độ trùng lặp cao, tiết kiệm đáng kể) +- Dữ liệu trie của hệ thống được loại trừ (xuất hiện ngẫu nhiên, lợi ích nén tối thiểu) + +Đối với các nút hiện có, việc kích hoạt thủ công quá trình nén cơ sở dữ liệu sẽ ghi đè dữ liệu cũ chưa được nén sang định dạng nén. Quy trình "quản lý hệ thống" này hợp nhất các bảng SSTable, đồng bộ hóa các thao tác xóa và áp dụng nén như một tác dụng phụ. + +**Kết quả:** Các nút chính thức trên mạng chính (Mainnet) ghi nhận giảm khoảng 50% dung lượng lưu trữ tổng thể (~2TB tiết kiệm), với phần lớn lợi ích tập trung vào các bảng dữ liệu chính và bảng giao dịch. Quá trình này mất khoảng 10 giờ và có thể được thực hiện đồng thời với quá trình xử lý khối thông thường. + +Đọc bài viết blog này để biết thêm chi tiết kỹ thuật: [Cách Kaia v2.1 thu hồi 2TB thông qua nén](https://blog.kaia.io/cutting-blockchain-storage-in-half/). + +Để biết cách kích hoạt nén, hãy tham khảo hướng dẫn [Optimize Node Storage](../../misc/operation/optimize-storage.md#database-compression). + +## Sơ đồ trạng thái FlatTrie (Th sperimental) + +FlatTrie là một phương án lưu trữ trạng thái thử nghiệm giúp giảm đáng kể kích thước cơ sở dữ liệu trạng thái của các nút lưu trữ bằng cách tái cấu trúc cách lưu trữ trạng thái tài khoản lịch sử. + +### Động lực + +Các nút lưu trữ phải duy trì dữ liệu trạng thái lịch sử đầy đủ cho tất cả các tài khoản ở mọi độ cao khối, cho phép thực hiện các truy vấn ngược thời gian và phân tích blockchain toàn diện. Điều này tạo ra một cấu hình lưu trữ hoàn toàn khác biệt so với các nút đầy đủ: tính đến tháng 8 năm 2025, một nút lưu trữ Kaia Mainnet yêu cầu hơn 35TB dung lượng đĩa, trong đó 31TB (89%) được sử dụng bởi cơ sở dữ liệu trạng thái. + +Cấu trúc Merkle Patricia Trie (MPT) truyền thống lưu trữ cả dữ liệu tài khoản (các nút lá) và các nút nhánh trung gian tạo thành cây Merkle. Các nút lưu trữ lịch sử đã duy trì các MPT hoàn chỉnh cho nhiều độ cao khối, dẫn đến việc các nút trung gian—không chứa dữ liệu tài khoản—tiếp tục tích lũy vô thời hạn. + +Các tối ưu hóa lưu trữ hiện có như [State Migration](https://medium.com/klaytn/klaytn-v1-5-0-state-migration-saving-node-storage-1358d87e4a7a) (xóa theo lô) và [StateDB Live Pruning](https://medium.com/klaytn/strong-efficient-management-of-blockchain-data-capacity-with-statedb-live-pruning-strong-6aaa09b05f91) về cơ bản yêu cầu xóa dữ liệu lịch sử, khiến chúng không thể áp dụng cho các nút lưu trữ phải duy trì lịch sử đầy đủ. + +### Khái niệm + +FlatTrie là một phương án lưu trữ trạng thái thử nghiệm được phát triển từ [Erigon Ethereum client](https://github.com/erigontech/erigon/). Nó tái cấu trúc bộ nhớ trạng thái bằng cách: + +- Lưu trữ trạng thái tài khoản lịch sử trong các bảng khóa-giá trị phẳng (mapping đơn giản giữa địa chỉ và dữ liệu tài khoản) +- Chỉ duy trì MPT hoàn chỉnh của khối mới nhất cùng với tất cả các nút nhánh trung gian. +- Tái tạo các gốc Merkle lịch sử theo yêu cầu bằng cách tạm thời xây dựng chỉ các nút nhánh cần thiết. + +Phương pháp này loại bỏ việc lưu trữ lâu dài các nút trung gian lịch sử đồng thời duy trì lịch sử trạng thái tài khoản đầy đủ và khả năng xác minh các gốc Merkle cho bất kỳ khối nào. + +**Thách thức trong việc thích ứng:** Việc triển khai của Erigon dựa trên cấu trúc tài khoản của Ethereum. Kaia sử dụng một phương thức mã hóa RLP khác để hỗ trợ các tính năng độc đáo như địa chỉ dễ đọc cho con người và nhiều loại khóa khác nhau. Việc tích hợp yêu cầu sửa đổi mô-đun băm Merkle của Erigon để xử lý các tài khoản như các chuỗi byte không thể đọc được, cùng với việc tạo ra ba lớp adapter (DomainsManager, WriteBuffer, DeferredContext) để kết nối giao diện Trie đa luồng của Kaia với yêu cầu cơ sở dữ liệu MDBX đơn luồng của Erigon. + +**Kết quả:** Trong các thí nghiệm trên mạng thử nghiệm Kairos, các nút lưu trữ FlatTrie tiêu thụ khoảng 75% dung lượng lưu trữ tổng cộng ít hơn so với các nút lưu trữ truyền thống, với kích thước cơ sở dữ liệu trạng thái giảm hơn 80%. Dự kiến sẽ có mức tiết kiệm tương tự đối với các nút lưu trữ Mainnet (từ ~35TB xuống ~10TB). + +**Hạn chế:** Phiên bản thử nghiệm v2.1.0 không hỗ trợ tính năng quay lại khối (API `debug_setHead`), tạo bằng chứng Merkle (API `eth_getProof`) hoặc tính năng cắt giảm trạng thái. Những hạn chế này xuất phát từ lựa chọn thiết kế của FlatTrie trong việc loại bỏ các nút nhánh lịch sử. + +Đọc bài viết blog này để biết thêm chi tiết kỹ thuật: [Kaia’s Experimental FlatTrie for Archive Nodes](https://blog.kaia.io/flatten-the-state-shrink-the-disk/). + +Để biết cách kích hoạt FlatTrie, hãy tham khảo hướng dẫn [Optimize Node Storage](../../misc/operation/optimize-storage.md#flattrie-state-scheme-experimental). diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md b/i18n/vi/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md index 75b307be0b84..36c03bb4f90c 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md @@ -62,7 +62,7 @@ The baseFee calculation depends on following parameters: - UPPER_BOUND_BASE_FEE: The maximum value for the base fee - LOWER_BOUND_BASE_FEE: The minimum value for the base fee -Below is an oversimplified version of the baseFee calculation. In its essense, the base fee change is proportional to the difference between GAS_TARGET and PREVIOUS_BLOCK_GAS_USED, and other parameters controls the change speed or bounds the baseFee. Refer to [KIP-71](https://github.com/kaiachain/kips/blob/main/KIPs/kip-71.md) for the exact formula. +Below is an oversimplified version of the baseFee calculation. Về bản chất, sự thay đổi phí cơ bản tỷ lệ thuận với sự chênh lệch giữa GAS_TARGET và PREVIOUS_BLOCK_GAS_USED, và các thông số khác điều chỉnh tốc độ thay đổi hoặc giới hạn phí cơ bản. Refer to [KIP-71](https://github.com/kaiachain/kips/blob/main/KIPs/kip-71.md) for the exact formula. ``` min(PREVIOUS_BLOCK_GAS_USED, MAX_BLOCK_GAS_USED_FOR_BASE_FEE) - GAS_TARGET diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/misc/faq.md b/i18n/vi/docusaurus-plugin-content-docs/current/misc/faq.md index 9d1275a69890..d649175d1b46 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/misc/faq.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/misc/faq.md @@ -3,6 +3,7 @@ - [Câu hỏi thường gặp](#faq) - [Kaia là gì? ](#what-is-kaia-) - [Kaia hỗ trợ tính tương đương của Ethereum như thế nào? ](#how-does-kaia-support-ethereum-equivalence-) + - [Chính sách phiên bản của Kaia là gì?] ](#what-is-kaias-versioning-policy-) - [Chính sách khí đốt của Kaia là gì? ](#what-is-kaias-gas-policy-) - [Cấu trúc tài khoản của Kaia có gì đặc biệt? ](#what-is-special-about-kaias-account-structure-) - [Tôi có thể bắt đầu phát triển dApp với Kaia ở đâu? ](#where-can-i-start-dapp-development-with-kaia-) @@ -30,6 +31,10 @@ Kaia is a high-performance Layer 1 blockchain designed for the mass adoption of Kaia is EVM-compatible and supports all Ethereum Cancun EVM features except EIP-4844 blob transactions. It provides the `eth` namespace RPC API, allowing seamless use of Ethereum SDKs and tools. Kaia-specific transaction types are represented as Type 0 legacy transactions within the eth namespace APIs, so Ethereum SDKs do not need to be aware of them. +## Chính sách phiên bản của Kaia là gì? + +Bạn có thể truy cập vào [GitHub](https://github.com/kaiachain/kaia/blob/dev/CONTRIBUTING.md#versioning-policy). + ## What is Kaia’s gas policy? Kaia uses a dynamic gas fee model that maintains low fees during normal network conditions but adjusts fees based on network congestion. The gas fee can change within a limited range per block, helping prevent network spam while keeping fees predictable. A portion of every transaction fee is automatically burned. The model prioritizes user experience and enterprise-friendliness while maintaining network stability. @@ -139,4 +144,4 @@ You can find complete working examples of fee delegation using several different - ethers-ext: [fee delegated value transfer example](https://docs.kaia.io/references/sdk/ethers-ext/v6/fee-delegated-transaction/value-transfer/) - web3js-ext: [fee delegated value transfer example](https://docs.kaia.io/references/sdk/web3js-ext/fee-delegated-transaction/value-transfer/) - web3j-ext: [fee delegated value transfer example](https://docs.kaia.io/references/sdk/web3j-ext/fee-delegated-transaction/value-transfer/) -- web3py-ext: [fee delegated value transfer example](https://docs.kaia.io/references/sdk/web3py-ext/fee-delegated-transaction/value-transfer/) \ No newline at end of file +- web3py-ext: [fee delegated value transfer example](https://docs.kaia.io/references/sdk/web3py-ext/fee-delegated-transaction/value-transfer/) diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md b/i18n/vi/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md index 76a9d9eeb900..3259f77c49ad 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md @@ -43,7 +43,7 @@ This FAQ addresses common questions and concerns for CEXs, node providers, walle ### What happened to Klaytn and Finschia? -Klaytn and Finschia merged to form Kaia through governance decisions made by both chains. You can view the voting results [here](https://medium.com/kaiachain/klaytn-and-finschia-merge-proposal-passes-creating-asias-largest-blockchain-ecosystem-7af570eb069a). The utility tokens of the two chains (KLAY and FNSA) are converted to the KAIA token. You can find the exchange rates for both tokens [here](../../kaiatech/kaia-white-paper.md#fnsa-issuancedistribution-status). +Klaytn and Finschia merged to form Kaia through governance decisions made by both chains. Bạn có thể xem kết quả bỏ phiếu [tại đây](https://blog.kaia.io/klaytn-and-finschia-merge-proposal-passes-creating-asias-largest-blockchain-ecosystem/). The utility tokens of the two chains (KLAY and FNSA) are converted to the KAIA token. You can find the exchange rates for both tokens [here](../../kaiatech/kaia-white-paper.md#fnsa-issuancedistribution-status). ### What happens to KLAY and FNSA? @@ -142,8 +142,8 @@ Kaia is a hard fork of the Klaytn chain, and the chain ID remains unchanged. The Here are the main information sources for the chain merge: - [Governance proposal](https://govforum.klaytn.foundation/t/kgp-25-klaytn-finschia-mainnet-merge/719) -- [Our vision behind the merge](https://medium.com/klaytn/finschia-klaytn-chain-merge-proposal-our-vision-for-asias-1-blockchain-ecosystem-7de1588e28c0) -- [Crafting the core of Kaia DeFi](https://medium.com/klaytn/crafting-the-core-of-project-dragons-defi-ecosystem-0fa561e02f56) -- [Responding to institutional demand](https://medium.com/klaytn/project-dragon-responding-to-institutional-demand-bd36e2e1e2a6) -- [Supplementary data and insights](https://medium.com/klaytn/project-dragon-supplementary-data-and-insights-d36abd25ca0f) -- [The Kaia brand story](https://medium.com/klaytn/say-hello-to-kaia-4182ccafe456) +- [Tầm nhìn đằng sau việc sáp nhập](https://blog.kaia.io/finschia-klaytn-chain-merge-proposal-our-vision-for-asias-no-1-blockchain-ecosystem/) +- [Xây dựng nền tảng cốt lõi của Kaia DeFi](https://blog.kaia.io/crafting-the-core-of-project-dragons-defi-ecosystem/) +- [Phản hồi nhu cầu của các tổ chức](https://blog.kaia.io/project-dragon-responding-to-institutional-demand/) +- [Dữ liệu bổ sung và thông tin chi tiết](https://blog.kaia.io/project-dragon-supplementary-data-and-insights/) +- [Câu chuyện thương hiệu Kaia](https://blog.kaia.io/say-hello-to-kaia/) diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md b/i18n/vi/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md index 730484f46516..ba0be1857035 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md @@ -2,12 +2,160 @@ Finschia users can swap their FNSA tokens on Finshia network to KAIA tokens on Kaia network at a fixed swap rate. The swap is mediated by a set of smart contract and programs, collectively called Kaiabridge. -A token swap process begins with the Finschia user sending the FNSA token to the `fwsap` module. The token is first swapped from `cony` to `kei` denomination, then transferred to `fbridge` module. The event from `fbridge` is recognized by the trusted relayers and submitted to bridge smart contracts on Kaia chain. The bridging request is handled in multiple steps: +Bạn có thể truy cập và sử dụng Kaiabridge trong bộ công cụ trực tuyến của chúng tôi [online toolkit](https://toolkit.kaia.io/kaiaBridge). -- Inflight: The token arrived in Finschia's `fbridge` module, but the relayers did not report to the Kaia smart contracts. -- Confirmed: The relayers submitted the request to the contracts ("provision"). Now the request enters a 30 minute timelock. -- Claimed: After the timelock has expired, the token has been transferred ("claim") to the destination account on Kaia chain. +Bạn có thể tìm thấy mã nguồn hợp đồng trong kho lưu trữ [GitHub kaiachain/kaia](https://github.com/kaiachain/kaia/tree/dev/contracts/contracts/system_contracts/kaiabridge) và địa chỉ triển khai trong trang [địa chỉ hợp đồng](https://docs.kaia.io/references/contract-addresses/). -Kaiabridge smart contracts has built-in multisig features. For instance, it takes multiple provision transactions from the Operator accounts for a request to be Confirmed. Each Operator account is held by a relayer, and the relayers are managed by Kaia Foundation and Finschia Foundation. +# Hướng dẫn sử dụng cho Kaiabridge -You can find the contract source codes in [kaiachain GitHub](https://github.com/kaiachain/kaia/tree/dev/contracts/contracts/system_contracts/kaiabridge) and deployed addresses in the [contract addresses](https://docs.kaia.io/references/contract-addresses/) page. \ No newline at end of file +## Điều kiện tiên quyết + +### 1. Chuyển tài khoản của bạn sang MetaMask hoặc Kaia Wallet. + +#### Với khóa riêng thô + +Nếu tài khoản của bạn có thể được xuất dưới dạng khóa riêng tư thô, hãy sao chép khóa riêng tư thô và nhập nó vào ví MetaMask hoặc Kaia. + +- [MetaMask](https://support.metamask.io/start/use-an-existing-wallet#import-using-a-private-key) +- [Kaia Wallet](https://www.kaiawallet.io/en_US/faq/?id=25) + +#### Với cụm từ khôi phục + +Nếu tài khoản của bạn chỉ có thể được xuất dưới dạng cụm từ khôi phục, hãy tính toán khóa riêng thô từ cụm từ khôi phục. Bạn có thể sử dụng bất kỳ công cụ nào hỗ trợ đường dẫn dẫn xuất BIP-39. Các công cụ này bao gồm [ethers.js](https://docs.ethers.org/v6/api/wallet/#HDNodeWallet), [viem](https://viem.sh/docs/accounts/local/hdKeyToAccount), [Foundry](https://getfoundry.sh/cast/reference/wallet/), và [BIP39 Tool](https://github.com/iancoleman/bip39). Ví Finschia thường sử dụng đường dẫn "m/44'/438'/0'/0/0" (theo [SLIP-044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)) làm đường dẫn dẫn xuất mặc định của họ. Bạn có thể cần sử dụng các đường dẫn dẫn xuất khác nếu ví Finschia của bạn có nhiều tài khoản hoặc sử dụng cấu hình khác. + +Sau khi đã tính toán được khóa riêng, hãy làm theo các hướng dẫn trong phần trên [Với khóa riêng thô](#with-raw-private-key). + +:::note[Example Sử dụng công cụ BIP39] + +Bạn có thể tính toán khóa riêng trên trang này: [BIP39 - Mã mnemonic](https://iancoleman.io/bip39/). + +Như một biện pháp phòng ngừa, khuyến cáo mạnh mẽ nên tuân thủ các hướng dẫn "Sử dụng ngoại tuyến" trên trang web và ngắt kết nối Internet trong quá trình thực hiện. + +1. Dán cụm từ khôi phục của bạn vào trường "BIP39 Mnemonic". +2. Đặt trường "Coin" thành "ETH - Ethereum". +3. Đặt "Đường dẫn dẫn xuất" thành "BIP32". +4. Đặt "Client" thành "Đường dẫn dẫn xuất tùy chỉnh". +5. Đặt "Đường dẫn dẫn xuất BIP32" thành "m/44'/438'/0'/0". +6. Trong phần "Địa chỉ được dẫn xuất", hãy tìm hàng đầu tiên có trường "Path" hiển thị "m/44'/438'/0'/0/0", khóa riêng thô của bạn sẽ được hiển thị trong trường "Khóa riêng". + +::: + +:::note[Example Sử dụng công cụ Foundry] + +1. Cài đặt [Foundry](https://getfoundry.sh/). +2. Nhập lệnh sau đây với cụm từ khôi phục của bạn vào `--mnemonic`. Khóa riêng tư thô sẽ được in ra. + ``` + Tạo ví với khóa riêng tư --mnemonic "test test test test test test test test test test test junk" --mnemonic-derivation-path "m/44'/438'/0'/0/0" + ``` + +::: + +### 2. Kiểm tra mạng của bạn + +Nếu bạn đang sử dụng MetaMask, hãy thêm mạng Kaia Mainnet vào danh sách mạng của bạn nếu bạn chưa thực hiện điều này. + +- [Kết nối MetaMask với Kaia](https://docs.kaia.io/build/tutorials/connecting-metamask/) + +### 3. Nạp tiền vào tài khoản của bạn + +Bạn cần gas để gửi giao dịch cho việc hoán đổi. Tham khảo [Get KAIA](https://docs.kaia.io/build/get-started/getting-kaia/) để xem hướng dẫn chi tiết. + +Chúng tôi khuyến nghị bạn nên có ít nhất 0.1 KAIA cho phí gas. + +## Đổi Finschia thành Kaia + +:::warning[This [Việc hoán đổi là không thể đảo ngược] + +Yêu cầu cung cấp và yêu cầu bồi thường chỉ có thể được xử lý một lần và không thể hủy bỏ. +Hãy đọc kỹ trước khi thực hiện theo các hướng dẫn này. + +::: + +### 1. Kết nối ví của bạn + +#### 1.1 Kết nối MetaMask + +Nhấp vào nút "Kết nối MetaMask". + +

Connect MetaMask

+ +Kiểm tra xem mục "Tài khoản" có hiển thị địa chỉ của bạn không. +Nếu không, hãy mở tiện ích mở rộng MetaMask và kiểm tra xem có thông báo rằng bạn không kết nối với trang web hay không. Nếu vậy, hãy nhấn nút "Kết nối tài khoản". + +

Connect Account

+ +#### 1.2 Kết nối Ví Kaia + +Nếu bạn đang sử dụng Kaia Wallet, trang web có thể yêu cầu bạn kết nối Kaia Wallet với dApp (trong trường hợp này là Kaia Online Toolkit). + +

Connect Kaia Wallet

+ +Nhấp vào "Kết nối" để kết nối ví Kaia của bạn. + +#### 2. Chuyển sang mạng chính Kaia + +Kiểm tra xem bạn đã thiết lập mạng của mình đúng cách thành "Kaia Mainnet" hoặc "Mainnet" chưa. Nếu không, hãy chuyển sang Kaia Mainnet. Nếu bạn đang sử dụng MetaMask và chưa thêm mạng Kaia Mainnet vào MetaMask, hãy tham khảo [Kiểm tra mạng của bạn](#2-check-your-network). + +#### 3. Xác định địa chỉ Finschia + +Nhấp vào "Tạo địa chỉ Finschia". Khi được yêu cầu ký vào tin nhắn, hãy nhấp vào "Xác nhận" hoặc "Ký". + +
+ Sign message in MetaMask + Sign message in Kaia Wallet +
+ +

+Kiểm tra xem "địa chỉ Finschia được dẫn xuất" có khớp với địa chỉ Finschia gốc của bạn và "số dư CONY" có khớp với số dư của bạn trong mạng Finschia (đơn vị CONY) hay không. + +
+ Address and CONY balance shown in the page + Address and CONY balance shown in your wallet +
+ +

+Ngoài ra, hãy đảm bảo tài khoản của bạn có đủ KAIA để thanh toán phí gas (bạn có thể kiểm tra trong ví của mình). + +
+ KAIA balance in MetaMask + KAIA balance in Kaia Wallet +
+ +

+Nếu tài khoản của bạn không có KAIA, hãy tham khảo [Nạp tiền vào tài khoản](#3-gas-up-your-account). + +#### 4. Yêu cầu cung cấp + +Nhấp vào "Yêu cầu cấp phép". Khi được yêu cầu ký tên vào tin nhắn và gửi giao dịch, hãy nhấp vào "Xác nhận". + +
+ Confirm provision transaction request in MetaMask + Confirm provision transaction request in Kaia Wallet +
+ +

+Quá trình này sẽ mất vài giây. Hãy đợi cho đến khi giao dịch hoàn tất. +Bạn có thể kiểm tra kết quả trên trang web. + +

Provision request successful

+ +
+Nếu không, hãy làm mới và bắt đầu lại từ đầu. + +#### 5. Yêu cầu bồi thường + +Nhấp vào "Yêu cầu bồi thường". Khi được yêu cầu xác nhận giao dịch, hãy nhấp vào "Xác nhận". + +
+ Confirm claim transaction request in MetaMask + Confirm claim transaction request in Kaia Wallet +
+ +

+Quá trình này sẽ mất vài giây. Hãy đợi cho đến khi giao dịch hoàn tất. +Bạn có thể kiểm tra kết quả trên trang web. + +

Claim request successful

+ +
+Kiểm tra số dư tài khoản của bạn. Số tiền yêu cầu nên là (số dư tài khoản của bạn) * (tỷ giá hối đoái, khoảng 148) trong [kei](https://docs.kaia.io/learn/token-economics/kaia-native-token/#units-of-kaia-). \ No newline at end of file diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md b/i18n/vi/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md index 44f62edc6fed..161a7deca220 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md @@ -101,7 +101,7 @@ Download a compressed file to the new directory. URLs can be found at the bottom ## Downloads -For efficiency, only batch pruned (state migrated) or live pruned database are provided. Read [Storage Optimization](../../learn/storage/state-pruning.md) for their concepts. If you want a full database without neither pruning, or even archive data, perform a fresh full sync from genesis. +For efficiency, only batch pruned (state migrated) or live pruned database are provided. Đọc [Tối ưu hóa lưu trữ](../../learn/storage/storage-optimization.md) để tìm hiểu về các khái niệm của họ. If you want a full database without neither pruning, or even archive data, perform a fresh full sync from genesis. | network | sync options | download | | ------- | -------------- | --------------------------------------------------------------------------------------------------- | diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md b/i18n/vi/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md index b7e7824a7c44..7d2bf28c379a 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md @@ -2,8 +2,8 @@ This page explains how to delete historical block states to reduce the storage requirement. Kaia offers two approaches for pruning block states: -- [Live Pruning](../../learn/storage/state-pruning.md#state-live-pruning): With the live pruning feature enabled, the block states beyond a certain retention period will be automatically deleted. -- [Batch Pruning: State Migration](../../learn/storage/state-pruning.md#state-batch-pruning-state-migration): The block states can be state-migrated, meaning the block states before a certain block number become available. +- [Cắt tỉa trực tiếp](../../learn/storage/storage-optimization.md#state-live-pruning): Khi tính năng cắt tỉa trực tiếp được kích hoạt, các trạng thái khối vượt quá khoảng thời gian lưu trữ nhất định sẽ được tự động xóa. +- [Cắt lọc theo lô: Di chuyển trạng thái](../../learn/storage/storage-optimization.md#state-batch-pruning-state-migration): Các trạng thái khối có thể được di chuyển trạng thái, nghĩa là các trạng thái khối trước một số khối nhất định sẽ trở nên khả dụng. ## Understanding Pruning Impacts diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md b/i18n/vi/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md new file mode 100644 index 000000000000..dab49cdbb41a --- /dev/null +++ b/i18n/vi/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md @@ -0,0 +1,293 @@ +# Tối ưu hóa bộ nhớ nút + +[Kaia v2.1.0](https://github.com/kaiachain/kaia/releases/tag/v2.1.0) giới thiệu hai tính năng tối ưu hóa lưu trữ bổ sung có thể giảm đáng kể yêu cầu về không gian đĩa: + +- **Nén cơ sở dữ liệu**: Giảm dung lượng lưu trữ bằng cách nén dữ liệu khối lặp lại. +- **FlatTrie State Scheme**: Tính năng thử nghiệm giúp giảm đáng kể kích thước cơ sở dữ liệu trạng thái của các nút lưu trữ. + +Hướng dẫn này giải thích cách áp dụng các tối ưu hóa này cho nút Kaia của bạn. + +## Nén cơ sở dữ liệu + +Nén cơ sở dữ liệu sử dụng thuật toán nén Snappy tích hợp sẵn trong LevelDB để giảm kích thước của tiêu đề khối, nội dung giao dịch và biên lai — những thành phần thường chứa dữ liệu lặp lại như việc thêm số 0 vào các giao dịch được mã hóa theo ABI. + +**Tiết kiệm dự kiến:** + +- Nút đầy đủ: Giảm khoảng 2TB (từ khoảng 4,2TB xuống còn khoảng 2TB trên Mainnet) + +### Điều kiện tiên quyết + +- Kaia phiên bản 2.1.0 hoặc cao hơn +- Đối với nén thủ công: Dung lượng đĩa trống đủ và khả năng xử lý I/O đĩa liên tục (xem phần **Tác động tài nguyên** bên dưới) + +### Bật nén cho các cài đặt mới + +Từ phiên bản v2.1.0 trở đi, tính năng nén được bật theo mặc định. Chỉ cần khởi động nút của bạn: + +**Cài đặt gói:** + +```bash +# Configure network in kend.conf +sudo vi /etc/kend/conf/kend.conf +# Set: NETWORK=mainnet or NETWORK=kairos + +# Start node (compression enabled by default in v2.1.0+) +kend start + +# Verify +kend status +tail -f /var/kend/logs/kend.out +``` + +Tất cả dữ liệu mới được ghi sẽ được nén tự động. + +### Bật nén cho các nút hiện có + +Nếu bạn đang nâng cấp từ phiên bản trước v2.1.0: + +**Bước 1: Kiểm tra phiên bản của bạn** + +```bash +ken version +``` + +**Bước 2: Đối với phiên bản v2.1.0 và các phiên bản sau đó** + +Chức năng nén đã được kích hoạt theo mặc định. Dữ liệu mới được nén tự động. Bỏ qua Bước 4 để nén dữ liệu hiện có. + +**Bước 3: Chỉ áp dụng cho các phiên bản trước v2.1.0** + +Thêm cờ nén vào cấu hình của bạn: + +**Cài đặt gói:** + +```bash +sudo vi /etc/kend/conf/kend.conf +# Add to ADDITIONAL variable: +ADDITIONAL="--db.leveldb.compression 2" +``` + +Giá trị của cờ nén là: + +- `0`: Không nén +- `1`: Nén hóa đơn +- `2`: Nén tiêu đề, nội dung và biên lai (được khuyến nghị) +- `3`: Nén tất cả các bảng bao gồm cây trạng thái (không được khuyến nghị) + +:::note + +Tùy chọn 2 được khuyến nghị vì dữ liệu cây trạng thái (state trie) không nén tốt (trông ngẫu nhiên), do đó tùy chọn 3 chỉ mang lại lợi ích bổ sung tối thiểu. + +::: + +Sau đó khởi động lại: + +```bash +kend stop +kend start +``` + +**Bước 4: Nén dữ liệu hiện có (tùy chọn nhưng được khuyến nghị)** + +Kích hoạt quá trình nén cơ sở dữ liệu thông qua RPC. Kết nối với bảng điều khiển nút của bạn: + +```bash +ken attach --datadir /var/kend/data +``` + +Trong giao diện điều khiển, kích hoạt quá trình nén bằng cách sử dụng preset "allbutstate": + +```javascript +> debug.chaindbCompact({ "preset": "allbutstate" }) +null +``` + +**Các preset có sẵn:** + +- `"default"`: Nén toàn bộ các thành phần cơ sở dữ liệu +- `"allbutstate"`: Nén chọn lọc loại trừ cây trạng thái (được khuyến nghị cho nén) +- `"custom"`: Định nghĩa các khoảng tùy chỉnh cho các bảng cơ sở dữ liệu cụ thể. + +Quá trình nén diễn ra ở chế độ nền. Theo dõi tiến trình trong nhật ký nút của bạn: + +```bash +tail -f /var/kend/logs/kend.out | grep -i Compact +``` + +Bạn nên thấy các mục nhật ký như sau: + +``` +INFO[07/25,12:50:17 Z] [3] Compacting database started range=0x48-0x49 +INFO[07/25,12:55:17 Z] [3] Compacting database completed range=0x48-0x49 elapsed=5m0.085s +``` + +Nút sẽ tiếp tục xử lý các khối trong quá trình nén. + +**Thời gian dự kiến:** Khoảng 10 giờ cho một nút chính (Mainnet) đầy đủ (trên SSD với khoảng 4TB dữ liệu). Thời gian thực hiện có thể thay đổi tùy thuộc vào phần cứng và kích thước dữ liệu. + +**Tác động đến tài nguyên:** + +- Tốc độ I/O đĩa cao (đỉnh >400 MiB/s đọc, >300 MiB/s ghi) +- Tốc độ IOPS cao (thường >2000 thao tác/giây) +- Nút vẫn hoạt động bình thường và tiếp tục đồng bộ hóa các khối. + +:::note + +Trong khi nút vẫn hoạt động trong quá trình nén, hiệu suất truy vấn có thể bị ảnh hưởng trong các khoảng thời gian đỉnh điểm I/O. Đối với các nút RPC sản xuất, hãy lên lịch nén dữ liệu trong các khung thời gian bảo trì hoặc các khoảng thời gian có lưu lượng truy cập thấp. + +::: + +### Sử dụng bản sao lưu dữ liệu chuỗi đã nén sẵn (TBD) + +Các bản sao lưu dữ liệu chuỗi đã được nén trước đây dự kiến sẽ được cung cấp trong các bản phát hành tương lai nhưng hiện tại chưa có sẵn. Khi có sẵn, chúng sẽ được liệt kê trên trang [Chaindata Snapshot](https://docs.kaia.io/misc/operation/chaindata-snapshot/). + +Hiện tại, bạn phải: + +- Bật tính năng nén trên cài đặt mới v2.1.0+ (tự động cho dữ liệu mới) +- Thực hiện nén thủ công trên các nút hiện có (xem phần trên) + +Kiểm tra trang snapshot định kỳ để cập nhật thông tin về tính khả dụng của snapshot nén. + +### Kiểm tra xem tính năng nén đã được kích hoạt chưa. + +Kiểm tra nhật ký khởi động của nút để xem cấu hình nén: + +```bash +grep "compressionType" /var/kend/logs/kend.out +``` + +Tìm các mục nhật ký hiển thị `compressionType=snappy` cho các bảng không sử dụng cây trạng thái (non-state-trie tables). + +### Theo dõi và Khắc phục sự cố + +**Kiểm tra giảm sử dụng đĩa:** + +```bash +du -h --max-depth=1 /var/kend/data/klay/chaindata +``` + +So sánh trước và sau khi nén. Bạn sẽ thấy sự giảm đáng kể dung lượng lưu trữ trong các thư mục chứa các khối dữ liệu và biên lai. + +**Vấn đề thường gặp:** + +1. **Quá trình nén thất bại**: Đảm bảo có đủ dung lượng đĩa. Quá trình nén tạm thời yêu cầu thêm không gian để ghi đè dữ liệu. +2. **FlatTrie không khởi động được**: FlatTrie yêu cầu cơ sở dữ liệu trống. Nếu bạn gặp lỗi liên quan đến dữ liệu hiện có, hãy xóa thư mục chaindata và đồng bộ hóa từ genesis. +3. **Lỗi API Merkle proof**: FlatTrie không hỗ trợ `eth_getProof`. Sử dụng nút truyền thống nếu API này được yêu cầu. + +## Sơ đồ trạng thái FlatTrie (Th sperimental) + +FlatTrie là một phương án lưu trữ trạng thái thử nghiệm được phát triển từ client Ethereum Erigon. Nó lưu trữ trạng thái tài khoản trong một cấu trúc phẳng và chỉ duy trì cây Merkle Patricia Trie (MPT) hoàn chỉnh của khối mới nhất, tái tạo các cây lịch sử theo yêu cầu. + +**Tiết kiệm dự kiến:** + +- Tổng dung lượng lưu trữ: Giảm khoảng 75% (dự đoán dựa trên kết quả từ mạng thử nghiệm Kairos) +- Mạng thử nghiệm Kairos: 4,3TB → 1TB +- Mainnet: ~35TB → ~10TB (ước tính dựa trên tỷ lệ giảm tương ứng) + +:::warning + +FlatTrie là một tính năng thử nghiệm trong phiên bản v2.1.0. Không nên sử dụng cho mục đích sản xuất. Dự kiến sẽ có các vấn đề về tính ổn định, điểm nghẽn hiệu suất và các thay đổi gây ảnh hưởng đến tương thích trong các bản phát hành tương lai. Chỉ sử dụng cho môi trường thử nghiệm và phát triển. + +::: + +### Điều kiện tiên quyết + +- Kaia phiên bản 2.1.0 hoặc cao hơn +- **Phải đồng bộ hóa từ bản gốc** (không thể chuyển đổi cơ sở dữ liệu hiện có) +- Thư mục dữ liệu trống + +### Hạn chế hiện tại + +Trước khi kích hoạt FlatTrie, hãy hiểu rõ các hạn chế sau: + +**Các tính năng không được hỗ trợ:** + +- Cắt tỉa theo lô và cắt tỉa trực tiếp +- Quay lại khối (cờ `--start-block-number` và API `debug_setHead`) +- Tạo bằng chứng Merkle (API `eth_getProof`) + +**Sự không tương thích:** + +- Không thể di chuyển từ cơ sở dữ liệu hiện có (phải bắt đầu từ đầu) +- Không thể chuyển đổi giữa chế độ FlatTrie và chế độ không phải FlatTrie. +- Các cơ sở dữ liệu có và không có FlatTrie là không tương thích. + +### Bật FlatTrie + +**Bước 1: Chuẩn bị thư mục dữ liệu trống** + +```bash +# Ensure clean data directory +sudo rm -rf /var/kend/data +sudo mkdir -p /var/kend/data +``` + +Bước 2: Khởi động nút với cờ FlatTrie và đồng bộ hóa từ khối genesis. + +```bash +# Mainnet +ken --state.experimental-flat-trie + +# Kairos testnet +ken --state.experimental-flat-trie --kairos +``` + +:::note + +Khi FlatTrie được kích hoạt, chế độ lưu trữ sẽ được kích hoạt tự động mà không phụ thuộc vào các tùy chọn `--gcmode` và `--state.block-interval`. Các cờ này sẽ bị bỏ qua khi sử dụng FlatTrie. + +::: + +Bước 3: Chờ đồng bộ hóa hoàn tất + +Nút sẽ đồng bộ hóa tất cả các khối từ khối genesis. Quá trình này có thể mất vài tuần tùy thuộc vào phần cứng và mạng của bạn. + +### Kiểm tra xem FlatTrie có đang hoạt động không. + +Kiểm tra nhật ký khởi động của nút để xác nhận chế độ FlatTrie: + +```bash +grep -i "flat" /var/kend/logs/kend.out | head -20 +``` + +Bạn nên thấy các dấu hiệu cho thấy cây trie phẳng thử nghiệm đang hoạt động. + +### Theo dõi hiệu suất của FlatTrie + +FlatTrie sử dụng các cấu hình tài nguyên khác nhau so với bộ nhớ trạng thái truyền thống: + +**Đặc điểm dự kiến:** + +- Giảm sử dụng CPU +- Sử dụng bộ nhớ cao hơn (~30GB) +- Số lượng goroutine cao hơn (~900-1000) +- Thời gian hoàn tất khối chậm hơn + +Theo dõi các chỉ số này thông qua điểm cuối chỉ số Prometheus của nút hoặc bảng điều khiển Grafana. + +### Khắc phục sự cố FlatTrie + +**Không thể khởi động FlatTrie trên cơ sở dữ liệu hiện có:** +Nếu bạn gặp lỗi cho biết không thể kích hoạt FlatTrie trên dữ liệu không trống, bạn phải bắt đầu từ genesis. Xóa thư mục chaindata của bạn và thực hiện đồng bộ hóa đầy đủ với tùy chọn `--state.experimental-flat-trie`. + +**Lỗi API chứng minh Merkle:** +FlatTrie không hỗ trợ `eth_getProof` và các API chứng minh Merkle liên quan. Nếu ứng dụng của bạn yêu cầu các API này, hãy sử dụng một nút truyền thống thay thế. + +**Sử dụng bộ nhớ cao:** +Sử dụng bộ nhớ khoảng 30GB là điều mong đợi cho các nút FlatTrie trong quá trình đồng bộ hóa. Đảm bảo hệ thống của bạn có đủ RAM. Đội ngũ đang tiến hành tối ưu hóa để giảm thiểu điều này trong các phiên bản tương lai. + +**Tốc độ đồng bộ chậm:** +Tốc độ đồng bộ ban đầu với FlatTrie tương đương với các nút truyền thống. Nếu quá trình đồng bộ hóa chậm đáng kể, hãy kiểm tra: + +- Hiệu suất I/O ổ đĩa (SSD được khuyến nghị mạnh mẽ) +- Băng thông mạng +- Tỷ lệ sử dụng CPU + +## Các phương pháp tốt nhất + +1. **Luôn sao lưu trước khi thực hiện các thay đổi lớn**: Đặc biệt là trước khi thực hiện nén thủ công. +2. **Theo dõi dung lượng đĩa**: Đảm bảo bạn có đủ dung lượng trống trước khi nén. Quá trình nén tạm thời yêu cầu thêm không gian để ghi đè các tệp cơ sở dữ liệu. +3. **Nén lịch trình trong các khung giờ ít lưu lượng**: Nếu đang chạy các điểm cuối RPC công khai. +4. **Sử dụng SSD cho các nút sản xuất**: Cả nén và FlatTrie đều được hưởng lợi từ thao tác I/O ngẫu nhiên nhanh. +5. **Kế hoạch cho các tính năng thử nghiệm**: FlatTrie là tính năng thử nghiệm trong phiên bản v2.1.x. Kiểm tra kỹ lưỡng trước khi đưa vào sử dụng chính thức. +6. **Cập nhật thường xuyên**: Kiểm tra ghi chú phát hành để biết các tối ưu hóa trong tương lai và thời điểm FlatTrie chính thức ra khỏi giai đoạn thử nghiệm. \ No newline at end of file diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md b/i18n/vi/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md index e8fe870fb50a..310526d9de91 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md @@ -159,7 +159,7 @@ Keep in mind that the keystore and the password that you created is significantl ### (Optional) Download Chaindata Snapshot -Synching from the genesis block is time-consuming. You may use [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../../learn/storage/block-sync.md#full-sync) process. +Việc đồng bộ hóa từ khối genesis mất nhiều thời gian. You may use [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../../learn/storage/block-sync.md#full-sync) process. ## Startup the CN diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md b/i18n/vi/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md index df03ab141caa..4b0d47b46485 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md @@ -146,7 +146,7 @@ DATA_DIR=/var/kpnd/data ### (Optional) Download Chaindata Snapshot -Synching from the genesis block is time-consuming. You may use [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../../learn/storage/block-sync.md#full-sync) process. +Việc đồng bộ hóa từ khối genesis mất nhiều thời gian. You may use [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../../learn/storage/block-sync.md#full-sync) process. ## Startup the PN diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md b/i18n/vi/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md index 048148ffd732..031ea8563c76 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md @@ -10,14 +10,22 @@ The following sections show the recommended specifications for both CNs and PNs. ### Bare-metal Server -| Category | Specification | -| :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Server | Intel® Server System [M50CYP1UR212](https://www.intel.sg/content/www/xa/en/products/sku/214842/intel-server-system-m50cyp1ur212/specifications.html) | -| CPU | Intel® Xeon 8358 2.60 GHz \(32-core/64-thread\) | -| Memory | 128GB \(32GB \* 4\) | -| Storage | 4TB (or larger size) SSD (The preferred storage size and configuration could differ depending on the chain data size. Please consult the Kaia Team for more information.) | +#### Yêu cầu chung (Tất cả các loại nút) -Note that this is a recommended hardware specification for CNs and PNs, not an exact requirement. Any physical machine with similar hardware configurations would be sufficient to operate a CN or a PN. +| Category | Thông số kỹ thuật | +| :------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | +| CPU | Tần số cơ bản 2,6 GHz – Tần số tối đa 3,4 GHz hoặc cao hơn (ví dụ: Bộ xử lý Intel® Xeon® Scalable thế hệ thứ 3) | +| Storage | ≥ 4 TB SSD (điều chỉnh theo kích thước dữ liệu chuỗi; vui lòng liên hệ với Đội ngũ Kaia để được hướng dẫn) | + +Any physical machine with similar hardware configurations would be sufficient to operate a CN or a PN. + +#### Các thông số kỹ thuật được khuyến nghị theo loại nút + +| Node Type | Lõi/Luồng | Memory | +| :------------------------------------------- | :----------------- | :----------- | +| CN | 16 nhân / 32 luồng | 128 gigabyte | +| PN | 8 nhân / 16 luồng | 64 gigabyte | +| PN (with Live Pruning DB) | 4 nhân / 8 luồng | 32 gigabyte | You can use and apply a live-pruning option to use live-pruning DB. For more details, please refer https://docs.kaia.io/learn/storage/live-pruning/. However, note that live-pruning spec is not recommended for CNs but this may change in the future. @@ -49,11 +57,11 @@ The information above is from [https://azure.microsoft.com/en-us/pricing/details #### Recommended Specification for GCP -| Node Type | Model | vCPU | Memory \(GiB\) | Storage type \(GiB\) | Storage speed \(IOPS\) | Price \(asia-northeast3, USD/h\) | -| :------------------------------------------: | :--------------: | :--: | :---------------------------------: | :---------------------------------------: | :-----------------------------------------: | :---------------------------------------------------: | -| CN | c4-tiêu chuẩn-32 | 32 | 120 | 4,000 (Minimum) | 7500 | 2.03078256 | -| PN | n2-standard-16 | 16 | 64 | 4,000 (Minimum) | 7500 | 1.016243 | -| PN (with Live Pruning DB) | n2-standard-8 | 8 | 32 | 3,500 (Minimum) | 7500 | 0.508121 | +| Loại nút | Model | vCPU | Memory \(GiB\) | Storage type \(GiB\) | Storage speed \(IOPS\) | Price \(asia-northeast3, USD/h\) | +| :---------------------------------------------------------: | :--------------: | :--: | :---------------------------------: | :---------------------------------------: | :-----------------------------------------: | :---------------------------------------------------: | +| CN | c4-tiêu chuẩn-32 | 32 | 120 | 4,000 (Minimum) | 7500 | 2.03078256 | +| PN | n2-standard-16 | 16 | 64 | 4,000 (Minimum) | 7500 | 1.016243 | +| PN (với cơ sở dữ liệu cắt tỉa trực tiếp) | n2-standard-8 | 8 | 32 | 3,500 (Minimum) | 7500 | 0.508121 | The information above is from [https://cloud.google.com/compute/vm-instance-pricing#general-purpose_machine_type_family/](https://cloud.google.com/compute/vm-instance-pricing#general-purpose_machine_type_family/) and [https://cloud.google.com/storage/pricing#asia](https://cloud.google.com/storage/pricing#asia) and may be changed by Google. diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md b/i18n/vi/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md index 9b7b5981a1de..b2d9a118eb7e 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md @@ -27,7 +27,7 @@ echo "LOG_DIR=/var/kend/logs" >> conf/kend.conf ### (Optional) Download Chaindata Snapshot -Synching from the genesis block is time-consuming. You may use [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../learn/storage/block-sync.md#full-sync) process. Download and decompress the chaindata snapshot. Then mount the decompressed directory to the container. +Việc đồng bộ hóa từ khối genesis mất nhiều thời gian. You may use [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../learn/storage/block-sync.md#full-sync) process. Download and decompress the chaindata snapshot. Then mount the decompressed directory to the container. ## Start the container diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md b/i18n/vi/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md index e1dc46bc1f15..ff21d3a54080 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md @@ -115,7 +115,7 @@ DATA_DIR=/var/kend/data ### (Optional) Download Chaindata Snapshot -Synching from the genesis block is time-consuming. You may use [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../learn/storage/block-sync.md#full-sync) process. +Việc đồng bộ hóa từ khối genesis mất nhiều thời gian. You may use [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) to skip the [Full Sync](../../learn/storage/block-sync.md#full-sync) process. ## Startup the EN diff --git a/i18n/vi/docusaurus-plugin-content-docs/current/references/contract-addresses.md b/i18n/vi/docusaurus-plugin-content-docs/current/references/contract-addresses.md index 31c489c4ee8c..c43bc348d5db 100644 --- a/i18n/vi/docusaurus-plugin-content-docs/current/references/contract-addresses.md +++ b/i18n/vi/docusaurus-plugin-content-docs/current/references/contract-addresses.md @@ -15,6 +15,7 @@ Some Kaia features rely on the special smart contracts called _system contracts_ | KIP-113 SimpleBlsRegistry | proxy 0x3e80e75975bdb8e04B800485DD28BebeC6d97679
logic 0xb5ed8d6edd437a0d6ae828580c0aef5678d87f1a | proxy 0x4BEed0651C46aE5a7CB3b7737345d2ee733789e6
logic 0x6751096fe72d835307d7e635aed51296948b93c5 | | KIP-247 GaslessSwapRouter | 0xCf658F786bf4AC62D66d70Dd26B5c1395dA22c63 | 0x4b41783732810b731569E4d944F59372F411BEa2 | | KIP-226 CLRegistry | 0x25F4044c655Fc7B23c62bbC78ceF3B4EBFb4e478 | 0x25F4044c655Fc7B23c62bbC78ceF3B4EBFb4e478 | +| KIP-249 Điểm vào đấu giá | 0xFc5c1C92d8DE06F7143f71FeA209e04042dcff82 | 0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480 | Some contracts are not directly read by Kaia nodes but play crucial roles in operating the Kaia blockchain and its ecosystem. They include treasury, governance, and KAIA token bridge contracts. @@ -33,7 +34,9 @@ Some contracts are not directly read by Kaia nodes but play crucial roles in ope | Kaiabridge Judge | 0x64c91d6517b8f2fd7f4157c32DE4acfe1AeA2611 | 0x3735Ba95cca5DEd47Fa5b202a2Bbda4c63c0B1DD | | Kaiabridge Guardian | 0xE49D152E5FA576caFC18D2775AF4E58C135a6851 | 0xc9e8342C1da4c89A423258d9030414331b4761Cf | | KIP-163 PublicDelegationFactory | 0x29C8cc53d22F79D4024ecB67DB1a09b37bCdE415 | 0x98c47c2cda854cbb025d47de72149a7ec238ec33 | -| Nhà máy KIP-226 CLDEX | 0x2A4C5eCaafB26460F17d509EA4d15741AF5F5f0a | 0x537D58BdBC98c690bE5d3e3F638d4B93754B15Fd | -| Bộ định tuyến KIP-226 CLDEX | 0x21d3c567058277b19324FE22c8e4Bb3D2AE0D4C3 | 0x41F135a084897e4145CC2032e8701726af795e3a | +| Nhà máy KIP-226 CLDEX | 0x93fa0E1deE99ac4158a617a6EC79cB941bD9a39F | 0x666a9a72D2f708062a20e7Ca94f6dd5Ce6B33eA4 | +| Bộ định tuyến KIP-226 CLDEX | 0x5086273d9C8a79B7d2466aaCc52a6E43E22152A5 | 0x2871e95eaBFF0E71e4e4b706D7F1F3D24811673b | | KIP-226 StakingTrackerV2 | 0xF45c37c265f148894D6d9A4c066aFaAB00557c9c | 0x9b015Ab5916EE53e52Ef60f31E978b4001908c43 | | [WKAIA Chính thức](../build/smart-contracts/token-development/canonical-wkaia.md) | 0x19Aac5f612f524B754CA7e7c41cbFa2E981A4432 | 0x043c471bEe060e00A56CcD02c0Ca286808a5A436 | +| KIP-249 Kho lưu trữ tiền đặt cọc đấu giá | 0x0E66b62273Cc99BC519DD4dD0C0Cf689dd7b9876 | 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc | +| KIP-249 Kho phí đấu giá | 0x303BB9c9FF4Aa656ac4c8e9f99F8E4C133FDa665 | 0xE4e7d880786c53b6EA6cfA848Eb3a05eE97b2aCC | \ No newline at end of file diff --git a/i18n/vi/docusaurus-theme-classic/footer.json b/i18n/vi/docusaurus-theme-classic/footer.json index db9255e069c2..38217f018345 100644 --- a/i18n/vi/docusaurus-theme-classic/footer.json +++ b/i18n/vi/docusaurus-theme-classic/footer.json @@ -56,7 +56,11 @@ "description": "The label of footer link with label=Open Source linking to https://docs.kaia.io/misc/opensource/" }, "copyright": { - "message": "© Kaia DLT Foundation 2025. All rights reserved.", + "message": "", "description": "The footer copyright" + }, + "link.item.label.Blog": { + "message": "Blog", + "description": "The label of footer link with label=Blog linking to https://blog.kaia.io/" } } diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current.json b/i18n/zh-CN/docusaurus-plugin-content-docs/current.json index c42abaa153ed..4d03c2524a82 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current.json +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current.json @@ -5,23 +5,23 @@ }, "sidebar.buildSidebar.category.Get Started": { "message": "开始", - "description": "The label for category Get Started in sidebar buildSidebar" + "description": "The label for category 'Get Started' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Smart Contracts": { "message": "智能合约", - "description": "The label for category Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Deploy Smart Contracts": { "message": "部署智能合约", - "description": "The label for category Deploy Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Deploy Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Sample Contracts": { "message": "合同样本", - "description": "The label for category Sample Contracts in sidebar buildSidebar" + "description": "The label for category 'Sample Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Tutorials": { "message": "教程", - "description": "The label for category Tutorials in sidebar buildSidebar" + "description": "The label for category 'Tutorials' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Tools": { "message": "工具", @@ -29,51 +29,51 @@ }, "sidebar.buildSidebar.category.Wallets": { "message": "钱包", - "description": "The label for category Wallets in sidebar buildSidebar" + "description": "The label for category 'Wallets' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Wallet Libraries": { "message": "钱包图书馆", - "description": "The label for category Wallet Libraries in sidebar buildSidebar" + "description": "The label for category 'Wallet Libraries' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Oracles": { "message": "神谕", - "description": "The label for category Oracles in sidebar buildSidebar" + "description": "The label for category 'Oracles' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Indexers": { "message": "索引器", - "description": "The label for category Indexers in sidebar buildSidebar" + "description": "The label for category 'Indexers' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Cross-chain": { "message": "跨链", - "description": "The label for category Cross-chain in sidebar buildSidebar" + "description": "The label for category 'Cross-chain' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Block Explorers": { "message": "积木探险家", - "description": "The label for category Block Explorers in sidebar buildSidebar" + "description": "The label for category 'Block Explorers' in sidebar 'buildSidebar'" }, "sidebar.nodeSidebar.category.Endpoint Node": { "message": "端点节点", - "description": "The label for category Endpoint Node in sidebar nodeSidebar" + "description": "The label for category 'Endpoint Node' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Core Cell": { "message": "核心单元", - "description": "The label for category Core Cell in sidebar nodeSidebar" + "description": "The label for category 'Core Cell' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Install Core Cell": { "message": "安装核心单元", - "description": "The label for category Install Core Cell in sidebar nodeSidebar" + "description": "The label for category 'Install Core Cell' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Service Chain": { "message": "服务链", - "description": "The label for category Service Chain in sidebar nodeSidebar" + "description": "The label for category 'Service Chain' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Quick Start": { "message": "快速入门", - "description": "The label for category Quick Start in sidebar nodeSidebar" + "description": "The label for category 'Quick Start' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Configure Service Chain": { "message": "配置服务链", - "description": "The label for category Configure Service Chain in sidebar nodeSidebar" + "description": "The label for category 'Configure Service Chain' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Node Package Downloads": { "message": "节点软件包下载", @@ -81,11 +81,11 @@ }, "sidebar.refSidebar.category.RPC API Reference": { "message": "RPC API 参考", - "description": "The label for category RPC API Reference in sidebar refSidebar" + "description": "The label for category 'RPC API Reference' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.SDKs and Libraries": { "message": "SDK 和库", - "description": "The label for category SDKs and Libraries in sidebar refSidebar" + "description": "The label for category 'SDKs and Libraries' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.API References": { "message": "应用程序接口参考", @@ -97,31 +97,31 @@ }, "sidebar.learnSidebar.category.Transaction Fees": { "message": "交易费用", - "description": "The label for category Transaction Fees in sidebar learnSidebar" + "description": "The label for category 'Transaction Fees' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Verify Smart Contracts": { "message": "验证智能合约", - "description": "The label for category Verify Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Verify Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.learnSidebar.category.Data Management": { "message": "数据管理", - "description": "The label for category Data Management in sidebar learnSidebar" + "description": "The label for category 'Data Management' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Governance": { "message": "管理", - "description": "The label for category Governance in sidebar learnSidebar" + "description": "The label for category 'Governance' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Node Quick Reference": { "message": "节点快速参考", - "description": "The label for category Node Quick Reference in sidebar learnSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Kaia Safe": { "message": "Kaia Safe", - "description": "The label for category Kaia Safe in sidebar buildSidebar" + "description": "The label for category 'Kaia Safe' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Node Quick Reference": { "message": "节点快速参考", - "description": "The label for category Node Quick Reference in sidebar buildSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.link.KaiaScan": { "message": "KaiaScan", @@ -129,47 +129,47 @@ }, "sidebar.nodeSidebar.category.Node Quick Reference": { "message": "节点快速参考", - "description": "The label for category Node Quick Reference in sidebar nodeSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'nodeSidebar'" }, "sidebar.refSidebar.category.ethers-ext < v1.0.1": { "message": "ethers-ext < v1.0.1", - "description": "The label for category ethers-ext < v1.0.1 in sidebar refSidebar" + "description": "The label for category 'ethers-ext < v1.0.1' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore": { "message": "钥匙库", - "description": "The label for category keystore in sidebar refSidebar" + "description": "The label for category 'keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.ethers-ext": { "message": "ethers-ext", - "description": "The label for category ethers-ext in sidebar refSidebar" + "description": "The label for category 'ethers-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.v5": { "message": "v5", - "description": "The label for category v5 in sidebar refSidebar" + "description": "The label for category 'v5' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.v6": { "message": "v6", - "description": "The label for category v6 in sidebar refSidebar" + "description": "The label for category 'v6' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3js-ext": { "message": "web3js-ext", - "description": "The label for category web3js-ext in sidebar refSidebar" + "description": "The label for category 'web3js-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3j-ext": { "message": "web3j-ext", - "description": "The label for category web3j-ext in sidebar refSidebar" + "description": "The label for category 'web3j-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3py-ext": { "message": "web3py-ext", - "description": "The label for category web3py-ext in sidebar refSidebar" + "description": "The label for category 'web3py-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.Node Quick Reference": { "message": "节点快速参考", - "description": "The label for category Node Quick Reference in sidebar refSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'refSidebar'" }, "sidebar.buildSidebar.category.Hardware Wallets": { "message": "硬件钱包", - "description": "The label for category Hardware Wallets in sidebar buildSidebar" + "description": "The label for category 'Hardware Wallets' in sidebar 'buildSidebar'" }, "sidebar.miniDappSidebar.category.Build Mini dApps on LINE with Unity": { "message": "使用 Unity 在 LINE 上构建迷你 dApps", @@ -177,107 +177,107 @@ }, "sidebar.miniDappSidebar.category.Node Quick Reference": { "message": "节点快速参考", - "description": "The label for category Node Quick Reference in sidebar miniDappSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'miniDappSidebar'" }, "sidebar.learnSidebar.category.Core Concepts": { "message": "核心理念", - "description": "The label for category Core Concepts in sidebar learnSidebar" + "description": "The label for category 'Core Concepts' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Smart Contracts": { "message": "智能合约", - "description": "The label for category Smart Contracts in sidebar learnSidebar" + "description": "The label for category 'Smart Contracts' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Advanced Topics": { "message": "高级主题", - "description": "The label for category Advanced Topics in sidebar learnSidebar" + "description": "The label for category 'Advanced Topics' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Transaction Execution": { "message": "交易执行", - "description": "The label for category Transaction Execution in sidebar learnSidebar" + "description": "The label for category 'Transaction Execution' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Token Economics": { "message": "代币经济学", - "description": "The label for category Token Economics in sidebar learnSidebar" + "description": "The label for category 'Token Economics' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Transactions": { "message": "交易", - "description": "The label for category Transactions in sidebar buildSidebar" + "description": "The label for category 'Transactions' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Token Management": { "message": "代币管理", - "description": "The label for category Token Management in sidebar buildSidebar" + "description": "The label for category 'Token Management' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Team Finance": { "message": "团队财务", - "description": "The label for category Team Finance in sidebar buildSidebar" + "description": "The label for category 'Team Finance' in sidebar 'buildSidebar'" }, "sidebar.miniDappSidebar.category.LINE Mini DApp with Unity": { "message": "使用 Unity 的 LINE 迷你应用程序", - "description": "The label for category LINE Mini DApp with Unity in sidebar miniDappSidebar" + "description": "The label for category 'LINE Mini DApp with Unity' in sidebar 'miniDappSidebar'" }, "sidebar.miniDappSidebar.category.LINE Mini DApp with Cocos": { "message": "使用 Cocos 的 LINE 迷你应用程序", - "description": "The label for category LINE Mini DApp with Cocos in sidebar miniDappSidebar" + "description": "The label for category 'LINE Mini DApp with Cocos' in sidebar 'miniDappSidebar'" }, "sidebar.miniDappSidebar.category.Survey Mini DApp": { "message": "调查微型应用程序", - "description": "The label for category Survey Mini DApp in sidebar miniDappSidebar" + "description": "The label for category 'Survey Mini DApp' in sidebar 'miniDappSidebar'" }, "sidebar.learnSidebar.link.Docs Updates": { "message": "文件更新", - "description": "The label for link Docs Updates in sidebar learnSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'learnSidebar', linking to '/misc/updates'" }, "sidebar.buildSidebar.link.Docs Updates": { "message": "文件更新", - "description": "The label for link Docs Updates in sidebar buildSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'buildSidebar', linking to '/misc/updates'" }, "sidebar.nodeSidebar.category.Debugging and Diagnostics": { "message": "调试和诊断", - "description": "The label for category Debugging and Diagnostics in sidebar nodeSidebar" + "description": "The label for category 'Debugging and Diagnostics' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.link.Docs Updates": { "message": "文件更新", - "description": "The label for link Docs Updates in sidebar nodeSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'nodeSidebar', linking to '/misc/updates'" }, "sidebar.refSidebar.link.Docs Updates": { "message": "文件更新", - "description": "The label for link Docs Updates in sidebar refSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'refSidebar', linking to '/misc/updates'" }, "sidebar.miniDappSidebar.link.Docs Updates": { "message": "文件更新", - "description": "The label for link Docs Updates in sidebar miniDappSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'miniDappSidebar', linking to '/misc/updates'" }, "sidebar.learnSidebar.category.Finschia to Kaia": { "message": "芬斯基亚呼叫卡伊娅", - "description": "The label for category Finschia to Kaia in sidebar learnSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Finschia to Kaia": { "message": "芬斯基亚呼叫卡伊娅", - "description": "The label for category Finschia to Kaia in sidebar buildSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'buildSidebar'" }, "sidebar.nodeSidebar.category.Finschia to Kaia": { "message": "芬斯基亚呼叫卡伊娅", - "description": "The label for category Finschia to Kaia in sidebar nodeSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'nodeSidebar'" }, "sidebar.refSidebar.category.Finschia to Kaia": { "message": "芬斯基亚呼叫卡伊娅", - "description": "The label for category Finschia to Kaia in sidebar refSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'refSidebar'" }, "sidebar.miniDappSidebar.category.Finschia to Kaia": { "message": "芬斯基亚呼叫卡伊娅", - "description": "The label for category Finschia to Kaia in sidebar miniDappSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'miniDappSidebar'" }, "sidebar.buildSidebar.category.Wallet Configuration": { "message": "钱包配置", - "description": "The label for category Wallet Configuration in sidebar buildSidebar" + "description": "The label for category 'Wallet Configuration' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Wallet Operations": { "message": "钱包操作", - "description": "The label for category Wallet Operations in sidebar buildSidebar" + "description": "The label for category 'Wallet Operations' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.dApp Integration": { "message": "dApp 整合", - "description": "The label for category dApp Integration in sidebar buildSidebar" + "description": "The label for category 'dApp Integration' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Implementing Transactions": { "message": "实施交易", @@ -285,27 +285,27 @@ }, "sidebar.buildSidebar.category.Cookbooks": { "message": "烹饪书", - "description": "The label for category Cookbooks in sidebar buildSidebar" + "description": "The label for category 'Cookbooks' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Fundamentals": { "message": "基础知识", - "description": "The label for category Fundamentals in sidebar buildSidebar" + "description": "The label for category 'Fundamentals' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Token Development": { "message": "代币开发", - "description": "The label for category Token Development in sidebar buildSidebar" + "description": "The label for category 'Token Development' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Deployment & Verification": { "message": "部署与验证", - "description": "The label for category Deployment & Verification in sidebar buildSidebar" + "description": "The label for category 'Deployment & Verification' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Integrate Gas Abstraction (GA)": { "message": "整合气体抽取 (GA)", - "description": "The label for category Integrate Gas Abstraction (GA) in sidebar buildSidebar" + "description": "The label for category 'Integrate Gas Abstraction (GA)' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Kaia Agent Kit": { "message": "Kaia 代理套件", - "description": "The label for category Kaia Agent Kit in sidebar buildSidebar" + "description": "The label for category 'Kaia Agent Kit' in sidebar 'buildSidebar'" }, "sidebar.refSidebar.category.Gas Abstraction": { "message": "气体抽取", @@ -313,306 +313,306 @@ }, "sidebar.refSidebar.category.viem-ext": { "message": "viem-ext", - "description": "The label for category viem-ext in sidebar refSidebar" + "description": "The label for category 'viem-ext' in sidebar 'refSidebar'" }, "sidebar.buildSidebar.doc.Step 1: Foundation Setup": { "message": "步骤 1:地基设置", - "description": "The label for the doc item Step 1: Foundation Setup in sidebar buildSidebar, linking to the doc build/get-started/foundation-setup" + "description": "The label for the doc item 'Step 1: Foundation Setup' in sidebar 'buildSidebar', linking to the doc build/get-started/foundation-setup" }, "sidebar.buildSidebar.doc.Step 2: Set up Account and Networks": { "message": "步骤 2:设置账户和网络", - "description": "The label for the doc item Step 2: Set up Account and Networks in sidebar buildSidebar, linking to the doc build/get-started/wallet-config-get-started" + "description": "The label for the doc item 'Step 2: Set up Account and Networks' in sidebar 'buildSidebar', linking to the doc build/get-started/wallet-config-get-started" }, "sidebar.buildSidebar.doc.Step 3: Get KAIA": { "message": "步骤 3:获取 KAIA", - "description": "The label for the doc item Step 3: Get KAIA in sidebar buildSidebar, linking to the doc build/get-started/getting-kaia" + "description": "The label for the doc item 'Step 3: Get KAIA' in sidebar 'buildSidebar', linking to the doc build/get-started/getting-kaia" }, "sidebar.buildSidebar.doc.Step 4: Deploy Hello World Contract": { "message": "步骤 4:部署 Hello World 合约", - "description": "The label for the doc item Step 4: Deploy Hello World Contract in sidebar buildSidebar, linking to the doc build/get-started/kaiagreeter-get-started" + "description": "The label for the doc item 'Step 4: Deploy Hello World Contract' in sidebar 'buildSidebar', linking to the doc build/get-started/kaiagreeter-get-started" }, "sidebar.buildSidebar.doc.Step 5: Deploy your First Token Contract": { "message": "步骤 5:部署第一个代币合约", - "description": "The label for the doc item Step 5: Deploy your First Token Contract in sidebar buildSidebar, linking to the doc build/get-started/hardhat" + "description": "The label for the doc item 'Step 5: Deploy your First Token Contract' in sidebar 'buildSidebar', linking to the doc build/get-started/hardhat" }, "sidebar.buildSidebar.doc.Step 6: Build your First dApp on Kaia": { "message": "第 6 步:在 Kaia 上构建您的第一个应用程序", - "description": "The label for the doc item Step 6: Build your First dApp on Kaia in sidebar buildSidebar, linking to the doc build/get-started/scaffold-eth-get-started" + "description": "The label for the doc item 'Step 6: Build your First dApp on Kaia' in sidebar 'buildSidebar', linking to the doc build/get-started/scaffold-eth-get-started" }, "sidebar.buildSidebar.doc.Step 7: Build your Mini dApp on Kaia": { "message": "第 7 步:在 Kaia 上构建您的迷你应用程序", - "description": "The label for the doc item Step 7: Build your Mini dApp on Kaia in sidebar buildSidebar, linking to the doc minidapps/minidapps" + "description": "The label for the doc item 'Step 7: Build your Mini dApp on Kaia' in sidebar 'buildSidebar', linking to the doc minidapps/minidapps" }, "sidebar.buildSidebar.category.smart-contract-tools": { "message": "工具", - "description": "The label for category Tools in sidebar buildSidebar" + "description": "The label for category 'Tools' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Best Practices": { "message": "最佳做法", - "description": "The label for category Best Practices in sidebar buildSidebar" + "description": "The label for category 'Best Practices' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.build-tools": { "message": "工具", - "description": "The label for category Tools in sidebar buildSidebar" + "description": "The label for category 'Tools' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Gaming SDKs": { "message": "游戏 SDK", - "description": "The label for category Gaming SDKs in sidebar buildSidebar" + "description": "The label for category 'Gaming SDKs' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.doc.Proof of Play vRNG": { "message": "游戏证明 vRNG", - "description": "The label for the doc item Proof of Play vRNG in sidebar buildSidebar, linking to the doc build/tools/oracles/vrng-pop" + "description": "The label for the doc item 'Proof of Play vRNG' in sidebar 'buildSidebar', linking to the doc build/tools/oracles/vrng-pop" }, "sidebar.refSidebar.category.account-management-v5": { "message": "账户管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v5": { "message": "账户密钥", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v5": { "message": "签署交易", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v5": { "message": "标志信息", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-v5": { "message": "钥匙存储", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v5": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v5": { "message": "收费 委托交易", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v5": { "message": "智能合约", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-v5": { "message": "实用工具", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-v6": { "message": "账户管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v6": { "message": "账户密钥", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v6": { "message": "签署交易", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v6": { "message": "标志信息", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-v6": { "message": "钥匙存储", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v6": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v6": { "message": "收费 委托交易", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.gas-abstraction-ethers": { "message": "气体抽取", - "description": "The label for category Gas Abstraction in sidebar refSidebar" + "description": "The label for category 'Gas Abstraction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v6": { "message": "智能合约", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-v6": { "message": "实用工具", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-v1": { "message": "账户管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v1": { "message": "账户密钥", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v1": { "message": "签署交易", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v1": { "message": "标志信息", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v1": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v1": { "message": "收费 委托交易", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v1": { "message": "智能合约", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3js": { "message": "账户管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3js": { "message": "账户密钥", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3js": { "message": "签署交易", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3js": { "message": "标志信息", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3js": { "message": "钥匙存储", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3js": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3js": { "message": "收费 委托交易", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.gas-abstraction-web3js": { "message": "气体抽取", - "description": "The label for category Gas Abstraction in sidebar refSidebar" + "description": "The label for category 'Gas Abstraction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3js": { "message": "智能合约", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3js": { "message": "实用工具", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-viem": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-viem": { "message": "收费 委托交易", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-viem": { "message": "智能合约", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3j": { "message": "账户管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3j": { "message": "账户密钥", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3j": { "message": "签署交易", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3j": { "message": "标志信息", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3j": { "message": "钥匙存储", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3j": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3j": { "message": "收费 委托交易", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3j": { "message": "智能合约", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3j": { "message": "实用工具", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3py": { "message": "账户管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3py": { "message": "账户密钥", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3py": { "message": "签署交易", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3py": { "message": "标志信息", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3py": { "message": "钥匙存储", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3py": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3py": { "message": "收费 委托交易", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3py": { "message": "智能合约", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3py": { "message": "实用工具", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.doc.getting-started-ethers": { "message": "入门", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/ethers-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/ethers-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-ethers-v1": { "message": "入门", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/ethers-ext-prior-v1-0-1/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/ethers-ext-prior-v1-0-1/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3js": { "message": "入门", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3js-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3js-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-viem": { "message": "入门", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/viem-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/viem-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3j": { "message": "入门", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3j-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3j-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3py": { "message": "入门", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3py-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3py-ext/getting-started" } } diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md index 03f194f8747b..2f15936b473f 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md @@ -10,5 +10,5 @@ Web3.unity SDK 目前支持 Kaia 主网和 Kairos 测试网。 要开始在 Kaia 上构建支持区块链的游戏,请查看以下指南: -- [Kaia上的Unity游戏开发:使用ChainSafe铸造可流通代币](https://medium.com/kaiachain/unity-game-development-on-kaia-minting-fungible-tokens-with-chainsafe-beea9022c42d) -- [如何在 Kaia 上使用 Chainsafe 和 Thirdweb 对 Unity 游戏进行代币门](https://medium.com/kaiachain/how-to-token-gate-a-unity-game-using-chainsafe-and-thirdweb-on-kaia-93c574519da2) +- [Kaia上的Unity游戏开发:使用ChainSafe铸造可流通代币](https://blog.kaia.io/unity-game-development-on-kaia-minting-fungible-tokens-with-chainsafe/) +- [如何在 Kaia 上使用 Chainsafe 和 Thirdweb 对 Unity 游戏进行代币门](https://blog.kaia.io/how-to-token-gate-a-unity-game-using-chainsafe-and-thirdweb-on-kaia/) diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md index 471109ea9657..d58b25ea37c9 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md @@ -887,4 +887,4 @@ Fleek 是一种基础设施,使我们能够在 IPFS 上构建现代网站和 在此基础上,您还可以在前台探索一些其他选项,比如除了静态发送 1 KAIA 咖啡外,还可以添加一个新的输入字段,用于输入要发送的咖啡量。 您可以访问 [github](https://github.com/ayo-klaytn/buy-me-a-coffee) 上的完整代码库,也可以使用 [link](https://spring-fog-0605.on.fleek.co/) 测试网站。 -如果您想了解更多信息,请访问 [Kaia 文档](https://docs.klaytn.foundation/)、[Web3Onboard 文档](https://onboard.blocknative.com/docs/modules/react) 和 [Fleek 文档](https://docs.fleek.co/tutorials/hosting/)。 如果您有任何问题,请访问 [Kaia 论坛](https://devforum.kaia.io/)。 +如果您想了解更多信息,请访问 [Kaia 文档](https://docs.kaia.io)、[Web3Onboard 文档](https://onboard.blocknative.com/docs/modules/react) 和 [Fleek 文档](https://docs.fleek.co/tutorials/hosting/)。 如果您有任何问题,请访问 [Kaia 论坛](https://devforum.kaia.io/)。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md new file mode 100644 index 000000000000..cd2a85e7aaba --- /dev/null +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md @@ -0,0 +1,748 @@ +# 利用链式链接 CCIP 在 Kaia 上构建跨链 NFT:实用指南 + +## 介绍 + +NFT 已成为区块链技术最广为人知的用例之一,能够创建独一无二、可验证的数字资产。 然而,传统的 NFT 实现方式被束缚在单个区块链上。 这种限制降低了灵活性,使资产无法在社区、流动性和效用可能不同的生态系统中自由流动。 + +跨链 NFT 允许 NFT 在区块链之间无缝移动,同时保留其唯一性和出处,从而解决了这一难题。 借助 Chainlink 的跨链互操作性协议 (CCIP),开发人员可以使用标准化的安全消息框架在链之间建立可靠的桥梁。 + +在本指南中,您将使用 "先烧后铸 "模式构建和部署跨链 NFT。 NFT 将在源链上刻录,并以相同的 tokenId 和元数据在目标链上重新铸模,确保任何时候都只存在一个有效副本。 + +## 要求 + +开始之前,请确保您已做好以下设置: + +- [Node.js](https://nodejs.org/) 和 [npm](https://www.npmjs.com/) +- 硬礼帽 + - 安装:npm install --save-dev hardhat + - 初始化项目: `npx hardhat --init` +- [MetaMask](https://metamask.io/en-GB/download) 钱包 + - 创建或设置开发钱包。 + - 将 Kaia Kairos 测试网络和以太坊 Sepolia 网络添加到 MetaMask 中。 +- 从水龙头测试代币 + - [KAIA](https://faucet.kaia.io/): 在部署合约或发送交易时支付 Kaia 上的燃气费。 + - [LINK](https://faucets.chain.link/kaia-testnet) (testnet):使用 LINK 支付时涵盖 CCIP 费用。 + - [Sepolia ETH](https://faucets.chain.link/sepolia): 支付 Sepolia 上的燃气费,如果选择,还可支付本地 ETH 中的 CCIP 费用。 +- [Filebase](https://filebase.com/) 账户 + - 需要上传和检索 NFT 元数据(IPFS 存储)。 + +## 跨链 NFT 如何工作? + +NFT 是记录在单一区块链上的唯一数字代币。 其核心行为,包括铸币、转让和所有权,由与该链绑定的智能合约定义。 正因为如此,如果没有额外的机制,NFT 无法自然地在区块链之间移动。 为了实现互操作性,开发人员会在多个链上部署配套合约,并通过跨链消息传递将它们连接起来。 这就是跨链 NFT:存在于不同区块链上的等价代币,但在任何时候都只有一个副本处于活动状态。 + +跨链 NFT 通常有三种实现方式: + +- **焚烧和铸币**:在源链上烧制 NFT,然后在目的链上铸造等价物。 + +- **锁定和铸币**:在源链上锁定 NFT,并在目标链上铸造副本。 返回时需要烧毁复制品才能解锁原件。 + +- **锁定和解锁**:在多个链上部署相同的集合。 所有者锁定一条链上的 NFT,就能解锁另一条链上的对应 NFT,确保一次只能使用一个副本。 + +在本指南中,我们将在跨链 NFT 中使用燃烧和薄荷模型。 NFT 将从一条链上移除,然后在另一条链上重新创建,整个过程由 Chainlink CCIP 提供动力。 + +## 入门 + +在本指南中,您将使用 Chainlink CCIP 在 Kaia Kairos Testnet 和 Ethereum Sepolia 之间铸币和传输跨链 NFT。 + +到最后,您将能够 + +- 初始化为 Kairos Testnet 和 Ethereum Sepolia 配置的 Hardhat 项目 +- 将 Chainlink CCIP 合同和接口添加为依赖项 +- 实施跨链 NFT 合约,为跨链转账提供烧钱机制 +- 将合同部署到两个网络,并跨链发送 NFT。 + +### 创建硬礼帽项目 + +在本教程中,我们将使用 [Hardhat 3](https://hardhat.org/docs/getting-started#getting-started-with-hardhat-3) 来部署合同并与之交互。 Hardhat 3 提供了一些新功能,例如对加密密钥存储的本地支持、在 Solidity 中编写测试的能力以及改进的项目工具。 + +请按照以下步骤设置项目: + +1. 验证 Node.js 和 npm 的安装 + + 运行以下命令验证 Node.js 和 npm 是否已安装: + +```bash +node -v +npm -v +``` + +2. 初始化新项目目录 + + 创建一个新文件夹,导航进入,然后初始化一个 Node.js 项目: + +```bash +mkdir ccip-nft-kaia-hardhat-example +cd ccip-nft-kaia-hardhat-example +npm init -y +``` + +3. 创建 Hardhat 项目 + + 运行: + +```bash +npx hardhat --init +``` + +出现提示时,选择包含 Node.js 测试运行器和ether 的示例项目。 在当前目录下对其进行初始化,并安装所有需要的依赖项。 + +### 安装所需合同 + +安装 Chainlink CCIP 合同: + +```bash +npm i @chainlink/contracts-ccip --save-dev +``` + +安装标准链锁合同: + +```bash +npm i @chainlink/contracts --save-dev +``` + +安装 OpenZeppelin 合约(提供 ERC-721 和其他基本实现): + +```bash +npm i @openzeppelin/contracts --save-dev +``` + +## 配置 NFT 元数据 + +在撰写合同之前,让我们先确定一下我们要铸造的 NFT 的规格。 每个 NFT 都需要描述其名称、说明和图像的元数据,这些数据存储在一个 JSON 文件中,并托管在 IPFS 上。 + +在本指南中,我们将使用 Filebase 来存储图像和元数据。 如果您想创建自己的 NFT,请通过 Filebase 将图像和元数据 JSON 文件上传到 IPFS。 上传后,单击 "文件 "选项卡中的文件名并复制 IPFS URL。 它看起来类似于这样: + +```bash +https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmY1LZF8JHo2r3h4X5VzLLXtJujqnBFGTyo2aqR9joXnt8 +``` + +下面是您可以使用的元数据文件示例: + +```json +{ + "name": "Kairos NFT", + "description": "gkaia frens! gazuaaaaa!!!", + "image": "https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmRvQc4wZCp6NF7dFL4ywiWTG7FSH3KKGUAkXGgsdYfcKi" +} +``` + +## 编写智能合约 + +在本节中,您将使用由 Chainlink CCIP 支持的 "烧钱-铸币 "模式来实现在区块链之间进行 NFT 传输的合约。 + +在项目的合约目录下新建一个名为 "CrosschainNFT.sol "的文件,并粘贴以下代码: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; +import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import {ERC721URIStorage} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; +import {ERC721Burnable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; +import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import {Client} from "@chainlink/contracts-ccip/contracts/libraries/Client.sol"; +import {IRouterClient} from "@chainlink/contracts-ccip/contracts/interfaces/IRouterClient.sol"; +import {IAny2EVMMessageReceiver} from "@chainlink/contracts-ccip/contracts/interfaces/IAny2EVMMessageReceiver.sol"; +import {OwnerIsCreator} from "@chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol"; +import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; +/** + * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. + * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. + * DO NOT USE THIS CODE IN PRODUCTION. + */ + // Source chain is Ethereum Sepolia + // Destination chain is Kairos Testnet +contract CrosschainNFT is ERC721, ERC721URIStorage, ERC721Burnable, IAny2EVMMessageReceiver, ReentrancyGuard, OwnerIsCreator { + using SafeERC20 for IERC20; + enum PayFeesIn { + Native, + LINK + } + error InvalidRouter(address router); + error OnlyOnEthereumSepolia(); + error NotEnoughBalanceForFees(uint256 currentBalance, uint256 calculatedFees); + error NothingToWithdraw(); + error FailedToWithdrawEth(address owner, address target, uint256 value); + error ChainNotEnabled(uint64 chainSelector); + error SenderNotEnabled(address sender); + error OperationNotAllowedOnCurrentChain(uint64 chainSelector); + struct crosschainNFTDetails { + address crosschainNFTAddress; + bytes ccipExtraArgsBytes; + } + uint256 constant ETHEREUM_SEPOLIA_CHAIN_ID = 11155111; + string tokenNFTURI = "https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmY1LZF8JHo2r3h4X5VzLLXtJujqnBFGTyo2aqR9joXnt8"; + IRouterClient internal immutable i_ccipRouter; + LinkTokenInterface internal immutable i_linkToken; + uint64 private immutable i_currentChainSelector; + uint256 private _nextTokenId; + mapping(uint64 destChainSelector => crosschainNFTDetails crosschainNFTPerChain) public s_chains; + event ChainEnabled(uint64 chainSelector, address xNftAddress, bytes ccipExtraArgs); + event ChainDisabled(uint64 chainSelector); + event CrossChainSent( + address from, address to, uint256 tokenId, uint64 sourceChainSelector, uint64 destinationChainSelector + ); + event CrossChainReceived( + address from, address to, uint256 tokenId, uint64 sourceChainSelector, uint64 destinationChainSelector + ); + modifier onlyRouter() { + if (msg.sender != address(i_ccipRouter)) { + revert InvalidRouter(msg.sender); + } + _; + } + modifier onlyOnEthereumSepolia() { + if (block.chainid != ETHEREUM_SEPOLIA_CHAIN_ID) { + revert OnlyOnEthereumSepolia(); + } + _; + } + modifier onlyEnabledChain(uint64 _chainSelector) { + if (s_chains[_chainSelector].crosschainNFTAddress == address(0)) { + revert ChainNotEnabled(_chainSelector); + } + _; + } + modifier onlyEnabledSender(uint64 _chainSelector, address _sender) { + if (s_chains[_chainSelector].crosschainNFTAddress != _sender) { + revert SenderNotEnabled(_sender); + } + _; + } + modifier onlyOtherChains(uint64 _chainSelector) { + if (_chainSelector == i_currentChainSelector) { + revert OperationNotAllowedOnCurrentChain(_chainSelector); + } + _; + } + constructor(address ccipRouterAddress, address linkTokenAddress, uint64 currentChainSelector) + ERC721("Cross Chain NFT", "XNFT") + { + if (ccipRouterAddress == address(0)) revert InvalidRouter(address(0)); + i_ccipRouter = IRouterClient(ccipRouterAddress); + i_linkToken = LinkTokenInterface(linkTokenAddress); + i_currentChainSelector = currentChainSelector; + } + function mint() external onlyOnEthereumSepolia { + uint256 tokenId = _nextTokenId++; + _safeMint(msg.sender, tokenId); + _setTokenURI(tokenId, tokenNFTURI); + } + function enableChain(uint64 chainSelector, address crosschainNFTAddress, bytes memory ccipExtraArgs) + external + onlyOwner + onlyOtherChains(chainSelector) + { + s_chains[chainSelector] = crosschainNFTDetails({crosschainNFTAddress: crosschainNFTAddress, ccipExtraArgsBytes: ccipExtraArgs}); + emit ChainEnabled(chainSelector, crosschainNFTAddress, ccipExtraArgs); + } + function disableChain(uint64 chainSelector) external onlyOwner onlyOtherChains(chainSelector) { + delete s_chains[chainSelector]; + emit ChainDisabled(chainSelector); + } + function crossChainTransferFrom( + address from, + address to, + uint256 tokenId, + uint64 destinationChainSelector, + PayFeesIn payFeesIn + ) external nonReentrant onlyEnabledChain(destinationChainSelector) returns (bytes32 messageId) { + string memory tokenUri = tokenURI(tokenId); + _burn(tokenId); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(s_chains[destinationChainSelector].crosschainNFTAddress), + data: abi.encode(from, to, tokenId, tokenUri), + tokenAmounts: new Client.EVMTokenAmount[](0), + extraArgs: s_chains[destinationChainSelector].ccipExtraArgsBytes, + feeToken: payFeesIn == PayFeesIn.LINK ? address(i_linkToken) : address(0) + }); + // Get the fee required to send the CCIP message + uint256 fees = i_ccipRouter.getFee(destinationChainSelector, message); + if (payFeesIn == PayFeesIn.LINK) { + if (fees > i_linkToken.balanceOf(address(this))) { + revert NotEnoughBalanceForFees(i_linkToken.balanceOf(address(this)), fees); + } + // Approve the Router to transfer LINK tokens on contract's behalf. It will spend the fees in LINK + i_linkToken.approve(address(i_ccipRouter), fees); + // Send the message through the router and store the returned message ID + messageId = i_ccipRouter.ccipSend(destinationChainSelector, message); + } else { + if (fees > address(this).balance) { + revert NotEnoughBalanceForFees(address(this).balance, fees); + } + // Send the message through the router and store the returned message ID + messageId = i_ccipRouter.ccipSend{value: fees}(destinationChainSelector, message); + } + emit CrossChainSent(from, to, tokenId, i_currentChainSelector, destinationChainSelector); + } + /// @inheritdoc IAny2EVMMessageReceiver + function ccipReceive(Client.Any2EVMMessage calldata message) + external + virtual + override + onlyRouter + nonReentrant + onlyEnabledChain(message.sourceChainSelector) + onlyEnabledSender(message.sourceChainSelector, abi.decode(message.sender, (address))) + { + uint64 sourceChainSelector = message.sourceChainSelector; + (address from, address to, uint256 tokenId, string memory tokenUri) = + abi.decode(message.data, (address, address, uint256, string)); + _safeMint(to, tokenId); + _setTokenURI(tokenId, tokenUri); + emit CrossChainReceived(from, to, tokenId, sourceChainSelector, i_currentChainSelector); + } + function withdraw(address _beneficiary) public onlyOwner { + uint256 amount = address(this).balance; + if (amount == 0) revert NothingToWithdraw(); + (bool sent,) = _beneficiary.call{value: amount}(""); + if (!sent) revert FailedToWithdrawEth(msg.sender, _beneficiary, amount); + } + function withdrawToken(address _beneficiary, address _token) public onlyOwner { + uint256 amount = IERC20(_token).balanceOf(address(this)); + if (amount == 0) revert NothingToWithdraw(); + IERC20(_token).safeTransfer(_beneficiary, amount); + } + function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) { + return super.tokenURI(tokenId); + } + function getCCIPRouter() public view returns (address) { + return address(i_ccipRouter); + } + function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721URIStorage) returns (bool) { + return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || super.supportsInterface(interfaceId); + } +} +``` + +### 代码演练 + +CrosschainNFT 是一种 ERC-721 合约,它集成了 Chainlink CCIP,可在区块链之间传输 NFT。 它会在源链上刻录 NFT,并用相同的 tokenId 和 tokenURI 在目标链上重新刻录。 该合约通过 enableChain 维护经批准的目标链注册表,依靠 Chainlink 路由器(IRouterClient)进行跨链消息传递,并支持以本地天然气代币或 LINK 支付费用。 + +主要功能 + +- 启用链 + +允许合约所有者注册目标区块链。 它会在 s_chains 映射中存储对应的 NFT 合约地址和 CCIP 参数,将链作为有效的传输目标列入白名单。 设置完成后,会发出 ChainEnabled 事件。 + +- 交叉链转移从 + +执行 NFT 跨链转移。 它首先检查目标链是否已启用,然后检索 NFT 元数据(tokenURI)并在源链上刻录令牌。 然后,它将建立一个包含转账详情的 CCIP 报文,计算所需费用,并以 LINK 或本地天然气支付。 一旦信息通过路由器发送,就会发出 CrossChainSent 事件来记录传输过程。 + +现在,"CrosschainNFT.sol "的核心流程已经清楚,让我们进入下一步。 + +## 编译智能合约 + +要编译智能合约,请运行 + +```bash +npx hardhat build +``` + +## 部署智能合约 + +在本节中,我们将配置必要的变量,然后在 Ethereum Sepolia(源链)和 Kairos Testnet(目的链)上部署 "CrosschainNFT.sol "合约。 + +### 使用加密密钥库 + +Hardhat 3 的优势之一是能将私钥和 RPC URL 等敏感值存储在加密的密钥库中,而不是纯文本文件中。 在本指南中,我们将为 Sepolia 和 Kairos 的 _PRIVATE_KEY_ 和 _RPC URL_ 加密。 + +**添加私人密钥** + +```bash +npx hardhat keystore set PRIVATE_KEY +``` + +第一次运行该命令时,Hardhat 会提示你为密钥存储创建一个密码。 每次添加或更新值时都需要这个密码。 + +**为每个网络添加 RPC URL** + +```bash +npx hardhat keystore set KAIROS_RPC_URL +npx hardhat keystore set SEPOLIA_RPC_URL +``` + +最后,编辑 `hardhat.config.ts` 文件,加载这些加密值并配置两个网络。 + +```typescript +import type { HardhatUserConfig } from "hardhat/config"; +import hardhatToolboxMochaEthersPlugin from "@nomicfoundation/hardhat-toolbox-mocha-ethers"; +import { configVariable } from "hardhat/config"; +const config: HardhatUserConfig = { + plugins: [hardhatToolboxMochaEthersPlugin], + solidity: { + profiles: { + default: { + version: "0.8.28", + }, + production: { + version: "0.8.28", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + }, + }, + networks: { + hardhatMainnet: { + type: "edr-simulated", + chainType: "l1", + }, + hardhatOp: { + type: "edr-simulated", + chainType: "op", + }, + kairosTestnet: { + type: "http", + chainType: "l1", + url: configVariable("KAIROS_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + ethereumSepolia: { + type: "http", + chainType: "l1", + url: configVariable("SEPOLIA_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + }, +}; +export default config; +``` + +下一步是分别在 Ethereum Sepolia 和 Kairos Testnet 上部署 CrosschainNFT 智能合约。 + +### 在以太坊 Sepolia 上部署 CrosschainNFT.sol + +部署前,从 [Chainlink CCIP Directory](https://docs.chain.link/ccip/directory/testnet/chain/ethereum-testnet-sepolia) 中获取以太坊 Sepolia 的以下值: + +- 链条选择器 +- CCIP 路由器地址 +- LINK 令牌地址 + +您的部署脚本将需要这些值。 接下来,导航到项目中的_ignition/modules_文件夹,创建一个名为 "deployEthereumSepolia.ts "的新文件,并粘贴以下代码: + +```typescript +// This setup uses Hardhat Ignition to manage smart contract deployments. +// Learn more about it at https://hardhat.org/ignition +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const ETHEREUM_SEPOLIA_ROUTER_ADDRESS = `0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59`; +const ETHEREUM_SEPOLIA_LINK_TOKEN_ADDRESS = `0x779877A7B0D9E8603169DdbD7836e478b4624789`; +const ETHEREUM_SEPOLIA_CHAIN_SELECTOR = `16015286601757825753`; +const CrosschainNFTSepoliaModule = buildModule("CrosschainNFTSepoliaModule", (m) => { + const crosschainNFTSepolia = m.contract("CrosschainNFT", [ETHEREUM_SEPOLIA_ROUTER_ADDRESS, ETHEREUM_SEPOLIA_LINK_TOKEN_ADDRESS, ETHEREUM_SEPOLIA_CHAIN_SELECTOR], { + }); + return { crosschainNFTSepolia }; +}); +export default CrosschainNFTSepoliaModule; +``` + +运行部署脚本: + +```bash +npx hardhat ignition deploy ignition/modules/deployEthereumSepolia.ts --network ethereumSepolia +``` + +### 将 CrosschainNFT.sol 部署到 Kairos 测试网 + +部署前,从 [Chainlink CCIP Directory](https://docs.chain.link/ccip/directory/testnet/chain/kaia-testnet-kairos) 中获取下列 Kairos Testnet 的值: + +- 链条选择器 +- CCIP 路由器地址 +- LINK 令牌地址 + +您的部署脚本将需要这些值。 然后,导航到项目中的 _ignition/modules_ 文件夹,创建一个名为 `deployKairosTestnet.ts` 的新文件,并粘贴以下代码: + +```typescript +// This setup uses Hardhat Ignition to manage smart contract deployments. +// Learn more about it at https://hardhat.org/ignition + +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const KAIROS_TESTNET_ROUTER_ADDRESS = `0x41477416677843fCE577748D2e762B6638492755`; +const KAIROS_TESTNET_LINK_TOKEN_ADDRESS = `0xAF3243f975afe2269Da8Ffa835CA3A8F8B6A5A36`; +const KAIROS_TESTNET_CHAIN_SELECTOR = `2624132734533621656`; +const CrosschainNFTKairosModule = buildModule("CrosschainNFTKairosModule", (m) => { + const crosschainNFTKairos = m.contract("CrosschainNFT", [KAIROS_TESTNET_ROUTER_ADDRESS, KAIROS_TESTNET_LINK_TOKEN_ADDRESS, KAIROS_TESTNET_CHAIN_SELECTOR], { + }); + return { crosschainNFTKairos }; +}); +export default CrosschainNFTKairosModule; +``` + +运行部署脚本: + +```bash +npx hardhat ignition deploy ignition/modules/deployKairosTestnet.ts --network kairosTestnet +``` + +## 与智能合约互动 + +在本节中,我们将分别通过执行 enableChain、mint 和 crosschainTransfer 函数与已部署的 CrosschainNFT 智能合约进行交互。 + +### 步骤 1:在以太坊 Sepolia 上,调用 enableChain + +在调用 enableChain 之前,请准备好以下值: + +- **Sepolia合约地址**:部署在以太坊Sepolia上的CrosschainNFT.sol合约的地址。 +- **Kairos 合约地址**:部署在 Kairos Testnet 上的 CrosschainNFT.sol 合约的地址。 +- **链选择器**:2624132734533621656(Kairos Testnet 的 CCIP 链选择器)。 +- **CCIP extraArgs**:0x97a657c900000000000000000000000000000000000000000007A120 (这是 extraArgs 的默认编码值,gasLimit 设置为 500,000)。 + +接下来,在脚本文件夹中新建一个 TypeScript 文件,命名为 "enableChainSepolia.ts",并粘贴以下代码: + +```typescript +// scripts/enableChainSepolia.ts +import { network } from "hardhat"; +async function main() { + const connection = await network.connect({ + network: "ethereumSepolia" + }); + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory by name + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + // Contract addresses and parameters + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + const crosschainNFTAddressKairosTestnet = `0x8c464Bb9Bf364F68b898ed0708b8f5F66EF6Cfb1`; + const chainSelectorKairosTestnet = `2624132734533621656`; + const ccipExtraArgs = `0x97a657c9000000000000000000000000000000000000000000000000000000000007A120`; + // Attach to the deployed contract + const crosschainNFTSepolia = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + console.log(`Enabling chain for Kairos Testnet...`); + const tx = await crosschainNFTSepolia.enableChain( + chainSelectorKairosTestnet, + crosschainNFTAddressKairosTestnet, + ccipExtraArgs + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Chain enabled successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +运行以下命令调用该函数: + +```bash +npx hardhat run scripts/enableChainSepolia.ts --network ethereumSepolia +``` + +### 步骤 2:在 Kairos Testnet 上,调用 enableChain + +在调用 enableChain 之前,请准备好以下值: + +- **Kairos合约地址**:部署在Kairos测试网上的CrosschainNFT.sol合约的地址 +- **Sepolia合约地址**:部署在以太坊Sepolia上的CrosschainNFT.sol合约的地址 +- **链选择器**:16015286601757825753 (Kairos Testnet 的 CCIP 链选择器) +- **CCIP extraArgs**:0x97a657c900000000000000000000000000000000000000000007A120 (这是 extraArgs 的默认编码值,气体限值设置为 500,000) + +接下来,在脚本文件夹中新建一个 TypeScript 文件,命名为 "enableChainKairos.ts",并粘贴以下代码: + +```typescript +// scripts/enableChainKairos.ts +import { network } from "hardhat"; +async function main() { + const connection = await network.connect({ + network: "kairosTestnet" + }); + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory by name + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + // Contract addresses and parameters + const crosschainNFTAddressKairosTestnet = `0x8c464Bb9Bf364F68b898ed0708b8f5F66EF6Cfb1`; + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + const chainSelectorEthereumSepolia = `16015286601757825753`; + const ccipExtraArgs = `0x97a657c9000000000000000000000000000000000000000000000000000000000007A120`; + // Attach to the deployed contract on Kairos + const crosschainNFTKairos = CrosschainNFT.attach(crosschainNFTAddressKairosTestnet); + console.log(`Enabling chain for Ethereum Sepolia...`); + const tx = await crosschainNFTKairos.enableChain( + chainSelectorEthereumSepolia, + crosschainNFTAddressEthereumSepolia, + ccipExtraArgs + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Chain enabled successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +运行以下命令调用该函数: + +```bash +npx hardhat run scripts/enableChainKairos.ts --network KairosTestnet +``` + +### 第 3 步:在以太坊 Sepolia 上使用 LINK 为合约提供资金 + +为支付 CCIP 费用,请使用 LINK 为部署在以太坊 Sepolia(crosschainNFTAddressEthereumSepolia)上的 CrosschainNFT 合约提供资金。 您可以从提供的 [水龙头](https://faucets.chain.link/sepolia) 中获取测试 LINK。 在本指南中,发送 3 个 LINK 即可。 + +![](/img/build/tutorials/cc-ccip-fund-link.png) + +### 步骤 4:在以太坊 Sepolia 上铸币一个新的 CrosschainNFT + +接下来,在部署到以太坊 Sepolia 的 CrosschainNFT 合约上创建一个新的 NFT。 + +在脚本文件夹中创建一个新的 TypeScript 文件,命名为 "mint.ts",并粘贴以下代码: + +```typescript +// scripts/mint.ts +import { network } from "hardhat"; +async function main() { + // Connect to the network + const connection = await network.connect({ + network: "ethereumSepolia" + }); +if (connection.networkName !== "ethereumSepolia") { + console.error(`Must be called from Ethereum Sepolia`); + process.exitCode = 1; + return; + } + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22` + // Attach to the deployed contract + const crosschainNFT = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + console.log(`Minting NFT...`); + const tx = await crosschainNFT.mint(); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`NFT minted successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +该脚本将处理铸币过程,并为跨链传输 NFT 做好准备。 + +运行以下命令调用该函数: + +```bash +npx hardhat run scripts/mint.ts --network ethereumSepolia +``` + +### 步骤 5:跨链转移 NFT + +在以太坊 Sepolia 上,您将调用 crossChainTransferFrom 函数将您的 NFT 发送到 Kairos Testnet。 + +准备以下值: + +- **来自**:您在以太坊 Sepolia 上的 EOA 地址 +- **收件人**\*:收件人在 Kairos Testnet 上的 EOA 地址(也可以是您自己的地址) +- **tokenId**:要转移的 NFT 的 ID +- **目标链选择器**:2624132734533621656(Kairos Testnet 的 CCIP 链选择器) +- **payFeesIn**:1(表示将在 LINK 中支付 CCIP 费用) + +运行传输脚本 + +在脚本文件夹中新建一个 TypeScript 文件,命名为 "crossChainTransferNFT.ts",并粘贴以下代码: + +```typescript +// scripts/crossChainTransferNFT.ts +import { network } from "hardhat"; +async function main() { + // Connect to the network + const connection = await network.connect({ + network: "ethereumSepolia" + }); + // Check if we're on the correct network + if (connection.networkName !== "ethereumSepolia") { + console.error(`Must be called from Ethereum Sepolia`); + process.exitCode = 1; + return; + } + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + // Transfer parameters + const from = `0x7b467A6962bE0ac80784F131049A25CDE27d62Fb`; + const to = `0x7b467A6962bE0ac80784F131049A25CDE27d62Fb`; + const tokenId = 0; // Put NFT token id here + const destinationChainSelector = "2624132734533621656"; // Kairos Testnet + const payFeesIn = 1; // 0 - Native, 1 - LINK + // Attach to the deployed contract + const crosschainNFT = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + const tx = await crosschainNFT.crossChainTransferFrom( + from, + to, + tokenId, + destinationChainSelector, + payFeesIn + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Cross-chain transfer initiated successfully!`); + console.log(`Note: The NFT will arrive on Kairos Testnet after CCIP processes the message.`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +然后用 + +```bash +npx hardhat run scripts/crossChainTransferNFT.ts --network ethereumSepolia +``` + +验证转移 + +您可以在 [CCIP Explorer](https://ccip.chain.link/#/side-drawer/msg/0x2a43cf8076ed6290dd0bf8bdbbc87abe2d238da43b6bf514e70909dd0f35c9db) 上监控跨链转账,在 [Kaiascan](https://kairos.kaiascan.io/nft/0x7dcdaa882603b1cfeee42d1c382a1ecba595d87c/0?tabId=nftTokenTransfer&page=1) 上确认交易。 + +![](/img/build/tutorials/cc-nft-ccip-explorer.png) + +![](/img/build/tutorials/cc-nft-ccip-kaiascan.png) + +NFT 到达 Kairos Testnet 后,将其添加到您的 MetaMask 钱包中: + +1. 在 MetaMask 中打开 NFT 选项卡。 +2. 单击导入 NFT。 +3. 输入 Kairos Testnet 上的 CrosschainNFT 合约地址和您收到的 tokenId(例如 0)。 + +现在,您的 NFT 将出现在 MetaMask 钱包中。 + +![](/img/build/tutorials/cc-ccip-mm-view-nft.png) + +## 结论 + +在本教程中,您将学习如何使用 Chainlink CCIP 在 Kaia Kairos Testnet 和 Ethereum Sepolia 之间使用烧毁和铸币模型传输 NFT。 + +要深入了解 CCIP 并探索其他用例,请访问官方[Chainlink CCIP Documentation](https://docs.chain.link/ccip)。 + + + + diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md index 574bb6619ee3..f4a922a0922c 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md @@ -79,5 +79,5 @@ SwapTx 将在链上失败,但由于**KIP-245 的原子捆绑**,整个捆绑 **教育内容:** -- [如果用稳定币支付汽油费会怎样?](https://medium.com/kaiachain/pay-for-gas-fees-with-any-token-a-deep-dive-into-kaias-trustless-gas-abstraction-d670355a096b) -- [凯亚共识流动性公告](https://medium.com/kaiachain/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity-7c8a7393cd19) \ No newline at end of file +- [如果用稳定币支付汽油费会怎样?](https://blog.kaia.io/pay-for-gas-fees-with-any-token-a-deep-dive-into-kaias-trustless-gas-abstraction/) +- [凯亚共识流动性公告](https://blog.kaia.io/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity/) \ No newline at end of file diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md index 0f92d2d9d3a9..d39f712d947e 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md @@ -45,4 +45,4 @@ Kaia 的新人在以下情况下往往会遇到困难: ## 1.4 与共识流动性 (CL) 的关系 -GA 最初是为了提高[共识流动性代币](https://medium.com/kaiachain/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity-7c8a7393cd19)的效用而设计的,允许用户使用 CL 代币(如 BORA、Swapscanner)支付天然气。 不过,该功能也可以支持其他 ERC-20 代币,包括稳定币。 \ No newline at end of file +GA 最初是为了提高[共识流动性代币](https://blog.kaia.io/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity/)的效用而设计的,允许用户使用 CL 代币(如 BORA、Swapscanner)支付天然气。 不过,该功能也可以支持其他 ERC-20 代币,包括稳定币。 \ No newline at end of file diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md new file mode 100644 index 000000000000..729aa3aec0c4 --- /dev/null +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md @@ -0,0 +1,479 @@ +--- +id: integrate-gas-free-usdt-kaia-swap +title: 将天然气自由美元兑美元纳入 KAIA 掉期交易 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# 将天然气自由美元兑美元纳入 KAIA 掉期交易 + +本指南概述了 Gas-Free USDT 到 KAIA Swap 功能,包括其目的、前提条件、集成步骤和 API 参考资料。 它旨在帮助开发人员将无气体交换功能集成到 Kaia 网络上的去中心化应用程序(DApps)中。 + +## 导言 + +推出了 "gasFreeSwapKaia "API,使用户能够在 Kaia 网络上执行无燃气的 ERC20 代币交换(目前仅限于 USDT),而无需持有 KAIA 代币支付燃气费,甚至无需代表用户支付交易成本。 该应用程序接口特别支持使用 ERC20 许可证签名将 USDT 交换为 KAIA,以实现完全无气体的用户体验。 + +### 益处 + +- **100%无气体验**:用户无需任何 KAIA 代币即可进行交换 +- **增强用户入职**:新用户无需获取 KAIA 即可立即开始交换代币 +- **ERC20 许可证集成**:使用标准 ERC20 许可证签名进行安全、无气体令牌审批 + +### 如何使用 + +- **用户启动交换**:用户选择USDT金额交换KAIA +- **前端创建许可证**:DApp 构建一个 ERC20 许可签名,供用户签署 +- **用户签署许可证**:用户签署许可信息(无需气体) +- **DApp 调用 API**:前端向应用程序接口发送交换参数和许可证签名 +- **后台执行**:API 验证许可证、执行交换并支付所有天然气费用 +- **用户收到 KAIA**:本地 KAIA 令牌直接发送到用户钱包 + +## 先决条件和支持的环境 + +**服务端点** + + + + https://fee-delegation.kaia.io + + + + https://fee-delegation-kairos.kaia.io + + + +**支持的令牌对** + +应用程序接口目前仅支持单一交易对: + + + + 代币输入: USDT (`0xd077a400968890eacc75cdc901f0356c943e4fdb`) + +``` +Token Out: WKAIA (`0x19aac5f612f524b754ca7e7c41cbfa2e981a4432`) +``` + + + + + 令牌输入: TEST (`0xcb00ba2cab67a3771f9ca1fa48fda8881b457750`) + +``` +Token Out: WKAIA (`0x043c471bEe060e00A56CcD02c0Ca286808a5A436`) +``` + + + + +**获取测试令牌** + +为 Kairos Testnet 获取 TEST 令牌: + +- 在 Kaiascan 上打开 [ERC20 水龙头](https://kairos.kaiascan.io/address/0x78a6cacfe5d34e0566e56710c8789d207411001a?tabId=contract&page=1) +- 转到 "合同 "选项卡,然后选择 "_撰写合同_"。 +- 找到 claim(token) 函数 +- 输入 Kairos 上受支持的 GA 令牌的地址(本指南使用 TEST 的地址) +- 单击 _Query_ 提交请求。 您将很快收到 TEST 令牌。 + +![](/img/build/tutorials/test-tokens-faucet.png) + +**智能合同要求** + +该应用程序接口与 GaslessERC20PermitSwap 智能合约交互: + +- 支持基于 ERC20 许可证的审批 +- 与兼容 Uniswap V2 的 DEX 集成 +- 自动将 WKAIA 转换为本地 KAIA +- 执行最大交换限制以确保安全 + +**用户要求** + +在主网上,用户必须拥有零 KAIA 余额才能使用这项无气交换服务。 这一要求可确保只有真正需要进行无煤气交易的用户才能使用该服务。 在测试网络中,出于测试目的,这一限制被放宽。 + +主网和测试网的最大交换金额均限制为 1 USDT。 因为该功能的目的是让用户获得足够的 KAIA 以开始他们在 Kaia Chain 上的体验。 + +## 整合步骤 + +### 完整集成示例 + +```javascript +const { JsonRpcProvider, Wallet } = require('@kaiachain/ethers-ext/v6'); +const { Contract, parseUnits, formatUnits, Signature } = require('ethers'); + +async function fetchJson(url, init) { + if (typeof fetch !== 'undefined') { + return fetch(url, init); + } + const { default: nodeFetch } = await import('node-fetch'); + return nodeFetch(url, init); +} + +const GASLESS_SWAP_ABI = [ + 'function usdtToken() view returns (address)', + 'function wkaiaToken() view returns (address)', + 'function maxUsdtAmount() view returns (uint256)', + 'function getExpectedOutput(address tokenIn, address tokenOut, uint256 amountIn) view returns (uint256)', + 'function executeSwapWithPermit(address user, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOutMin, uint256 deadline, uint8 v, bytes32 r, bytes32 s)', +]; + +const ERC20_METADATA_ABI = [ + 'function decimals() view returns (uint8)', + 'function symbol() view returns (string)', + 'function name() view returns (string)', + 'function nonces(address owner) view returns (uint256)', + 'function balanceOf(address owner) view returns (uint256)', +]; + +async function buildPermitSignature({ token, owner, spender, value, deadline, domainVersion = '1' }) { + const [name, version, network, verifyingContract, nonce] = await Promise.all([ + token.name(), + Promise.resolve(domainVersion), + owner.provider.getNetwork(), + token.getAddress(), + token.nonces(owner.address), + ]); + + const domain = { + name, + version, + chainId: Number(network.chainId), + verifyingContract, + }; + + const types = { + Permit: [ + { name: 'owner', type: 'address' }, + { name: 'spender', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'nonce', type: 'uint256' }, + { name: 'deadline', type: 'uint256' }, + ], + }; + + const message = { + owner: owner.address, + spender, + value, + nonce, + deadline, + }; + + return Signature.from(await owner.signTypedData(domain, types, message)); +} + +async function executeGaslessSwap({ + rpcUrl, + serverUrl, + userWallet, + contractAddress, + amountIn = '0.01', // Amount in USDT + slippageBps = 50, // 0.5% slippage + permitDeadlineSeconds = 600 // 10 minutes +}) { + console.log('🚀 Starting gasless swap'); + + const provider = new JsonRpcProvider(rpcUrl); + const wallet = userWallet.connect(provider); + const swap = new Contract(contractAddress, GASLESS_SWAP_ABI, provider); + + // Get token addresses from contract + const [tokenInAddress, tokenOutAddress, maxUsdtAmount] = await Promise.all([ + swap.usdtToken(), + swap.wkaiaToken(), + swap.maxUsdtAmount(), + ]); + + const tokenIn = new Contract(tokenInAddress, ERC20_METADATA_ABI, provider); + const tokenOut = new Contract(tokenOutAddress, ERC20_METADATA_ABI, provider); + + const [tokenInDecimals, tokenOutDecimals, tokenInSymbol, tokenOutSymbol] = await Promise.all([ + tokenIn.decimals(), + tokenOut.decimals(), + tokenIn.symbol(), + tokenOut.symbol(), + ]); + + const amountInWei = parseUnits(amountIn, tokenInDecimals); + + // Check if amount exceeds contract maximum + if (amountInWei > maxUsdtAmount) { + throw new Error(`Amount (${amountIn} ${tokenInSymbol}) exceeds contract cap (${formatUnits(maxUsdtAmount, tokenInDecimals)} ${tokenInSymbol})`); + } + + // Get expected output and calculate minimum with slippage + const expectedOut = await swap.getExpectedOutput(tokenInAddress, tokenOutAddress, amountInWei); + const amountOutMin = (expectedOut * BigInt(10_000 - slippageBps)) / 10_000n; + + // Create permit signature + const deadline = BigInt(Math.floor(Date.now() / 1000) + permitDeadlineSeconds); + const signature = await buildPermitSignature({ + token: tokenIn, + owner: wallet, + spender: contractAddress, + value: amountInWei, + deadline, + }); + + // Prepare API payload + const payload = { + swap: { + user: wallet.address, + tokenIn: tokenInAddress, + tokenOut: tokenOutAddress, + amountIn: amountInWei.toString(), + amountOutMin: amountOutMin.toString(), + deadline: deadline.toString(), + }, +permitSignature: signature.serialized, + }; + + console.log('From:', wallet.address); + console.log('Swap amount:', formatUnits(amountInWei, tokenInDecimals), tokenInSymbol); + console.log('Minimum out:', formatUnits(amountOutMin, tokenOutDecimals), tokenOutSymbol); + + // Check balance before swap + const balanceBefore = await provider.getBalance(wallet.address); + + // Call the API + const response = await fetchJson(`${serverUrl}/api/gasFreeSwapKaia`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + + const result = await response.json().catch(() => ({})); + console.log('HTTP status:', response.status); + console.log('Response:', JSON.stringify(result, null, 2)); + + if (response.ok && result.status) { + console.log('🎉 Gasless swap request succeeded'); + + // Check balance after swap + const balanceAfter = await provider.getBalance(wallet.address); + console.log('Balance before:', formatUnits(balanceBefore, 18), 'KAIA'); + console.log('Balance after:', formatUnits(balanceAfter, 18), 'KAIA'); + console.log('Balance difference:', formatUnits(balanceAfter - balanceBefore, 18), 'KAIA'); + + return result; + } else { + console.error('❌ Gasless swap request failed'); + throw new Error(`Swap failed: ${result.data || result.message || 'Unknown error'}`); + } +} + +// Usage example +async function main() { + try { + const userWallet = new Wallet('your_private_key'); + + const result = await executeGaslessSwap({ + rpcUrl: 'https://public-en-kairos.node.kaia.io', + serverUrl: 'https://fee-delegation-kairos.kaia.io', + userWallet: userWallet, + contractAddress: '0xaaFe47636ACe87E2B8CAaFADb03E87090277Ff7B', + amountIn: '0.002', + slippageBps: 50, + }); + + console.log('Transaction hash:', result.data.hash); + } catch (error) { + console.error('💥 Swap failed:', error.message); + } +} + +main(); +``` + +## API 参考端点 + +- URL:`/api/gasFreeSwapKaia`. +- 方法邮寄 +- Content-Type: 应用程序/json + +### 申请正文 + +```javascript +{ + "swap": { + "user": "0x742d35Cc6635C0532925a3b8D400e6D2A4b8E0bb", + "tokenIn": "0xcb00ba2cab67a3771f9ca1fa48fda8881b457750", + "tokenOut": "0x043c471bEe060e00A56CcD02c0Ca286808a5A436", + "amountIn": "1000000", + "amountOutMin": "950000000000000000", + "deadline": "1699123456" + }, + "permitSignature": "0x…65-byte signature string…" +} +``` + +### 参数 + +**交换**(对象,必填): + +- 用户(字符串):签署许可证的令牌所有者的地址 +- tokenIn(字符串):输入令牌的地址(必须与配置的 USDT 地址一致) +- tokenOut(字符串):输出令牌的地址(必须与配置的 WKAIA 地址一致) +- amountIn (字符串):以字符串形式表示的输入代币数量(以魏/最小单位表示) +- amountOutMin (字符串):最小预期产出代币(滑移保护) +- deadline (字符串):许可证和交换到期的 Unix 时间戳(秒数 + +**permitSignature** (字符串,必填): + +- 必须是 65 字节的有效十六进制字符串 +- 包含序列化的 ERC20 许可证签名 + +### 回复格式 + +#### 成功响应 (200) + +```javascript +{ + "message": "Request was successful", + "data": { + "_type": "TransactionReceipt", + "blockHash": "0x2a7ae196f6e7363fe3cfc79132c1d16292d159e231d73b4308f598a3222d1f57", + "blockNumber": 191523443, + "contractAddress": null, + "cumulativeGasUsed": "215000", + "from": "0x6C4ED74027ab609f506efCdd224041c9F5b5CDE1", + "gasPrice": "25000000000", + "gasUsed": "215000", + "hash": "0x0ca73736ceecf2dcf0ec2e1f65760d0b4f7348726cb9a0477710172b1dd44350", + "status": 1, + "to": "0x45bD04d5f14DD9AB908109cFEa816F758FaE6709", + "type": 49, + "feePayer": "0x1234567890abcdef1234567890abcdef12345678", + "feePayerSignatures": ["0x..."], + "logs": [ + { + "address": "0x...", + "topics": ["0x..."], + "data": "0x..." + } + ] + }, + "status": true, + "requestId": "req_abc123def456" +} +``` + +#### 错误回复 + +**400 Bad Request - Validation Errors:** + +```javascript +{ + "message": "Bad request", + "data": "Permit deadline has expired", + "error": "BAD_REQUEST", + "status": false, + "requestId": "req_error_123" +} +``` + +**400 错误请求 - 交易还原:** + +```javascript +{ + "message": "Bad request", + "data": "execution reverted: Permit already used", + "error": "BAD_REQUEST", + "status": false, + "requestId": "req_revert_456" +} +``` + +**500 内部服务器错误:**\* + +```javascript +{ + "message": "Internal server error", + "data": "Sending transaction was failed after 5 try, network is busy. Error message: Network timeout", + "error": "INTERNAL_ERROR", + "status": false, + "requestId": "req_error_789" +} +``` + +## 错误处理 + +### 常见错误情景 + +| 错误 | HTTP 状态 | 说明 | 解决方案 | +| ------------ | ------- | ----------------------------- | ------------------------------------------- | +| 缺少必填字段 | 400 | _swap_ 或 _permitSignature_ 丢失 | 包括所有必要参数 | +| 用户拥有 KAIA 余额 | 400 | 用户的 KAIA 余额必须为零 | 只有 KAIA 余额为零的用户才能使用此服务 | +| 签名格式无效 | 400 | 许可签名不是有效的十六进制字符串 | 提供有效的 65 字节十六进制签名 | +| 无效地址 | 400 | 畸形以太坊地址 | 验证地址是否有效 | +| 不支持的令牌 | 400 | 令牌不在允许列表中 | 仅使用配置的令牌地址 | +| 截止日期已过 | 400 | 过去的许可期限 | 使用未来时间戳 | +| 金额过大 | 400 | 超过合同最高限额 | 从合同中检查 _maxUsdtAmount()_ | +| 报价不足 | 400 | 滑动过于严格 | 提高滑动容差或减少滑动量 | +| 油价太高 | 400 | 网络拥塞 | 等待油价下降 | +| 网络超时 | 500 | RPC 提供商问题 | 延迟后重试请求 | + +## 安全考虑因素 + +### 天然气价格保护 + +当天然气价格超过 50 克韦时,API 会拒绝交易,以防止成本过高。 监控天然气价格,并在高拥堵时段通知用户。 + +### 签名安全 + +- 切勿重复使用许可证签名 +- 始终使用合理的截止时间(5-30 分钟) +- 签署前验证所有参数 +- 在所有应用程序接口通信中使用 HTTPS + +## 智能合约详情 + +### 无燃气 ERC20PermitSwap 合同地址 + + + + ``` + 0x45bD04d5f14DD9AB908109cFEa816F758FaE6709 + ``` + + + + ``` + 0xaaFe47636ACe87E2B8CAaFADb03E87090277Ff7B + ``` + + + +### 主要功能 + +**executeSwapWithPermit** - 使用许可证签名执行无气体交换: + +- 验证许可和交换参数 +- 使用许可证转移代币 +- 执行 DEX 交换 +- 将 WKAIA 转换为本地 KAIA +- 向用户发送本地 KAIA + +**getExpectedOutput** - 获取预期输出量的视图函数: + +```javascript +function getExpectedOutput( + address tokenIn, + address tokenOut, + uint256 amountIn +) external view returns (uint256) +``` + +### 合同限额 + +- 每次掉期的最大 USDT1,000,000(1 美元兑 6 位小数) +- 支持的货币对:USDT → WKAIA → 本地 KAIA +- 通过签名跟踪提供防重放保护 + +## 其他资源 + +- [ERC20 许可标准 (EIP-2612)](https://eips.ethereum.org/EIPS/eip-2612) +- [Kaia Ethers Extension](https://github.com/kaiachain/ethers-ext) + + diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md new file mode 100644 index 000000000000..dd3781c71faf --- /dev/null +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md @@ -0,0 +1,352 @@ +# Kaia MEV 拍卖 SDK 搜索指南 + +[Kaia v2.1.0](https://github.com/kaiachain/kaia/releases/tag/v2.1.0) 引入了 MEV 拍卖系统,使搜索者能够参与公平、透明的 MEV 机会拍卖。 本指南全面介绍了使用 Kaia MEV 拍卖 SDK 的搜索工作流程。 + +:::info + +本指南使用 Kairos 测试网络端点和合同地址。 主网计划于 2025 年 12 月中旬启动。 部署到主网时,相应更新所有端点和合同地址。 + +::: + +搜索工作流程包括四个主要步骤: + +![](/img/build/tutorials/searcher-guide-1.png) + +1. **存款**:搜索者将 KAIA 代币存入 "AuctionDepositVault "以资助竞拍活动 +2. **出价**:搜索者通过向拍卖师提交密封标书来竞争回跑时段 +3. **提交中标**:拍卖师选出中标者,并将中标结果转发给共识节点 (CN) +4. **执行竞标交易**:CN 通过 "AuctionEntryPoint "合同执行中标交易 + +详细技术背景见 [KIP-249](https://kips.kaia.io/KIPs/kip-249)。 + +## 先决条件 + +在开始之前,请确保您已 + +- 有 KAIA 代币存款的资金钱包 +- 为 SDK 示例安装了 [Go](https://golang.org/) (版本 1.25+)。 +- 访问 Kaia 网络端点(本指南使用 Kairos 测试网) +- (可选)已安装 [Foundry](https://getfoundry.sh/) (用于 `cast` 命令) + +**拍卖人终端:** + +- Kairos (testnet):`https://auctioneer-kairos.kaia.io`. +- 主网:`https://auctioneer.kaia.io` + +**探索者终端:** + +- Kairos (testnet):`https://mev-kairos.kaia.io`. +- 主网:`https://mev.kaia.io` + +**网络终端:** + +- Kairos (testnet):`https://public-en-kairos.node.kaia.io`. +- 主网:https://public-en.node.kaia.io + +**合同地址(凯罗斯):** + +- AuctionFeeVault: `0xE4e7d880786c53b6EA6cfA848Eb3a05eE97b2aCC` +- AuctionDepositVault: `0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc` +- AuctionEntryPoint: `0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480` + +有关主网合约地址(主网启动后可用),请查看 [Contract Addresses](../../references/contract-addresses.md)。 + +:::tip[Monitor MEV 机会] + +搜索者可以通过以下方式识别有利可图的交易 + +- **订阅拍卖商的待处理交易 API**:该应用程序接口可直接从共识节点流式传输交易,使您能够实时检测 MEV 机会。 请参阅下文[订阅待处理交易](#step-3-subscribe-to-pending-transactions) 部分。 +- **独立监控网络 mempool**:通过订阅待处理 tx,实现自己的 MEV 机会检测逻辑。 + +::: + +## 步骤 1:存款 + +![](/img/build/tutorials/searcher-guide-2.png) + +拍卖保证金金库 "保存着您的竞拍余额。 您的保证金必须包括投标金额和执行投标所需的预计燃气费。 + +### 了解存款要求 + +您的押金余额必须包括 + +- **出价金额**:您愿意为赢得拍卖支付的 KAIA +- **估计天然气费**:投标执行期间消耗的天然气(执行后扣除并发送给区块投标人) + +:::warning[Always 保持足够的存款余额] + +如果您的余额不足以支付出价金额和预计的汽油费,拍卖师将在确认时拒绝您的出价。 + +::: + +### 存款方法 + +合同规定了两种存款方式: + +**方法 1:"存款() "**\* + +使用发件人的余额存款。 存款记入汇款人账户。 + +```bash +# Deploy deposit of 200 KAIA +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "deposit()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 --value 200000000000000000000 +``` + +**方法 2:"depositFor(地址搜索器)"**\* + +代表另一个账户存款。 用于从单一来源资助多个搜索者地址。 + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "depositFor(address)" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 --value 200000000000000000000 +``` + +### 检查您的余额 + +查询当前存款余额: + +```bash +cast call 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "depositBalances(address)(uint256)" --rpc-url "https://public-en-kairos.node.kaia.io" +``` + +有关详细的存款示例,请参阅 [DEPOSIT.md guide](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/DEPOSIT.md)。 + +## 第 2 步:提交投标书 + +![](/img/build/tutorials/searcher-guide-3.png) + +一旦发现有利可图的交易,请向拍卖师提交竞标书。 出价是密封的(在拍卖结束前隐藏),并根据出价金额进行竞争。 + +### 投标结构 + +投标书由以下字段组成(如 [types.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/types.go) 中所定义): + +```go +type AuctionBid struct { + TargetTxRaw []byte // Raw transaction bytes of target tx + TargetTxHash common.Hash // Transaction to backrun + BlockNumber *big.Int // Target block number + Sender common.Address // Your searcher address + To common.Address // Contract to call + Nonce uint64 // Current nonce from AuctionEntryPoint + Bid *big.Int // Your bid in KAIA + CallGasLimit uint64 // Gas limit for your backrun logic + Data []byte // Encoded function call + SearcherSig []byte // EIP-712 signature from searcher +} +``` + +:::info + +您提交出价后,拍卖师会验证并添加自己的签名("AuctioneerSignature"),然后将中标出价转发给共识节点。 您只需提供 `SearcherSig`(您的 EIP-712 签名)。 + +::: + +### 提交投标书 + +SDK 在 [`example/submitbid.go`](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go) 中提供了一个完整的工作示例。 示例说明 + +- 与拍卖商建立 HTTPS 连接 +- 从 EN 端点检测新区块 +- 生成目标交易和相应出价 +- 向拍卖师提交标书 + +**需要采取的行动**:运行代码前,请在代码中替换您的私人密钥。 检查源代码中的 "TODO: "注释。 + +运行示例: + +```bash +# From repository root +go run example/submitbid.go +``` + +### 投标验证 + +拍卖人、投标人和智能合约各自对出价进行特定的验证检查。 主要验证规则包括 + +- **区块编号**:必须为 currentBlockNumber + 1 或 currentBlockNumber + 2 +- **出价金额**:必须大于 0 且小于或等于您的可用存款余额 +- **调用数据大小**:不得超过 `BidTxMaxDataSize` (64KB) +- **呼叫气体限制**:不得超过 `BidTxMaxCallGasLimit` (10,000,000) +- **nonce**:必须与您在 `AuctionEntryPoint` 中的当前 nonce 匹配。 查询时使用 + ```bash + cast call 0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480 "nonces(address)(uint256)" --rpc-url "https://public-en-kairos.node.kaia.io" + ``` +- **签名**:必须是有效的 EIP-712 签名(请参阅 [submitbid.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go) 以了解实施情况) +- **保证金覆盖范围**:必须有足够的保证金来支付 "投标金额 + 估计燃气费 +- **唯一性**:同一区块内不能有其他中标(除非针对同一交易) +- **拍卖人签名**:必须有效(由拍卖师在您提交后添加) + +有关哪个实体执行哪些检查的完整验证矩阵,请参阅[投标验证指南](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/bid_validation.md)。 + +## 步骤 3:订阅待处理交易 + +![](/img/build/tutorials/searcher-guide-4.png) + +Auctioneer 提供 WebSocket 订阅服务,可直接从共识节点流式传输待处理交易。 这样,搜索人员就能实时发现 MEV 机会。 + +SDK 在 [example/subscribe_pendingtx.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/subscribe_pendingtx.go) 中提供了一个完整的示例。 + +示例说明 + +- 建立与拍卖商的 WebSocket 连接 +- 订阅待处理交易流 +- 处理收到的交易以确定 MEV 机会 + +运行示例: + +```bash +# From repository root +go run example/subscribe_pendingtx.go +``` + +当检测到待处理交易时,订阅会持续打印交易哈希值。 您可以扩展本示例,实现自己的 MEV 检测逻辑。 + +## 步骤 4:了解执行 + +当您的出价获胜时,共识节点会通过 "AuctionEntryPoint "合约执行您的出价: + +![](/img/build/tutorials/searcher-guide-1.png) + +### 执行流程 + +执行过程包括三个阶段: + +1. **验证阶段**:合同验证区块号、签名、Nonce 和投标金额 +2. \*\* 投标付款阶段\*\*:从您的保证金中扣除投标金额并将其发送至生态系统基金 +3. **执行阶段**:您的反向运行由 EntryPoint 合同执行(无论执行结果如何,都会支付竞标款) + +**主要安全功能:** + +- 验证器代表您执行竞标(防止撤回竞标以逃避付款) +- Nonce 增量可防止重放攻击 +- 双重签名(搜索者 + 拍卖者)未经授权替换或操纵出价 +- 出价付款与回转执行结果无关 + +详细执行流程请参见 [ENTRYPOINT.md guide](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/ENTRYPOINT.md)。 + +## 步骤 5:提取资金 + +![](/img/build/tutorials/searcher-guide-5.png) + +提款需要两个步骤,并有锁定期: + +### 1. 储备金提取 + +启动提款并开始 60 秒锁定期: + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "reserveWithdraw()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 +``` + +### 2. 完全退出 + +60 秒后,转账预留金额: + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "withdraw()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 +``` + +:::info[Security 说明] + +有锁定期的两步提款程序: + +- 防止在拍卖活动期间闪退 +- 通过确保搜索者遵守出价,维护协议的完整性 +- 防止快速资本操纵攻击 + +::: + +## 应用程序接口参考 + +拍卖商为搜索者提供两个主要的应用程序接口: + +**1. 提交投标宣传短片**\* + +- **终端**:POST /api/v1/auction/send +- **目的**:为 MEV 机会提交密封投标 + +**2. 待处理交易订阅** + +- **终点**:GET /api/v1/subscriber/pendingtx +- **目的**:来自共识节点的待处理交易实时流 +- **示例**:请参阅 [subscribe_pendingtx.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/subscribe_pendingtx.go) 中的实现示例。 + +**完整的应用程序接口文档:** + +- OpenAPI (Swagger) 规范可从以下网址获取: + - **Kairos**: https://auctioneer-kairos.kaia.io/docs + - **主网**:主网启动后可用 +- API 使用:[API 文档](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/api_doc.md) + +## 故障排除 + +### 常见问题 + +| 问题类别 | 症状 | 原因 | 解决方案 | +| ---------- | ---------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | +| **余额不足** | 被拍卖商拒绝的出价 | 押金余额不包括出价金额 + 预计汽油费 | 使用 `depositBalances()` 查看余额并存入更多 KAIA | +| **不匹配** | 投标被拒绝或执行失败 | Nonce 与 `AuctionEntryPoint` 中的当前 nonce 不匹配 | 在每次出价前使用 `nonces()` 查询当前的 nonce。 记住:非ces 只在执行时递增,而不是在提交时递增 | +| **街区编号范围** | 被拍卖商拒绝的出价 | 目标块超出允许范围`[current+1, current+allowFutureBlock]` | 确保区块编号在范围内(通常为 +1 或 +2)。 请参阅常见问题,了解双重提交战略 | +| **无效签名** | 被拍卖商拒绝的出价 | 不正确的 EIP-712 签名结构 | 验证域分隔符和类型散列。 正确执行请参考 [submitbid.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go) | +| **气体限值问题** | 执行失败或投标被拒绝 | 调用气体上限 "过低或超过上限 (10,000,000) | 在测试网上测试反向运行逻辑,以测量实际耗气量 | + +## 常见问题 + +### 订阅 + +\*\*问:每个搜索器允许多少并发连接? + +答:每个搜索器地址只允许有一个待处理交易订阅连接。 + +\*\*问:订阅连接的有效期有多长? + +答:连接在 24 小时后自动关闭。 请注意,如果正在进行滚动更新,连接可能会提前 24 小时关闭。 + +### 应用程序接口性能和延迟 + +\*\*问:在提交投标时,如何尽量减少应用程序接口延迟? + +答:拍卖商使用的是带有 HTTPS 协议的 L7 负载平衡器。 初始握手耗时取决于网络状态。 要绕过发送后续竞标 API 时的初始延迟,强烈建议建立保持连接。 + +\*\*问:我是否应该注意 API 速率限制? + +答:为防止被 Auctioneer API 服务器阻止,请不要在短时间内多次发送 `ping` API。 + +\*\*问:地理位置是否会影响延迟? + +答:是的。 拍卖师服务器在 GCP KR(首尔)地区运行。 建议您将基础架构托管在地理位置较近的区域,以最大限度地减少延迟和地理延迟。 + +### 竞价时机和区块目标 + +\*\*问:为什么我的投标有时会针对错误的区块编号? + +答:您提交投标的时间对 CN(共识节点)的开采时间非常敏感。 如果拍卖开始较晚(接近开采时间),出价交易将被插入下一个区块之后(区块编号 +2 而不是 +1)。 这意味着您应该将目标块编号设置为 +2。 + +\*\*问:如何提高投标包含率? + +答:目标区块编号对 CN 挖矿时间表有固有的敏感性:如果您的目标区块编号是 +2,但由于处理时间较早,交易插入的区块编号是 +1,那么竞标就会失败。 因此,建议通过两次发送竞价交易来最大限度地提高包含概率:一次目标区块编号为 +1,另一次目标区块编号为 +2。 + +## 最佳做法 + +- **监控存款余额**:保持足够的余额以支付多次投标 +- \*\* 小心处理 Nonces\*\*:出价前一定要查询最新的 nonce +- **优化检测**:加快 MEV 检测速度,提高竞争优势 +- **在 Kairos 上进行测试**:在部署主网之前在测试网上验证您的策略 +- **监控结果**:通过 MEV Explorer 跟踪拍卖结果,完善您的竞价策略 +- \*\* 设置适当的气体限值\*\*:兼顾充足气体和成本效益 + +## 资源 + +- [SDK资源库](https://github.com/kaiachain/auctioneer-sdk) +- [KIP-249规范](https://kips.kaia.io/KIPs/kip-249) +- [示例代码](https://github.com/kaiachain/auctioneer-sdk/tree/dev/example) +- API 文档:[auctioneer-kairos.kaia.io/docs](https://auctioneer-kairos.kaia.io/docs) (Kairos), TBU (Mainnet) +- MEV 浏览器:[mev-kairos.kaia.io](https://mev-kairos.kaia.io) (Kairos), TBU (Mainnet) +- [常见问题](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/FAQ.md) + +## 获取帮助 + +有关问题或疑问: + +- 在 [Kaia DevForum](https://devforum.kaia.io) 发表文章 +- 在 [SDK 资源库] 中打开一个问题(https://github.com/kaiachain/auctioneer-sdk/issues) diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md new file mode 100644 index 000000000000..7b5bc13bdbcd --- /dev/null +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md @@ -0,0 +1,325 @@ +# 如何使用 Pyth 在 Kaia 上获取实时价格 + +## 介绍 + +Pyth 是一个去中心化的神谕网络,它在主要由推式神谕驱动的生态系统中采用了一种独特的方法。 Pyth 不需要以固定的时间间隔向合同推送数据,而是允许你按需提取真实世界的数据。 这种模式为开发人员提供了更多控制权,有助于避免不必要的链上更新。 通过这种集成,开发人员可以获取实时数据,并使用按使用付费的模式,即只有在请求更新时才收费。 + +在本指南中,您将学习如何使用 Pyth 的实时价格馈送来读取法定货币 IDR 的价值。 您的 Solidity 智能合约将使用 [pyth-sdk-solidity](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity) 从 Pyth 获取美元/印尼盾价格,您将使用 [hermes-client](https://github.com/pyth-network/pyth-crosschain/tree/main/apps/hermes/client/js) 更新并获取最新价格。 + +为了快速入门,您可以在 [GitHub](https://github.com/ayo-klaytn/pyth-kaia-hardhat-example) 上找到本教程的完整代码。 这为您提供了随时可用的参考资料,帮助您更快地设置项目和安装。 + +## 要求 + +在开始之前,请确保具备以下条件: + +- [Node.js 和 npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) + + 需要安装依赖项和运行开发工具。 + +- 由 KAIA 测试网络代币出资的钱包。 + + 您需要 KAIA 来支付 Kairos 测试网络的部署和交易气体费用。 您可以从 [Kaia 水龙头] (https://faucet.kaia.io/) 申请免费测试网络 KAIA。 + +## 设置开发环境 + +在本节中,您将设置开发环境,编译 Oracle 合同,并准备使用 Hardhat 进行部署。 + +**1. 创建硬头巾项目** + +为项目创建一个新目录并初始化 Hardhat: + +```bash +mkdir pyth-kaia-hardhat-example && cd pyth-kaia-hardhat-example +npm init -y +npx hardhat@next --init +``` + +根据提示接受默认回复。 在本指南中,我们将使用摩卡和以太模板。 + +通过检查 Hardhat 版本来验证您的安装: + +```bash +npx hardhat --version +``` + +**2. 设置加密机密** + +现在,您将使用 Hardhat 的加密密钥库存储 RPC URL 和私人密钥。 + +运行以下命令 + +```bash +npx hardhat keystore set KAIROS_RPC_URL +npx hardhat keystore set PRIVATE_KEY +``` + +确保为每个变量输入密码和值,以保持加密。 + +**3. 配置文件中的参考秘诀** + +打开 `hardhat.config.ts`,更新网络部分以引用加密机密。 如果使用了不同的密钥名称,请相应更新密钥。 + +```typescript +import { configVariable } from "hardhat/config"; +module.exports = { + networks: { + kairos: { + url: configVariable("KAIROS_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + }, +}; +``` + +## 创建合约并从 Pyth Oracles 获取价格 + +在本节中,您将安装 [Pyth Solidity SDK](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity),创建一个 PriceConsumer 合约,并使用 Hardhat 进行部署。 该合约将读取 Pyth 价格源,稍后你将使用从 Hermes 获取的价格数据对其进行更新。 + +### 安装 Pyth SDK + +Pyth 提供了一个 Solidity SDK,可让您与链上 Pyth 价格反馈合约进行交互。 SDK 公开了 IPyth 接口和相关结构。 + +使用 npm 安装 SDK: + +```bash +npm install --save-dev @pythnetwork/pyth-sdk-solidity +``` + +### 创建 PriceConsumer 合同 + +在 `contracts/PriceConsumer.sol` 中创建一个新文件,并添加以下代码: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; +import "@pythnetwork/pyth-sdk-solidity/IPyth.sol"; +import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol"; +contract PriceConsumer { + IPyth public pyth; + constructor(address pythContract) { + pyth = IPyth(pythContract); + } + function updatePrice(bytes[] calldata priceUpdateData) + external + payable + { + // Pay the Pyth fee for receiving price updates + uint fee = pyth.getUpdateFee(priceUpdateData); + require(msg.value >= fee, "Not enough fee sent"); + // Update the Pyth price state + pyth.updatePriceFeeds{value: fee}(priceUpdateData); + // Can fetch the price and use it as well + //PythStructs.Price memory currentBasePrice = pyth.getPriceNoOlderThan(priceFeedId, 60); + } + function getLatestPrice(bytes32 priceFeedId) public view returns (int64, int32) { + // Read the current price from a price feed if it is less than 60 seconds old. + // Each price feed (e.g., USD/IDR) is identified by a price feed ID. + // The complete list of feed IDs is available at https://docs.pyth.network/price-feeds/price-feeds + PythStructs.Price memory currentBasePrice = pyth.getPriceNoOlderThan(priceFeedId, 60); + + // uint256 basePrice = PythUtils.convertToUint( + // currentBasePrice.price, + // currentBasePrice.expo, + // 18 + // ); + + return (currentBasePrice.price, currentBasePrice.expo); + } +} +``` + +**走过** + +价格消费者合同: + +- 从 `@pythnetwork/pyth-sdk-solidity` 导入 Pyth 接口和结构体。 +- 商店 + - Pyth 合约实例 (pyth)。 + - 美元/印度卢比的价格输入 ID (usdIdrPriceId)。 +- Exposes `updateAndGetUsdIdrPrice`, which: + - 使用 IPyth.getUpdateFee 计算更新费用。 + - 调用 IPyth.updatePriceFeeds,输入所需费用。 + - 调用 IPyth.getPriceNoOlderThan 读取新的美元/印度卢比价格。 + - 返回原始价格、指数和发布时间。 + +稍后,您的离链爱马仕客户端将建立 priceUpdate 字节数组,并在需要新价格时将其传入此函数。 + +### 编制合同 + +运行以下命令编译合同 + +``` +npx hardhat compile +``` + +## 部署合同 + +要部署 PriceConsumer 合同,需要创建一个 Ignition 模块,然后运行部署命令。 + +**创建点火模块** + +在 `ignition/modules/PriceConsumer.ts` 创建一个新文件: + +```typescript +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const pythContractAddress = "0x2880ab155794e7179c9ee2e38200202908c17b43"; +export default buildModule("PriceConsumerModule", (m) => { + const priceConsumer = m.contract("PriceConsumer", [pythContractAddress]); + return { priceConsumer }; +}); +``` + +**部署合同** + +使用 Ignition 模块将 PriceConsumer 合同部署到 Kairos 测试网络: + +```bash +npx hardhat ignition deploy --network kairos ignition/modules/PriceConsumer.ts +``` + +出现提示时,输入先前为加密机密配置的密钥库密码。 + +完成上述操作后,您的 "PriceConsumer.sol "合约就会部署到 Kairos 测试网上,并准备好从 Pyth 消费实时美元/印尼盾价格。 + +## 从 TypeScript 互动 + +在最后一步,您将使用 TypeScript 与已部署的 PriceConsumer 合约交互。 该脚本将通过 Hermes 客户端请求 Pyth 价格更新数据,并在链上发送,从而获取最新的美元/印尼盾价格。 + +**安装依赖项** + +安装所需的软件包: + +```bash +npm install --save-dev tsx @pythnetwork/hermes-client @dotenv +``` + +\*\* 设置 .env\*\* + +在项目根目录下创建 .env 文件,并添加私人密钥: + +```bash +PRIVATE_KEY="0xDEAD....." // REPLACE WITH YOUR PRIVATE KEY +``` + +**创建交互脚本** + +在 **scripts/interact.ts**创建一个新文件,并添加以下内容: + +```typescript +import { HermesClient } from "@pythnetwork/hermes-client"; +import { ethers } from "ethers"; +import 'dotenv/config' + +// 1. Setup +const hermes = new HermesClient("https://hermes.pyth.network"); +const provider = new ethers.JsonRpcProvider( + "https://public-en-kairos.node.kaia.io" +); + +const PK = process.env.PRIVATE_KEY; +const wallet = new ethers.Wallet(PK, provider); + + +// 2. Your deployed contract +const priceConsumerAddress = "0x91e89aa32224dEd5dA483a83a4de45bF4bE57caA"; // REPLACE WITH DEPLOYED PRICE CONSUMER CONTRACT + +const priceConsumerAbi = [ + "function updatePrice(bytes[] priceUpdateData) external payable", + "function getLatestPrice(bytes32 priceId) public view returns(int64, int32)", +]; + +const priceConsumer = new ethers.Contract( + priceConsumerAddress, + priceConsumerAbi, + wallet +); + +// 3. Price feed IDs +const priceId = + "0x6693afcd49878bbd622e46bd805e7177932cf6ab0b1c91b135d71151b9207433"; // FX.USD/IDR Beta Price Feed ID + +async function run() { + // Fetch Hermes price update binary + const update = await hermes.getLatestPriceUpdates([priceId], { + encoding: "hex", + }); + console.log(update); + + const priceUpdateData = ["0x" + update.binary.data]; // must be array of bytes + + console.log(priceUpdateData); + + // Estimate fee required by Pyth contract + // EVM Network Price Feed Contract Addresses: https://docs.pyth.network/price-feeds/core/contract-addresses/evm + + const pythContractAddress = "0x2880ab155794e7179c9ee2e38200202908c17b43"; + const pythAbi = [ + "function getUpdateFee(bytes[] calldata data) external view returns(uint)", + ]; + console.log("Pyth contract address:", pythContractAddress); + const pyth = new ethers.Contract(pythContractAddress, pythAbi, wallet); + const fee = await pyth.getUpdateFee(priceUpdateData); + console.log("Pyth fee:", fee.toString()); + + // Call your contract + const tx = await priceConsumer.updatePrice(priceUpdateData, { + value: fee, // pay the pyth update fee + gasLimit: 500000, + }); + console.log("Tx sent:", tx.hash); + const receipt = await tx.wait(); + console.log("Tx confirmed"); + console.log(receipt); + + // 4. Get latest price from contract + try { + console.log("=== Latest Price from Contract ==="); + const [price, expo] = await priceConsumer.getLatestPrice(priceId); + console.log("Price Value : " + price.toString()); + console.log("Exponent Value : " + expo.toString()); + } catch (error) { + console.log(error); + // @ts-ignore + console.error("\nError calling getLatestPrice:", error.message); + console.log( + "This usually means the price is older than 60 seconds or hasn't been updated yet." + ); + console.log("Make sure updatePrice() was called successfully first."); + } +} +run(); + +``` + +**剧本** + +用以下命令执行脚本 + +```bash +npx tsx scripts/interact.ts +``` + +**输出示例** + +```bash +Tx sent: 0x79c5dcb7abd9605b070bf9062ba2e2382272d23d58f7b50446c3107b7784fc8e +Tx confirmed +=== Latest Price from Contract === +Price Value : 1669784988 +Exponent Value : -5 +======== —— ========= +``` + +在搜索栏中粘贴交易哈希值,即可在 Kairos 浏览器上验证您的交易。 这证明更新和读取操作均已成功。 + +## 结论 + +在本教程中,你创建了一个从 Pyth 读取实时价格的 Solidity 合约,将其部署到 Kairos 测试网络,并使用 Hermes 客户端与之交互。 您还了解到 Pyth 基于拉动的设计如何让您控制价格更新的时间和方式。 + +欲了解更多信息,请浏览 + +- Pyth API 的 [EVM 合同参考](https://api-reference.pyth.network/price-feeds/evm/getPriceNoOlderThan) +- [Pyth Oracle AMM 示例](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/evm)用于完整的端到端实施 + + + diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md index ba29fcfc2909..8bfbfb4149e4 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md @@ -190,6 +190,7 @@ Kaia 有一个未经验证的区块执行时间限制。 由于执行时间无 | TSTORE | 280 | | TLOAD | 220 | | MCOPY | 250 | +| CLZ | 0 | ## Precompiled contracts computation cost table @@ -201,7 +202,7 @@ Kaia 有一个未经验证的区块执行时间限制。 由于执行时间无 | 0x02 | sha256hash | numOfWords(input) / 32 \* 100 + 1,000 | | 0x03 | ripemd160hash | numOfWords(input) / 32 \* 10 + 100 | | 0x04 | dataCopy | 0 | -| 0x05 | bigModExp | 查看代码 [此处](https://github.com/kaiachain/kaia/blob/75c149a464998eb946311f3a290d4b1ea339eaba/blockchain/vm/contracts.go#L340) | +| 0x05 | bigModExp | 查看代码 [here](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L586) | | 0x06 | bn256Add | 8,000 | | 0x07 | bn256ScalarMul | 100,000 | | 0x08 | bn256Pairing | numOfPairings(input) \* 1,000,000 + 2,000,000 | @@ -210,13 +211,23 @@ Kaia 有一个未经验证的区块执行时间限制。 由于执行时间无 | 0x3FD | vmLog | 10 | | 0x3FE | feePayer | 10 | | 0x3FF | validateSender | numOfSigs(input) \* 180,000 + 10,000 | +| 0x0b | bls12381G1Add | 18,750 | +| 0x0c | bls12381G1MultiExp | 查看代码 [here](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L1155) | +| 0x0d | bls12381G2Add | 30,000 | +| 0x0e | bls12381G2MultiExp | 查看代码 [here](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L1261) | +| 0x0f | bls12381配对 | 配对数(输入)\* 1,630,000 + 1,885,000 | +| 0x10 | bls12381MapG1 | 275,000 | +| 0x11 | bls12381MapG2 | 1,190,000 | +| 0x100 | p256验证 | 235,000 | ## Hardfork Changes -| Hardfork | New items | Changes | | | -| ------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | - | -| Cancun EVM | BLOBBASEFEE (0x49)
BLOBHASH (0x50)
TSTORE (0x5c) opcode
TLOAD (0x5d)
MCOPY (0x5e)
kzg (0x0a) precompiled contract | 提高计算成本限制
从 100,000,000 提高到 150,000,000

降低某些操作码的计算成本
由于 CPU 性能提高
-Sdiv (0x05):739 -> 360
-Mod (0x06):812 -> 320
-Addmod (0x08):1410 -> 360
-Mulmod (0x09):1760 -> 700
-Exp (0x0A):5000 -> 720
-Sha3 (0x20): 2465 -> 560
-Mstore8 (0x53):5142 -> 230
-Log1, Log2, Log3, Log4 (0xA1-0xA4):1000 -> 500

由于数据库大小增加,某些操作码的计算成本会增加

-SLOAD (0x54):835 -> 2550
-SSTORE (0x55):1548 -> 2510 | | | -| Shanghai EVM | PUSH0 (0x5f) opcode | | | | -| Kore | | modExp (0x05) 预编译合同
使用新的气体计算逻辑。
计算成本也受到影响。
更加准确。 | | | -| London EVM | BaseFee (0x48) opcode | | | | -| Istanbul EVM | CHAINID (0x46) opcode
SELFBALANCE (0x47) opcode
blake2f (0x09) precompiled contract | 降低过高操作码的计算成本
- ADDMOD (0x08):3349 -> 1410
- MULMOD (0x09):4757 -> 1760
- XOR (0x18):657 -> 454
- NOT (0x19):1289 -> 364
- SHL (0x1B): 1603 -> 478
- SHR (0x1C):1815 -> 834 | | | +| Hardfork | New items | Changes | +| ------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 大阪电子记录仪 | CLZ (0x1e) 操作码
p256Verify (0x100) 预编译合同 | modExp (0x05) 预编译合同
使用新的气体计算逻辑。
计算成本也受到影响。
更加准确。 | +| 布拉格 EVM | bls12381G1Add (0x0b) 预编译合同
bls12381G1MultiExp (0x0c) 预编译合同
bls12381G2Add (0x0d) 预编译合同
bls12381G2MultiExp(0x0e) 预编译合同
bls12381Pairing (0x0f) 预编译合同
bls12381MapG1 (0x10) 预编译合同
bls12381MapG2 (0x11) 预编译合同
| | +| Cancun EVM | BLOBBASEFEE (0x49) 操作码
BLOBHASH (0x50) 操作码
TSTORE (0x5c) 操作码
TLOAD (0x5d) 操作码
MCOPY (0x5e) 操作码
kzg (0x0a) 预编译合同 | 提高计算成本限制
从 100,000,000 提高到 150,000,000

降低某些操作码的计算成本
由于 CPU 性能提高
-Sdiv (0x05):739 -> 360
-Mod (0x06):812 -> 320
-Addmod (0x08):1410 -> 360
-Mulmod (0x09):1760 -> 700
-Exp (0x0A):5000 -> 720
-Sha3 (0x20): 2465 -> 560
-Mstore8 (0x53):5142 -> 230
-Log1, Log2, Log3, Log4 (0xA1-0xA4):1000 -> 500

由于数据库大小增加,某些操作码的计算成本会增加

-SLOAD (0x54):835 -> 2550
-SSTORE (0x55):1548 -> 2510 | +| Shanghai EVM | PUSH0 (0x5f) opcode | | +| Kore | | modExp (0x05) 预编译合同
使用新的气体计算逻辑。
计算成本也受到影响。
更加准确。 | +| London EVM | BaseFee (0x48) opcode | | +| Istanbul EVM | CHAINID (0x46) opcode
SELFBALANCE (0x47) opcode
blake2f (0x09) precompiled contract | 降低过高操作码的计算成本
- ADDMOD (0x08):3349 -> 1410
- MULMOD (0x09):4757 -> 1760
- XOR (0x18):657 -> 454
- NOT (0x19):1289 -> 364
- SHL (0x1B): 1603 -> 478
- SHR (0x1C):1815 -> 834 | diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md index b3de4d71d77d..9865b499247a 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md @@ -34,7 +34,7 @@ Kaia 的 `callTracer` 输出格式与 go-ethereum 完全相同,但以下内容除外: -- 对于受尊敬的交易,这两个字段都会提供。 +- 对于反向交易,两个字段都提供。 - result.revertReason\`:还原原因字符串(如果有)。 - result.revoted.contract\`:已还原合同的地址。 - result.revted.message:与 revertReason 相同 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md new file mode 100644 index 000000000000..1d118a749058 --- /dev/null +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md @@ -0,0 +1,107 @@ +# 存储优化 + +随着 Kaia 区块链的增长,存储区块链数据所需的存储空间也在增长。 Kaia 采用两种主要技术来管理这种不断增长的存储需求: + +## 状态批量修剪(状态迁移) + +状态迁移是一种批量剪枝功能,可在不中断运行节点的情况下应用于现有节点。 + +### 动机 + +区块状态或 StateDB 将链上账户和合约存储在一个 trie 数据结构中。 trie 数据结构可存储过时和最新状态,以便使用梅克尔散列进行验证。 随着事务执行状态更改,状态三元组会无限增长。 截至发稿时(2024 年 8 月),Kaia 主网存档节点大小超过 20TB,甚至完整节点也超过 10TB。 + +### 概念 + +状态迁移会删除处理新区块时不需要的旧区块状态。 它将状态 trie 从 "旧 "复制到 "新"。 并非所有三元组节点都会被复制。 从选择性区块的状态根可到达的区块被复制。 复制完成后,旧目录将被删除,因此只剩下所选区块的状态。 + +阅读这些博客文章,了解更多技术细节: +[状态迁移:节省节点存储](https://medium.com/klaytn/klaytn-v1-5-0-state-migration-saving-node-storage-1358d87e4a7a), +[Kaia 状态迁移:减少区块链数据的有效方法](https://medium.com/klaytn/klaytn-state-migration-an-efficient-way-to-reduce-blockchain-data-6615a3b36523) + +关于如何执行批量剪枝,请参阅[状态迁移指南](../../misc/operation/node-pruning.md#how-to-perform-batch-pruning)。 + +## 国家现场修剪 + +状态实时剪枝是解决状态数据库规模不断扩大问题的一种新方案。 与批量剪枝(状态迁移)不同,实时剪枝会在节点进程阻塞时自动一点一点地删除旧状态。 + +### 动机 + +区块状态或 StateDB 将链上账户和合约存储在一个 trie 数据结构中。 trie 数据结构可存储过时和最新状态,以便使用梅克尔散列进行验证。 随着事务执行状态更改,状态三元组会无限增长。 截至发稿时(2025 年 8 月),Kaia 主网存档节点大小超过 20TB,甚至完整节点也超过 10TB。 + +在此之前,"状态迁移 "通过有选择性地复制最近的状态并删除其余状态来删除旧状态,从而缓解了这一问题。 这样可以将整个节点的大小减小到 5TB 以下。 + +然而,国家移民也有其自身的缺点。 它的缺点是需要花几天时间遍历整个州的 Trie,开销很大。 此外,状态迁移必须手动触发。 为了克服这些限制,引入了实时修剪技术。 + +### 概念 + +三元组修剪很难,因为三元组节点是否过时并不确定。 在原始状态三元组结构中,一个三元组节点可以是多个尝试的一部分,每个尝试构成一个不同的区块。 即使三元组节点(如账户余额)更新为另一个值,也不能删除该三元组节点,因为其他父节点可能仍然需要它。 这个问题被称为哈希重复问题。 + +实时剪枝会有意重复具有相同内容的三元组节点。 在 "实时剪枝 "模式下,三元组节点不会被哈希值引用,而是被 ExtHash 引用。 ExtHash 是内容的 32 字节哈希值加上 7 字节序列索引。 序列索引是单调递增的,因此每个三角形节点都是唯一的。 + +``` +Hash: 32-byte Keccak256 +ExtHash: 32-byte Keccak256 + 7-byte Serial index +``` + +这样,只要三元组节点的内容发生变化,就可以认为该三元组节点已经过时。 Merkle 哈希值的计算方法与此相同,只是忽略了序列索引,使其在共识方面与非实时剪枝节点兼容。 + +阅读这篇博客文章,了解更多技术细节:[利用 StateDB 实时剪枝高效管理区块链数据容量](https://medium.com/klaytn/strong-efficient-management-of-blockchain-data-capacity-with-statedb-live-pruning-strong-6aaa09b05f91). + +有关如何启用实时修剪,请参阅[实时修剪指南](../../misc/operation/node-pruning.md#how-to-perform-live-pruning)。 + +## 数据压缩 + +数据压缩通过在选定的数据库表中应用 LevelDB 内置的 Snappy 压缩算法来减少块数据的存储大小。 + +### 动机 + +由于 EVM 事务中的 ABI 编码标准,由标题、事务主体和收据组成的块数据通常包含高度重复的字节序列。 例如,Solidity 的 ABI 编码使用零填充来满足 32 字节字对齐的要求,从而导致事务调用数据中出现较长的零。 交易收据在事件日志和返回值中显示出类似的模式。 + +尽管存在这种天然冗余,Kaia 的底层 LevelDB 存储引擎默认情况下并不使用压缩功能,从而使重复数据不必要地占用磁盘空间。 截至 2025 年 7 月,一个 Kaia Mainnet 完整节点占用了超过 4.2TB 的存储空间,其中约 3.6TB 属于未压缩的区块数据。 + +### 概念 + +Kaia v2.1.0 激活了 LevelDB 的 Snappy 压缩算法,可选择性地应用于数据库表。 使用"--db.leveldb.compression "标记可进行细粒度控制: + +- 压缩标题、正文和收据(冗余度高,可节省大量资金) +- 不包括州三级数据(似乎是随机的,压缩效益极小) + +对于现有节点,手动触发数据库压缩可将未压缩的旧数据重写为压缩格式。 这个 "内务整理 "过程会合并 SST 表、核对删除内容,并应用压缩作为副作用。 + +**结果:** 主网全节点的总存储量减少了约 50%(节省约 2TB 的存储空间),其中正文和收据表的存储空间增加最多。 这一过程大约需要 10 个小时,可与正常的区块处理同时进行。 + +阅读这篇博客文章,了解更多技术细节:[Kaia v2.1 如何通过压缩回收 2TB](https://blog.kaia.io/cutting-blockchain-storage-in-half/). + +有关启用压缩的方法,请参阅 [优化节点存储指南](../../misc/operation/optimize-storage.md#database-compression)。 + +## FlatTrie 状态方案(试验性) + +FlatTrie 是一种实验性的状态存储方案,它通过调整历史账户状态的存储方式,大幅减少了归档节点状态数据库的大小。 + +### 动机 + +存档节点必须保留所有区块高度的所有账户的完整历史状态数据,以便进行时间旅行查询和全面的区块链分析。 这就造成了与完整节点截然不同的存储情况:截至 2025 年 8 月,一个 Kaia Mainnet 归档节点需要超过 35TB 的磁盘空间,其中 31TB (89%)被状态数据库占用。 + +传统的 Merkle Patricia Trie(MPT)结构同时存储账户数据(树叶)和构成 Merkle 树的中间分支节点。 存档节点历来为多个区块高度维护完整的 MPT,导致中间节点(本身不传输账户数据)无限期累积。 + +现有的存储优化,如[State Migration](https://medium.com/klaytn/klaytn-v1-5-0-state-migration-saving-node-storage-1358d87e4a7a)(批量剪枝)和[StateDB Live Pruning](https://medium.com/klaytn/strong-efficient-management-of-blockchain-data-capacity-with-statedb-live-pruning-strong-6aaa09b05f91),从根本上说需要删除历史数据,因此不适用于必须保留完整历史数据的归档节点。 + +### 概念 + +FlatTrie 是一种实验性的状态存储方案,改编自[Erigon 以太坊客户端](https://github.com/erigontech/erigon/)。 它通过以下方式重构状态存储 + +- 在平面键值表中存储历史账户状态(简单的地址 → 账户数据映射) +- 只保留最新区块与所有中间分支节点的完整 MPT +- 只临时建立必要的分支节点,按需重建历史 Merkle 根节点 + +这种方法消除了历史中间节点的持久存储,同时保留了完整的账户状态历史,并能验证任何区块的 Merkle 根。 + +\*\* 适应挑战:\*\* Erigon 的实施假设以太坊的账户结构。 Kaia 使用不同的 RLP 编码,支持人类可读地址和多种密钥类型等独特功能。 集成工作需要修改 Erigon 的 Merkle 哈希算法模块,将账户视为不透明字节字符串,同时创建三个适配器层(DomainsManager、WriteBuffer、DeferredContext),以便将 Kaia 的多线程 Trie 接口与 Erigon 的单线程 MDBX 数据库需求连接起来。 + +**结果:** 在 Kairos 测试网实验中,FlatTrie 归档节点比传统归档节点少消耗约 75% 的总存储空间,状态数据库大小减少了 80% 以上。 预计主网归档节点也会有类似的节省(从 ~35TB 到 ~10TB)。 + +**限制:** 实验性 v2.1.0 实现不支持块回卷(`debug_setHead` API)、默克尔证明生成(`eth_getProof` API)或状态剪枝功能。 这些限制源于 FlatTrie 丢弃历史分支节点的设计选择。 + +阅读这篇博客文章,了解更多技术细节:[Kaia 的存档节点 FlatTrie 实验](https://blog.kaia.io/flatten-the-state-shrink-the-disk/). + +有关启用 FlatTrie 的方法,请参阅 [优化节点存储指南](../../misc/operation/optimize-storage.md#flattrie-state-scheme-experimental)。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md index 040517710ffc..035958a004b4 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md @@ -62,7 +62,7 @@ - 基本费用上限:基本费用的最大值 - 基本费用下限值:基本费用的最小值 -以下是基础费用计算的简化版本。 从本质上讲,基本费用的变化与 GAS_TARGET 和 PREVIOUS_BLOCK_GAS_USED 之间的差额成正比,其他参数控制着基本费用的变化速度或界限。 准确公式请参阅 [KIP-71](https://github.com/kaiachain/kips/blob/main/KIPs/kip-71.md)。 +以下是基础费用计算的简化版本。 从本质上讲,基本费用的变化与 GAS_TARGET 和 PREVIO_BLOCK_GAS_USED 之间的差额成正比,其他参数控制着基本费用的变化速度或界限。 准确公式请参阅 [KIP-71](https://github.com/kaiachain/kips/blob/main/KIPs/kip-71.md)。 ``` min(PREVIOUS_BLOCK_GAS_USED, MAX_BLOCK_GAS_USED_FOR_BASE_FEE) - GAS_TARGET diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/faq.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/faq.md index 74d8913f8aa4..564cbb796ed9 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/faq.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/faq.md @@ -3,6 +3,7 @@ - [常见问题](#faq) - [Kaia 是什么? ](#what-is-kaia-) - [Kaia 如何支持以太坊等价交换? ](#how-does-kaia-support-ethereum-equivalence-) + - [Kaia 的版本管理策略是什么? ](#what-is-kaias-versioning-policy-) - [凯亚的天然气政策是什么? ](#what-is-kaias-gas-policy-) - [Kaia 的账户结构有什么特别之处? ](#what-is-special-about-kaias-account-structure-) - [在哪里可以开始使用 Kaia 开发 dApp? ](#where-can-i-start-dapp-development-with-kaia-) @@ -30,6 +31,10 @@ Kaia 是高性能的第 1 层区块链,专为 Web3 的大规模应用(尤其 Kaia 与 EVM 兼容,支持除 EIP-4844 blob 交易之外的所有以太坊坎昆 EVM 功能。 它提供 `eth` 命名空间 RPC API,允许无缝使用以太坊 SDK 和工具。 Kaia 特有的交易类型在以太坊命名空间 API 中表示为 0 型传统交易,因此以太坊 SDK 无需了解这些类型。 +## Kaia 的版本管理策略是什么? + +您可以在 [github](https://github.com/kaiachain/kaia/blob/dev/CONTRIBUTING.md#versioning-policy) 上查看。 + ## Kaia 的天然气政策是什么? Kaia 采用动态天然气收费模式,在正常网络条件下保持低收费,但会根据网络拥堵情况调整收费。 手续费可在每个区块的有限范围内变化,有助于防止网络垃圾邮件,同时保持费用的可预测性。 每笔交易的部分费用会自动烧掉。 该模式优先考虑用户体验和企业友好性,同时保持网络稳定性。 @@ -139,4 +144,4 @@ Kaia 的网络浏览器扩展钱包 [Kaia Wallet](https://chromewebstore.google. - ethers-ext:[收费委托价值转移示例](https://docs.kaia.io/references/sdk/ethers-ext/v6/fee-delegated-transaction/value-transfer/) - web3js-ext:[收费委托值转移示例](https://docs.kaia.io/references/sdk/web3js-ext/fee-delegated-transaction/value-transfer/) - web3j-ext:[收费委托值转移示例](https://docs.kaia.io/references/sdk/web3j-ext/fee-delegated-transaction/value-transfer/) -- web3py-ext:[收费委托价值转移示例](https://docs.kaia.io/references/sdk/web3py-ext/fee-delegated-transaction/value-transfer/) \ No newline at end of file +- web3py-ext:[收费委托价值转移示例](https://docs.kaia.io/references/sdk/web3py-ext/fee-delegated-transaction/value-transfer/) diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md index 9d34aac6ce2e..83a35756c208 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md @@ -43,7 +43,7 @@ ### Klaytn和Finschia -Klaytn 和 Finschia 通过管理决策合并为 Kaia。 您可以查看投票结果 [此处](https://medium.com/kaiachain/klaytn-and-finschia-merge-proposal-passes-creating-asias-largest-blockchain-ecosystem-7af570eb069a)。 两条链(KLAY 和 FNSA)的实用代币转换为 KAIA 代币。 您可以在 [此处] 找到这两种代币的汇率(../../kaiatech/kaia-white-paper.md#fnsa-issuancedistribution-status)。 +Klaytn 和 Finschia 通过管理决策合并为 Kaia。 您可以查看投票结果 [此处](https://blog.kaia.io/klaytn-and-finschia-merge-proposal-passes-creating-asias-largest-blockchain-ecosystem/)。 两条链(KLAY 和 FNSA)的实用代币转换为 KAIA 代币。 您可以在 [此处] 找到这两种代币的汇率(../../kaiatech/kaia-white-paper.md#fnsa-issuancedistribution-status)。 ### KLAY 和 FNSA 会怎么样? @@ -142,8 +142,8 @@ Kaia 是 Klaytn 链的硬分叉,链 ID 保持不变。 之前的测试网络 " 以下是链合并的主要信息: - [治理建议](https://govforum.klaytn.foundation/t/kgp-25-klaytn-finschia-mainnet-merge/719) -- [合并背后的愿景](https://medium.com/klaytn/finschia-klaytn-chain-merge-proposal-our-vision-for-asias-1-blockchain-ecosystem-7de1588e28c0) -- [制作 Kaia DeFi 的核心](https://medium.com/klaytn/crafting-the-core-of-project-dragons-defi-ecosystem-0fa561e02f56) -- [回应机构需求](https://medium.com/klaytn/project-dragon-responding-to-institutional-demand-bd36e2e1e2a6) -- [补充数据和见解](https://medium.com/klaytn/project-dragon-supplementary-data-and-insights-d36abd25ca0f) -- [Kaia品牌故事](https://medium.com/klaytn/say-hello-to-kaia-4182ccafe456) +- [合并背后的愿景](https://blog.kaia.io/finschia-klaytn-chain-merge-proposal-our-vision-for-asias-no-1-blockchain-ecosystem/) +- [制作 Kaia DeFi 的核心](https://blog.kaia.io/crafting-the-core-of-project-dragons-defi-ecosystem/) +- [回应机构需求](https://blog.kaia.io/project-dragon-responding-to-institutional-demand/) +- [补充数据和见解](https://blog.kaia.io/project-dragon-supplementary-data-and-insights/) +- [Kaia品牌故事](https://blog.kaia.io/say-hello-to-kaia/) diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md index 41a53ebde817..ea72091c7dcb 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md @@ -2,12 +2,160 @@ Finschia 用户可以按固定交换率将其在 Finshia 网络上的 FNSA 代币交换为 Kaia 网络上的 KAIA 代币。 这种交换由一套智能合约和程序(统称为 Kaiabridge)进行调解。 -代币交换过程由 Finschia 用户将 FNSA 代币发送到 `fwsap` 模块开始。 代币首先从 "cony "交换到 "kei "面值,然后转移到 "fbridge "模块。 fbridge "事件由可信中继器识别,并提交给 Kaia 链上的桥接智能合约。 桥接请求分多个步骤处理: +您可以在我们的[在线工具包](https://toolkit.kaia.io/kaiaBridge) 中访问和使用 Kaiabridge。 -- 飞行中:代币到达 Finschia 的 "fbridge "模块,但中继器没有向 Kaia 智能合约报告。 -- 确认:转述人向合同("条款")提交了申请。 现在,请求进入 30 分钟的时间锁定。 -- 已认领:时间锁定到期后,令牌已被转移("认领")到 Kaia 链上的目标账户。 +您可以在[GitHub kaiachain/kaia 代码库](https://github.com/kaiachain/kaia/tree/dev/contracts/contracts/system_contracts/kaiabridge) 中找到合同源代码,在[合同地址](https://docs.kaia.io/references/contract-addresses/) 页面中找到部署地址。 -Kaiabridge 智能合约内置多重签名功能。 例如,需要操作员账户进行多次备付交易,申请才能得到确认。 每个操作员账户由一个中继器持有,中继器由 Kaia 基金会和 Finschia 基金会管理。 +# Kaiabridge 用户指南 -您可以在 [kaiachain GitHub](https://github.com/kaiachain/kaia/tree/dev/contracts/contracts/system_contracts/kaiabridge) 中找到合同源代码,在 [合同地址](https://docs.kaia.io/references/contract-addresses/) 页面中找到部署地址。 \ No newline at end of file +## 先决条件 + +### 1. 将您的账户移至 MetaMask 或 Kaia 钱包 + +#### 使用原始私人密钥 + +如果您的账户可以导出原始私钥,请复制原始私钥并导入 MetaMask 或 Kaia 钱包。 + +- [MetaMask](https://support.metamask.io/start/use-an-existing-wallet#import-using-a-private-key) +- [Kaia 钱包](https://www.kaiawallet.io/en_US/faq/?id=25) + +#### 带恢复短语 + +如果账户只能以恢复短语的形式导出,请根据恢复短语计算原始私钥。 您可以使用任何支持 BIP-39 派生路径的工具。 这些工具包括 [ethers.js](https://docs.ethers.org/v6/api/wallet/#HDNodeWallet)、[viem](https://viem.sh/docs/accounts/local/hdKeyToAccount)、[Foundry](https://getfoundry.sh/cast/reference/wallet/)和[BIP39 工具](https://github.com/iancoleman/bip39)。 Finschia 钱包通常使用 "m/44'/438'/0'/0/0 "路径(根据 [SLIP-044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md))作为默认派生路径。 如果您的 Finschia 钱包有多个账户或使用不同的配置,您可能需要使用其他派生路径。 + +计算出私钥后,请按照上一节[使用原始私钥](#with-raw-private-key) 中的说明进行操作。 + +:::note[Example 使用 BIP39 工具] + +您可以在此网页上计算私钥:[BIP39 - 助记符代码](https://iancoleman.io/bip39/). + +为谨慎起见,强烈建议按照页面上的 "离线使用 "说明操作,并在操作过程中阻止互联网连接。 + +1. 在 "BIP39 助记符 "字段中粘贴恢复短语。 +2. 将 "币 "字段设置为 "ETH - 以太坊"。 +3. 将 "派生路径 "设为 "BIP32"。 +4. 将 "客户端 "设为 "自定义派生路径"。 +5. 将 "BIP32 衍生路径 "设为 "m/44'/438'/0'/0"。 +6. 在 "派生地址 "中,查找 "路径 "显示为 "m/44'/438'/0'/0/0 "的第一行,你的原始私钥就显示在 "私钥 "字段中。 + +::: + +:::note[Example 使用铸造工具] + +1. 安装 [Foundry](https://getfoundry.sh/)。 +2. 键入以下命令,在"--助记符 "中输入恢复短语。 原始私钥将被打印出来。 + ``` + cast wallet private-key --mnemonic "test test test test test test test test junk" --mnemonic-derivation-path "m/44'/438'/0'/0/0" + ``` + +::: + +### 2. 检查您的网络 + +如果您正在使用 MetaMask,请手动将 Kaia Mainnet 添加到您的网络(如果您还没有这样做)。 + +- [将 MetaMask 连接到 Kaia](https://docs.kaia.io/build/tutorials/connecting-metamask/) + +### 3. 为您的账户加油 + +您需要汽油来进行交换交易。 详细说明请参阅 [Get KAIA](https://docs.kaia.io/build/get-started/getting-kaia/)。 + +我们建议您至少准备 0.1 KAIA 的汽油费。 + +## 将 Finschia 换成 Kaia + +:::warning[This 交换不可逆转] + +备付金和报销申请只能处理一次,不能撤销。 +请仔细阅读这些说明。 + +::: + +### 1. 连接您的钱包 + +#### 1.1 连接元掩码 + +点击 "连接 MetaMask "按钮。 + +

Connect MetaMask

+ +查看 "账户 "是否显示您的地址。 +如果没有,请打开 MetaMask 扩展,看看它是否显示您没有连接到页面。 如果是,请点击 "连接账户 "按钮。 + +

Connect Account

+ +#### 1.2 连接 Kaia 钱包 + +如果您使用的是 Kaia 钱包,网站可能会要求您将 Kaia 钱包连接到 dApp(此处为 Kaia 在线工具包)。 + +

Connect Kaia Wallet

+ +点击 "连接",连接您的 Kaia 钱包。 + +#### 2. 切换到 Kaia 主网 + +检查是否已将网络正确设置为 "Kaia Mainnet "或 "Mainnet"。 如果没有,请切换到 Kaia Mainnet。 如果您使用的是 MetaMask,且未在 MetaMask 中添加 Kaia Mainnet 网络,请参阅 [检查您的网络](#2-check-your-network)。 + +#### 3. 得出芬斯基亚地址 + +单击 "生成 Finschia 地址"。 出现签署信息的提示时,点击 "确认 "或 "签署"。 + +
+ Sign message in MetaMask + Sign message in Kaia Wallet +
+ +

+检查 "派生 Finschia 地址 "是否与您的原始 Finschia 地址一致,以及 "CONY 余额 "是否与您在 Finschia 网络(CONY)中的余额一致。 + +
+ Address and CONY balance shown in the page + Address and CONY balance shown in your wallet +
+ +

+此外,请确保您的账户中有可用来支付汽油费的 KAIA(您可以在钱包中查看)。 + +
+ KAIA balance in MetaMask + KAIA balance in Kaia Wallet +
+ +

+如果账户中没有 KAIA,请参阅 [Gas up your account](#3-gas-up-your-account)。 + +#### 4. 要求提供 + +点击 "申请提供"。 出现签署信息和发送交易的提示时,点击 "确认"。 + +
+ Confirm provision transaction request in MetaMask + Confirm provision transaction request in Kaia Wallet +
+ +

+整个过程只需几秒钟。 等待交易完成。 +您可以在页面中查看结果。 + +

Provision request successful

+ +
+如果没有,请刷新并从头开始。 + +#### 5. 申请索赔 + +点击 "申请索赔"。 出现发送交易的提示时,点击 "确认"。 + +
+ Confirm claim transaction request in MetaMask + Confirm claim transaction request in Kaia Wallet +
+ +

+整个过程只需几秒钟。 等待交易完成。 +您可以在页面中查看结果。 + +

Claim request successful

+ +
+查看最新余额。 索赔金额应为(您的余额)*(兑换率,约 148),单位为 [kei](https://docs.kaia.io/learn/token-economics/kaia-native-token/#units-of-kaia-)。 \ No newline at end of file diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md index 734a810fd7ae..03506a1df540 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md @@ -101,7 +101,7 @@ ## 下载 -为提高效率,只提供批量剪枝(状态迁移)或实时剪枝数据库。 请阅读 [Storage Optimization](../../learn/storage/state-pruning.md),了解它们的概念。 如果你想要一个完整的数据库,既不需要剪枝,也不需要存档数据,那就从创世中执行一次全新的完整同步。 +为提高效率,只提供批量剪枝(状态迁移)或实时剪枝数据库。 请阅读 [Storage Optimization](../../learn/storage/storage-optimization.md) 了解它们的概念。 如果你想要一个完整的数据库,既不需要剪枝,也不需要存档数据,那就从创世中执行一次全新的完整同步。 | 网络 | 同步选项 | 下载 | | -- | -------------- | --------------------------------------------------------------------------------------------------- | diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md index df3c243c6568..08c36bb3fd71 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md @@ -2,8 +2,8 @@ 本页介绍如何删除历史块状态以减少存储需求。 Kaia 提供了两种修剪块状态的方法: -- [实时修剪](../../learn/storage/state-pruning.md#state-live-pruning):启用实时修剪功能后,超过一定保留期限的块状态将被自动删除。 -- [批量剪枝:状态迁移](../../learn/storage/state-pruning.md#state-batch-pruning-state-migration):区块状态可以进行状态迁移,也就是说,在某个区块编号之前的区块状态都是可用的。 +- [实时修剪](../../learn/storage/storage-optimization.md#state-live-pruning):启用实时修剪功能后,超过一定保留期限的块状态将被自动删除。 +- [批量剪枝:状态迁移](../../learn/storage/storage-optimization.md#state-batch-pruning-state-migration):区块状态可以进行状态迁移,即某个区块编号之前的区块状态可以使用。 ## 了解修剪的影响 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md new file mode 100644 index 000000000000..34e154a7fdb5 --- /dev/null +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md @@ -0,0 +1,293 @@ +# 优化节点存储 + +[Kaia v2.1.0](https://github.com/kaiachain/kaia/releases/tag/v2.1.0) 引入了两个互补的存储优化功能,可显著减少磁盘空间需求: + +- **数据库压缩**:通过压缩重复数据块来减少存储空间 +- **FlatTrie 状态方案**:大幅减少归档节点状态数据库大小的实验性功能 + +本指南介绍如何将这些优化应用到 Kaia 节点。 + +## 数据库压缩 + +数据库压缩使用 LevelDB 内置的 Snappy 压缩技术来缩小块头、事务主体和收据的大小,这些数据通常包含重复数据,如 ABI 编码事务中的零填充。 + +\*\* 预期节余:\*\* + +- 全节点:减少 ~2TB (主网从 ~4.2TB 减少到 ~2TB) + +### 先决条件 + +- Kaia v2.1.0 或更高版本 +- 对于手动压缩:足够的可用磁盘空间和接受持续磁盘 I/O 的能力(请参阅下文**资源影响**部分)。 + +### 为新安装启用压缩功能 + +从 v2.1.0 版开始,默认启用压缩功能。 只需启动节点即可: + +**软件包安装:** + +```bash +# Configure network in kend.conf +sudo vi /etc/kend/conf/kend.conf +# Set: NETWORK=mainnet or NETWORK=kairos + +# Start node (compression enabled by default in v2.1.0+) +kend start + +# Verify +kend status +tail -f /var/kend/logs/kend.out +``` + +所有新写入的数据都将自动压缩。 + +### 为现有节点启用压缩功能 + +如果您是从 v2.1.0 之前的版本升级: + +**第 1 步:检查版本** + +```bash +ken version +``` + +**第 2 步:适用于 v2.1.0 及更高版本** + +默认情况下已启用压缩功能。 新数据会自动压缩。 跳至步骤 4 压缩现有数据。 + +**第 3 步:仅适用于 v2.1.0 之前的版本** + +在配置中添加压缩标志: + +**软件包安装:** + +```bash +sudo vi /etc/kend/conf/kend.conf +# Add to ADDITIONAL variable: +ADDITIONAL="--db.leveldb.compression 2" +``` + +压缩标志值为 + +- `0`:无压缩 +- `1`:只压缩收据 +- `2`:压缩标题、正文和收据(推荐) +- `3`:压缩所有表格,包括状态三(不建议使用) + +:::note + +建议采用方案 2,因为状态三角数据压缩效果不好(显得随机),所以方案 3 带来的额外好处微乎其微。 + +::: + +然后重新启动: + +```bash +kend stop +kend start +``` + +**第 4 步:压缩现有数据(可选但建议)** + +通过 RPC 触发数据库压缩。 连接到节点控制台: + +```bash +ken attach --datadir /var/kend/data +``` + +在控制台中,使用 "allbutstate "预设触发压缩: + +```javascript +> debug.chaindbCompact({ "preset": "allbutstate" }) +null +``` + +**可用预设:** + +- "默认":全方位压缩所有数据库组件 +- `"allbutstate"`:选择性压缩,不包括状态 trie(推荐用于压缩) +- "自定义":为特定数据库表定义自定义范围 + +压缩在后台运行。 在节点日志中监控进度: + +```bash +tail -f /var/kend/logs/kend.out | grep -i Compact +``` + +您应该会看到类似的日志条目: + +``` +INFO[07/25,12:50:17 Z] [3] Compacting database started range=0x48-0x49 +INFO[07/25,12:55:17 Z] [3] Compacting database completed range=0x48-0x49 elapsed=5m0.085s +``` + +在压缩过程中,节点将继续处理数据块。 + +**预计持续时间:** 一个主网完整节点(固态硬盘上有 ~4TB 数据)大约需要 10 小时。 持续时间因硬件和数据大小而异。 + +**对资源的影响:** + +- 磁盘 I/O 高(读取峰值 >400 MiB/秒,写入峰值 >300 MiB/秒) +- 磁盘 IOPS 高(通常大于 2000 次/秒) +- 节点保持运行并继续同步区块 + +:::note + +虽然节点在压缩期间保持运行,但在 I/O 高峰期,查询性能可能会受到影响。 对于生产 RPC 节点,在维护窗口或低流量时段安排压实。 + +::: + +### 使用预压缩 Chaindata 快照(待定) + +预压缩链数据快照计划在未来发布,但目前尚未提供。 当这些信息可用时,它们将被列入 [Chaindata 快照页面](https://docs.kaia.io/misc/operation/chaindata-snapshot/)。 + +目前,您必须 + +- 在新安装的 v2.1.0+ 版本中启用压缩(新数据自动压缩) +- 在现有节点上运行手动压缩(见上文) + +定期查看快照页面,了解有关压缩快照可用性的更新。 + +### 验证压缩是否激活 + +检查节点启动日志,查看压缩配置: + +```bash +grep "compressionType" /var/kend/logs/kend.out +``` + +查找日志中显示 "compressionType=snappy "的非州-三角形表。 + +### 监控和故障排除 + +**检查磁盘使用减少情况:** + +```bash +du -h --max-depth=1 /var/kend/data/klay/chaindata +``` + +比较压实前后的效果。 在包含区块正文和收据的目录中,你应该能看到存储空间的大幅减少。 + +**常见问题:** + +1. **压缩失败**:确保有足够的磁盘空间。 压缩暂时需要额外的空间来重写数据。 +2. **FlatTrie无法启动**:FlatTrie 需要一个空数据库。 如果看到有关现有数据的错误,请删除 chaindata 目录并从 genesis 同步。 +3. **默克尔证明 API 错误**:FlatTrie 不支持 `eth_getProof`。 如果需要此 API,请使用传统节点。 + +## FlatTrie 状态方案(试验性) + +FlatTrie 是一种实验性的状态存储方案,改编自 Erigon 以太坊客户端。 它以扁平结构存储账户状态,只维护最新区块的完整 Merkle Patricia Trie (MPT),按需重建历史尝试。 + +**预期节省:** + +- 总存储量:~减少约 75%(根据 Kairos 测试网结果预测) +- Kairos 测试网:4.3TB → 1TB +- 主网:~35TB → ~10TB(根据缩减比例估算) + +:::warning + +FlatTrie 是 v2.1.0 中的一项实验功能。 不建议用于生产。 未来版本中可能会出现稳定性问题、性能瓶颈和破坏性更改。 仅用于测试和开发环境。 + +::: + +### 先决条件 + +- Kaia v2.1.0 或更高版本 +- **必须从创世同步**(不能转换现有数据库) +- 空数据目录 + +### 目前的限制 + +在启用 FlatTrie 之前,请了解这些限制: + +**不支持的功能:** + +- 批量修剪和现场修剪 +- 块回卷("--start-block-number "标志和 "debug_setHead "API) +- 默克尔证明生成(`eth_getProof` API) + +**不兼容问题:** + +- 无法从现有数据库迁移(必须从创世开始) +- 无法在 FlatTrie 和非 FlatTrie 模式之间切换 +- 有 FlatTrie 和没有 FlatTrie 的数据库不兼容 + +### 启用 FlatTrie + +**第 1 步:准备空数据目录** + +```bash +# Ensure clean data directory +sudo rm -rf /var/kend/data +sudo mkdir -p /var/kend/data +``` + +**第 2 步:使用 FlatTrie 标志启动节点,并从创世同步** + +```bash +# Mainnet +ken --state.experimental-flat-trie + +# Kairos testnet +ken --state.experimental-flat-trie --kairos +``` + +:::note + +启用 FlatTrie 后,归档模式会自动激活,与 `--gcmode`和 `--state.block-interval`标志无关。 使用 FlatTrie 时,这些标记将被忽略。 + +::: + +**步骤 3:等待完全同步** + +节点将同步创世中的所有区块。 这可能需要几周时间,具体取决于您的硬件和网络。 + +### 验证 FlatTrie 是否处于活动状态 + +检查节点启动日志,确认 FlatTrie 模式: + +```bash +grep -i "flat" /var/kend/logs/kend.out | head -20 +``` + +您应该能看到实验性平面三维模型已激活的迹象。 + +### 监控 FlatTrie 性能 + +与传统的状态存储相比,FlatTrie 使用不同的资源配置文件: + +**预期特点:** + +- 降低 CPU 使用率 +- 更高的内存使用率(~30GB) +- 更高的程序运行次数(约 900-1000 次) +- 区块最终完成时间较慢 + +通过节点的 Prometheus 指标端点或 Grafana 面板监控这些指标。 + +### 故障排除 FlatTrie + +**无法在现有数据库上启动 FlatTrie:** +如果你看到错误提示无法在非空数据上启用 FlatTrie,你必须从 genesis 开始。 删除 chaindata 目录,使用 `--state.experimental-flat-trie` 标志执行完全同步。 + +\*\* Merkle proof API 失败:\*\* +FlatTrie 不支持 `eth_getProof` 和相关的 Merkle proof API。 如果您的应用程序需要这些 API,请使用传统节点。 + +\*\* 高内存使用量:\*\* +同步过程中,FlatTrie 节点的内存使用量预计约为 30GB。 确保系统有足够的内存。 团队正在进行优化,以便在未来版本中减少这种情况。 + +\*\* 同步速度慢:\*\* +使用 FlatTrie 的初始同步速度与传统节点相当。 如果同步速度明显变慢,请进行检查: + +- 磁盘 I/O 性能(强烈建议使用固态硬盘) +- 网络带宽 +- CPU 使用率 + +## 最佳做法 + +1. **在进行重大更改前**\*始终进行备份:特别是在运行手动压缩之前。 +2. **监控磁盘空间**:确保压缩前有足够的可用空间。 压缩暂时需要额外空间来重写数据库文件。 +3. **在低流量时段安排压缩**:如果运行公共 RPC 端点。 +4. \*\* 生产节点使用固态硬盘\*\*:压缩和 FlatTrie 都受益于快速随机 I/O。 +5. \*\* 实验性功能计划\*\*:FlatTrie 在 2.1.x 版中是试验性的。 生产使用前进行彻底测试。 +6. **保持更新**:查看发布说明,了解未来的优化和 FlatTrie 从实验状态毕业的时间。 \ No newline at end of file diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md index 4b002c993145..7ec2143415b2 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md @@ -159,7 +159,7 @@ REWARDBASE="d13f7da0032b1204f77029dc1ecbf4dae2f04241" ### (可选)下载 Chaindata 快照 -从创世区块进行同步操作非常耗时。 您可以使用 [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) 跳过 [Full Sync](../../../learn/storage/block-sync.md#full-sync) 过程。 +从创世区块进行同步非常耗时。 您可以使用 [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) 跳过 [Full Sync](../../../learn/storage/block-sync.md#full-sync) 过程。 ## 启动 CN diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md index 91de502e334a..6aa96356cdd6 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md @@ -146,7 +146,7 @@ DATA_DIR=/var/kpnd/data ### (可选)下载 Chaindata 快照 -从创世区块进行同步操作非常耗时。 您可以使用 [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) 跳过 [Full Sync](../../../learn/storage/block-sync.md#full-sync) 过程。 +从创世区块进行同步非常耗时。 您可以使用 [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) 跳过 [Full Sync](../../../learn/storage/block-sync.md#full-sync) 过程。 ## 启动 PN diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md index 808e4d0c81f5..047b17a96475 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md @@ -10,14 +10,22 @@ ### 裸机服务器 -| 类别 | 规格 | -| :-- | :----------------------------------------------------------------------------------------------------------------------------------------- | -| 服务器 | 英特尔® 服务器系统 [M50CYP1UR212](https://www.intel.sg/content/www/xa/en/products/sku/214842/intel-server-system-m50cyp1ur212/specifications.html) | -| CPU | Intel® Xeon 8358 2.60 GHz (32 核/64 线程) | -| 内存 | 128gb (32gb \* 4\) | -| 存储 | 4TB(或更大容量)固态硬盘(首选存储容量和配置可能因链数据大小而异。 更多信息请咨询 Kaia 团队)。 | +#### 一般要求(所有节点类型) -请注意,这只是 CN 和 PN 的推荐硬件规格,并非确切要求。 任何具有类似硬件配置的物理机器都足以运行 CN 或 PN。 +| 类别 | 规格 | +| :-- | :-------------------------------------------------------------------------------------------- | +| CPU | 基本频率 2.6 GHz - 最大频率 3.4 GHz 或更高(例如,第 3 代 Intel® Xeon® 可扩展处理器) | +| 存储 | ≥ 4 TB SSD(根据链数据大小进行调整;请咨询 Kaia 团队以获得指导) | + +任何具有类似硬件配置的物理机器都足以运行 CN 或 PN。 + +#### 按节点类型推荐的规格 + +| Node Type | 核心/线程 | 内存 | +| :------------------------------------------- | :--------- | :---- | +| CN | 16 核/32 线程 | 128GB | +| PN | 8 核/16 线程 | 64 GB | +| PN (with Live Pruning DB) | 4 核/8 线程 | 32 GB | 您可以使用和应用实时修剪选项来使用实时修剪 DB。 更多详情,请参阅 https://docs.kaia.io/learn/storage/live-pruning/。 但要注意的是,目前不建议对 CN 进行活体修剪,但这一做法将来可能会改变。 @@ -37,11 +45,11 @@ #### 建议的 "Azure "规范 -| Node Type | Model | vCPU | 内存(GiB) | 存储类型 (GiB\) | 存储速度(IOPS) | 价格(韩国中部,美元/小时) | -| :------------------------------------------: | :-----: | :--: | :-----: | :---------------------------: | :--------: | :-------------------: | -| CN | D32s v5 | 32 | 128 | P50 (4096) | 7500 | 1.888 | -| PN | D16s v5 | 16 | 64 | P50 (4096) | 7500 | 0.944 | -| PN (with Live Pruning DB) | D8s v5 | 8 | 32 | P50 (4096) | 7500 | 0.472 | +| 节点类型 | Model | vCPU | 内存(GiB) | 存储类型 (GiB\) | 存储速度(IOPS) | 价格(韩国中部,美元/小时) | +| :----------: | :-----: | :--: | :-----: | :---------------------------: | :--------: | :-------------------: | +| CN | D32s v5 | 32 | 128 | P50 (4096) | 7500 | 1.888 | +| PN | D16s v5 | 16 | 64 | P50 (4096) | 7500 | 0.944 | +| PN(带实时修剪 DB) | D8s v5 | 8 | 32 | P50 (4096) | 7500 | 0.472 | 此存储规范源自 Azure Premium Disk 规范。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md index 31e9f523d116..c2f31236ba35 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md @@ -27,7 +27,7 @@ echo "LOG_DIR=/var/kend/logs" >> conf/kend.conf ### (可选)下载 Chaindata 快照 -从创世区块进行同步操作非常耗时。 您可以使用 [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) 跳过 [Full Sync](../../learn/storage/block-sync.md#full-sync) 过程。 下载并解压 chaindata 快照。 然后将解压后的目录挂载到容器中。 +从创世区块进行同步非常耗时。 您可以使用 [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) 跳过 [Full Sync](../../learn/storage/block-sync.md#full-sync) 过程。 下载并解压 chaindata 快照。 然后将解压后的目录挂载到容器中。 ## 启动容器 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md index e3774d8d6a2a..359b308033a3 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md @@ -115,7 +115,7 @@ DATA_DIR=/var/kend/data ### (可选)下载 Chaindata 快照 -从创世区块进行同步操作非常耗时。 您可以使用 [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) 跳过 [Full Sync](../../learn/storage/block-sync.md#full-sync) 过程。 +从创世区块进行同步非常耗时。 您可以使用 [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) 跳过 [Full Sync](../../learn/storage/block-sync.md#full-sync) 过程。 ## 启动 EN diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/references/contract-addresses.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/references/contract-addresses.md index 612e3c14333f..e605d684a419 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/references/contract-addresses.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/references/contract-addresses.md @@ -15,6 +15,7 @@ Kaia 的某些功能依赖于称为_系统合约_的特殊智能合约。 它们 | KIP-113 SimpleBlsRegistry | proxy 0x3e80e75975bdb8e04B800485DD28BebeC6d97679
logic 0xb5ed8d6edd437a0d6ae828580c0aef5678d87f1a | proxy 0x4BEed0651C46aE5a7CB3b7737345d2ee733789e6
logic 0x6751096fe72d835307d7e635aed51296948b93c5 | | KIP-247 无气体交换路由器 | 0xCf658F786bf4AC62D66d70Dd26B5c1395dA22c63 | 0x4b41783732810b731569E4d944F59372F411BEa2 | | KIP-226 CLRegistry | 0x25F4044c655Fc7B23c62bbC78ceF3B4EBFb4e478 | 0x25F4044c655Fc7B23c62bbC78ceF3B4EBFb4e478 | +| KIP-249 拍卖入口点 | 0xFc5c1C92d8DE06F7143f71FeA209e04042dcff82 | 0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480 | 有些合约不会被 Kaia 节点直接读取,但在 Kaia 区块链及其生态系统的运行中发挥着至关重要的作用。 其中包括财务、治理和 KAIA 代币桥接合约。 @@ -33,7 +34,9 @@ Kaia 的某些功能依赖于称为_系统合约_的特殊智能合约。 它们 | Kaiabridge Judge | 0x64c91d6517b8f2fd7f4157c32DE4acfe1AeA2611 | 0x3735Ba95cca5DEd47Fa5b202a2Bbda4c63c0B1DD | | Kaiabridge Guardian | 0xE49D152E5FA576caFC18D2775AF4E58C135a6851 | 0xc9e8342C1da4c89A423258d9030414331b4761Cf | | KIP-163 PublicDelegationFactory | 0x29C8cc53d22F79D4024ecB67DB1a09b37bCdE415 | 0x98c47c2cda854cbb025d47de72149a7ec238ec33 | -| KIP-226 CLDEXFactory | 0x2A4C5eCaafB26460F17d509EA4d15741AF5F5f0a | 0x537D58BdBC98c690bE5d3e3F638d4B93754B15Fd | -| KIP-226 CLDEX 路由器 | 0x21d3c567058277b19324FE22c8e4Bb3D2AE0D4C3 | 0x41F135a084897e4145CC2032e8701726af795e3a | +| KIP-226 CLDEXFactory | 0x93fa0E1deE99ac4158a617a6EC79cB941bD9a39F | 0x666a9a72D2f708062a20e7Ca94f6dd5Ce6B33eA4 | +| KIP-226 CLDEX 路由器 | 0x5086273d9C8a79B7d2466aaCc52a6E43E22152A5 | 0x2871e95eaBFF0E71e4e4b706D7F1F3D24811673b | | KIP-226 StakingTrackerV2 | 0xF45c37c265f148894D6d9A4c066aFaAB00557c9c | 0x9b015Ab5916EE53e52Ef60f31E978b4001908c43 | | [Canonical WKAIA](../build/smart-contracts/token-development/canonical-wkaia.md) | 0x19Aac5f612f524B754CA7e7c41cbFa2E981A4432 | 0x043c471bEe060e00A56CcD02c0Ca286808a5A436 | +| KIP-249 拍卖存款保管箱 | 0x0E66b62273Cc99BC519DD4dD0C0Cf689dd7b9876 | 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc | +| KIP-249 拍卖收费库 | 0x303BB9c9FF4Aa656ac4c8e9f99F8E4C133FDa665 | 0xE4e7d880786c53b6EA6cfA848Eb3a05eE97b2aCC | \ No newline at end of file diff --git a/i18n/zh-CN/docusaurus-theme-classic/footer.json b/i18n/zh-CN/docusaurus-theme-classic/footer.json index c1d461f00aae..67e48e1c916a 100644 --- a/i18n/zh-CN/docusaurus-theme-classic/footer.json +++ b/i18n/zh-CN/docusaurus-theme-classic/footer.json @@ -56,7 +56,11 @@ "description": "The label of footer link with label=Open Source linking to https://docs.kaia.io/misc/opensource/" }, "copyright": { - "message": "© Kaia DLT Foundation 2025. All rights reserved.", + "message": "© Kaia DLT Foundation 2026. All rights reserved.", "description": "The footer copyright" + }, + "link.item.label.Blog": { + "message": "博客", + "description": "The label of footer link with label=Blog linking to https://blog.kaia.io/" } } diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current.json b/i18n/zh-TW/docusaurus-plugin-content-docs/current.json index 423611fbdc54..63e573a61de6 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current.json +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current.json @@ -5,23 +5,23 @@ }, "sidebar.buildSidebar.category.Get Started": { "message": "開始", - "description": "The label for category Get Started in sidebar buildSidebar" + "description": "The label for category 'Get Started' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Smart Contracts": { "message": "智能合約", - "description": "The label for category Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Deploy Smart Contracts": { "message": "部署智能合約", - "description": "The label for category Deploy Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Deploy Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Sample Contracts": { "message": "合同樣本", - "description": "The label for category Sample Contracts in sidebar buildSidebar" + "description": "The label for category 'Sample Contracts' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Tutorials": { "message": "教程", - "description": "The label for category Tutorials in sidebar buildSidebar" + "description": "The label for category 'Tutorials' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Tools": { "message": "工具", @@ -29,51 +29,51 @@ }, "sidebar.buildSidebar.category.Wallets": { "message": "錢包", - "description": "The label for category Wallets in sidebar buildSidebar" + "description": "The label for category 'Wallets' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Wallet Libraries": { "message": "錢包圖書館", - "description": "The label for category Wallet Libraries in sidebar buildSidebar" + "description": "The label for category 'Wallet Libraries' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Oracles": { "message": "神諭", - "description": "The label for category Oracles in sidebar buildSidebar" + "description": "The label for category 'Oracles' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Indexers": { "message": "索引器", - "description": "The label for category Indexers in sidebar buildSidebar" + "description": "The label for category 'Indexers' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Cross-chain": { "message": "跨鏈", - "description": "The label for category Cross-chain in sidebar buildSidebar" + "description": "The label for category 'Cross-chain' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Block Explorers": { "message": "積木探險家", - "description": "The label for category Block Explorers in sidebar buildSidebar" + "description": "The label for category 'Block Explorers' in sidebar 'buildSidebar'" }, "sidebar.nodeSidebar.category.Endpoint Node": { "message": "端點節點", - "description": "The label for category Endpoint Node in sidebar nodeSidebar" + "description": "The label for category 'Endpoint Node' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Core Cell": { "message": "核心單元", - "description": "The label for category Core Cell in sidebar nodeSidebar" + "description": "The label for category 'Core Cell' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Install Core Cell": { "message": "安裝核心單元", - "description": "The label for category Install Core Cell in sidebar nodeSidebar" + "description": "The label for category 'Install Core Cell' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Service Chain": { "message": "服務鏈", - "description": "The label for category Service Chain in sidebar nodeSidebar" + "description": "The label for category 'Service Chain' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Quick Start": { "message": "快速入門", - "description": "The label for category Quick Start in sidebar nodeSidebar" + "description": "The label for category 'Quick Start' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Configure Service Chain": { "message": "配置服務鏈", - "description": "The label for category Configure Service Chain in sidebar nodeSidebar" + "description": "The label for category 'Configure Service Chain' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.category.Node Package Downloads": { "message": "節點軟件包下載", @@ -81,11 +81,11 @@ }, "sidebar.refSidebar.category.RPC API Reference": { "message": "RPC API 參考", - "description": "The label for category RPC API Reference in sidebar refSidebar" + "description": "The label for category 'RPC API Reference' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.SDKs and Libraries": { "message": "SDK 和庫", - "description": "The label for category SDKs and Libraries in sidebar refSidebar" + "description": "The label for category 'SDKs and Libraries' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.API References": { "message": "應用程序接口參考", @@ -97,31 +97,31 @@ }, "sidebar.learnSidebar.category.Transaction Fees": { "message": "交易費用", - "description": "The label for category Transaction Fees in sidebar learnSidebar" + "description": "The label for category 'Transaction Fees' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Verify Smart Contracts": { "message": "驗證智能合約", - "description": "The label for category Verify Smart Contracts in sidebar buildSidebar" + "description": "The label for category 'Verify Smart Contracts' in sidebar 'buildSidebar'" }, "sidebar.learnSidebar.category.Data Management": { "message": "數據管理", - "description": "The label for category Data Management in sidebar learnSidebar" + "description": "The label for category 'Data Management' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Governance": { "message": "管理", - "description": "The label for category Governance in sidebar learnSidebar" + "description": "The label for category 'Governance' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Node Quick Reference": { "message": "節點快速參考", - "description": "The label for category Node Quick Reference in sidebar learnSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Kaia Safe": { "message": "Kaia Safe", - "description": "The label for category Kaia Safe in sidebar buildSidebar" + "description": "The label for category 'Kaia Safe' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Node Quick Reference": { "message": "節點快速參考", - "description": "The label for category Node Quick Reference in sidebar buildSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.link.KaiaScan": { "message": "KaiaScan", @@ -129,47 +129,47 @@ }, "sidebar.nodeSidebar.category.Node Quick Reference": { "message": "節點快速參考", - "description": "The label for category Node Quick Reference in sidebar nodeSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'nodeSidebar'" }, "sidebar.refSidebar.category.ethers-ext < v1.0.1": { "message": "ethers-ext < v1.0.1", - "description": "The label for category ethers-ext < v1.0.1 in sidebar refSidebar" + "description": "The label for category 'ethers-ext < v1.0.1' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore": { "message": "鑰匙庫", - "description": "The label for category keystore in sidebar refSidebar" + "description": "The label for category 'keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.ethers-ext": { "message": "ethers-ext", - "description": "The label for category ethers-ext in sidebar refSidebar" + "description": "The label for category 'ethers-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.v5": { "message": "v5", - "description": "The label for category v5 in sidebar refSidebar" + "description": "The label for category 'v5' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.v6": { "message": "v6", - "description": "The label for category v6 in sidebar refSidebar" + "description": "The label for category 'v6' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3js-ext": { "message": "web3js-ext", - "description": "The label for category web3js-ext in sidebar refSidebar" + "description": "The label for category 'web3js-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3j-ext": { "message": "web3j-ext", - "description": "The label for category web3j-ext in sidebar refSidebar" + "description": "The label for category 'web3j-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.web3py-ext": { "message": "web3py-ext", - "description": "The label for category web3py-ext in sidebar refSidebar" + "description": "The label for category 'web3py-ext' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.Node Quick Reference": { "message": "節點快速參考", - "description": "The label for category Node Quick Reference in sidebar refSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'refSidebar'" }, "sidebar.buildSidebar.category.Hardware Wallets": { "message": "硬件錢包", - "description": "The label for category Hardware Wallets in sidebar buildSidebar" + "description": "The label for category 'Hardware Wallets' in sidebar 'buildSidebar'" }, "sidebar.miniDappSidebar.category.Build Mini dApps on LINE with Unity": { "message": "使用 Unity 在 LINE 上構建迷你 dApps", @@ -177,107 +177,107 @@ }, "sidebar.miniDappSidebar.category.Node Quick Reference": { "message": "節點快速參考", - "description": "The label for category Node Quick Reference in sidebar miniDappSidebar" + "description": "The label for category 'Node Quick Reference' in sidebar 'miniDappSidebar'" }, "sidebar.learnSidebar.category.Core Concepts": { "message": "核心理念", - "description": "The label for category Core Concepts in sidebar learnSidebar" + "description": "The label for category 'Core Concepts' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Smart Contracts": { "message": "智慧型契約", - "description": "The label for category Smart Contracts in sidebar learnSidebar" + "description": "The label for category 'Smart Contracts' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Advanced Topics": { "message": "進階主題", - "description": "The label for category Advanced Topics in sidebar learnSidebar" + "description": "The label for category 'Advanced Topics' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Transaction Execution": { "message": "交易執行", - "description": "The label for category Transaction Execution in sidebar learnSidebar" + "description": "The label for category 'Transaction Execution' in sidebar 'learnSidebar'" }, "sidebar.learnSidebar.category.Token Economics": { "message": "代幣經濟學", - "description": "The label for category Token Economics in sidebar learnSidebar" + "description": "The label for category 'Token Economics' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Transactions": { "message": "交易", - "description": "The label for category Transactions in sidebar buildSidebar" + "description": "The label for category 'Transactions' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Token Management": { "message": "代幣管理", - "description": "The label for category Token Management in sidebar buildSidebar" + "description": "The label for category 'Token Management' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Team Finance": { "message": "團隊財務", - "description": "The label for category Team Finance in sidebar buildSidebar" + "description": "The label for category 'Team Finance' in sidebar 'buildSidebar'" }, "sidebar.miniDappSidebar.category.LINE Mini DApp with Unity": { "message": "使用 Unity 的 LINE Mini DApp", - "description": "The label for category LINE Mini DApp with Unity in sidebar miniDappSidebar" + "description": "The label for category 'LINE Mini DApp with Unity' in sidebar 'miniDappSidebar'" }, "sidebar.miniDappSidebar.category.LINE Mini DApp with Cocos": { "message": "使用 Cocos 的 LINE Mini DApp", - "description": "The label for category LINE Mini DApp with Cocos in sidebar miniDappSidebar" + "description": "The label for category 'LINE Mini DApp with Cocos' in sidebar 'miniDappSidebar'" }, "sidebar.miniDappSidebar.category.Survey Mini DApp": { "message": "調查迷你 DApp", - "description": "The label for category Survey Mini DApp in sidebar miniDappSidebar" + "description": "The label for category 'Survey Mini DApp' in sidebar 'miniDappSidebar'" }, "sidebar.learnSidebar.link.Docs Updates": { "message": "文件更新", - "description": "The label for link Docs Updates in sidebar learnSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'learnSidebar', linking to '/misc/updates'" }, "sidebar.buildSidebar.link.Docs Updates": { "message": "文件更新", - "description": "The label for link Docs Updates in sidebar buildSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'buildSidebar', linking to '/misc/updates'" }, "sidebar.nodeSidebar.category.Debugging and Diagnostics": { "message": "除錯與診斷", - "description": "The label for category Debugging and Diagnostics in sidebar nodeSidebar" + "description": "The label for category 'Debugging and Diagnostics' in sidebar 'nodeSidebar'" }, "sidebar.nodeSidebar.link.Docs Updates": { "message": "文件更新", - "description": "The label for link Docs Updates in sidebar nodeSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'nodeSidebar', linking to '/misc/updates'" }, "sidebar.refSidebar.link.Docs Updates": { "message": "文件更新", - "description": "The label for link Docs Updates in sidebar refSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'refSidebar', linking to '/misc/updates'" }, "sidebar.miniDappSidebar.link.Docs Updates": { "message": "文件更新", - "description": "The label for link Docs Updates in sidebar miniDappSidebar, linking to /misc/updates" + "description": "The label for link 'Docs Updates' in sidebar 'miniDappSidebar', linking to '/misc/updates'" }, "sidebar.learnSidebar.category.Finschia to Kaia": { "message": "Finschia 至 Kaia", - "description": "The label for category Finschia to Kaia in sidebar learnSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'learnSidebar'" }, "sidebar.buildSidebar.category.Finschia to Kaia": { "message": "Finschia 至 Kaia", - "description": "The label for category Finschia to Kaia in sidebar buildSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'buildSidebar'" }, "sidebar.nodeSidebar.category.Finschia to Kaia": { "message": "Finschia 至 Kaia", - "description": "The label for category Finschia to Kaia in sidebar nodeSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'nodeSidebar'" }, "sidebar.refSidebar.category.Finschia to Kaia": { "message": "Finschia 至 Kaia", - "description": "The label for category Finschia to Kaia in sidebar refSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'refSidebar'" }, "sidebar.miniDappSidebar.category.Finschia to Kaia": { "message": "Finschia 至 Kaia", - "description": "The label for category Finschia to Kaia in sidebar miniDappSidebar" + "description": "The label for category 'Finschia to Kaia' in sidebar 'miniDappSidebar'" }, "sidebar.buildSidebar.category.Wallet Configuration": { "message": "錢包組態", - "description": "The label for category Wallet Configuration in sidebar buildSidebar" + "description": "The label for category 'Wallet Configuration' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Wallet Operations": { "message": "錢包運作", - "description": "The label for category Wallet Operations in sidebar buildSidebar" + "description": "The label for category 'Wallet Operations' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.dApp Integration": { "message": "dApp 整合", - "description": "The label for category dApp Integration in sidebar buildSidebar" + "description": "The label for category 'dApp Integration' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Implementing Transactions": { "message": "執行交易", @@ -285,27 +285,27 @@ }, "sidebar.buildSidebar.category.Cookbooks": { "message": "烹飪書籍", - "description": "The label for category Cookbooks in sidebar buildSidebar" + "description": "The label for category 'Cookbooks' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Fundamentals": { "message": "基礎", - "description": "The label for category Fundamentals in sidebar buildSidebar" + "description": "The label for category 'Fundamentals' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Token Development": { "message": "代幣開發", - "description": "The label for category Token Development in sidebar buildSidebar" + "description": "The label for category 'Token Development' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Deployment & Verification": { "message": "部署與驗證", - "description": "The label for category Deployment & Verification in sidebar buildSidebar" + "description": "The label for category 'Deployment & Verification' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Integrate Gas Abstraction (GA)": { "message": "整合瓦斯抽取 (GA)", - "description": "The label for category Integrate Gas Abstraction (GA) in sidebar buildSidebar" + "description": "The label for category 'Integrate Gas Abstraction (GA)' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Kaia Agent Kit": { "message": "Kaia 代理套件", - "description": "The label for category Kaia Agent Kit in sidebar buildSidebar" + "description": "The label for category 'Kaia Agent Kit' in sidebar 'buildSidebar'" }, "sidebar.refSidebar.category.Gas Abstraction": { "message": "瓦斯抽取", @@ -313,306 +313,306 @@ }, "sidebar.refSidebar.category.viem-ext": { "message": "viem-ext", - "description": "The label for category viem-ext in sidebar refSidebar" + "description": "The label for category 'viem-ext' in sidebar 'refSidebar'" }, "sidebar.buildSidebar.doc.Step 1: Foundation Setup": { "message": "步驟 1:地基設定", - "description": "The label for the doc item Step 1: Foundation Setup in sidebar buildSidebar, linking to the doc build/get-started/foundation-setup" + "description": "The label for the doc item 'Step 1: Foundation Setup' in sidebar 'buildSidebar', linking to the doc build/get-started/foundation-setup" }, "sidebar.buildSidebar.doc.Step 2: Set up Account and Networks": { "message": "步驟 2:設定帳號和網路", - "description": "The label for the doc item Step 2: Set up Account and Networks in sidebar buildSidebar, linking to the doc build/get-started/wallet-config-get-started" + "description": "The label for the doc item 'Step 2: Set up Account and Networks' in sidebar 'buildSidebar', linking to the doc build/get-started/wallet-config-get-started" }, "sidebar.buildSidebar.doc.Step 3: Get KAIA": { "message": "步驟 3:取得 KAIA", - "description": "The label for the doc item Step 3: Get KAIA in sidebar buildSidebar, linking to the doc build/get-started/getting-kaia" + "description": "The label for the doc item 'Step 3: Get KAIA' in sidebar 'buildSidebar', linking to the doc build/get-started/getting-kaia" }, "sidebar.buildSidebar.doc.Step 4: Deploy Hello World Contract": { "message": "步驟 4:部署 Hello World 合約", - "description": "The label for the doc item Step 4: Deploy Hello World Contract in sidebar buildSidebar, linking to the doc build/get-started/kaiagreeter-get-started" + "description": "The label for the doc item 'Step 4: Deploy Hello World Contract' in sidebar 'buildSidebar', linking to the doc build/get-started/kaiagreeter-get-started" }, "sidebar.buildSidebar.doc.Step 5: Deploy your First Token Contract": { "message": "步驟 5:部署您的第一份代幣合約", - "description": "The label for the doc item Step 5: Deploy your First Token Contract in sidebar buildSidebar, linking to the doc build/get-started/hardhat" + "description": "The label for the doc item 'Step 5: Deploy your First Token Contract' in sidebar 'buildSidebar', linking to the doc build/get-started/hardhat" }, "sidebar.buildSidebar.doc.Step 6: Build your First dApp on Kaia": { "message": "步驟 6:在 Kaia 上建立您的第一個 dApp", - "description": "The label for the doc item Step 6: Build your First dApp on Kaia in sidebar buildSidebar, linking to the doc build/get-started/scaffold-eth-get-started" + "description": "The label for the doc item 'Step 6: Build your First dApp on Kaia' in sidebar 'buildSidebar', linking to the doc build/get-started/scaffold-eth-get-started" }, "sidebar.buildSidebar.doc.Step 7: Build your Mini dApp on Kaia": { "message": "步驟 7:在 Kaia 上建立您的迷你 dApp", - "description": "The label for the doc item Step 7: Build your Mini dApp on Kaia in sidebar buildSidebar, linking to the doc minidapps/minidapps" + "description": "The label for the doc item 'Step 7: Build your Mini dApp on Kaia' in sidebar 'buildSidebar', linking to the doc minidapps/minidapps" }, "sidebar.buildSidebar.category.smart-contract-tools": { "message": "工具", - "description": "The label for category Tools in sidebar buildSidebar" + "description": "The label for category 'Tools' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Best Practices": { "message": "最佳實務", - "description": "The label for category Best Practices in sidebar buildSidebar" + "description": "The label for category 'Best Practices' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.build-tools": { "message": "工具", - "description": "The label for category Tools in sidebar buildSidebar" + "description": "The label for category 'Tools' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.category.Gaming SDKs": { "message": "遊戲 SDK", - "description": "The label for category Gaming SDKs in sidebar buildSidebar" + "description": "The label for category 'Gaming SDKs' in sidebar 'buildSidebar'" }, "sidebar.buildSidebar.doc.Proof of Play vRNG": { "message": "遊戲證明 vRNG", - "description": "The label for the doc item Proof of Play vRNG in sidebar buildSidebar, linking to the doc build/tools/oracles/vrng-pop" + "description": "The label for the doc item 'Proof of Play vRNG' in sidebar 'buildSidebar', linking to the doc build/tools/oracles/vrng-pop" }, "sidebar.refSidebar.category.account-management-v5": { "message": "帳戶管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v5": { "message": "帳戶鑰匙", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v5": { "message": "簽署交易", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v5": { "message": "標誌訊息", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-v5": { "message": "鑰匙店", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v5": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v5": { "message": "授權交易費用", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v5": { "message": "智慧型契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-v5": { "message": "工具", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-v6": { "message": "帳戶管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v6": { "message": "帳戶鑰匙", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v6": { "message": "簽署交易", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v6": { "message": "標誌訊息", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-v6": { "message": "鑰匙店", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v6": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v6": { "message": "授權交易費用", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.gas-abstraction-ethers": { "message": "瓦斯抽取", - "description": "The label for category Gas Abstraction in sidebar refSidebar" + "description": "The label for category 'Gas Abstraction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v6": { "message": "智慧型契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-v6": { "message": "工具", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-v1": { "message": "帳戶管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-v1": { "message": "帳戶鑰匙", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-v1": { "message": "簽署交易", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-v1": { "message": "標誌訊息", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-v1": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-v1": { "message": "授權交易費用", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-v1": { "message": "智慧型契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3js": { "message": "帳戶管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3js": { "message": "帳戶鑰匙", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3js": { "message": "簽署交易", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3js": { "message": "標誌訊息", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3js": { "message": "鑰匙店", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3js": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3js": { "message": "授權交易費用", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.gas-abstraction-web3js": { "message": "瓦斯抽取", - "description": "The label for category Gas Abstraction in sidebar refSidebar" + "description": "The label for category 'Gas Abstraction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3js": { "message": "智慧型契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3js": { "message": "工具", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-viem": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-viem": { "message": "授權交易費用", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-viem": { "message": "智慧型契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3j": { "message": "帳戶管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3j": { "message": "帳戶鑰匙", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3j": { "message": "簽署交易", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3j": { "message": "標誌訊息", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3j": { "message": "鑰匙店", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3j": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3j": { "message": "授權交易費用", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3j": { "message": "智慧型契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3j": { "message": "工具", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-management-web3py": { "message": "帳戶管理", - "description": "The label for category Account Management in sidebar refSidebar" + "description": "The label for category 'Account Management' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.account-key-web3py": { "message": "帳戶鑰匙", - "description": "The label for category Account Key in sidebar refSidebar" + "description": "The label for category 'Account Key' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-transaction-web3py": { "message": "簽署交易", - "description": "The label for category Sign Transaction in sidebar refSidebar" + "description": "The label for category 'Sign Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.sign-message-web3py": { "message": "標誌訊息", - "description": "The label for category Sign Message in sidebar refSidebar" + "description": "The label for category 'Sign Message' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.keystore-web3py": { "message": "鑰匙店", - "description": "The label for category Keystore in sidebar refSidebar" + "description": "The label for category 'Keystore' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.basic-transaction-web3py": { "message": "基本交易", - "description": "The label for category Basic Transaction in sidebar refSidebar" + "description": "The label for category 'Basic Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.fee-delegated-transaction-web3py": { "message": "授權交易費用", - "description": "The label for category Fee Delegated Transaction in sidebar refSidebar" + "description": "The label for category 'Fee Delegated Transaction' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.smart-contract-web3py": { "message": "智慧型契約", - "description": "The label for category Smart Contract in sidebar refSidebar" + "description": "The label for category 'Smart Contract' in sidebar 'refSidebar'" }, "sidebar.refSidebar.category.utils-web3py": { "message": "工具", - "description": "The label for category Utils in sidebar refSidebar" + "description": "The label for category 'Utils' in sidebar 'refSidebar'" }, "sidebar.refSidebar.doc.getting-started-ethers": { "message": "開始使用", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/ethers-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/ethers-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-ethers-v1": { "message": "開始使用", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/ethers-ext-prior-v1-0-1/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/ethers-ext-prior-v1-0-1/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3js": { "message": "開始使用", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3js-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3js-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-viem": { "message": "開始使用", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/viem-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/viem-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3j": { "message": "開始使用", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3j-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3j-ext/getting-started" }, "sidebar.refSidebar.doc.getting-started-web3py": { "message": "入門", - "description": "The label for the doc item Getting-Started in sidebar refSidebar, linking to the doc references/sdk/web3py-ext/getting-started" + "description": "The label for the doc item 'Getting-Started' in sidebar 'refSidebar', linking to the doc references/sdk/web3py-ext/getting-started" } } diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md index 056e8b6cf6fa..24f8e247565e 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tools/gaming-sdks/chainsafe.md @@ -10,5 +10,5 @@ Web3.unity SDK 目前支援 Kaia Mainnet 和 Kairos Testnet。 若要開始在 Kaia 上建立支援區塊鏈的遊戲,請查看下列指南: -- [Unity Game Development on Kaia: Minting Fungible Tokens with ChainSafe](https://medium.com/kaiachain/unity-game-development-on-kaia-minting-fungible-tokens-with-chainsafe-beea9022c42d) -- [如何在 Kaia 上使用 Chainsafe 和 Thirdweb 對 Unity 遊戲進行代幣閘門](https://medium.com/kaiachain/how-to-token-gate-a-unity-game-using-chainsafe-and-thirdweb-on-kaia-93c574519da2) +- [Unity Game Development on Kaia: Minting Fungible Tokens with ChainSafe](https://blog.kaia.io/unity-game-development-on-kaia-minting-fungible-tokens-with-chainsafe/) +- [如何在 Kaia 上使用 Chainsafe 和 Thirdweb 對 Unity 遊戲進行代幣閘門](https://blog.kaia.io/how-to-token-gate-a-unity-game-using-chainsafe-and-thirdweb-on-kaia/) diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md index 0120698825d4..6d59e09d38e6 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/buy-me-a-coffee.md @@ -887,4 +887,4 @@ Fleek 是一種基礎設施,使我們能夠在 IPFS 上構建現代網站和 在此基礎上,您還可以在前臺探索一些其他選項,比如除了靜態發送 1 KAIA 咖啡外,還可以添加一個新的輸入字段,用於輸入要發送的咖啡量。 您可以訪問 [github](https://github.com/ayo-klaytn/buy-me-a-coffee) 上的完整代碼庫,也可以使用 [link](https://spring-fog-0605.on.fleek.co/) 測試網站。 -如果您想了解更多信息,請訪問 [Kaia 文檔](https://docs.klaytn.foundation/)、[Web3Onboard 文檔](https://onboard.blocknative.com/docs/modules/react) 和 [Fleek 文檔](https://docs.fleek.co/tutorials/hosting/)。 如果您有任何問題,請訪問 [Kaia 論壇](https://devforum.kaia.io/)。 +如果您想瞭解更多資訊,請造訪 [Kaia Docs](https://docs.kaia.io)、[Web3Onboard Docs](https://onboard.blocknative.com/docs/modules/react) 和 [Fleek Docs](https://docs.fleek.co/tutorials/hosting/)。 如果您有任何問題,請訪問 [Kaia 論壇](https://devforum.kaia.io/)。 diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md new file mode 100644 index 000000000000..0177abeabbfd --- /dev/null +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/cross-chain-nft.md @@ -0,0 +1,748 @@ +# 使用 Chainlink CCIP 在 Kaia 上建立跨鏈 NFT:實用指南 + +## 介紹 + +NFT 已經成為區塊鏈技術最知名的用例之一,能夠創建獨一無二、可驗證的數位資產。 然而,傳統的 NFT 實作被綁定在單一區塊鏈上。 此限制降低了靈活性,並使資產無法在社群、流動性和效用可能不同的生態系統中自由移動。 + +跨鏈 NFT 可讓 NFT 在區塊鏈之間無縫移動,同時保留其唯一性和來源,從而解決了這一挑戰。 透過 Chainlink 的跨鏈互通協定 (CCIP),開發人員可以使用標準化、安全的訊息傳輸架構,在各鏈之間建立可靠的橋梁。 + +在本指南中,您將使用「燒機-造幣」模式建立並部署 Crosschain NFT。 NFT 會在來源鏈上燒錄,並在目的地鏈上以相同的 tokenId 和元資料重新製作,以確保在任何時候都只有一份有效的副本存在。 + +## 要求 + +開始之前,請確認您已完成下列設定: + +- [Node.js](https://nodejs.org/) 和 [npm](https://www.npmjs.com/) +- 硬帽 + - 安裝:安裝: `npm install --save-dev hardhat` + - 初始化專案: `npx hardhat --init` +- [MetaMask](https://metamask.io/en-GB/download) 錢包 + - 建立或設定開發錢包。 + - 將 Kaia Kairos Testnet 和 Ethereum Sepolia 網路同時加入 MetaMask。 +- 來自水龍頭的測試代幣 + - [KAIA](https://faucet.kaia.io/): 部署契約或傳送交易時,在 Kaia 上支付瓦斯費。 + - [LINK](https://faucets.chain.link/kaia-testnet) (testnet):以 LINK 付款時涵蓋 CCIP 費用。 + - [Sepolia ETH](https://faucets.chain.link/sepolia): 支付 Sepolia 上的瓦斯費,如果選擇了,也可以支付原生 ETH 的 CCIP 費用。 +- [Filebase](https://filebase.com/) 帳戶 + - 需要上傳和擷取 NFT 元資料 (IPFS 儲存)。 + +## 跨鏈 NFT 如何運作? + +NFT 是記錄在單一區塊鏈上的唯一數位代幣。 其核心行為,包括鑄幣、轉讓和所有權,都是由與該鏈相連的智慧型契約所定義的。 正因如此,如果沒有額外的機制,NFT 就無法自然地在區塊鏈間移動。 為了實現互操作性,開發人員會在多個鏈上部署配套合約,並透過跨鏈訊息將其連結起來。 結果就是跨區塊鏈 NFT:存在於各區塊鏈上的等價代幣,但在任何特定時間只有一份是有效的。 + +跨鏈 NFT 通常以三種方式之一實現: + +- \*\* 燒錄與鑄造\*\*:在來源鏈上燒錄 NFT,然後在目的地鏈上鑄造等值的 NFT。 + +- **鎖定和鑄造**:在來源鏈上鎖定 NFT,並在目的地鑄造複本。 返回時需要燒毀複製品以解鎖正本。 + +- \*\* 鎖定與解鎖\*\*:相同的集合部署在多個鏈上。 擁有者鎖定一條鏈上的 NFT,以解鎖另一條鏈上的對應副本,確保一次只能使用一個副本。 + +在本指南中,我們將使用燃燒和薄荷模型來進行 Crosschain NFT。 NFT 將從一條鏈上移除,並在另一條鏈上重新建立,整個過程由 Chainlink CCIP 驅動。 + +## 開始使用 + +在本指南中,您將使用 Chainlink CCIP 在 Kaia Kairos Testnet 和 Ethereum Sepolia 之間製造和傳輸跨鏈 NFT。 + +到最後,您將能夠 + +- 初始化同時為 Kairos Testnet 和 Ethereum Sepolia 設定的 Hardhat 專案 +- 新增 Chainlink CCIP 契約和介面為依賴項目 +- 實施跨鏈 NFT 契約,並針對跨鏈轉移採用燒幣機制 +- 將合約部署到兩個網路,並跨鏈傳送 NFT。 + +### 建立硬頭帽專案 + +在本教程中,我們將使用 [Hardhat 3](https://hardhat.org/docs/getting-started#getting-started-with-hardhat-3) 來部署和互動我們的合約。 Hardhat 3 提供了新功能,例如本機支援加密的 keystores、在 Solidity 中撰寫測試的能力,以及改進的專案工具。 + +按照以下步驟設定專案: + +1. 驗證 Node.js 和 npm 安裝 + + 執行下列指令以驗證 Node.js 和 npm 是否已安裝: + +```bash +node -v +npm -v +``` + +2. 初始化新的專案目錄 + + 建立新資料夾,導覽到其中,並初始化 Node.js 專案: + +```bash +mkdir ccip-nft-kaia-hardhat-example +cd ccip-nft-kaia-hardhat-example +npm init -y +``` + +3. 建立硬帽專案 + + 運行: + +```bash +npx hardhat --init +``` + +出現提示時,請選擇包含 Node.js 測試 runner 和 ethers 的範例專案。 在目前目錄中初始化,並安裝所有需要的相依性。 + +### 安裝所需的合約 + +安裝 Chainlink CCIP 合約: + +```bash +npm i @chainlink/contracts-ccip --save-dev +``` + +安裝標準 Chainlink 合約: + +```bash +npm i @chainlink/contracts --save-dev +``` + +安裝 OpenZeppelin 契約 (提供 ERC-721 及其他基礎實作): + +```bash +npm i @openzeppelin/contracts --save-dev +``` + +## 設定 NFT 元資料 + +在撰寫合約之前,讓我們先定義我們要鑄造的 NFT 的規格。 每個 NFT 都需要描述其名稱、描述和影像的元資料,儲存於 JSON 檔案中,並託管於 IPFS。 + +在本指南中,我們將使用 Filebase 來儲存影像和元資料。 如果您想要建立自己的 NFT,請透過 Filebase 將影像和 metadata JSON 檔案上傳至 IPFS。 上傳後,按一下檔案索引標籤中的檔案名稱,並複製 IPFS URL。 它看起來會與此相似: + +```bash +https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmY1LZF8JHo2r3h4X5VzLLXtJujqnBFGTyo2aqR9joXnt8 +``` + +以下是您可以使用的範例 metadata 檔案: + +```json +{ + "name": "Kairos NFT", + "description": "gkaia frens! gazuaaaaa!!!", + "image": "https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmRvQc4wZCp6NF7dFL4ywiWTG7FSH3KKGUAkXGgsdYfcKi" +} +``` + +## 撰寫智慧型契約 + +在本節中,您將使用由 Chainlink CCIP 驅動的燃燒-造幣模型實現合約,使 NFT 在區塊鏈之間轉移。 + +在專案的 contracts 目錄中建立新檔案,命名為 `CrosschainNFT.sol`,並將下列程式碼貼入其中: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; +import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import {ERC721URIStorage} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; +import {ERC721Burnable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; +import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import {Client} from "@chainlink/contracts-ccip/contracts/libraries/Client.sol"; +import {IRouterClient} from "@chainlink/contracts-ccip/contracts/interfaces/IRouterClient.sol"; +import {IAny2EVMMessageReceiver} from "@chainlink/contracts-ccip/contracts/interfaces/IAny2EVMMessageReceiver.sol"; +import {OwnerIsCreator} from "@chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol"; +import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; +/** + * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. + * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. + * DO NOT USE THIS CODE IN PRODUCTION. + */ + // Source chain is Ethereum Sepolia + // Destination chain is Kairos Testnet +contract CrosschainNFT is ERC721, ERC721URIStorage, ERC721Burnable, IAny2EVMMessageReceiver, ReentrancyGuard, OwnerIsCreator { + using SafeERC20 for IERC20; + enum PayFeesIn { + Native, + LINK + } + error InvalidRouter(address router); + error OnlyOnEthereumSepolia(); + error NotEnoughBalanceForFees(uint256 currentBalance, uint256 calculatedFees); + error NothingToWithdraw(); + error FailedToWithdrawEth(address owner, address target, uint256 value); + error ChainNotEnabled(uint64 chainSelector); + error SenderNotEnabled(address sender); + error OperationNotAllowedOnCurrentChain(uint64 chainSelector); + struct crosschainNFTDetails { + address crosschainNFTAddress; + bytes ccipExtraArgsBytes; + } + uint256 constant ETHEREUM_SEPOLIA_CHAIN_ID = 11155111; + string tokenNFTURI = "https://disastrous-turquoise-parakeet.myfilebase.com/ipfs/QmY1LZF8JHo2r3h4X5VzLLXtJujqnBFGTyo2aqR9joXnt8"; + IRouterClient internal immutable i_ccipRouter; + LinkTokenInterface internal immutable i_linkToken; + uint64 private immutable i_currentChainSelector; + uint256 private _nextTokenId; + mapping(uint64 destChainSelector => crosschainNFTDetails crosschainNFTPerChain) public s_chains; + event ChainEnabled(uint64 chainSelector, address xNftAddress, bytes ccipExtraArgs); + event ChainDisabled(uint64 chainSelector); + event CrossChainSent( + address from, address to, uint256 tokenId, uint64 sourceChainSelector, uint64 destinationChainSelector + ); + event CrossChainReceived( + address from, address to, uint256 tokenId, uint64 sourceChainSelector, uint64 destinationChainSelector + ); + modifier onlyRouter() { + if (msg.sender != address(i_ccipRouter)) { + revert InvalidRouter(msg.sender); + } + _; + } + modifier onlyOnEthereumSepolia() { + if (block.chainid != ETHEREUM_SEPOLIA_CHAIN_ID) { + revert OnlyOnEthereumSepolia(); + } + _; + } + modifier onlyEnabledChain(uint64 _chainSelector) { + if (s_chains[_chainSelector].crosschainNFTAddress == address(0)) { + revert ChainNotEnabled(_chainSelector); + } + _; + } + modifier onlyEnabledSender(uint64 _chainSelector, address _sender) { + if (s_chains[_chainSelector].crosschainNFTAddress != _sender) { + revert SenderNotEnabled(_sender); + } + _; + } + modifier onlyOtherChains(uint64 _chainSelector) { + if (_chainSelector == i_currentChainSelector) { + revert OperationNotAllowedOnCurrentChain(_chainSelector); + } + _; + } + constructor(address ccipRouterAddress, address linkTokenAddress, uint64 currentChainSelector) + ERC721("Cross Chain NFT", "XNFT") + { + if (ccipRouterAddress == address(0)) revert InvalidRouter(address(0)); + i_ccipRouter = IRouterClient(ccipRouterAddress); + i_linkToken = LinkTokenInterface(linkTokenAddress); + i_currentChainSelector = currentChainSelector; + } + function mint() external onlyOnEthereumSepolia { + uint256 tokenId = _nextTokenId++; + _safeMint(msg.sender, tokenId); + _setTokenURI(tokenId, tokenNFTURI); + } + function enableChain(uint64 chainSelector, address crosschainNFTAddress, bytes memory ccipExtraArgs) + external + onlyOwner + onlyOtherChains(chainSelector) + { + s_chains[chainSelector] = crosschainNFTDetails({crosschainNFTAddress: crosschainNFTAddress, ccipExtraArgsBytes: ccipExtraArgs}); + emit ChainEnabled(chainSelector, crosschainNFTAddress, ccipExtraArgs); + } + function disableChain(uint64 chainSelector) external onlyOwner onlyOtherChains(chainSelector) { + delete s_chains[chainSelector]; + emit ChainDisabled(chainSelector); + } + function crossChainTransferFrom( + address from, + address to, + uint256 tokenId, + uint64 destinationChainSelector, + PayFeesIn payFeesIn + ) external nonReentrant onlyEnabledChain(destinationChainSelector) returns (bytes32 messageId) { + string memory tokenUri = tokenURI(tokenId); + _burn(tokenId); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(s_chains[destinationChainSelector].crosschainNFTAddress), + data: abi.encode(from, to, tokenId, tokenUri), + tokenAmounts: new Client.EVMTokenAmount[](0), + extraArgs: s_chains[destinationChainSelector].ccipExtraArgsBytes, + feeToken: payFeesIn == PayFeesIn.LINK ? address(i_linkToken) : address(0) + }); + // Get the fee required to send the CCIP message + uint256 fees = i_ccipRouter.getFee(destinationChainSelector, message); + if (payFeesIn == PayFeesIn.LINK) { + if (fees > i_linkToken.balanceOf(address(this))) { + revert NotEnoughBalanceForFees(i_linkToken.balanceOf(address(this)), fees); + } + // Approve the Router to transfer LINK tokens on contract's behalf. It will spend the fees in LINK + i_linkToken.approve(address(i_ccipRouter), fees); + // Send the message through the router and store the returned message ID + messageId = i_ccipRouter.ccipSend(destinationChainSelector, message); + } else { + if (fees > address(this).balance) { + revert NotEnoughBalanceForFees(address(this).balance, fees); + } + // Send the message through the router and store the returned message ID + messageId = i_ccipRouter.ccipSend{value: fees}(destinationChainSelector, message); + } + emit CrossChainSent(from, to, tokenId, i_currentChainSelector, destinationChainSelector); + } + /// @inheritdoc IAny2EVMMessageReceiver + function ccipReceive(Client.Any2EVMMessage calldata message) + external + virtual + override + onlyRouter + nonReentrant + onlyEnabledChain(message.sourceChainSelector) + onlyEnabledSender(message.sourceChainSelector, abi.decode(message.sender, (address))) + { + uint64 sourceChainSelector = message.sourceChainSelector; + (address from, address to, uint256 tokenId, string memory tokenUri) = + abi.decode(message.data, (address, address, uint256, string)); + _safeMint(to, tokenId); + _setTokenURI(tokenId, tokenUri); + emit CrossChainReceived(from, to, tokenId, sourceChainSelector, i_currentChainSelector); + } + function withdraw(address _beneficiary) public onlyOwner { + uint256 amount = address(this).balance; + if (amount == 0) revert NothingToWithdraw(); + (bool sent,) = _beneficiary.call{value: amount}(""); + if (!sent) revert FailedToWithdrawEth(msg.sender, _beneficiary, amount); + } + function withdrawToken(address _beneficiary, address _token) public onlyOwner { + uint256 amount = IERC20(_token).balanceOf(address(this)); + if (amount == 0) revert NothingToWithdraw(); + IERC20(_token).safeTransfer(_beneficiary, amount); + } + function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) { + return super.tokenURI(tokenId); + } + function getCCIPRouter() public view returns (address) { + return address(i_ccipRouter); + } + function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721URIStorage) returns (bool) { + return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || super.supportsInterface(interfaceId); + } +} +``` + +### 代碼演練 + +CrosschainNFT 是一種 ERC-721 契約,整合 Chainlink CCIP 以在區塊鏈之間轉移 NFT。 它會在來源鏈上燒錄 NFT,並使用相同的 tokenId 和 tokenURI 在目的地上重新燒錄。 該合約透過 enableChain 維護已核准目的鏈的註冊表,依賴 Chainlink Router (IRouterClient) 進行跨鏈訊息傳輸,並支援以原生瓦斯代幣或 LINK 支付費用。 + +主要功能 + +- 啟用鏈 + +允許合約擁有者註冊目標區塊鏈。 它會在 s_chains 映射中儲存對應的 NFT 合約位址和 CCIP 參數,將鏈白名單列為有效的傳輸目標。 當設定完成時,會發出 ChainEnabled 事件。 + +- CrossChainTransferFrom + +執行 NFT 跨鏈傳輸。 它首先檢查目的地鏈是否啟用,然後擷取 NFT 元資料 (tokenURI),並在來源鏈上燒錄令牌。 接下來,它會建立一個包含轉帳詳細資訊的 CCIP 訊息,計算所需費用,並以 LINK 或本地瓦斯支付。 一旦訊息透過路由器傳送,就會發佈 CrossChainSent 事件來記錄傳輸。 + +現在,`CrosschainNFT.sol` 的核心流程已經清楚,讓我們進入下一步。 + +## 編譯智慧型契約 + +要編譯您的智慧型契約,請執行 + +```bash +npx hardhat build +``` + +## 部署智慧契約 + +在本節中,我們將設定必要的變數,然後在 Ethereum Sepolia(源鏈)和 Kairos Testnet(目的鏈)上部署「CrosschainNFT.sol」契約。 + +### 使用加密金鑰庫 + +Hardhat 3 的優點之一,是能夠將私鑰和 RPC URL 等敏感值儲存在加密的 keystore 中,而非純文字檔案中。 在本指南中,我們將為 Sepolia 和 Kairos 的 _PRIVATE_KEY_ 和 _RPC URL_ 加密。 + +\*\* 新增您的私人密碼匙\*\* + +```bash +npx hardhat keystore set PRIVATE_KEY +``` + +第一次執行此指令時,Hardhat 會提示您為 keystore 建立密碼。 每次新增或更新值時,您都需要這個密碼。 + +\*\* 為每個網路加入 RPC URL\*\* + +```bash +npx hardhat keystore set KAIROS_RPC_URL +npx hardhat keystore set SEPOLIA_RPC_URL +``` + +最後,編輯您的 `hardhat.config.ts` 檔案以載入這些加密值,並設定兩個網路。 + +```typescript +import type { HardhatUserConfig } from "hardhat/config"; +import hardhatToolboxMochaEthersPlugin from "@nomicfoundation/hardhat-toolbox-mocha-ethers"; +import { configVariable } from "hardhat/config"; +const config: HardhatUserConfig = { + plugins: [hardhatToolboxMochaEthersPlugin], + solidity: { + profiles: { + default: { + version: "0.8.28", + }, + production: { + version: "0.8.28", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + }, + }, + networks: { + hardhatMainnet: { + type: "edr-simulated", + chainType: "l1", + }, + hardhatOp: { + type: "edr-simulated", + chainType: "op", + }, + kairosTestnet: { + type: "http", + chainType: "l1", + url: configVariable("KAIROS_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + ethereumSepolia: { + type: "http", + chainType: "l1", + url: configVariable("SEPOLIA_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + }, +}; +export default config; +``` + +下一步是將 CrosschainNFT 智慧型契約分別部署到 Ethereum Sepolia 和 Kairos Testnet。 + +### 將 CrosschainNFT.sol 部署至 Ethereum Sepolia + +部署前,請從 [Chainlink CCIP Directory](https://docs.chain.link/ccip/directory/testnet/chain/ethereum-testnet-sepolia) 取得下列 Ethereum Sepolia 的值: + +- 鏈條選擇器 +- CCIP 路由器位址 +- LINK 記憶體位址 + +您的部署腳本將需要這些值。 接下來,導覽到專案中的 _ignition/modules_ 資料夾,建立一個名為:`deployEthereumSepolia.ts` 的新檔案,並將下列程式碼貼入其中: + +```typescript +// This setup uses Hardhat Ignition to manage smart contract deployments. +// Learn more about it at https://hardhat.org/ignition +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const ETHEREUM_SEPOLIA_ROUTER_ADDRESS = `0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59`; +const ETHEREUM_SEPOLIA_LINK_TOKEN_ADDRESS = `0x779877A7B0D9E8603169DdbD7836e478b4624789`; +const ETHEREUM_SEPOLIA_CHAIN_SELECTOR = `16015286601757825753`; +const CrosschainNFTSepoliaModule = buildModule("CrosschainNFTSepoliaModule", (m) => { + const crosschainNFTSepolia = m.contract("CrosschainNFT", [ETHEREUM_SEPOLIA_ROUTER_ADDRESS, ETHEREUM_SEPOLIA_LINK_TOKEN_ADDRESS, ETHEREUM_SEPOLIA_CHAIN_SELECTOR], { + }); + return { crosschainNFTSepolia }; +}); +export default CrosschainNFTSepoliaModule; +``` + +執行部署指令碼: + +```bash +npx hardhat ignition deploy ignition/modules/deployEthereumSepolia.ts --network ethereumSepolia +``` + +### 將 CrosschainNFT.sol 部署至 Kairos Testnet + +部署前,請從 [Chainlink CCIP Directory](https://docs.chain.link/ccip/directory/testnet/chain/kaia-testnet-kairos) 取得下列 Kairos Testnet 的值: + +- 鏈條選擇器 +- CCIP 路由器位址 +- LINK 記憶體位址 + +您的部署腳本將需要這些值。 接下來,導覽到專案中的 _ignition/modules_ 資料夾,建立一個名為:`deployKairosTestnet.ts` 的新檔案,並將下列程式碼貼入其中: + +```typescript +// This setup uses Hardhat Ignition to manage smart contract deployments. +// Learn more about it at https://hardhat.org/ignition + +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const KAIROS_TESTNET_ROUTER_ADDRESS = `0x41477416677843fCE577748D2e762B6638492755`; +const KAIROS_TESTNET_LINK_TOKEN_ADDRESS = `0xAF3243f975afe2269Da8Ffa835CA3A8F8B6A5A36`; +const KAIROS_TESTNET_CHAIN_SELECTOR = `2624132734533621656`; +const CrosschainNFTKairosModule = buildModule("CrosschainNFTKairosModule", (m) => { + const crosschainNFTKairos = m.contract("CrosschainNFT", [KAIROS_TESTNET_ROUTER_ADDRESS, KAIROS_TESTNET_LINK_TOKEN_ADDRESS, KAIROS_TESTNET_CHAIN_SELECTOR], { + }); + return { crosschainNFTKairos }; +}); +export default CrosschainNFTKairosModule; +``` + +執行部署指令碼: + +```bash +npx hardhat ignition deploy ignition/modules/deployKairosTestnet.ts --network kairosTestnet +``` + +## 與智慧契約互動 + +在本節中,我們將分別執行 enableChain、mint 和 crosschainTransfer 函式,與已部署的 CrosschainNFT 智慧合約互動。 + +### 步驟 1:在 Ethereum Sepolia 上,呼叫 enableChain + +在呼叫 enableChain 前,請準備下列值: + +- **Sepolia合約地址**:部署在Ethereum Sepolia上的CrosschainNFT.sol合約地址。 +- **Kairos 合約位址**:部署在 Kairos Testnet 上的 CrosschainNFT.sol 合約位址。 +- **鏈選擇器**:2624132734533621656(Kairos Testnet 的 CCIP 鏈選擇器)。 +- **CCIP extraArgs**:0x97a657c900000000000000000000000000000000000000000007A120 (這是 extraArgs 的預設編碼值,gasLimit 設定為 500,000)。 + +接下來,在 scripts 資料夾中建立一個新的 TypeScript 檔案,將其命名為:`enableChainSepolia.ts` 並將下列程式碼貼入其中: + +```typescript +// scripts/enableChainSepolia.ts +import { network } from "hardhat"; +async function main() { + const connection = await network.connect({ + network: "ethereumSepolia" + }); + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory by name + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + // Contract addresses and parameters + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + const crosschainNFTAddressKairosTestnet = `0x8c464Bb9Bf364F68b898ed0708b8f5F66EF6Cfb1`; + const chainSelectorKairosTestnet = `2624132734533621656`; + const ccipExtraArgs = `0x97a657c9000000000000000000000000000000000000000000000000000000000007A120`; + // Attach to the deployed contract + const crosschainNFTSepolia = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + console.log(`Enabling chain for Kairos Testnet...`); + const tx = await crosschainNFTSepolia.enableChain( + chainSelectorKairosTestnet, + crosschainNFTAddressKairosTestnet, + ccipExtraArgs + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Chain enabled successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +執行以下指令來呼叫函式: + +```bash +npx hardhat run scripts/enableChainSepolia.ts --network ethereumSepolia +``` + +### 步驟 2:在 Kairos Testnet 上,呼叫 enableChain + +在呼叫 enableChain 前,請準備下列值: + +- **Kairos 契約位址**:部署在 Kairos Testnet 上的 CrosschainNFT.sol 契約位址 +- **Sepolia 契約位址**:部署在 Ethereum Sepolia 上的 CrosschainNFT.sol 契約位址 +- \*\* 鏈選擇器\*\*:16015286601757825753 (Kairos Testnet 的 CCIP 鏈選擇器) +- **CCIP extraArgs**:0x97a657c900000000000000000000000000000000000000000007A120 (這是 extraArgs 的預設編碼值,gasLimit 設定為 500,000) + +接下來,在 scripts 資料夾中建立新的 TypeScript 檔案,將其命名為:`enableChainKairos.ts` 並將下列程式碼貼入其中: + +```typescript +// scripts/enableChainKairos.ts +import { network } from "hardhat"; +async function main() { + const connection = await network.connect({ + network: "kairosTestnet" + }); + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory by name + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + // Contract addresses and parameters + const crosschainNFTAddressKairosTestnet = `0x8c464Bb9Bf364F68b898ed0708b8f5F66EF6Cfb1`; + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + const chainSelectorEthereumSepolia = `16015286601757825753`; + const ccipExtraArgs = `0x97a657c9000000000000000000000000000000000000000000000000000000000007A120`; + // Attach to the deployed contract on Kairos + const crosschainNFTKairos = CrosschainNFT.attach(crosschainNFTAddressKairosTestnet); + console.log(`Enabling chain for Ethereum Sepolia...`); + const tx = await crosschainNFTKairos.enableChain( + chainSelectorEthereumSepolia, + crosschainNFTAddressEthereumSepolia, + ccipExtraArgs + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Chain enabled successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +執行以下指令來呼叫函式: + +```bash +npx hardhat run scripts/enableChainKairos.ts --network KairosTestnet +``` + +### 步驟 3:在 Ethereum Sepolia 上使用 LINK 為契約注資 + +為了支付 CCIP 費用,請使用 LINK 為部署在 Ethereum Sepolia (crosschainNFTAddressEthereumSepolia) 上的 CrosschainNFT 合約提供資金。 您可以從提供的 [龍頭](https://faucets.chain.link/sepolia) 取得測試 LINK。 在本指南中,發送 3 個 LINK 即可。 + +![](/img/build/tutorials/cc-ccip-fund-link.png) + +### 步驟 4:在 Ethereum Sepolia 上鑄造新的 CrosschainNFT + +接下來,在部署到 Ethereum Sepolia 的 CrosschainNFT 合約上建立新的 NFT。 + +在 scripts 資料夾中建立一個新的 TypeScript 檔案,命名為 `mint.ts` 並貼上下列程式碼: + +```typescript +// scripts/mint.ts +import { network } from "hardhat"; +async function main() { + // Connect to the network + const connection = await network.connect({ + network: "ethereumSepolia" + }); +if (connection.networkName !== "ethereumSepolia") { + console.error(`Must be called from Ethereum Sepolia`); + process.exitCode = 1; + return; + } + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22` + // Attach to the deployed contract + const crosschainNFT = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + console.log(`Minting NFT...`); + const tx = await crosschainNFT.mint(); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`NFT minted successfully!`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +這個腳本會處理造幣過程,並為跨鏈轉移準備 NFT。 + +執行以下指令來呼叫函式: + +```bash +npx hardhat run scripts/mint.ts --network ethereumSepolia +``` + +### 步驟 5:跨鏈傳輸 NFT + +在 Ethereum Sepolia 上,您將呼叫 crossChainTransferFrom 函式,將您的 NFT 傳送至 Kairos Testnet。 + +Pepare 以下值: + +- **from**:您在 Ethereum Sepolia 上的 EOA 位址 +- **至**:收件人在 Kairos Testnet 上的 EOA 地址(也可以是您自己的地址) +- **tokenId**:您要轉移的 NFT 的 ID +- **destinationChainSelector**:2624132734533621656(Kairos Testnet 的 CCIP 鏈選擇器) +- **payFeesIn**:1(表示 CCIP 費用將以 LINK 方式支付) + +執行傳輸指令碼 + +在 scripts 資料夾中建立新的 TypeScript 檔案,將其命名為 `crossChainTransferNFT.ts` 並將下列程式碼貼入其中: + +```typescript +// scripts/crossChainTransferNFT.ts +import { network } from "hardhat"; +async function main() { + // Connect to the network + const connection = await network.connect({ + network: "ethereumSepolia" + }); + // Check if we're on the correct network + if (connection.networkName !== "ethereumSepolia") { + console.error(`Must be called from Ethereum Sepolia`); + process.exitCode = 1; + return; + } + const { ethers } = connection; + const [signer] = await ethers.getSigners(); + console.log(`Using account: ${signer.address}`); + // Get the contract factory + const CrosschainNFT = await ethers.getContractFactory("CrosschainNFT", signer); + const crosschainNFTAddressEthereumSepolia = `0xb1fe42BBd7842703820C7480c22409b872319B22`; + // Transfer parameters + const from = `0x7b467A6962bE0ac80784F131049A25CDE27d62Fb`; + const to = `0x7b467A6962bE0ac80784F131049A25CDE27d62Fb`; + const tokenId = 0; // Put NFT token id here + const destinationChainSelector = "2624132734533621656"; // Kairos Testnet + const payFeesIn = 1; // 0 - Native, 1 - LINK + // Attach to the deployed contract + const crosschainNFT = CrosschainNFT.attach(crosschainNFTAddressEthereumSepolia); + const tx = await crosschainNFT.crossChainTransferFrom( + from, + to, + tokenId, + destinationChainSelector, + payFeesIn + ); + console.log(`Transaction hash: ${tx.hash}`); + console.log(`Waiting for confirmation...`); + const receipt = await tx.wait(); + + console.log(`Transaction confirmed in block: ${receipt?.blockNumber}`); + console.log(`Cross-chain transfer initiated successfully!`); + console.log(`Note: The NFT will arrive on Kairos Testnet after CCIP processes the message.`); +} +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); +``` + +然後用以下方式執行腳本: + +```bash +npx hardhat run scripts/crossChainTransferNFT.ts --network ethereumSepolia +``` + +驗證轉移 + +您可以在[CCIP Explorer](https://ccip.chain.link/#/side-drawer/msg/0x2a43cf8076ed6290dd0bf8bdbbc87abe2d238da43b6bf514e70909dd0f35c9db)上監控跨鏈轉移,並在[Kaiascan](https://kairos.kaiascan.io/nft/0x7dcdaa882603b1cfeee42d1c382a1ecba595d87c/0?tabId=nftTokenTransfer&page=1)上確認交易。 + +![](/img/build/tutorials/cc-nft-ccip-explorer.png) + +![](/img/build/tutorials/cc-nft-ccip-kaiascan.png) + +一旦 NFT 到達 Kairos Testnet,請將它加入您的 MetaMask 錢包: + +1. 在 MetaMask 中開啟 NFT 索引標籤。 +2. 按一下匯入 NFT。 +3. 在 Kairos Testnet 上輸入 CrosschainNFT 合約位址和您收到的 tokenId (例如 0)。 + +您的NFT現在會出現在您的MetaMask錢包中。 + +![](/img/build/tutorials/cc-ccip-mm-view-nft.png) + +## 總結 + +在本教程中,您學會了如何使用 Chainlink CCIP 在 Kaia Kairos Testnet 和 Ethereum Sepolia 之間使用燒幣模式傳輸 NFT。 + +若要深入瞭解 CCIP 並探索其他使用案例,請造訪官方 [Chainlink CCIP Documentation](https://docs.chain.link/ccip)。 + + + + diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md index 6ad6f84047a4..8f85501187aa 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-advanced.md @@ -79,5 +79,5 @@ SwapTx 會在鏈上失敗,但由於 \*\*KIP-245 的原子捆綁 \*\*,整個 **教育內容:** -- [如果可以用穩定幣支付瓦斯費呢?](https://medium.com/kaiachain/pay-for-gas-fees-with-any-token-a-deep-dive-into-kaias-trustless-gas-abstraction-d670355a096b) -- [Kaia Consensus 流動資金公告](https://medium.com/kaiachain/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity-7c8a7393cd19) \ No newline at end of file +- [如果可以用穩定幣支付瓦斯費呢?](https://blog.kaia.io/pay-for-gas-fees-with-any-token-a-deep-dive-into-kaias-trustless-gas-abstraction/) +- [Kaia Consensus 流動資金公告](https://blog.kaia.io/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity/) \ No newline at end of file diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md index 7865d9920d68..7474a37a1057 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/ga-tutorial/ga-intro.md @@ -45,4 +45,4 @@ Kaia 新來者在下列情況下經常會遇到困難: ## 1.4 與 Consensus Liquidity (CL) 的關係 -GA 原本是為了增加 [Consensus Liquidity tokens](https://medium.com/kaiachain/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity-7c8a7393cd19) 的效用而設計,讓使用者可以使用 CL tokens (例如 BORA、Swapscanner) 支付瓦斯。 不過,該功能也可以支援其他 ERC-20 代幣,包括穩定幣。 \ No newline at end of file +GA 原本是為了增加 [Consensus Liquidity tokens](https://blog.kaia.io/kaia-consensus-liquidity-a-new-paradigm-in-blockchain-liquidity/) 的效用而設計,讓使用者可以使用 CL tokens (例如 BORA、Swapscanner) 支付瓦斯。 不過,該功能也可以支援其他 ERC-20 代幣,包括穩定幣。 \ No newline at end of file diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md new file mode 100644 index 000000000000..49e5aac7c6a0 --- /dev/null +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/integrate-gas-free-usdt-kaia-swap.md @@ -0,0 +1,479 @@ +--- +id: integrate-gas-free-usdt-kaia-swap +title: 將無瓦斯 USDT 整合至 KAIA 掉期 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# 將無瓦斯 USDT 整合至 KAIA 掉期 + +本指南概述 Gas-Free USDT 至 KAIA Swap 功能,包括其目的、先決條件、整合步驟和 API 參考資料。 它旨在幫助開發人員將無氣體交換功能整合到 Kaia 網路上的分散式應用程式 (DApp) 中。 + +## 簡介 + +推出了 `gasFreeSwapKaia` API,讓使用者可以在 Kaia 網路上執行無瓦斯的 ERC20 代幣交換 (目前僅限於 USDT ),而不需要持有 KAIA 代幣來支付瓦斯費用,甚至在代表使用者支付交易成本時也是如此。 API 特別支援使用 ERC20 許可簽章將 USDT 交換成 KAIA,以提供完全無瓦斯的使用者體驗。 + +### 優點 + +- **100%無瓦斯體驗**:使用者不需要任何 KAIA 代幣即可進行交換 +- **增強使用者上線**:新使用者可立即開始交換代幣,無需取得 KAIA +- **ERC20 許可證整合**:使用標準 ERC20 許可證簽章進行安全、無氣代幣核准 + +### 如何運作 + +- **使用者啟動交換**:使用者選擇USDT金額來交換KAIA +- **前端建立許可證**:DApp 建構 ERC20 許可證簽章供使用者簽署 +- **使用者簽署許可證**:使用者簽署許可證訊息(無需瓦斯) +- **DApp 呼叫 API**:前端將交換參數和許可簽章傳送至 API +- \*\* 後端執行\*\*:API 驗證許可證、執行交換並支付所有瓦斯費用 +- **用戶收到 KAIA**:原生的 KAIA 代幣會直接傳送到使用者的錢包中 + +## 先決條件和支援的環境 + +\*\* 服務端點\*\* + + + + https://fee-delegation.kaia.io + + + + https://fee-delegation-kairos.kaia.io + + + +**支援的代幣對** + +API 目前僅支援單一交易對: + + + + 代幣: USDT (`0xd077a400968890eacc75cdc901f0356c943e4fdb`) + +``` +Token Out: WKAIA (`0x19aac5f612f524b754ca7e7c41cbfa2e981a4432`) +``` + + + + + 代幣輸入: TEST (`0xcb00ba2cab67a3771f9ca1fa48fda8881b457750`) + +``` +Token Out: WKAIA (`0x043c471bEe060e00A56CcD02c0Ca286808a5A436`) +``` + + + + +\*\* 取得測試代號\*\* + +要取得 Kairos Testnet 的 TEST 代幣: + +- 在 Kaiascan 上開啟 [ERC20 Faucet](https://kairos.kaiascan.io/address/0x78a6cacfe5d34e0566e56710c8789d207411001a?tabId=contract&page=1) +- 移至「合約」標籤,然後選擇「撰寫合約」\*。 +- 找到 claim(token) 函式 +- 貼入 Kairos 上受支援的 GA 令牌位址 (本指南使用 TEST 的位址) +- 按一下 _Query_ 以提交要求。 您應該很快就會收到您的 TEST 代幣。 + +![](/img/build/tutorials/test-tokens-faucet.png) + +**智慧型合約要求** + +API 與 GaslessERC20PermitSwap 智慧型合約互動: + +- 支援以 ERC20 許可證為基礎的核准 +- 與 Uniswap V2 相容的 DEX 整合 +- 自動將 WKAIA 轉換為原生 KAIA +- 強制執行安全的最大交換限制 + +\*\* 使用者需求\*\* + +在主網路上,使用者必須擁有零 KAIA 結餘才能使用這項無瓦斯交換服務。 這項要求可確保只有真正需要無瓦斯交易的使用者才能使用這項服務,以達到入會目的。 在 testnet 上,為了測試目的,此限制會被放寬。 + +主網路和測試網路的最大交換金額限制為 1 USDT。 由於此功能是設計給使用者接收足夠的 KAIA 來開始他們在 Kaia Chain 上的體驗。 + +## 整合步驟 + +### 完整的整合範例 + +```javascript +const { JsonRpcProvider, Wallet } = require('@kaiachain/ethers-ext/v6'); +const { Contract, parseUnits, formatUnits, Signature } = require('ethers'); + +async function fetchJson(url, init) { + if (typeof fetch !== 'undefined') { + return fetch(url, init); + } + const { default: nodeFetch } = await import('node-fetch'); + return nodeFetch(url, init); +} + +const GASLESS_SWAP_ABI = [ + 'function usdtToken() view returns (address)', + 'function wkaiaToken() view returns (address)', + 'function maxUsdtAmount() view returns (uint256)', + 'function getExpectedOutput(address tokenIn, address tokenOut, uint256 amountIn) view returns (uint256)', + 'function executeSwapWithPermit(address user, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOutMin, uint256 deadline, uint8 v, bytes32 r, bytes32 s)', +]; + +const ERC20_METADATA_ABI = [ + 'function decimals() view returns (uint8)', + 'function symbol() view returns (string)', + 'function name() view returns (string)', + 'function nonces(address owner) view returns (uint256)', + 'function balanceOf(address owner) view returns (uint256)', +]; + +async function buildPermitSignature({ token, owner, spender, value, deadline, domainVersion = '1' }) { + const [name, version, network, verifyingContract, nonce] = await Promise.all([ + token.name(), + Promise.resolve(domainVersion), + owner.provider.getNetwork(), + token.getAddress(), + token.nonces(owner.address), + ]); + + const domain = { + name, + version, + chainId: Number(network.chainId), + verifyingContract, + }; + + const types = { + Permit: [ + { name: 'owner', type: 'address' }, + { name: 'spender', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'nonce', type: 'uint256' }, + { name: 'deadline', type: 'uint256' }, + ], + }; + + const message = { + owner: owner.address, + spender, + value, + nonce, + deadline, + }; + + return Signature.from(await owner.signTypedData(domain, types, message)); +} + +async function executeGaslessSwap({ + rpcUrl, + serverUrl, + userWallet, + contractAddress, + amountIn = '0.01', // Amount in USDT + slippageBps = 50, // 0.5% slippage + permitDeadlineSeconds = 600 // 10 minutes +}) { + console.log('🚀 Starting gasless swap'); + + const provider = new JsonRpcProvider(rpcUrl); + const wallet = userWallet.connect(provider); + const swap = new Contract(contractAddress, GASLESS_SWAP_ABI, provider); + + // Get token addresses from contract + const [tokenInAddress, tokenOutAddress, maxUsdtAmount] = await Promise.all([ + swap.usdtToken(), + swap.wkaiaToken(), + swap.maxUsdtAmount(), + ]); + + const tokenIn = new Contract(tokenInAddress, ERC20_METADATA_ABI, provider); + const tokenOut = new Contract(tokenOutAddress, ERC20_METADATA_ABI, provider); + + const [tokenInDecimals, tokenOutDecimals, tokenInSymbol, tokenOutSymbol] = await Promise.all([ + tokenIn.decimals(), + tokenOut.decimals(), + tokenIn.symbol(), + tokenOut.symbol(), + ]); + + const amountInWei = parseUnits(amountIn, tokenInDecimals); + + // Check if amount exceeds contract maximum + if (amountInWei > maxUsdtAmount) { + throw new Error(`Amount (${amountIn} ${tokenInSymbol}) exceeds contract cap (${formatUnits(maxUsdtAmount, tokenInDecimals)} ${tokenInSymbol})`); + } + + // Get expected output and calculate minimum with slippage + const expectedOut = await swap.getExpectedOutput(tokenInAddress, tokenOutAddress, amountInWei); + const amountOutMin = (expectedOut * BigInt(10_000 - slippageBps)) / 10_000n; + + // Create permit signature + const deadline = BigInt(Math.floor(Date.now() / 1000) + permitDeadlineSeconds); + const signature = await buildPermitSignature({ + token: tokenIn, + owner: wallet, + spender: contractAddress, + value: amountInWei, + deadline, + }); + + // Prepare API payload + const payload = { + swap: { + user: wallet.address, + tokenIn: tokenInAddress, + tokenOut: tokenOutAddress, + amountIn: amountInWei.toString(), + amountOutMin: amountOutMin.toString(), + deadline: deadline.toString(), + }, +permitSignature: signature.serialized, + }; + + console.log('From:', wallet.address); + console.log('Swap amount:', formatUnits(amountInWei, tokenInDecimals), tokenInSymbol); + console.log('Minimum out:', formatUnits(amountOutMin, tokenOutDecimals), tokenOutSymbol); + + // Check balance before swap + const balanceBefore = await provider.getBalance(wallet.address); + + // Call the API + const response = await fetchJson(`${serverUrl}/api/gasFreeSwapKaia`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + + const result = await response.json().catch(() => ({})); + console.log('HTTP status:', response.status); + console.log('Response:', JSON.stringify(result, null, 2)); + + if (response.ok && result.status) { + console.log('🎉 Gasless swap request succeeded'); + + // Check balance after swap + const balanceAfter = await provider.getBalance(wallet.address); + console.log('Balance before:', formatUnits(balanceBefore, 18), 'KAIA'); + console.log('Balance after:', formatUnits(balanceAfter, 18), 'KAIA'); + console.log('Balance difference:', formatUnits(balanceAfter - balanceBefore, 18), 'KAIA'); + + return result; + } else { + console.error('❌ Gasless swap request failed'); + throw new Error(`Swap failed: ${result.data || result.message || 'Unknown error'}`); + } +} + +// Usage example +async function main() { + try { + const userWallet = new Wallet('your_private_key'); + + const result = await executeGaslessSwap({ + rpcUrl: 'https://public-en-kairos.node.kaia.io', + serverUrl: 'https://fee-delegation-kairos.kaia.io', + userWallet: userWallet, + contractAddress: '0xaaFe47636ACe87E2B8CAaFADb03E87090277Ff7B', + amountIn: '0.002', + slippageBps: 50, + }); + + console.log('Transaction hash:', result.data.hash); + } catch (error) { + console.error('💥 Swap failed:', error.message); + } +} + +main(); +``` + +## API 參考端點 + +- URL:`/api/gasFreeSwapKaia` +- 方法:POST +- 內容類型:application/json + +### 請求正文 + +```javascript +{ + "swap": { + "user": "0x742d35Cc6635C0532925a3b8D400e6D2A4b8E0bb", + "tokenIn": "0xcb00ba2cab67a3771f9ca1fa48fda8881b457750", + "tokenOut": "0x043c471bEe060e00A56CcD02c0Ca286808a5A436", + "amountIn": "1000000", + "amountOutMin": "950000000000000000", + "deadline": "1699123456" + }, + "permitSignature": "0x…65-byte signature string…" +} +``` + +### 參數 + +**swap** (object, required): + +- user (字串):簽署許可證的令牌擁有者的地址 +- tokenIn (字串):輸入令牌的位址(必須與設定的 USDT 位址相符) +- tokenOut (字串):輸出 token 的位址 (必須與設定的 WKAIA 位址相符) +- amountIn (字串):以字串形式顯示的輸入代幣數量 (單位為 wei/最小單位) +- amountOutMin (字串):最小預期輸出代幣(滑點保護) +- deadline (字串):許可證和交換到期的 Unix 時間戳 (秒) + +**permitSignature** (字串,必填): + +- 必須是 65 位元組的有效十六進位字串 +- 包含序列化的 ERC20 許可證簽章 + +### 回應格式 + +#### 成功回應 (200) + +```javascript +{ + "message": "Request was successful", + "data": { + "_type": "TransactionReceipt", + "blockHash": "0x2a7ae196f6e7363fe3cfc79132c1d16292d159e231d73b4308f598a3222d1f57", + "blockNumber": 191523443, + "contractAddress": null, + "cumulativeGasUsed": "215000", + "from": "0x6C4ED74027ab609f506efCdd224041c9F5b5CDE1", + "gasPrice": "25000000000", + "gasUsed": "215000", + "hash": "0x0ca73736ceecf2dcf0ec2e1f65760d0b4f7348726cb9a0477710172b1dd44350", + "status": 1, + "to": "0x45bD04d5f14DD9AB908109cFEa816F758FaE6709", + "type": 49, + "feePayer": "0x1234567890abcdef1234567890abcdef12345678", + "feePayerSignatures": ["0x..."], + "logs": [ + { + "address": "0x...", + "topics": ["0x..."], + "data": "0x..." + } + ] + }, + "status": true, + "requestId": "req_abc123def456" +} +``` + +#### 錯誤回應 + +**400 Bad Request - Validation Errors:** + +```javascript +{ + "message": "Bad request", + "data": "Permit deadline has expired", + "error": "BAD_REQUEST", + "status": false, + "requestId": "req_error_123" +} +``` + +**400 Bad Request - Transaction Revert:** + +```javascript +{ + "message": "Bad request", + "data": "execution reverted: Permit already used", + "error": "BAD_REQUEST", + "status": false, + "requestId": "req_revert_456" +} +``` + +**500 內部伺服器錯誤:** + +```javascript +{ + "message": "Internal server error", + "data": "Sending transaction was failed after 5 try, network is busy. Error message: Network timeout", + "error": "INTERNAL_ERROR", + "status": false, + "requestId": "req_error_789" +} +``` + +## 錯誤處理 + +### 常見錯誤情況 + +| 錯誤 | HTTP 狀態 | 說明 | 解決方案 | +| ------------ | ------- | ----------------------------- | ------------------------------------------- | +| 遺漏必填欄位 | 400 | _swap_ 或 _permitSignature_ 遺失 | 包含所有必要參數 | +| 使用者有 KAIA 結餘 | 400 | 使用者的 KAIA 結餘必須為零 | 只有 KAIA 結餘為零的使用者才能使用此服務 | +| 簽名格式無效 | 400 | 許可簽章不是有效的十六進制字串 | 提供有效的 65 位元組十六進位簽章 | +| 無效地址 | 400 | 畸形的 Ethereum 位址 | 驗證地址是否有效 | +| 不支援的代號 | 400 | 代號不在允許清單中 | 僅使用已設定的 token 位址 | +| 截止日期已過 | 400 | 過去的許可期限 | 使用未來時間戳記 | +| 金額太大 | 400 | 超過合約上限 | 從契約中檢查 _maxUsdtAmount()_ | +| 報價不足 | 400 | 滑動過於嚴格 | 增加滑動容限或減少滑動量 | +| 瓦斯價格過高 | 400 | 網路擁塞 | 等待較低的汽油價格 | +| 網路超時 | 500 | RPC 提供者問題 | 延遲後重試請求 | + +## 安全考量 + +### 瓦斯價格保護 + +API 會在瓦斯價格超過 50 gwei 時拒絕交易,以防止成本過高。 監控瓦斯價格,並在高壅塞期通知使用者。 + +### 簽名安全性 + +- 切勿重複使用許可證簽名 +- 永遠使用合理的期限 (5-30 分鐘) +- 簽署前驗證所有參數 +- 所有 API 通訊使用 HTTPS + +## 智慧型契約詳細資訊 + +### 無瓦斯ERC20許可證交換合約地址 + + + + ``` + 0x45bD04d5f14DD9AB908109cFEa816F758FaE6709 + ``` + + + + ``` + 0xaaFe47636ACe87E2B8CAaFADb03E87090277Ff7B + ``` + + + +### 主要功能 + +**executeSwapWithPermit** - 使用許可簽章執行無氣體交換: + +- 驗證許可證和交換參數 +- 使用許可證轉移代幣 +- 執行 DEX 掉期 +- 將 WKAIA 轉換為本機 KAIA +- 傳送本機 KAIA 給使用者 + +**getExpectedOutput** - 檢視函式,用來取得預期的輸出金額: + +```javascript +function getExpectedOutput( + address tokenIn, + address tokenOut, + uint256 amountIn +) external view returns (uint256) +``` + +### 合約限制 + +- 每次掉期的最高 USDT:1,000,000 (1 USDT 含 6 位小數) +- 支援的交易對:USDT → WKAIA → 本地 KAIA +- 透過簽章追蹤提供防重複保護 + +## 其他資源 + +- [ERC20 許可證標準 (EIP-2612)](https://eips.ethereum.org/EIPS/eip-2612) +- [Kaia Ethers Extension](https://github.com/kaiachain/ethers-ext) + + diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md new file mode 100644 index 000000000000..1b8523310439 --- /dev/null +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/mev-auction-sdk-guide.md @@ -0,0 +1,352 @@ +# Kaia MEV 拍賣 SDK 搜尋者指南 + +[Kaia v2.1.0](https://github.com/kaiachain/kaia/releases/tag/v2.1.0) 推出 MEV Auction 系統,讓搜尋者能參與公平、透明的 MEV 機會拍賣。 本指南提供使用 Kaia MEV Auction SDK 的搜尋器工作流程的全面演練。 + +:::info + +本指南使用 Kairos 測試網路端點和合約位址。 主網路預計於 2025 年 12 月中推出。 部署到主網路時,請相應更新所有端點和合約位址。 + +::: + +搜尋器工作流程包含四個主要步驟: + +![](/img/build/tutorials/searcher-guide-1.png) + +1. **存款**:搜尋者將 KAIA 代幣存入`AuctionDepositVault`以資助競標活動 +2. **出價**:搜尋者向拍賣官提交密封的競標書,以競逐回力賽時段。 +3. **提交中標**:拍賣官會選出贏家,並將贏得的出價轉寄給 Consensus 節點 (CN)。 +4. \*\* 執行中標交易\*\*:CN 透過「AuctionEntryPoint」合約執行中標交易 + +詳細技術背景請參閱 [KIP-249](https://kips.kaia.io/KIPs/kip-249)。 + +## 先決條件 + +開始之前,請確保您已 + +- 用 KAIA 代幣存款的資金皮夾 +- 已安裝 [Go](https://golang.org/) (1.25 版以上) 以取得 SDK 範例 +- 存取 Kaia 網路端點 (本指南使用 Kairos testnet) +- (可選)已安裝 [Foundry](https://getfoundry.sh/) (用於 `cast` 指令) + +**拍賣者端點:** + +- Kairos (testnet):`https://auctioneer-kairos.kaia.io` +- 主網絡:`https://auctioneer.kaia.io` + +**探索者端點:** + +- Kairos (testnet):`https://mev-kairos.kaia.io` +- 主網絡:`https://mev.kaia.io` + +**網路端點:** + +- Kairos (testnet):`https://public-en-kairos.node.kaia.io` +- 主網絡:`https://public-en.node.kaia.io` + +**合約地址(Kairos):** + +- AuctionFeeVault: `0xE4e7d880786c53b6EA6cfA848Eb3a05eE97b2aCC` +- AuctionDepositVault: `0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc` +- AuctionEntryPoint: `0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480` + +如需主網路合約地址 (主網路啟動後可用),請檢查 [合約地址](../../references/contract-addresses.md)。 + +:::tip[Monitor MEV 商機] + +搜尋者可透過以下方式識別有利可圖的交易 + +- **訂閱拍賣商的待定交易 API**:此 API 可直接從 Consensus 節點串流交易,讓您即時偵測 MEV 機會。 請參閱下面的 [訂閱待處理交易](#step-3-subscribe-to-pending-transactions) 章節。 +- \*\* 獨立監控網路 mempool\*\*:透過訂閱待定 tx 來實作您自己的 MEV 機會偵測邏輯。 + +::: + +## 步驟 1:存入資金 + +![](/img/build/tutorials/searcher-guide-2.png) + +AuctionDepositVault 儲存您的競投餘額。 您的保證金必須涵蓋您的出價金額和執行出價的預估瓦斯費。 + +### 瞭解存款要求 + +您的押金餘額必須包括 + +- **出價金額**:您願意為贏得拍賣而支付的 KAIA +- \*\* 估計瓦斯費\*\*:執行競標期間所消耗的瓦斯(在執行後扣除,並發送給整批提案者) + +:::warning[Always 維持足夠的存款餘額] + +如果您的餘額不足以支付競投金額加上預估的瓦斯費用,您的競投將會被拍賣官在確認時拒絕。 + +::: + +### 存款方法 + +合約提供兩種存款方式: + +**方法 1: `deposit()`** + +使用寄件者的餘額存款。 存款會存入寄件者的帳戶。 + +```bash +# Deploy deposit of 200 KAIA +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "deposit()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 --value 200000000000000000000 +``` + +**方法 2:`depositFor(位址搜尋器)`**\* + +代表另一個帳戶存款。 有助於從單一來源為多個搜尋器地址提供資金。 + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "depositFor(address)" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 --value 200000000000000000000 +``` + +### 檢查您的餘額 + +查詢您目前的存款餘額: + +```bash +cast call 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "depositBalances(address)(uint256)" --rpc-url "https://public-en-kairos.node.kaia.io" +``` + +詳細的存款範例,請參閱 [DEPOSIT.md guide](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/DEPOSIT.md)。 + +## 步驟 2:提交出價 + +![](/img/build/tutorials/searcher-guide-3.png) + +一旦發現有利可圖的交易,請向拍賣官提交出價。 出價是密封的(在拍賣結束前隱藏),並根據出價金額進行競爭。 + +### 投標架構 + +出價由下列欄位組成 (如 [types.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/types.go) 所定義): + +```go +type AuctionBid struct { + TargetTxRaw []byte // Raw transaction bytes of target tx + TargetTxHash common.Hash // Transaction to backrun + BlockNumber *big.Int // Target block number + Sender common.Address // Your searcher address + To common.Address // Contract to call + Nonce uint64 // Current nonce from AuctionEntryPoint + Bid *big.Int // Your bid in KAIA + CallGasLimit uint64 // Gas limit for your backrun logic + Data []byte // Encoded function call + SearcherSig []byte // EIP-712 signature from searcher +} +``` + +:::info + +在您提交出價之後,拍賣官會驗證並加入自己的簽章 (`AuctioneerSignature`),然後才會將中標出價轉寄給 Consensus 節點。 您只需要提供 `SearcherSig` (您的 EIP-712 簽章)。 + +::: + +### 提交投標 + +SDK 在 [`example/submitbid.go`](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go) 提供了一個完整的工作範例。 範例說明: + +- 與拍賣官建立 HTTPS 連線 +- 從 EN 端點偵測新區塊 +- 產生目標交易和相對應的出價 +- 向拍賣官提交出價 + +\*\* 必須採取的行動\*\*:執行程式碼前,請先在程式碼中更換您的私人密碼匙。 檢查原始碼中的「TODO:」註解。 + +執行範例: + +```bash +# From repository root +go run example/submitbid.go +``` + +### 出價驗證 + +拍賣商、投標者和智慧型契約各自對出價執行特定的驗證檢查。 主要驗證規則包括 + +- \*\* 區塊號碼\*\*:必須是 currentBlockNumber + 1 或 currentBlockNumber + 2 +- \*\* 出價金額\*\*:必須大於 0 且小於或等於您的可用存款餘額 +- **呼叫資料大小**:不得超過 `BidTxMaxDataSize` (64KB) +- **呼叫瓦斯限制**:不得超過 `BidTxMaxCallGasLimit` (10,000,000) +- **Nonce**:必須符合您目前在 `AuctionEntryPoint` 中的 nonce。 查詢它: + ```bash + cast call 0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480 "nonces(address)(uint256)" --rpc-url "https://public-en-kairos.node.kaia.io" + ``` +- \*\* 簽署\*\*:必須是有效的 EIP-712 簽署(執行方式請參閱 [submitbid.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go) +- **保證金保障**:必須有足夠的保證金支付`出價金額 + 預估瓦斯費`。 +- \*\* 唯一性\*\*:同一區塊中不能有另一個中標(除非針對同一筆交易) +- **拍賣官簽名**:必須有效(由拍賣官在您提交後添加) + +如需完整的驗證矩陣,顯示哪些實體執行哪些檢查,請參閱 [投標驗證指南](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/bid_validation.md)。 + +## 步驟 3:訂閱待決交易 + +![](/img/build/tutorials/searcher-guide-4.png) + +Auctioneer 提供 WebSocket 訂閱服務,可直接從 Consensus 節點串流待處理的交易。 這可讓搜尋人員即時偵測到 MEV 機會。 + +SDK 在 [example/subscribe_pendingtx.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/subscribe_pendingtx.go) 中提供了一個完整的範例。 + +範例說明: + +- 建立與拍賣官的 WebSocket 連線 +- 訂閱待處理交易串流 +- 處理收到的交易以找出 MEV 機會 + +執行範例: + +```bash +# From repository root +go run example/subscribe_pendingtx.go +``` + +當偵測到待處理交易時,訂閱會持續列印交易切細值。 您可以擴充本範例以實作您自己的 MEV 檢測邏輯。 + +## 步驟 4:了解執行 + +當您的出價獲勝時,Consensus Node 會透過 `AuctionEntryPoint` 契約執行: + +![](/img/build/tutorials/searcher-guide-1.png) + +### 執行流程 + +執行過程包含三個階段: + +1. **驗證階段**:合約驗證區塊號碼、簽名、nonce 和投標金額 +2. **出價付款階段**:從您的訂金中扣除出價金額,並傳送至生態系統基金 +3. **執行階段**:您的 backrun 由 EntryPoint 合約執行(無論執行結果如何,都會進行出價付款) + +\*\* 主要安全功能:\*\* + +- 驗證員代表您執行出價(防止還原出價以逃避付款) +- Nonce 增量可防止重播攻擊 +- 雙重簽名 (搜尋員 + 拍賣員) 未經授權的出價取代或操控 +- 無論後續執行結果如何,出價付款都會發生 + +詳細執行流程請參閱 [ENTRYPOINT.md guide](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/ENTRYPOINT.md)。 + +## 步驟 5:提取資金 + +![](/img/build/tutorials/searcher-guide-5.png) + +提款需要經過鎖定期的兩個步驟: + +### 1. 提取儲備 + +啟動提款並開始 60 秒鎖定時間: + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "reserveWithdraw()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 +``` + +### 2. 完全退出 + +60 秒後,轉移預留金額: + +```bash +cast send --private-key 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc "withdraw()" --rpc-url "https://public-en-kairos.node.kaia.io" --confirmations 0 +``` + +:::info[Security 附註] + +鎖定期的兩步提款程序: + +- 防止在有效拍賣期間閃存退出 +- 確保搜尋者遵守出價,以維持協議的完整性 +- 防範快速資本操控攻擊 + +::: + +## API 參考資料 + +Auctioneer 為搜尋者提供兩個主要的 API: + +**1. 提交投標 API** + +- **端點**:POST /api/v1/auction/send +- **目的**:提交 MEV 機會的密封標書 + +**2. 待處理交易訂閱** + +- **端點**:GET /api/v1/subscriber/pendingtx +- **目的**:來自共識節點的待處理交易即時串流 +- **範例**:請參閱 [subscribe_pendingtx.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/subscribe_pendingtx.go) 中的實作範例。 + +**完整的 API 文件:** + +- OpenAPI (Swagger) 規格可在以下網址取得: + - **Kairos**: https://auctioneer-kairos.kaia.io/docs + - **主網路**:主網推出後可用 +- API 使用方式:[API 文件](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/api_doc.md) + +## 疑難排解 + +### 常見問題 + +| 問題類別 | 症狀 | 原因 | 解決方案 | +| --------------- | --------- | ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| **餘額不足** | 被拍賣官拒絕的出價 | 押金餘額不包括出價金額 + 預估汽油費 | 使用 `depositBalances()` 檢查餘額,並存入更多 KAIA | +| **Nonce 錯配** | 投標被拒或執行失敗 | Nonce 與 `AuctionEntryPoint` 中的目前 nonce 不相符 | 在每次出價前使用 `nonces()` 查詢目前的 nonce。 請記住:nonces 只會在執行時遞增,不會在提交時遞增。 | +| \*\* 區塊號碼範圍\*\* | 被拍賣官拒絕的出價 | 目標區塊超出允許範圍`[current+1, current+allowFutureBlock]` | 確保區塊號碼在範圍之內(通常為 +1 或 +2)。 有關雙重提交策略,請參閱常見問題 | +| \*\* 無效簽名\*\* | 被拍賣官拒絕的出價 | 不正確的 EIP-712 簽名結構 | 驗證網域分隔符和類型切細值。 請參考 [submitbid.go](https://github.com/kaiachain/auctioneer-sdk/blob/dev/example/submitbid.go) 以取得正確的執行方式 | +| \*\* 氣體限制問題\*\* | 執行失敗或出價被拒 | CallGasLimit」過低或超過最大值 (10,000,000) | 在 testnet 上測試 backrun 邏輯,以測量實際瓦斯消耗量 | + +## 常見問題 + +### 訂閱 + +\*\*問:每個搜尋者允許多少個並發連線? + +答:每個搜尋者位址只允許一個待處理交易訂閱連線。 + +\*\*問:訂閱連線的有效期為多久? + +答:連線會在 24 小時後自動關閉。 請注意,如果正在進行滾動更新,連線可能會提前於 24 小時關閉。 + +### API 效能與延遲 + +\*\*問:在提交出價時,如何盡量減少 API 延遲? + +答:拍賣官使用 HTTPS 通訊協定的 L7 負載平衡器。 初始握手耗費的時間取決於網路狀態。 若要在傳送後續出價 API 時繞過這個初始延遲,強烈建議建立保持連線。 + +\*\*問:我應該注意 API 的速率限制嗎? + +答:為了避免被 Auctioneer API 伺服器封鎖,請不要在短時間內傳送太多次 `ping` API。 + +\*\*問:地理位置是否會影響延遲? + +答:是的。 Auctioneer 伺服器在 GCP KR (Seoul) 區域執行。 建議您將基礎結構託管在地理位置接近的區域,以盡量減少延遲並降低地理延遲。 + +### 出價時間與區塊目標 + +\*\*問:為什麼我的出價有時會瞄準錯誤的區塊號碼? + +答:您提交出價的時間對 CN(共識節點)的開採時間高度敏感。 如果拍賣開始得較晚(接近挖礦時間),出價交易會插入下一個區塊之後(區塊號碼 +2 而不是 +1)。 這表示您應該將目標區塊號碼設定為 +2。 + +\*\*問:如何提高我的出價包含率? + +答:目標區塊編號本質上對 CN 挖礦時間表很敏感:如果您的目標區塊為 +2,但交易因處理時間較早而在區塊 +1 插入,則出價將會失敗。 因此,建議透過兩次傳送您的出價交易來最大化納入機率:一次目標區塊號碼為 +1,另一次目標區塊號碼為 +2。 + +## 最佳實務 + +- **監控存款餘額**:保持足夠餘額以支付多次出價 +- **謹慎處理 Nonces**:出價前請務必查詢最新的 nonce +- **最佳化偵測**:更快速的 MEV 檢測可提升競爭優勢 +- \*\* 在 Kairos 上測試\*\*:在部署主網路之前,先在測試網路上驗證您的策略 +- **監控結果**:透過 MEV Explorer 追蹤拍賣結果,以完善您的競投策略 +- \*\* 設定適當的瓦斯限制\*\*:在充足瓦斯與成本效益之間取得平衡 + +## 資源 + +- [SDK 儲存庫](https://github.com/kaiachain/auctioneer-sdk) +- [KIP-249 規格](https://kips.kaia.io/KIPs/kip-249) +- [範例程式碼](https://github.com/kaiachain/auctioneer-sdk/tree/dev/example) +- API 文件:[auctioneer-kairos.kaia.io/docs](https://auctioneer-kairos.kaia.io/docs) (Kairos), TBU (Mainnet) +- MEV Explorer:[mev-kairos.kaia.io](https://mev-kairos.kaia.io) (Kairos), TBU (Mainnet) +- [FAQ](https://github.com/kaiachain/auctioneer-sdk/blob/dev/user-guide/FAQ.md) + +## 尋求協助 + +有關問題或疑問: + +- 張貼在 [Kaia DevForum](https://devforum.kaia.io) +- 在 [SDK 套件庫] 中開啟問題(https://github.com/kaiachain/auctioneer-sdk/issues) diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md new file mode 100644 index 000000000000..555046cb893d --- /dev/null +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/build/tutorials/pyth-real-time-price.md @@ -0,0 +1,325 @@ +# 如何使用 Pyth 在 Kaia 上取得即時價格 + +## 介紹 + +Pyth 是一個分散式甲骨文網路,在主要由推式甲骨文驅動的生態系統中採用獨特的方法。 Pyth 不會以固定的時間間隔將資料推送至您的合約,而是讓您可以依需求取得真實世界的資料。 此模式可讓開發人員擁有更多控制權,並有助於避免不必要的 onchain 更新。 透過此一整合,開發人員可以取得即時資料,並使用按使用量付費的模式,只有在要求更新時才需付費。 + +在本指南中,您將學習如何使用 Pyth 的即時價格源來讀取法定貨幣 IDR 的價值。 您的 Solidity 智慧合約將使用 [pyth-sdk-solidity](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity) 從 Pyth 擷取 USD/IDR 價格,您將使用 [hermes-client](https://github.com/pyth-network/pyth-crosschain/tree/main/apps/hermes/client/js) 更新並擷取最新價格。 + +若要快速入門,您可以在 [GitHub](https://github.com/ayo-klaytn/pyth-kaia-hardhat-example) 上找到本教學的完整程式碼。 這可提供即時可用的參考,並協助您更快速地設定專案和安裝。 + +## 要求 + +開始之前,請確保您已準備好下列各項: + +- [Node.js 與 npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) + + 安裝相依性和執行開發工具所需的軟體。 + +- 以 KAIA testnet 代幣為資金的錢包。 + + 您需要 KAIA 來支付 Kairos 測試網的部署和交易瓦斯費用。 您可以向 [Kaia Faucet](https://faucet.kaia.io/) 索取免費的測試網路 KAIA。 + +## 設定開發環境 + +在本節中,您將設定開發環境、編譯您的 oracle 合約,並準備使用 Hardhat 進行部署。 + +**1. 建立硬帽專案** + +為專案建立新目錄,並初始化 Hardhat: + +```bash +mkdir pyth-kaia-hardhat-example && cd pyth-kaia-hardhat-example +npm init -y +npx hardhat@next --init +``` + +出現提示時,接受預設回應。 在本指南中,我們將使用 Mocha 和 Ethers 模版。 + +通過檢查 Hardhat 版本來驗證您的安裝: + +```bash +npx hardhat --version +``` + +**2. 設定加密的秘密** + +現在您將使用 Hardhat 的加密 keystore 來儲存您的 RPC URL 和私人密碼匙。 + +執行下列指令: + +```bash +npx hardhat keystore set KAIROS_RPC_URL +npx hardhat keystore set PRIVATE_KEY +``` + +請務必輸入您的密碼和每個變數的值,以保持其加密。 + +**3. 設定檔中的參考秘訣** + +開啟 `hardhat.config.ts`,更新 networks 區段以引用加密的秘密。 如果您使用不同的秘密名稱,請相應更新金鑰。 + +```typescript +import { configVariable } from "hardhat/config"; +module.exports = { + networks: { + kairos: { + url: configVariable("KAIROS_RPC_URL"), + accounts: [configVariable("PRIVATE_KEY")], + }, + }, +}; +``` + +## 建立契約並從 Pyth Oracles 取得價格 + +在本節中,您將安裝 [Pyth Solidity SDK](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity)、建立 PriceConsumer 契約,並使用 Hardhat 部署它。 合約會讀取 Pyth 價格源,您稍後會使用從 Hermes 取得的價格資料來更新。 + +### 安裝 Pyth SDK + +Pyth 提供一個 Solidity SDK,讓您可以與 onchain Pyth 價格饋送契約互動。 SDK 開放 IPyth 介面和相關的結構。 + +使用 npm 安裝 SDK: + +```bash +npm install --save-dev @pythnetwork/pyth-sdk-solidity +``` + +### 建立 PriceConsumer 合約 + +在 `contracts/PriceConsumer.sol` 建立新檔案,並加入下列程式碼: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; +import "@pythnetwork/pyth-sdk-solidity/IPyth.sol"; +import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol"; +contract PriceConsumer { + IPyth public pyth; + constructor(address pythContract) { + pyth = IPyth(pythContract); + } + function updatePrice(bytes[] calldata priceUpdateData) + external + payable + { + // Pay the Pyth fee for receiving price updates + uint fee = pyth.getUpdateFee(priceUpdateData); + require(msg.value >= fee, "Not enough fee sent"); + // Update the Pyth price state + pyth.updatePriceFeeds{value: fee}(priceUpdateData); + // Can fetch the price and use it as well + //PythStructs.Price memory currentBasePrice = pyth.getPriceNoOlderThan(priceFeedId, 60); + } + function getLatestPrice(bytes32 priceFeedId) public view returns (int64, int32) { + // Read the current price from a price feed if it is less than 60 seconds old. + // Each price feed (e.g., USD/IDR) is identified by a price feed ID. + // The complete list of feed IDs is available at https://docs.pyth.network/price-feeds/price-feeds + PythStructs.Price memory currentBasePrice = pyth.getPriceNoOlderThan(priceFeedId, 60); + + // uint256 basePrice = PythUtils.convertToUint( + // currentBasePrice.price, + // currentBasePrice.expo, + // 18 + // ); + + return (currentBasePrice.price, currentBasePrice.expo); + } +} +``` + +**走過** + +PriceConsumer 合約: + +- 從`@pythnetwork/pyth-sdk-solidity`匯入 Pyth 介面和結構。 +- 商店: + - Pyth 契約實例 (pyth)。 + - 美元 / IDR 的價格源 ID (usdIdrPriceId)。 +- Exposes `updateAndGetUsdIdrPrice`, which: + - 使用 IPyth.getUpdateFee 計算更新費用。 + - 使用所需費用呼叫 IPyth.updatePriceFeeds。 + - 呼叫 IPyth.getPriceNoOlderThan 讀取新的 USD / IDR 價格。 + - 傳回原始價格、分數和發佈時間。 + +之後,您的離鏈 Hermes 客戶端會建立 priceUpdate bytes 陣列,並在需要新價格時將其傳入此函式。 + +### 編寫合約 + +執行下列指令來編譯您的合約: + +``` +npx hardhat compile +``` + +## 部署合約 + +要部署 PriceConsumer 合約,您需要建立一個 Ignition 模組,然後執行部署指令。 + +\*\* 建立點火模組\*\* + +在 `ignition/modules/PriceConsumer.ts` 建立新檔案: + +```typescript +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +const pythContractAddress = "0x2880ab155794e7179c9ee2e38200202908c17b43"; +export default buildModule("PriceConsumerModule", (m) => { + const priceConsumer = m.contract("PriceConsumer", [pythContractAddress]); + return { priceConsumer }; +}); +``` + +**部署合約** + +使用您的 Ignition 模組,將 PriceConsumer 合約部署到 Kairos 測試網: + +```bash +npx hardhat ignition deploy --network kairos ignition/modules/PriceConsumer.ts +``` + +出現提示時,請輸入之前為加密機密設定的 keystore 密碼。 + +一旦完成,您的「PriceConsumer.sol」合約就會部署在 Kairos 測試網路上,並準備好從 Pyth 消耗即時美元 / IDR 價格。 + +## 從 TypeScript 互動 + +在最後一步,您將使用 TypeScript 與已部署的 PriceConsumer 契約互動。 這個腳本會透過 Hermes 客戶端請求 Pyth 價格更新資料,取得最新的 USD/IDR 價格,並在鏈上傳送。 + +\*\* 安裝相依性\*\* + +安裝所需的套件: + +```bash +npm install --save-dev tsx @pythnetwork/hermes-client @dotenv +``` + +\*\* 設定 .env\*\* + +在專案根目錄中建立 .env 檔案,並加入您的私人金鑰: + +```bash +PRIVATE_KEY="0xDEAD....." // REPLACE WITH YOUR PRIVATE KEY +``` + +\*\* 建立互動腳本\*\* + +在 **scripts/interact.ts** 建立新檔案,並加入下列內容: + +```typescript +import { HermesClient } from "@pythnetwork/hermes-client"; +import { ethers } from "ethers"; +import 'dotenv/config' + +// 1. Setup +const hermes = new HermesClient("https://hermes.pyth.network"); +const provider = new ethers.JsonRpcProvider( + "https://public-en-kairos.node.kaia.io" +); + +const PK = process.env.PRIVATE_KEY; +const wallet = new ethers.Wallet(PK, provider); + + +// 2. Your deployed contract +const priceConsumerAddress = "0x91e89aa32224dEd5dA483a83a4de45bF4bE57caA"; // REPLACE WITH DEPLOYED PRICE CONSUMER CONTRACT + +const priceConsumerAbi = [ + "function updatePrice(bytes[] priceUpdateData) external payable", + "function getLatestPrice(bytes32 priceId) public view returns(int64, int32)", +]; + +const priceConsumer = new ethers.Contract( + priceConsumerAddress, + priceConsumerAbi, + wallet +); + +// 3. Price feed IDs +const priceId = + "0x6693afcd49878bbd622e46bd805e7177932cf6ab0b1c91b135d71151b9207433"; // FX.USD/IDR Beta Price Feed ID + +async function run() { + // Fetch Hermes price update binary + const update = await hermes.getLatestPriceUpdates([priceId], { + encoding: "hex", + }); + console.log(update); + + const priceUpdateData = ["0x" + update.binary.data]; // must be array of bytes + + console.log(priceUpdateData); + + // Estimate fee required by Pyth contract + // EVM Network Price Feed Contract Addresses: https://docs.pyth.network/price-feeds/core/contract-addresses/evm + + const pythContractAddress = "0x2880ab155794e7179c9ee2e38200202908c17b43"; + const pythAbi = [ + "function getUpdateFee(bytes[] calldata data) external view returns(uint)", + ]; + console.log("Pyth contract address:", pythContractAddress); + const pyth = new ethers.Contract(pythContractAddress, pythAbi, wallet); + const fee = await pyth.getUpdateFee(priceUpdateData); + console.log("Pyth fee:", fee.toString()); + + // Call your contract + const tx = await priceConsumer.updatePrice(priceUpdateData, { + value: fee, // pay the pyth update fee + gasLimit: 500000, + }); + console.log("Tx sent:", tx.hash); + const receipt = await tx.wait(); + console.log("Tx confirmed"); + console.log(receipt); + + // 4. Get latest price from contract + try { + console.log("=== Latest Price from Contract ==="); + const [price, expo] = await priceConsumer.getLatestPrice(priceId); + console.log("Price Value : " + price.toString()); + console.log("Exponent Value : " + expo.toString()); + } catch (error) { + console.log(error); + // @ts-ignore + console.error("\nError calling getLatestPrice:", error.message); + console.log( + "This usually means the price is older than 60 seconds or hasn't been updated yet." + ); + console.log("Make sure updatePrice() was called successfully first."); + } +} +run(); + +``` + +**執行腳本** + +用以下指令執行腳本: + +```bash +npx tsx scripts/interact.ts +``` + +\*\* 輸出範例\*\* + +```bash +Tx sent: 0x79c5dcb7abd9605b070bf9062ba2e2382272d23d58f7b50446c3107b7784fc8e +Tx confirmed +=== Latest Price from Contract === +Price Value : 1669784988 +Exponent Value : -5 +======== —— ========= +``` + +在搜尋列中貼上交易切細值,即可在 Kairos explorer 上驗證您的交易。 這證明更新和讀取作業成功。 + +## 總結 + +在本教程中,您建立了一個 Solidity 契約,可從 Pyth 讀取即時價格,並將其部署到 Kairos 測試網路,並使用 Hermes 客戶端與其互動。 您也了解到 Pyth 基於拉動的設計如何讓您控制價格更新發生的時間和方式。 + +如需更多資訊,請探索: + +- [EVM Contract Reference](https://api-reference.pyth.network/price-feeds/evm/getPriceNoOlderThan) for Pyth API +- [Pyth Oracle AMM 實例](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/evm)為完整的端對端實作 + + + diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md index 81afcd2f716e..66f0f0f55c74 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/computation/computation-cost.md @@ -190,6 +190,7 @@ Kaia 有區塊執行時間的非驗證限制。 由於執行時間無法在驗 | TSTORE | 280 | | TLOAD | 220 | | MCOPY | 250 | +| CLZ | 0 | ## Precompiled contracts computation cost table @@ -201,7 +202,7 @@ Kaia 有區塊執行時間的非驗證限制。 由於執行時間無法在驗 | 0x02 | sha256hash | numOfWords(input) / 32 \* 100 + 1,000 | | 0x03 | ripemd160hash | numOfWords(input) / 32 \* 10 + 100 | | 0x04 | dataCopy | 0 | -| 0x05 | bigModExp | 查看代碼 [此處](https://github.com/kaiachain/kaia/blob/75c149a464998eb946311f3a290d4b1ea339eaba/blockchain/vm/contracts.go#L340) | +| 0x05 | bigModExp | 請參閱程式碼 [here](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L586) | | 0x06 | bn256Add | 8,000 | | 0x07 | bn256ScalarMul | 100,000 | | 0x08 | bn256Pairing | numOfPairings(input) \* 1,000,000 + 2,000,000 | @@ -210,13 +211,23 @@ Kaia 有區塊執行時間的非驗證限制。 由於執行時間無法在驗 | 0x3FD | vmLog | 10 | | 0x3FE | feePayer | 10 | | 0x3FF | validateSender | numOfSigs(input) \* 180,000 + 10,000 | +| 0x0b | bls12381G1Add | 18,750 | +| 0x0c | bls12381G1MultiExp | 請參閱程式碼 [here](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L1155) | +| 0x0d | bls12381G2Add | 30,000 | +| 0x0e | bls12381G2MultiExp | 請參閱程式碼 [here](https://github.com/kaiachain/kaia/blob/45e53b7ff01cb3febefbebbb16c0456718b49842/blockchain/vm/contracts.go#L1261) | +| 0x0f | bls12381配對 | numOfPairings(input) \* 1,630,000 + 1,885,000 | +| 0x10 | bls12381MapG1 | 275,000 | +| 0x11 | bls12381MapG2 | 1,190,000 | +| 0x100 | p256Verify | 235,000 | ## Hardfork Changes -| Hardfork | New items | Changes | | | -| ------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | - | -| Cancun EVM | BLOBBASEFEE (0x49)
BLOBHASH (0x50)
TSTORE (0x5c) opcode
TLOAD (0x5d)
MCOPY (0x5e)
kzg (0x0a) precompiled contract | 提高計算成本限制
從 100,000,000 提高到 150,000,000

降低某些操作碼的計算成本
由於 CPU 性能提高
-Sdiv (0x05):739 -> 360
-Mod (0x06):812 -> 320
-Addmod (0x08):1410 -> 360
-Mulmod (0x09):1760 -> 700
-Exp (0x0A):5000 -> 720
-Sha3 (0x20): 2465 -> 560
-Mstore8 (0x53):5142 -> 230
-Log1, Log2, Log3, Log4 (0xA1-0xA4):1000 -> 500

由於數據庫大小增加,某些操作碼的計算成本會增加

-SLOAD (0x54):835 -> 2550
-SSTORE (0x55):1548 -> 2510 | | | -| Shanghai EVM | PUSH0 (0x5f) opcode | | | | -| Kore | | modExp (0x05) 預編譯合同
使用新的氣體計算邏輯。
計算成本也受到影響。
更加準確。 | | | -| London EVM | BaseFee (0x48) opcode | | | | -| Istanbul EVM | CHAINID (0x46) opcode
SELFBALANCE (0x47) opcode
blake2f (0x09) precompiled contract | 降低過高操作碼的計算成本
- ADDMOD (0x08):3349 -> 1410
- MULMOD (0x09):4757 -> 1760
- XOR (0x18):657 -> 454
- NOT (0x19):1289 -> 364
- SHL (0x1B): 1603 -> 478
- SHR (0x1C):1815 -> 834 | | | +| Hardfork | New items | Changes | +| ------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 大阪 EVM | CLZ (0x1e) 作業碼
p256Verify (0x100) 預編譯合約 | modExp (0x05) 預編譯合同
使用新的氣體計算邏輯。
計算成本也受到影響。
更加準確。 | +| 布拉格 EVM | bls12381G1Add (0x0b) 預先編譯的合約
bls12381G1MultiExp (0x0c) 預先編譯的合約
bls12381G2Add (0x0d) 預先編譯的合約
bls12381G2MultiExp(0x0e) 預先編譯的合約
bls12381Pairing (0x0f) 預先編譯的合約
bls12381MapG1 (0x10) 預先編譯的合約
bls12381MapG2 (0x11) 預先編譯的合約
| | +| Cancun EVM | BLOBBASEFEE (0x49) 操作碼
BLOBHASH (0x50) 操作碼
TSTORE (0x5c) 操作碼
TLOAD (0x5d) 操作碼
MCOPY (0x5e) 操作碼
kzg (0x0a) 預編譯合約 | 提高計算成本限制
從 100,000,000 提高到 150,000,000

降低某些操作碼的計算成本
由於 CPU 性能提高
-Sdiv (0x05):739 -> 360
-Mod (0x06):812 -> 320
-Addmod (0x08):1410 -> 360
-Mulmod (0x09):1760 -> 700
-Exp (0x0A):5000 -> 720
-Sha3 (0x20): 2465 -> 560
-Mstore8 (0x53):5142 -> 230
-Log1, Log2, Log3, Log4 (0xA1-0xA4):1000 -> 500

由於數據庫大小增加,某些操作碼的計算成本會增加

-SLOAD (0x54):835 -> 2550
-SSTORE (0x55):1548 -> 2510 | +| Shanghai EVM | PUSH0 (0x5f) opcode | | +| Kore | | modExp (0x05) 預先編譯的合約
使用新的瓦斯計算邏輯。
計算成本也會受到影響。
變得更準確。 | +| London EVM | BaseFee (0x48) opcode | | +| Istanbul EVM | CHAINID (0x46) opcode
SELFBALANCE (0x47) opcode
blake2f (0x09) precompiled contract | 降低過高操作碼的計算成本
- ADDMOD (0x08):3349 -> 1410
- MULMOD (0x09):4757 -> 1760
- XOR (0x18):657 -> 454
- NOT (0x19):1289 -> 364
- SHL (0x1B): 1603 -> 478
- SHR (0x1C):1815 -> 834 | diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md index 4e86b4b97b4b..be1e9a83c719 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/computation/debug-tracing.md @@ -34,7 +34,7 @@ Kaia 的 `callTracer` 輸出格式與 go-ethereum 完全相同,但以下內容除外: -- 對於受尊敬的交易,這兩個字段都會提供。 +- 對於反向交易,兩個欄位都會提供。 - result.revertReason\`:還原原因字符串(如果有)。 - result.revoted.contract\`:已還原合同的地址。 - result.revted.message:與 revertReason 相同 diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md new file mode 100644 index 000000000000..5ccc5af0a256 --- /dev/null +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/storage/storage-optimization.md @@ -0,0 +1,107 @@ +# 儲存優化 + +隨著 Kaia 區塊鏈的成長,儲存區塊鏈資料所需的儲存空間也在增加。 Kaia 實作了兩種主要技術來管理這種不斷成長的儲存需求: + +## 狀態批次修剪(狀態遷移) + +State Migration 是一種批次修剪功能,可應用於現有節點,而不會中斷執行中的節點。 + +### 動機 + +區塊狀態或 StateDB 以 trie 資料結構儲存鏈上帳號與契約。 trie 資料結構被設計來儲存過時和最近的狀態,因此可以使用 Merkle hash 來驗證它們。 當交易執行狀態變更時,狀態 trie 就會無限擴大。 截至撰寫本文時(2024 年 8 月),Kaia Mainnet 存檔節點大小超過 20TB,即使是完整節點也超過 10TB。 + +### 概念 + +State Migration 會刪除處理新區塊時不需要的舊區塊狀態。 它將狀態 trie 從「舊」複製到「新」。 並非所有 trie 節點都會被複製。 從選擇區塊的狀態根可到達的區塊被複製。 複製之後,舊目錄會被刪除,因此您只剩下選取區塊的狀態。 + +閱讀這些部落格文章,瞭解更多技術細節: +[State Migration: Saving Node Storage](https://medium.com/klaytn/klaytn-v1-5-0-state-migration-saving-node-storage-1358d87e4a7a), +[Kaia State Migration: An Efficient Way to Reduce Blockchain Data](https://medium.com/klaytn/klaytn-state-migration-an-efficient-way-to-reduce-blockchain-data-6615a3b36523) + +有關如何執行 Batch Pruning,請參閱 [State Migration Guide](../../misc/operation/node-pruning.md#how-to-perform-batch-pruning)。 + +## 國家現場修剪 + +State Live Pruning 是解決狀態資料庫大小不斷增加問題的新方案。 與 Batch Pruning(狀態遷移)不同,Live Pruning 會隨著節點程序的阻塞,一點一滴地自動刪除舊的狀態。 + +### 動機 + +區塊狀態或 StateDB 以 trie 資料結構儲存鏈上帳號與契約。 trie 資料結構被設計來儲存過時和最近的狀態,因此可以使用 Merkle hash 來驗證它們。 當交易執行狀態變更時,狀態 trie 就會無限擴大。 截至撰寫本文時(2025 年 8 月),Kaia Mainnet 存檔節點大小超過 20TB,即使是完整節點也超過 10TB。 + +在此之前,「狀態遷移」已經透過選擇性複製最近的狀態並刪除其餘的狀態來刪除舊的狀態,從而緩解了這個問題。 這樣可以將完整節點大小縮小到 5 TB 以下。 + +儘管如此,國家移民也有其缺點。 它需要花費數天的時間來遍歷整個州的 trie,因此開銷很高。 此外,狀態轉移必須手動觸發。 為了克服這些限制,我們引進了 Live Pruning 技術。 + +### 概念 + +Trie 剪枝很困難,因為無法確定某個 trie 節點是否過時。 在原始狀態 trie 結構中,一個 trie 節點可以是多個 tries 的一部分,每個 tries 構成一個不同的區塊。 即使 trie 節點 (例如帳戶餘額) 更新為其他值,也不能刪除 trie 節點,因為其他父節點可能仍然需要它。 這個問題被稱為雜湊重複問題。 + +Live Pruning 會故意重複具有相同內容的 trie 節點。 在 Live Pruning 的情況下,一個 trie 節點不會被其切細值所引用,而是被其 ExtHash 所引用。 ExtHash 是內容的 32 位元組雜湊值加上 7 位元組序列索引。 序列索引是單調遞增的,因此每個 trie 節點都是唯一的。 + +``` +Hash: 32-byte Keccak256 +ExtHash: 32-byte Keccak256 + 7-byte Serial index +``` + +這樣,每當 trie 節點的內容改變時,就可以安全地假設這個 trie 節點現在已經過期。 只要忽略序列索引,就能以同樣的方式計算 Merkle 哈希,使其在共識方面與非活剪節點相容。 + +閱讀這篇部落格文章,瞭解更多技術細節:[Efficient Management of Blockchain Data Capacity with StateDB Live Pruning](https://medium.com/klaytn/strong-efficient-management-of-blockchain-data-capacity-with-statedb-live-pruning-strong-6aaa09b05f91). + +有關如何啟用即時修剪,請參閱 [即時修剪指南](../../misc/operation/node-pruning.md#how-to-perform-live-pruning)。 + +## 資料壓縮 + +資料壓縮可將 LevelDB 內建的 Snappy 壓縮演算法套用至選定的資料庫表,從而減少區塊資料的儲存大小。 + +### 動機 + +由於 EVM 交易中的 ABI 編碼標準,由標頭、交易正文和收據組成的區塊資料通常包含高度重複的位元組序列。 舉例來說,Solidity 的 ABI 編碼使用零填充來滿足 32 位元組字元對齊的需求,導致交易呼叫資料有長時間的零。 交易收據在事件日誌和回傳值中也呈現相似的模式。 + +儘管有這種自然的備援,Kaia 的底層 LevelDB 儲存引擎預設並未使用壓縮,讓重複資料不必要地消耗磁碟空間。 截至 2025 年 7 月,Kaia Mainnet 完整節點佔用了超過 4.2 TB 的儲存空間,其中約 3.6 TB 屬於未壓縮的區塊資料。 + +### 概念 + +Kaia v2.1.0 啟動 LevelDB 的 Snappy 壓縮演算法,並選擇性地應用於資料庫資料表。 `--db.leveldb.compression` 旗標可實現粒度控制: + +- 壓縮標頭、正文和收據 (冗餘度高,大幅節省成本) +- 排除州立 trie 資料 (看似隨機,壓縮效益極低) + +對於現有節點,手動觸發資料庫壓縮可將舊的未壓縮資料重寫為壓縮格式。 這個「內務管理」過程會合併 SSTables、協調刪除,並應用壓縮作為副作用。 + +**結果:** Mainnet 完整節點的總儲存空間減少約 50% (~2TB 節省空間),大部分的增益在正文和收據資料表。 此過程約需 10 小時,可與一般區塊處理同時進行。 + +閱讀這篇部落格文章,瞭解更多技術細節:[Kaia v2.1 如何透過壓縮回收 2TB](https://blog.kaia.io/cutting-blockchain-storage-in-half/). + +有關啟用壓縮的方法,請參閱 [優化節點儲存指南](../../misc/operation/optimize-storage.md#database-compression)。 + +## FlatTrie 國家方案 (實驗性) + +FlatTrie 是一種實驗性的狀態儲存方案,透過重整歷史帳戶狀態的儲存方式,大幅降低歸檔節點狀態資料庫的大小。 + +### 動機 + +歸檔節點必須保留所有區塊高度的所有帳戶的完整歷史狀態資料,以便進行時間旅行查詢和全面的區塊鏈分析。 這造成了與完整節點截然不同的儲存配置文件:截至 2025 年 8 月,Kaia Mainnet 存檔節點需要超過 35 TB 的磁碟空間,其中 31 TB (89%) 被狀態資料庫消耗。 + +傳統的 Merkle Patricia Trie (MPT) 結構會同時儲存帳號資料 (樹葉) 和形成 Merkle 樹的中間分支節點。 過去,歸檔節點會為多個區塊高度保留完整的 MPT,導致中間節點 (本身不傳送帳戶資料) 無限期累積。 + +現有的儲存最佳化,例如 [State Migration](https://medium.com/klaytn/klaytn-v1-5-0-state-migration-saving-node-storage-1358d87e4a7a) (batch pruning) 和 [StateDB Live Pruning](https://medium.com/klaytn/strong-efficient-management-of-blockchain-data-capacity-with-statedb-live-pruning-strong-6aaa09b05f91) 從根本上需要刪除歷史資料,因此不適用於必須保留完整歷史資料的歸檔節點。 + +### 概念 + +FlatTrie 是一個實驗性的狀態儲存方案,改編自 [Erigon Ethereum client](https://github.com/erigontech/erigon/)。 它透過以下方式重組狀態儲存 + +- 在平面鍵值表中儲存歷史帳戶狀態(簡單地址 → 帳戶資料對應) +- 僅保留最新區塊的完整 MPT 與所有中間分支節點 +- 透過暫時只建立必要的分支節點,按需重建歷史 Merkle 根 + +此方法可消除歷史中間節點的持續儲存,同時保留完整的帳戶狀態歷史,並能夠驗證任何區塊的 Merkle 根。 + +**適應性挑戰:** Erigon 的實作假設了 Ethereum 的帳戶結構。 Kaia 使用不同的 RLP 編碼,以支援獨特的功能,例如人類可讀地址和多種金鑰類型。 整合過程需要修改 Erigon 的 Merkle 散列模組,將帳戶視為不透明的 bytestring,並建立三個適配器層 (DomainsManager、WriteBuffer、DeferredContext),以銜接 Kaia 的多執行緒 Trie 介面與 Erigon 的單執行緒 MDBX 資料庫需求。 + +**結果:** 在 Kairos 測試網路實驗中,FlatTrie 歸檔節點消耗的總儲存空間比傳統歸檔節點少約 75%,狀態資料庫大小減少超過 80%。 預計 Mainnet 存檔節點也會有類似的節省 (從 ~35TB 減至 ~10TB)。 + +\*\* 限制:\*\* 試驗性 v2.1.0 實作不支援區塊回卷 (`debug_setHead` API)、Merkle 證明生成 (`eth_getProof` API) 或狀態修剪功能。 這些限制源自 FlatTrie 捨棄歷史分支節點的設計選擇。 + +閱讀這篇部落格文章,瞭解更多技術細節:[Kaia's Experimental FlatTrie for Archive Nodes](https://blog.kaia.io/flatten-the-state-shrink-the-disk/). + +有關如何啟用 FlatTrie,請參閱 [優化節點儲存指南](../../misc/operation/optimize-storage.md#flattrie-state-scheme-experimental)。 diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md index 8c5314db59ea..976ccc445af9 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/learn/transaction-fees/transaction-fees.md @@ -62,7 +62,7 @@ - 基本費用上限:基本費用的最大值 - 基本費用下限值:基本費用的最小值 -以下是基礎費用計算的簡化版本。 從本質上講,基本費用的變化與 GAS_TARGET 和 PREVIOUS_BLOCK_GAS_USED 之間的差額成正比,其他參數控制著基本費用的變化速度或界限。 準確公式請參閱 [KIP-71](https://github.com/kaiachain/kips/blob/main/KIPs/kip-71.md)。 +以下是基礎費用計算的簡化版本。 就其本質而言,基本費用的變化與 GAS_TARGET 和 PREVIOUS_BLOCK_GAS_USED 之間的差異成正比,其他參數則控制基本費用的變化速度或界線。 準確公式請參閱 [KIP-71](https://github.com/kaiachain/kips/blob/main/KIPs/kip-71.md)。 ``` min(PREVIOUS_BLOCK_GAS_USED, MAX_BLOCK_GAS_USED_FOR_BASE_FEE) - GAS_TARGET diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/faq.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/faq.md index 748084e52081..a7b6e8cbd9ca 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/faq.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/faq.md @@ -3,6 +3,7 @@ - [FAQ](#faq) - [Kaia是什麼? ](#what-is-kaia-) - [Kaia如何支援Ethereum等價性? ](#how-does-kaia-support-ethereum-equivalence-) + - [Kaia的版本政策是什麼? ](#what-is-kaias-versioning-policy-) - [Kaia的瓦斯政策是什麼? ](#what-is-kaias-gas-policy-) - [Kaia的帳戶結構有何特別之處? ](#what-is-special-about-kaias-account-structure-) - [我可以從哪裡開始使用 Kaia 開發 dApp? ](#where-can-i-start-dapp-development-with-kaia-) @@ -30,6 +31,10 @@ Kaia 是高性能的第 1 層區塊鏈,專為 Web3 的大規模應用(尤其 Kaia 與 EVM 兼容,支持除 EIP-4844 blob 交易之外的所有以太坊坎昆 EVM 功能。 它提供 `eth` 命名空間 RPC API,允許無縫使用以太坊 SDK 和工具。 Kaia 特有的交易類型在以太坊命名空間 API 中表示為 0 型傳統交易,因此以太坊 SDK 無需瞭解這些類型。 +## Kaia 的版本政策是什麼? + +您可以從 [github](https://github.com/kaiachain/kaia/blob/dev/CONTRIBUTING.md#versioning-policy) 查閱。 + ## Kaia 的天然氣政策是什麼? Kaia 採用動態天然氣收費模式,在正常網絡條件下保持低收費,但會根據網絡擁堵情況調整收費。 手續費可在每個區塊的有限範圍內變化,有助於防止網絡垃圾郵件,同時保持費用的可預測性。 每筆交易的部分費用會自動燒掉。 該模式優先考慮用戶體驗和企業友好性,同時保持網絡穩定性。 @@ -139,4 +144,4 @@ Kaia 的網絡瀏覽器擴展錢包 [Kaia Wallet](https://chromewebstore.google. - ethers-ext:[收費委託價值轉移示例](https://docs.kaia.io/references/sdk/ethers-ext/v6/fee-delegated-transaction/value-transfer/) - web3js-ext:[收費委託值轉移示例](https://docs.kaia.io/references/sdk/web3js-ext/fee-delegated-transaction/value-transfer/) - web3j-ext:[收費委託值轉移示例](https://docs.kaia.io/references/sdk/web3j-ext/fee-delegated-transaction/value-transfer/) -- web3py-ext:[收費委託價值轉移示例](https://docs.kaia.io/references/sdk/web3py-ext/fee-delegated-transaction/value-transfer/) \ No newline at end of file +- web3py-ext:[收費委託價值轉移示例](https://docs.kaia.io/references/sdk/web3py-ext/fee-delegated-transaction/value-transfer/) diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md index 920ae70bca3d..e1a4a408982a 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/kaia-transition/faq-chain-transition.md @@ -43,7 +43,7 @@ Please note that most of the information provided in this FAQ reflects a transit ### Klaytn和Finschia -Klaytn 和 Finschia 通過管理決策合併為 Kaia。 您可以查看投票結果 [此處](https://medium.com/kaiachain/klaytn-and-finschia-merge-proposal-passes-creating-asias-largest-blockchain-ecosystem-7af570eb069a)。 兩條鏈(KLAY 和 FNSA)的實用代幣轉換為 KAIA 代幣。 您可以在 [此處] 找到這兩種代幣的匯率(../../kaiatech/kaia-white-paper.md#fnsa-issuancedistribution-status)。 +Klaytn 和 Finschia 通過管理決策合併為 Kaia。 您可以檢視投票結果 [這裡](https://blog.kaia.io/klaytn-and-finschia-merge-proposal-passes-creating-asias-largest-blockchain-ecosystem/)。 兩條鏈(KLAY 和 FNSA)的實用代幣轉換為 KAIA 代幣。 您可以在 [此處] 找到這兩種代幣的匯率(../../kaiatech/kaia-white-paper.md#fnsa-issuancedistribution-status)。 ### KLAY 和 FNSA 會怎麼樣? @@ -142,8 +142,8 @@ Kaia 是 Klaytn 鏈的硬分叉,鏈 ID 保持不變。 之前的測試網絡 " 以下是鏈合併的主要信息: - [治理建議](https://govforum.klaytn.foundation/t/kgp-25-klaytn-finschia-mainnet-merge/719) -- [合併背後的願景](https://medium.com/klaytn/finschia-klaytn-chain-merge-proposal-our-vision-for-asias-1-blockchain-ecosystem-7de1588e28c0) -- [製作 Kaia DeFi 的核心](https://medium.com/klaytn/crafting-the-core-of-project-dragons-defi-ecosystem-0fa561e02f56) -- [回應機構需求](https://medium.com/klaytn/project-dragon-responding-to-institutional-demand-bd36e2e1e2a6) -- [補充數據和見解](https://medium.com/klaytn/project-dragon-supplementary-data-and-insights-d36abd25ca0f) -- [Kaia品牌故事](https://medium.com/klaytn/say-hello-to-kaia-4182ccafe456) +- [合併背後的願景](https://blog.kaia.io/finschia-klaytn-chain-merge-proposal-our-vision-for-asias-no-1-blockchain-ecosystem/) +- [Crafting the core of Kaia DeFi](https://blog.kaia.io/crafting-the-core-of-project-dragons-defi-ecosystem/) +- [回應機構需求](https://blog.kaia.io/project-dragon-responding-to-institutional-demand/) +- [Supplementary data and insights](https://blog.kaia.io/project-dragon-supplementary-data-and-insights/) +- [Kaia品牌故事](https://blog.kaia.io/say-hello-to-kaia/) diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md index b102d6363bbb..bf53bc033602 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/kaia-transition/kaiabridge.md @@ -2,12 +2,160 @@ Finschia 用戶可以按固定交換率將其在 Finshia 網絡上的 FNSA 代幣交換為 Kaia 網絡上的 KAIA 代幣。 這種交換由一套智能合約和程序(統稱為 Kaiabridge)進行調解。 -代幣交換過程由 Finschia 用戶將 FNSA 代幣發送到 `fwsap` 模塊開始。 代幣首先從 "cony "交換到 "kei "面值,然後轉移到 "fbridge "模塊。 fbridge "事件由可信中繼器識別,並提交給 Kaia 鏈上的橋接智能合約。 橋接請求分多個步驟處理: +您可以在我們的 [線上工具包](https://toolkit.kaia.io/kaiaBridge) 中存取並使用 Kaiabridge。 -- 飛行中:代幣到達 Finschia 的 "fbridge "模塊,但中繼器沒有向 Kaia 智能合約報告。 -- 確認:轉述人向合同("條款")提交了申請。 現在,請求進入 30 分鐘的時間鎖定。 -- 已認領:時間鎖定到期後,令牌已被轉移("認領")到 Kaia 鏈上的目標賬戶。 +您可以在 [GitHub kaiachain/kaia 儲存庫](https://github.com/kaiachain/kaia/tree/dev/contracts/contracts/system_contracts/kaiabridge) 找到合約原始碼,並在 [合約地址](https://docs.kaia.io/references/contract-addresses/) 頁面找到已部署的地址。 -Kaiabridge 智能合約內置多重簽名功能。 例如,需要操作員賬戶進行多次備付交易,申請才能得到確認。 每個操作員賬戶由一箇中繼器持有,中繼器由 Kaia 基金會和 Finschia 基金會管理。 +# Kaiabridge 使用手冊 -您可以在 [kaiachain GitHub](https://github.com/kaiachain/kaia/tree/dev/contracts/contracts/system_contracts/kaiabridge) 中找到合同源代碼,在 [合同地址](https://docs.kaia.io/references/contract-addresses/) 頁面中找到部署地址。 \ No newline at end of file +## 先決條件 + +### 1. 將您的帳戶移至 MetaMask 或 Kaia Wallet + +#### 使用原始私人密碼匙 + +如果您的帳戶可以匯出原始私密金鑰,複製原始私密金鑰並匯入 MetaMask 或 Kaia 皮夾。 + +- [MetaMask](https://support.metamask.io/start/use-an-existing-wallet#import-using-a-private-key) +- [Kaia Wallet](https://www.kaiawallet.io/en_US/faq/?id=25) + +#### 使用恢復詞組 + +如果您的帳戶只能以復原片語匯出,請從復原片語計算原始私密金鑰。 您可以使用任何支援 BIP-39 派生路徑的工具。 這些工具包括 [ethers.js](https://docs.ethers.org/v6/api/wallet/#HDNodeWallet)、[viem](https://viem.sh/docs/accounts/local/hdKeyToAccount)、[Foundry](https://getfoundry.sh/cast/reference/wallet/),以及 [BIP39 Tool](https://github.com/iancoleman/bip39)。 Finschia 錢包通常使用 "m/44'/438'/0'/0/0" 路徑 (根據 [SLIP-044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)) 作為預設的衍生路徑。 如果您的 Finschia 錢包有多個帳號或使用不同的設定,您可能需要使用其他衍生路徑。 + +計算出私密金鑰後,請依照上一節 [使用原始私密金鑰](#with-raw-private-key) 的指示操作。 + +:::note[Example 使用 BIP39 工具] + +您可以在此頁面計算私密金鑰:[BIP39 - 助記碼](https://iancoleman.io/bip39/). + +為慎重起見,強烈建議您遵循頁面上的「離線使用」指示,並在過程中封鎖網際網路連線。 + +1. 在「BIP39 默念」欄位貼上您的復原詞組。 +2. 將「Coin」欄位設為「ETH - Ethereum」。 +3. 將「衍生路徑」設為「BIP32」。 +4. 將「使用者端」設為「自訂衍生路徑」。 +5. 設定「BIP32 衍生路徑」為「m/44'/438'/0'/0」。 +6. 在「衍生位址」中,尋找「路徑」顯示「m/44'/438'/0'/0/0」的第一行,您的原始私密金鑰會顯示在「私密金鑰」欄位中。 + +::: + +:::note[Example 使用 Foundry 工具] + +1. 安裝 [Foundry](https://getfoundry.sh/)。 +2. 在 `--mnemonic` 中輸入以下命令,並輸入您的復原短語。 原始私密金鑰將會被列印出來。 + ``` + cast wallet private-key --mnemonic "test test test test test test test test junk" --mnemonic-derivation-path "m/44'/438'/0'/0/0" + ``` + +::: + +### 2. 檢查您的網路 + +如果您使用 MetaMask,請手動將 Kaia Mainnet 加入您的網路 (如果您尚未這麼做)。 + +- [將 MetaMask 連接到 Kaia](https://docs.kaia.io/build/tutorials/connecting-metamask/) + +### 3. 為您的帳戶加油 + +您需要瓦斯來發送交換的交易。 詳細說明請參閱 [Get KAIA](https://docs.kaia.io/build/get-started/getting-kaia/) 。 + +我們建議您至少準備 0.1 KAIA 的汽油費。 + +## 將 Finschia 交換成 Kaia + +:::warning[This 交換是不可逆的] + +備付金與索賠請求只能處理一次,且不能還原。 +在您遵循這些指示之前,請仔細閱讀。 + +::: + +### 1. 連接您的錢包 + +#### 1.1 連接 MetaMask + +按一下「連接 MetaMask」按鈕。 + +

Connect MetaMask

+ +檢查「帳戶」是否顯示您的地址。 +如果沒有,請開啟 MetaMask 擴充套件,看看它是否顯示您未連接到頁面。 如果是,請按「連結帳戶」按鈕。 + +

Connect Account

+ +#### 1.2 連接 Kaia 皮夾 + +如果您使用的是 Kaia Wallet,網站可能會要求您將 Kaia Wallet 連接到 dApp (在此情況下為 Kaia Online Toolkit)。 + +

Connect Kaia Wallet

+ +按一下「連線」以連線您的 Kaia Wallet。 + +#### 2. 切換至 Kaia 主網路 + +檢查您是否已將網路正確設定為「Kaia Mainnet」或「Mainnet」。 如果沒有,請切換至 Kaia Mainnet。 如果您使用的是 MetaMask,而您沒有在 MetaMask 中加入 Kaia Mainnet 網路,請參考 [檢查您的網路](#2-check-your-network)。 + +#### 3. 衍生 Finschia 地址 + +按一下「衍生 Finschia 位址」。 出現簽署訊息的提示時,按一下「確認」或「簽署」。 + +
+ Sign message in MetaMask + Sign message in Kaia Wallet +
+ +

+檢查 「派生 finschia 位址 」是否與您的原始 Finschia 位址相符,以及 「cony 餘額 」是否與您在 Finschia 網路中的餘額相符(在 CONY 中)。 + +
+ Address and CONY balance shown in the page + Address and CONY balance shown in your wallet +
+ +

+此外,請確定您的帳戶有一些 KAIA 來支付瓦斯費(您可以在錢包中查看)。 + +
+ KAIA balance in MetaMask + KAIA balance in Kaia Wallet +
+ +

+如果您的帳戶中沒有任何 KAIA,請參考 [Gas up your account](#3-gas-up-your-account)。 + +#### 4. 要求提供 + +按一下「請求提供」。 出現簽署訊息和傳送交易的提示時,按一下「確認」。 + +
+ Confirm provision transaction request in MetaMask + Confirm provision transaction request in Kaia Wallet +
+ +

+此過程應該只需要幾秒鐘。 等待交易完成。 +您可以在頁面中檢查結果。 + +

Provision request successful

+ +
+如果沒有,請重新整理並從頭開始。 + +#### 5. 要求索賠 + +按一下「請求索賠」。 出現傳送交易的提示時,按一下「確認」。 + +
+ Confirm claim transaction request in MetaMask + Confirm claim transaction request in Kaia Wallet +
+ +

+此過程應該只需要幾秒鐘。 等待交易完成。 +您可以在頁面中檢查結果。 + +

Claim request successful

+ +
+檢查您的最新餘額。 索賠金額應為 (您的 cony 結餘) * (兌換率,約 148) [kei](https://docs.kaia.io/learn/token-economics/kaia-native-token/#units-of-kaia-)。 \ No newline at end of file diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md index fe420d0ed20c..3dbda6776343 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/operation/chaindata-snapshot.md @@ -101,7 +101,7 @@ ## 下載 -為提高效率,只提供批量剪枝(狀態遷移)或即時剪枝數據庫。 請閱讀 [Storage Optimization](../../learn/storage/state-pruning.md),瞭解它們的概念。 如果你想要一個完整的數據庫,既不需要剪枝,也不需要存檔數據,那就從創世中執行一次全新的完整同步。 +為提高效率,只提供批量剪枝(狀態遷移)或即時剪枝數據庫。 請閱讀 [儲存最佳化](../../learn/storage/storage-optimization.md) 以瞭解其概念。 如果你想要一個完整的數據庫,既不需要剪枝,也不需要存檔數據,那就從創世中執行一次全新的完整同步。 | 網絡 | 同步選項 | 下載 | | -- | -------------- | --------------------------------------------------------------------------------------------------- | diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md index 0174233b00c4..022e20de4d50 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/operation/node-pruning.md @@ -2,8 +2,8 @@ 本頁介紹如何刪除歷史塊狀態以減少存儲需求。 Kaia 提供了兩種修剪塊狀態的方法: -- [即時修剪](../../learn/storage/state-pruning.md#state-live-pruning):啟用即時修剪功能後,超過一定保留期限的塊狀態將被自動刪除。 -- [批量剪枝:狀態遷移](../../learn/storage/state-pruning.md#state-batch-pruning-state-migration):區塊狀態可以進行狀態遷移,也就是說,在某個區塊編號之前的區塊狀態都是可用的。 +- [Live Pruning](../../learn/storage/storage-optimization.md#state-live-pruning):啟用即時修剪功能後,超過一定保留期限的區塊狀態會被自動刪除。 +- [Batch Pruning: State Migration](../../learn/storage/storage-optimization.md#state-batch-pruning-state-migration):區塊狀態可以進行狀態遷移,也就是在某個區塊號碼之前的區塊狀態變得可用。 ## 瞭解修剪的影響 diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md new file mode 100644 index 000000000000..661cad1cf3f7 --- /dev/null +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/misc/operation/optimize-storage.md @@ -0,0 +1,293 @@ +# 最佳化節點儲存 + +[Kaia v2.1.0](https://github.com/kaiachain/kaia/releases/tag/v2.1.0) 引入了兩個互補的儲存最佳化功能,可大幅降低磁碟空間需求: + +- **資料庫壓縮**:透過壓縮重複的區塊資料來減少儲存空間 +- **FlatTrie 狀態方案**:大幅減少歸檔節點狀態資料庫大小的實驗性功能 + +本指南說明如何將這些最佳化套用到您的 Kaia 節點。 + +## 資料庫壓縮 + +資料庫壓縮會使用 LevelDB 內建的 Snappy 壓縮功能,以縮小區塊標頭、交易正文和收據的大小 - 這些資料通常包含重複資料,例如 ABI 編碼交易中的零填充。 + +\*\* 預計節省:\*\* + +- 完整節點:縮減 ~2TB (在主網路上從 ~4.2TB 減至 ~2TB) + +### 先決條件 + +- Kaia v2.1.0 或更高版本 +- 針對手動壓縮:充足的可用磁碟空間,以及接受持續磁碟 I/O 的能力 (請參閱下面的 \*\* 資源影響\*\* 部分) + +### 啟用新安裝的壓縮功能 + +從 v2.1.0 開始,預設啟用壓縮。 只需啟動您的節點: + +\*\* 套件安裝:\*\* + +```bash +# Configure network in kend.conf +sudo vi /etc/kend/conf/kend.conf +# Set: NETWORK=mainnet or NETWORK=kairos + +# Start node (compression enabled by default in v2.1.0+) +kend start + +# Verify +kend status +tail -f /var/kend/logs/kend.out +``` + +所有新寫入的資料都會自動壓縮。 + +### 啟用現有節點的壓縮功能 + +如果您從 v2.1.0 之前的版本升級: + +**第 1 步:檢查您的版本** + +```bash +ken version +``` + +**步驟 2:適用於 v2.1.0 及更新版本** + +預設已啟用壓縮功能。 新資料會自動壓縮。 跳至步驟 4 以壓縮現有資料。 + +**步驟 3:僅適用於 v2.1.0 之前的版本** + +將壓縮旗標加入您的設定: + +\*\* 套件安裝:\*\* + +```bash +sudo vi /etc/kend/conf/kend.conf +# Add to ADDITIONAL variable: +ADDITIONAL="--db.leveldb.compression 2" +``` + +壓縮標誌值為 + +- `0`:無壓縮 +- `1`:僅壓縮收據 +- `2`:壓縮標頭、正文和收據 (建議使用) +- `3`:壓縮所有表格,包括狀態 trie (不建議使用) + +:::note + +建議使用選項 2,因為狀態 trie 資料壓縮得不好(顯得隨機),所以選項 3 帶來的額外好處微乎其微。 + +::: + +然後再重新啟動: + +```bash +kend stop +kend start +``` + +**步驟 4:壓縮現有資料(選擇性但建議)** + +透過 RPC 觸發資料庫壓縮。 附加到您的節點控制台: + +```bash +ken attach --datadir /var/kend/data +``` + +在主控台中,使用「allbutstate」預設觸發壓縮: + +```javascript +> debug.chaindbCompact({ "preset": "allbutstate" }) +null +``` + +**可用預設:** + +- `「預設」`:全方位壓縮所有資料庫元件 +- `"allbutstate"`:選擇性壓縮排除狀態 trie (建議用於壓縮) +- `「自訂」`:為特定資料庫表定義自訂範圍 + +壓縮在背景中執行。 在節點日誌中監控進度: + +```bash +tail -f /var/kend/logs/kend.out | grep -i Compact +``` + +您應該會看到類似的記錄項目: + +``` +INFO[07/25,12:50:17 Z] [3] Compacting database started range=0x48-0x49 +INFO[07/25,12:55:17 Z] [3] Compacting database completed range=0x48-0x49 elapsed=5m0.085s +``` + +節點在壓縮期間會繼續處理區塊。 + +\*\* 預計持續時間:\*\* 一個 Mainnet 完整節點約需 10 小時 (在 SSD 上有 ~4TB 資料)。 時間長短視硬體和資料大小而定。 + +**資源影響:** + +- 高磁碟 I/O(讀取峰值 >400 MiB/秒,寫入峰值 >300 MiB/秒) +- 高磁碟 IOPS (通常 >2000 次/秒) +- 節點保持運作,並繼續同步區塊 + +:::note + +雖然節點在壓縮期間仍可運作,但在 I/O 峰值期間,查詢效能可能會受到影響。 對於生產 RPC 節點,請排定在維護視窗或低流量時段進行壓縮。 + +::: + +### 使用預先壓縮的 Chaindata 快照 (TBD) + +預先壓縮的 chaindata 快照計劃在未來的版本中推出,但目前尚未提供。 當這些資料可用時,它們將會列在 [Chaindata Snapshot page](https://docs.kaia.io/misc/operation/chaindata-snapshot/) 上。 + +目前,您必須 + +- 在新的 v2.1.0+ 安裝中啟用壓縮(對於新資料自動啟用) +- 在現有節點上執行手動壓縮(請參閱上文) + +定期檢查快照頁面,以取得壓縮快照可用性的更新。 + +### 驗證壓縮是否啟用 + +檢查您的節點啟動日誌,以瞭解壓縮設定: + +```bash +grep "compressionType" /var/kend/logs/kend.out +``` + +針對非州-trie 資料表,尋找顯示 `compressionType=snappy` 的記錄項目。 + +### 監控與故障排除 + +**檢查磁碟使用量的減少:** + +```bash +du -h --max-depth=1 /var/kend/data/klay/chaindata +``` + +比較壓實前和壓實後。 您應該會發現包含區塊正文和收據的目錄中的儲存空間大幅減少。 + +**常見問題:** + +1. **壓縮失敗**:確保有足夠的磁碟空間。 壓縮暫時需要額外的空間來重寫資料。 +2. **FlatTrie 無法啟動**:FlatTrie 需要一個空的資料庫。 如果看到關於現有資料的錯誤,請刪除 chaindata 目錄,然後從 genesis 同步。 +3. **Merkle proof API 錯誤**:FlatTrie 不支援 `eth_getProof`。 如果需要此 API,請使用傳統節點。 + +## FlatTrie 國家方案 (實驗性) + +FlatTrie 是一個實驗性的狀態儲存方案,改編自 Erigon Ethereum 客戶端。 它以平面結構儲存帳戶狀態,並只維護最新區塊的完整 Merkle Patricia Trie (MPT),可依需求重建歷史試圖。 + +\*\* 預計節省:\*\* + +- 總儲存:減少 ~75% (根據 Kairos 測試網路結果預測) +- Kairos 測試網路:4.3 TB → 1 TB +- 主網路:~35TB → ~10TB (根據比例減少估計) + +:::warning + +FlatTrie 是 v2.1.0 中的實驗性功能。 不建議用於生產。 預期在未來的版本中會出現潛在的穩定性問題、效能瓶頸和破壞性變更。 僅用於測試和開發環境。 + +::: + +### 先決條件 + +- Kaia v2.1.0 或更高版本 +- \*\* 必須從 genesis 同步\*\* (無法轉換現有資料庫) +- 清空資料目錄 + +### 目前的限制 + +啟用 FlatTrie 之前,請先瞭解這些限制: + +\*\* 不支援的功能:\*\* + +- 批量修剪和現場修剪 +- 區塊倒帶 (`--start-block-number`標誌和`debug_setHead`API) +- 生成 Merkle 證明 (`eth_getProof` API) + +**不相容:** + +- 無法從現有資料庫遷移 (必須從創世紀開始) +- 無法在 FlatTrie 和非 FlatTrie 模式之間切換 +- 有 FlatTrie 和沒有 FlatTrie 的資料庫不相容 + +### 啟用 FlatTrie + +**步驟 1:準備空資料目錄** + +```bash +# Ensure clean data directory +sudo rm -rf /var/kend/data +sudo mkdir -p /var/kend/data +``` + +**步驟 2:以 FlatTrie 標誌啟動節點,並從 genesis 同步** + +```bash +# Mainnet +ken --state.experimental-flat-trie + +# Kairos testnet +ken --state.experimental-flat-trie --kairos +``` + +:::note + +當 FlatTrie 啟用時,不論 `--gcmode`和 `--state.block-interval`旗標為何,歸檔模式都會自動啟動。 使用 FlatTrie 時,這些標記會被忽略。 + +::: + +**步驟 3:等待完全同步** + +節點會同步所有來自 genesis 的區塊。 這可能需要數週的時間,視您的硬體和網路而定。 + +### 驗證 FlatTrie 是否活躍 + +檢查您的節點啟動記錄,確認 FlatTrie 模式: + +```bash +grep -i "flat" /var/kend/logs/kend.out | head -20 +``` + +您應該會看到實驗性平面 trie 已經啟動的跡象。 + +### 監控 FlatTrie 性能 + +與傳統的狀態儲存相比,FlatTrie 使用不同的資源配置文件: + +\*\* 預期特性:\*\* + +- 較低的 CPU 使用率 +- 較高的記憶體使用量 (~30GB) +- 較高的程序計數 (~900-1000) +- 較慢的區塊定稿時間 + +透過節點的 Prometheus metrics endpoint 或 Grafana 面板監控這些指標。 + +### 排除 FlatTrie 的故障 + +\*\* 無法在現有資料庫上啟動 FlatTrie:\*\* +如果您看到錯誤顯示 FlatTrie 無法在非空資料上啟動,您必須從 genesis 開始。 刪除您的 chaindata 目錄,並使用 `--state.experimental-flat-trie` 標誌執行完全同步。 + +\*\* Merkle proof API 失敗:\*\* +FlatTrie 不支援 `eth_getProof` 及相關的 Merkle proof API。 如果您的應用程式需要這些 API,請改用傳統的節點。 + +\*\* 高記憶體使用量:\*\* +同步過程中,FlatTrie 節點的記憶體使用量預計約為 30GB。 確保您的系統有足夠的 RAM。 該團隊正在進行優化,以在未來版本中減少這種情況。 + +\*\* 同步速度慢:\*\* +使用 FlatTrie 的初始同步速度與傳統節點相當。 如果同步速度明顯變慢,請檢查: + +- 磁碟 I/O 效能 (強烈建議使用 SSD) +- 網路頻寬 +- CPU 使用率 + +## 最佳實務 + +1. **在進行重大變更**之前,請務必先進行備份:尤其是在執行手動壓縮之前。 +2. **監控磁碟空間**:確保壓縮之前有足夠的可用空間。 壓縮暫時需要額外的空間來重寫資料庫檔案。 +3. **在低流量時段安排壓縮**:如果執行公共 RPC 端點。 +4. \*\* 使用 SSD 作為生產節點\*\*:壓縮和 FlatTrie 都能從快速隨機 I/O 中獲益。 +5. \*\* 實驗性功能的計劃\*\*:FlatTrie 在 v2.1.x 中是實驗性的。 在生產使用前進行徹底測試。 +6. \*\* 保持更新\*\*:請查閱發行說明,以瞭解未來的最佳化,以及 FlatTrie 何時會從實驗狀態畢業。 \ No newline at end of file diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md index 8b70d3c2c417..3aeefac8fe8a 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-consensus-nodes.md @@ -159,7 +159,7 @@ REWARDBASE="d13f7da0032b1204f77029dc1ecbf4dae2f04241" ### (可選)下載 Chaindata 快照 -從創世區塊進行同步操作非常耗時。 您可以使用 [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) 跳過 [Full Sync](../../../learn/storage/block-sync.md#full-sync) 過程。 +從 genesis 區塊進行同步處理非常耗時。 您可以使用 [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) 跳過 [Full Sync](../../../learn/storage/block-sync.md#full-sync) 過程。 ## 啟動 CN diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md index ba328c5c17f3..a1d385e0bde4 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/core-cell/install/install-proxy-nodes.md @@ -146,7 +146,7 @@ DATA_DIR=/var/kpnd/data ### (可選)下載 Chaindata 快照 -從創世區塊進行同步操作非常耗時。 您可以使用 [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) 跳過 [Full Sync](../../../learn/storage/block-sync.md#full-sync) 過程。 +從 genesis 區塊進行同步處理非常耗時。 您可以使用 [Chaindata Snapshot](../../../misc/operation/chaindata-snapshot.md) 跳過 [Full Sync](../../../learn/storage/block-sync.md#full-sync) 過程。 ## 啟動 PN diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md index bddd4d6c7cfd..81c8b64d2f73 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/core-cell/system-requirements.md @@ -10,14 +10,22 @@ ### 裸機服務器 -| 類別 | 規格 | -| :-- | :----------------------------------------------------------------------------------------------------------------------------------------- | -| 服務器 | 英特爾® 服務器系統 [M50CYP1UR212](https://www.intel.sg/content/www/xa/en/products/sku/214842/intel-server-system-m50cyp1ur212/specifications.html) | -| CPU | Intel® Xeon 8358 2.60 GHz (32 核/64 線程) | -| 內存 | 128gb (32gb \* 4\) | -| 存儲 | 4TB(或更大容量)固態硬盤(首選存儲容量和配置可能因鏈數據大小而異。 更多信息請諮詢 Kaia 團隊)。 | +#### 一般要求(所有節點類型) -請注意,這只是 CN 和 PN 的推薦硬件規格,並非確切要求。 任何具有類似硬件配置的物理機器都足以運行 CN 或 PN。 +| 類別 | 規格 | +| :-- | :------------------------------------------------------------------------------------------- | +| CPU | 2.6 GHz 基本頻率 - 3.4 GHz 最大頻率或更高(例如,第 3 代 Intel® Xeon® 可擴充處理器) | +| 存儲 | ≥ 4 TB SSD (依據連鎖資料大小調整;請洽詢 Kaia 團隊以取得指引) | + +任何具有類似硬件配置的物理機器都足以運行 CN 或 PN。 + +#### 依節點類型建議的規格 + +| Node Type | 核心/線程 | 內存 | +| :------------------------------------------- | :------------ | :---- | +| CN | 16 核心 / 32 線程 | 128GB | +| PN | 8 核心 / 16 線程 | 64 GB | +| PN (with Live Pruning DB) | 4 核心 / 8 線程 | 32 GB | 您可以使用和應用即時修剪選項來使用即時修剪 DB。 更多詳情,請參閱 https://docs.kaia.io/learn/storage/live-pruning/。 但要注意的是,目前不建議對 CN 進行活體修剪,但這一做法將來可能會改變。 @@ -37,11 +45,11 @@ #### 建議的 "Azure "規範 -| Node Type | Model | vCPU | 內存(GiB) | 存儲類型 (GiB\) | 存儲速度(IOPS) | 價格(韓國中部,美元/小時) | -| :------------------------------------------: | :-----: | :--: | :-----: | :---------------------------: | :--------: | :-------------------: | -| CN | D32s v5 | 32 | 128 | P50 (4096) | 7500 | 1.888 | -| PN | D16s v5 | 16 | 64 | P50 (4096) | 7500 | 0.944 | -| PN (with Live Pruning DB) | D8s v5 | 8 | 32 | P50 (4096) | 7500 | 0.472 | +| 節點類型 | Model | vCPU | 內存(GiB) | 存儲類型 (GiB\) | 存儲速度(IOPS) | 價格(韓國中部,美元/小時) | +| :----------: | :-----: | :--: | :-----: | :---------------------------: | :--------: | :-------------------: | +| CN | D32s v5 | 32 | 128 | P50 (4096) | 7500 | 1.888 | +| PN | D16s v5 | 16 | 64 | P50 (4096) | 7500 | 0.944 | +| PN(帶即時修剪 DB) | D8s v5 | 8 | 32 | P50 (4096) | 7500 | 0.472 | 此存儲規範源自 Azure Premium Disk 規範。 @@ -49,11 +57,11 @@ #### 建議的 GCP 規範 -| 節點類型 | 模型 | vCPU | 內存(GiB) | 存儲類型 (GiB\) | 存儲速度(IOPS) | 價格(亞洲-東北3,美元/小時) | -| :----------: | :------------: | :--: | :-----: | :---------: | :--------: | :------------------------: | -| CN | c4-standard-32 | 32 | 120 | 4,000(最少) | 7500 | 2.03078256 | -| PN | n2- 標準-16 | 16 | 64 | 4,000(最少) | 7500 | 1.016243 | -| PN(帶即時修剪 DB) | n2- 標準-8 | 8 | 32 | 3,500(最低) | 7500 | 0.508121 | +| 節點類型 | 模型 | vCPU | 內存(GiB) | 存儲類型 (GiB\) | 存儲速度(IOPS) | 價格(亞洲-東北3,美元/小時) | +| :-----------------------------: | :------------: | :--: | :-----: | :---------: | :--------: | :------------------------: | +| CN | c4-standard-32 | 32 | 120 | 4,000(最少) | 7500 | 2.03078256 | +| PN | n2- 標準-16 | 16 | 64 | 4,000(最少) | 7500 | 1.016243 | +| PN (含活修剪 DB) | n2- 標準-8 | 8 | 32 | 3,500(最低) | 7500 | 0.508121 | 以上信息來自 [https://cloud.google.com/compute/vm-instance-pricing#general-purpose_machine_type_family/](https://cloud.google.com/compute/vm-instance-pricing#general-purpose_machine_type_family/) 和 [https://cloud.google.com/storage/pricing#asia](https://cloud.google.com/storage/pricing#asia),谷歌可能會對其進行修改。 diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md index 9ba3ad1ddb94..48c838ffbfdd 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/endpoint-node/docker-setup.md @@ -27,7 +27,7 @@ echo "LOG_DIR=/var/kend/logs" >> conf/kend.conf ### (可選)下載 Chaindata 快照 -從創世區塊進行同步操作非常耗時。 您可以使用 [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) 跳過 [Full Sync](../../learn/storage/block-sync.md#full-sync) 過程。 下載並解壓 chaindata 快照。 然後將解壓後的目錄掛載到容器中。 +從 genesis 區塊進行同步處理非常耗時。 您可以使用 [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) 跳過 [Full Sync](../../learn/storage/block-sync.md#full-sync) 過程。 下載並解壓 chaindata 快照。 然後將解壓後的目錄掛載到容器中。 ## 啟動容器 diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md index 9e6a64aa3fb6..adbb47ad2d54 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/nodes/endpoint-node/install-endpoint-nodes.md @@ -115,7 +115,7 @@ DATA_DIR=/var/kend/data ### (可選)下載 Chaindata 快照 -從創世區塊進行同步操作非常耗時。 您可以使用 [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) 跳過 [Full Sync](../../learn/storage/block-sync.md#full-sync) 過程。 +從 genesis 區塊進行同步處理非常耗時。 您可以使用 [Chaindata Snapshot](../../misc/operation/chaindata-snapshot.md) 跳過 [Full Sync](../../learn/storage/block-sync.md#full-sync) 過程。 ## 啟動 EN diff --git a/i18n/zh-TW/docusaurus-plugin-content-docs/current/references/contract-addresses.md b/i18n/zh-TW/docusaurus-plugin-content-docs/current/references/contract-addresses.md index 537b6601f9eb..f269b32d8d03 100644 --- a/i18n/zh-TW/docusaurus-plugin-content-docs/current/references/contract-addresses.md +++ b/i18n/zh-TW/docusaurus-plugin-content-docs/current/references/contract-addresses.md @@ -15,6 +15,7 @@ Kaia 的某些功能依賴於稱為_系統合約_的特殊智能合約。 它們 | KIP-113 SimpleBlsRegistry | proxy 0x3e80e75975bdb8e04B800485DD28BebeC6d97679
logic 0xb5ed8d6edd437a0d6ae828580c0aef5678d87f1a | proxy 0x4BEed0651C46aE5a7CB3b7737345d2ee733789e6
logic 0x6751096fe72d835307d7e635aed51296948b93c5 | | KIP-247 無瓦斯交換路由器 | 0xCf658F786bf4AC62D66d70Dd26B5c1395dA22c63 | 0x4b41783732810b731569E4d944F59372F411BEa2 | | KIP-226 CLRegistry | 0x25F4044c655Fc7B23c62bbC78ceF3B4EBFb4e478 | 0x25F4044c655Fc7B23c62bbC78ceF3B4EBFb4e478 | +| KIP-249 AuctionEntryPoint | 0xFc5c1C92d8DE06F7143f71FeA209e04042dcff82 | 0x2fF66A8b9f133ca4774bEAd723b8a92fA1e28480 | 有些合約不會被 Kaia 節點直接讀取,但在 Kaia 區塊鏈及其生態系統的運行中發揮著至關重要的作用。 其中包括財務、治理和 KAIA 代幣橋接合約。 @@ -33,7 +34,9 @@ Kaia 的某些功能依賴於稱為_系統合約_的特殊智能合約。 它們 | Kaiabridge Judge | 0x64c91d6517b8f2fd7f4157c32DE4acfe1AeA2611 | 0x3735Ba95cca5DEd47Fa5b202a2Bbda4c63c0B1DD | | Kaiabridge Guardian | 0xE49D152E5FA576caFC18D2775AF4E58C135a6851 | 0xc9e8342C1da4c89A423258d9030414331b4761Cf | | KIP-163 PublicDelegationFactory | 0x29C8cc53d22F79D4024ecB67DB1a09b37bCdE415 | 0x98c47c2cda854cbb025d47de72149a7ec238ec33 | -| KIP-226 CLDEXFactory | 0x2A4C5eCaafB26460F17d509EA4d15741AF5F5f0a | 0x537D58BdBC98c690bE5d3e3F638d4B93754B15Fd | -| KIP-226 CLDEXRouter | 0x21d3c567058277b19324FE22c8e4Bb3D2AE0D4C3 | 0x41F135a084897e4145CC2032e8701726af795e3a | +| KIP-226 CLDEXFactory | 0x93fa0E1deE99ac4158a617a6EC79cB941bD9a39F | 0x666a9a72D2f708062a20e7Ca94f6dd5Ce6B33eA4 | +| KIP-226 CLDEXRouter | 0x5086273d9C8a79B7d2466aaCc52a6E43E22152A5 | 0x2871e95eaBFF0E71e4e4b706D7F1F3D24811673b | | KIP-226 StakingTrackerV2 | 0xF45c37c265f148894D6d9A4c066aFaAB00557c9c | 0x9b015Ab5916EE53e52Ef60f31E978b4001908c43 | | [Canonical WKAIA](../build/smart-contracts/token-development/canonical-wkaia.md) | 0x19Aac5f612f524B754CA7e7c41cbFa2E981A4432 | 0x043c471bEe060e00A56CcD02c0Ca286808a5A436 | +| KIP-249 AuctionDepositVault | 0x0E66b62273Cc99BC519DD4dD0C0Cf689dd7b9876 | 0x2A168bCdeB9006eC6E71f44B7686c9a9863C1FBc | +| KIP-249 AuctionFeeVault | 0x303BB9c9FF4Aa656ac4c8e9f99F8E4C133FDa665 | 0xE4e7d880786c53b6EA6cfA848Eb3a05eE97b2aCC | \ No newline at end of file diff --git a/i18n/zh-TW/docusaurus-theme-classic/footer.json b/i18n/zh-TW/docusaurus-theme-classic/footer.json index d05b80728e3a..3451a6a8bb44 100644 --- a/i18n/zh-TW/docusaurus-theme-classic/footer.json +++ b/i18n/zh-TW/docusaurus-theme-classic/footer.json @@ -56,7 +56,11 @@ "description": "The label of footer link with label=Open Source linking to https://docs.kaia.io/misc/opensource/" }, "copyright": { - "message": "© Kaia DLT Foundation 2025. All rights reserved.", + "message": "", "description": "The footer copyright" + }, + "link.item.label.Blog": { + "message": "部落格", + "description": "The label of footer link with label=Blog linking to https://blog.kaia.io/" } }