From d7022e48adea49fbf5e68043849ff1d992924bdf Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Thu, 9 Jan 2025 19:51:00 +0200 Subject: [PATCH 01/14] Changed file structure that supports multi language support. Translated into ua language index.md, rpc.md, terminology.md, actions.md --- docs/{ => en}/advanced/actions.md | 0 docs/{ => en}/advanced/confirmation.md | 0 docs/{ => en}/advanced/index.md | 0 docs/{ => en}/advanced/lookup-tables.md | 0 docs/{ => en}/advanced/retry.md | 0 docs/{ => en}/advanced/state-compression.md | 0 docs/{ => en}/advanced/versions.md | 0 docs/{ => en}/clients/index.md | 0 docs/{ => en}/clients/javascript-reference.md | 0 docs/{ => en}/clients/javascript.md | 0 docs/{ => en}/clients/rust.md | 0 docs/{ => en}/core/accounts.md | 0 docs/{ => en}/core/clusters.md | 0 docs/{ => en}/core/cpi.md | 0 docs/{ => en}/core/fees.md | 0 docs/{ => en}/core/index.md | 0 docs/{ => en}/core/pda.md | 0 docs/{ => en}/core/programs.md | 0 docs/{ => en}/core/tokens.md | 0 docs/{ => en}/core/transactions.md | 0 docs/{ => en}/economics/index.md | 0 .../inflation/_adjusted_staking_yield.md | 0 .../economics/inflation/inflation-schedule.md | 0 .../economics/inflation/terminology.md | 0 docs/{ => en}/economics/staking/index.md | 0 .../economics/staking/stake-accounts.md | 0 .../economics/staking/stake-programming.md | 0 docs/{ => en}/index.md | 0 docs/{ => en}/intro/dev.md | 0 docs/{ => en}/intro/index.md | 0 docs/{ => en}/intro/installation.md | 0 .../quick-start/cross-program-invocation.md | 0 .../intro/quick-start/deploying-programs.md | 0 docs/{ => en}/intro/quick-start/index.md | 0 .../quick-start/program-derived-address.md | 0 .../intro/quick-start/reading-from-network.md | 0 .../intro/quick-start/writing-to-network.md | 0 docs/{ => en}/intro/wallets.md | 0 docs/{ => en}/more/exchange.md | 0 docs/{ => en}/more/index.md | 0 .../programs/anchor/client-typescript.md | 0 docs/{ => en}/programs/anchor/cpi.md | 0 docs/{ => en}/programs/anchor/idl.md | 0 docs/{ => en}/programs/anchor/index.md | 0 docs/{ => en}/programs/anchor/pda.md | 0 .../programs/anchor/program-structure.md | 0 docs/{ => en}/programs/deploying.md | 0 docs/{ => en}/programs/examples.md | 0 docs/{ => en}/programs/faq.md | 0 docs/{ => en}/programs/index.md | 0 docs/{ => en}/programs/limitations.md | 0 docs/{ => en}/programs/rust/index.md | 0 .../programs/rust/program-structure.md | 0 docs/{ => en}/programs/testing.md | 0 docs/{ => en}/rpc.md | 0 .../rpc/deprecated/confirmTransaction.mdx | 0 .../rpc/deprecated/getConfirmedBlock.mdx | 0 .../rpc/deprecated/getConfirmedBlocks.mdx | 0 .../getConfirmedBlocksWithLimit.mdx | 0 .../getConfirmedSignaturesForAddress2.mdx | 0 .../deprecated/getConfirmedTransaction.mdx | 0 .../getFeeCalculatorForBlockhash.mdx | 0 .../rpc/deprecated/getFeeRateGovernor.mdx | 0 docs/{ => en}/rpc/deprecated/getFees.mdx | 0 .../rpc/deprecated/getRecentBlockhash.mdx | 0 .../deprecated/getSignatureConfirmation.mdx | 0 .../rpc/deprecated/getSignatureStatus.mdx | 0 .../rpc/deprecated/getSnapshotSlot.mdx | 0 .../rpc/deprecated/getStakeActivation.mdx | 0 docs/{ => en}/rpc/deprecated/index.mdx | 0 docs/{ => en}/rpc/http/getAccountInfo.mdx | 0 docs/{ => en}/rpc/http/getBalance.mdx | 0 docs/{ => en}/rpc/http/getBlock.mdx | 0 docs/{ => en}/rpc/http/getBlockCommitment.mdx | 0 docs/{ => en}/rpc/http/getBlockHeight.mdx | 0 docs/{ => en}/rpc/http/getBlockProduction.mdx | 0 docs/{ => en}/rpc/http/getBlockTime.mdx | 0 docs/{ => en}/rpc/http/getBlocks.mdx | 0 docs/{ => en}/rpc/http/getBlocksWithLimit.mdx | 0 docs/{ => en}/rpc/http/getClusterNodes.mdx | 0 docs/{ => en}/rpc/http/getEpochInfo.mdx | 0 docs/{ => en}/rpc/http/getEpochSchedule.mdx | 0 docs/{ => en}/rpc/http/getFeeForMessage.mdx | 0 .../rpc/http/getFirstAvailableBlock.mdx | 0 docs/{ => en}/rpc/http/getGenesisHash.mdx | 0 docs/{ => en}/rpc/http/getHealth.mdx | 0 .../rpc/http/getHighestSnapshotSlot.mdx | 0 docs/{ => en}/rpc/http/getIdentity.mdx | 0 .../rpc/http/getInflationGovernor.mdx | 0 docs/{ => en}/rpc/http/getInflationRate.mdx | 0 docs/{ => en}/rpc/http/getInflationReward.mdx | 0 docs/{ => en}/rpc/http/getLargestAccounts.mdx | 0 docs/{ => en}/rpc/http/getLatestBlockhash.mdx | 0 docs/{ => en}/rpc/http/getLeaderSchedule.mdx | 0 .../rpc/http/getMaxRetransmitSlot.mdx | 0 .../rpc/http/getMaxShredInsertSlot.mdx | 0 .../getMinimumBalanceForRentExemption.mdx | 0 .../{ => en}/rpc/http/getMultipleAccounts.mdx | 0 docs/{ => en}/rpc/http/getProgramAccounts.mdx | 0 .../rpc/http/getRecentPerformanceSamples.mdx | 0 .../rpc/http/getRecentPrioritizationFees.mdx | 0 .../rpc/http/getSignatureStatuses.mdx | 0 .../rpc/http/getSignaturesForAddress.mdx | 0 docs/{ => en}/rpc/http/getSlot.mdx | 0 docs/{ => en}/rpc/http/getSlotLeader.mdx | 0 docs/{ => en}/rpc/http/getSlotLeaders.mdx | 0 .../rpc/http/getStakeMinimumDelegation.mdx | 0 docs/{ => en}/rpc/http/getSupply.mdx | 0 .../rpc/http/getTokenAccountBalance.mdx | 0 .../rpc/http/getTokenAccountsByDelegate.mdx | 0 .../rpc/http/getTokenAccountsByOwner.mdx | 0 .../rpc/http/getTokenLargestAccounts.mdx | 0 docs/{ => en}/rpc/http/getTokenSupply.mdx | 0 docs/{ => en}/rpc/http/getTransaction.mdx | 0 .../{ => en}/rpc/http/getTransactionCount.mdx | 0 docs/{ => en}/rpc/http/getVersion.mdx | 0 docs/{ => en}/rpc/http/getVoteAccounts.mdx | 0 docs/{ => en}/rpc/http/index.mdx | 0 docs/{ => en}/rpc/http/isBlockhashValid.mdx | 0 docs/{ => en}/rpc/http/minimumLedgerSlot.mdx | 0 docs/{ => en}/rpc/http/requestAirdrop.mdx | 0 docs/{ => en}/rpc/http/sendTransaction.mdx | 0 .../{ => en}/rpc/http/simulateTransaction.mdx | 0 docs/{ => en}/rpc/index.mdx | 0 docs/{ => en}/rpc/json-structures.mdx | 0 .../rpc/websocket/accountSubscribe.mdx | 0 .../rpc/websocket/accountUnsubscribe.mdx | 0 .../{ => en}/rpc/websocket/blockSubscribe.mdx | 0 .../rpc/websocket/blockUnsubscribe.mdx | 0 docs/{ => en}/rpc/websocket/index.mdx | 0 docs/{ => en}/rpc/websocket/logsSubscribe.mdx | 0 .../rpc/websocket/logsUnsubscribe.mdx | 0 .../rpc/websocket/programSubscribe.mdx | 0 .../rpc/websocket/programUnsubscribe.mdx | 0 docs/{ => en}/rpc/websocket/rootSubscribe.mdx | 0 .../rpc/websocket/rootUnsubscribe.mdx | 0 .../rpc/websocket/signatureSubscribe.mdx | 0 .../rpc/websocket/signatureUnsubscribe.mdx | 0 docs/{ => en}/rpc/websocket/slotSubscribe.mdx | 0 .../rpc/websocket/slotUnsubscribe.mdx | 0 .../rpc/websocket/slotsUpdatesSubscribe.mdx | 0 .../rpc/websocket/slotsUpdatesUnsubscribe.mdx | 0 docs/{ => en}/rpc/websocket/voteSubscribe.mdx | 0 .../rpc/websocket/voteUnsubscribe.mdx | 0 docs/{ => en}/terminology.md | 0 docs/uk/advanced/actions.md | 1038 ++++++++++++ docs/uk/advanced/confirmation.md | 402 +++++ docs/uk/advanced/index.md | 5 + docs/uk/advanced/lookup-tables.md | 192 +++ docs/uk/advanced/retry.md | 329 ++++ docs/uk/advanced/state-compression.md | 339 ++++ docs/uk/advanced/versions.md | 191 +++ docs/uk/clients/index.md | 5 + docs/uk/clients/javascript-reference.md | 861 ++++++++++ docs/uk/clients/javascript.md | 409 +++++ docs/uk/clients/rust.md | 53 + docs/uk/core/accounts.md | 197 +++ docs/uk/core/clusters.md | 169 ++ docs/uk/core/cpi.md | 134 ++ docs/uk/core/fees.md | 496 ++++++ docs/uk/core/index.md | 117 ++ docs/uk/core/pda.md | 394 +++++ docs/uk/core/programs.md | 95 ++ docs/uk/core/tokens.md | 580 +++++++ docs/uk/core/transactions.md | 415 +++++ docs/uk/economics/index.md | 52 + .../inflation/_adjusted_staking_yield.md | 170 ++ .../economics/inflation/inflation-schedule.md | 88 ++ docs/uk/economics/inflation/terminology.md | 112 ++ docs/uk/economics/staking/index.md | 98 ++ docs/uk/economics/staking/stake-accounts.md | 146 ++ .../uk/economics/staking/stake-programming.md | 28 + docs/uk/index.md | 73 + docs/uk/intro/dev.md | 195 +++ docs/uk/intro/index.md | 5 + docs/uk/intro/installation.md | 664 ++++++++ .../quick-start/cross-program-invocation.md | 608 +++++++ .../intro/quick-start/deploying-programs.md | 379 +++++ docs/uk/intro/quick-start/index.md | 119 ++ .../quick-start/program-derived-address.md | 1098 +++++++++++++ .../intro/quick-start/reading-from-network.md | 401 +++++ .../intro/quick-start/writing-to-network.md | 365 +++++ docs/uk/intro/wallets.md | 69 + docs/uk/more/exchange.md | 1294 +++++++++++++++ docs/uk/more/index.md | 6 + docs/uk/programs/anchor/client-typescript.md | 354 +++++ docs/uk/programs/anchor/cpi.md | 551 +++++++ docs/uk/programs/anchor/idl.md | 516 ++++++ docs/uk/programs/anchor/index.md | 384 +++++ docs/uk/programs/anchor/pda.md | 325 ++++ docs/uk/programs/anchor/program-structure.md | 399 +++++ docs/uk/programs/deploying.md | 331 ++++ docs/uk/programs/examples.md | 157 ++ docs/uk/programs/faq.md | 194 +++ docs/uk/programs/index.md | 5 + docs/uk/programs/limitations.md | 112 ++ docs/uk/programs/rust/index.md | 474 ++++++ docs/uk/programs/rust/program-structure.md | 1407 +++++++++++++++++ docs/uk/programs/testing.md | 235 +++ docs/uk/rpc.md | 10 + docs/uk/rpc/deprecated/confirmTransaction.mdx | 13 + docs/uk/rpc/deprecated/getConfirmedBlock.mdx | 202 +++ docs/uk/rpc/deprecated/getConfirmedBlocks.mdx | 65 + .../getConfirmedBlocksWithLimit.mdx | 72 + .../getConfirmedSignaturesForAddress2.mdx | 120 ++ .../deprecated/getConfirmedTransaction.mdx | 153 ++ .../getFeeCalculatorForBlockhash.mdx | 94 ++ docs/uk/rpc/deprecated/getFeeRateGovernor.mdx | 74 + docs/uk/rpc/deprecated/getFees.mdx | 91 ++ docs/uk/rpc/deprecated/getRecentBlockhash.mdx | 85 + .../deprecated/getSignatureConfirmation.mdx | 13 + docs/uk/rpc/deprecated/getSignatureStatus.mdx | 13 + docs/uk/rpc/deprecated/getSnapshotSlot.mdx | 58 + docs/uk/rpc/deprecated/getStakeActivation.mdx | 97 ++ docs/uk/rpc/deprecated/index.mdx | 6 + docs/uk/rpc/http/getAccountInfo.mdx | 138 ++ docs/uk/rpc/http/getBalance.mdx | 72 + docs/uk/rpc/http/getBlock.mdx | 287 ++++ docs/uk/rpc/http/getBlockCommitment.mdx | 65 + docs/uk/rpc/http/getBlockHeight.mdx | 66 + docs/uk/rpc/http/getBlockProduction.mdx | 94 ++ docs/uk/rpc/http/getBlockTime.mdx | 75 + docs/uk/rpc/http/getBlocks.mdx | 79 + docs/uk/rpc/http/getBlocksWithLimit.mdx | 77 + docs/uk/rpc/http/getClusterNodes.mdx | 69 + docs/uk/rpc/http/getEpochInfo.mdx | 76 + docs/uk/rpc/http/getEpochSchedule.mdx | 64 + docs/uk/rpc/http/getFeeForMessage.mdx | 80 + docs/uk/rpc/http/getFirstAvailableBlock.mdx | 45 + docs/uk/rpc/http/getGenesisHash.mdx | 45 + docs/uk/rpc/http/getHealth.mdx | 78 + docs/uk/rpc/http/getHighestSnapshotSlot.mdx | 75 + docs/uk/rpc/http/getIdentity.mdx | 50 + docs/uk/rpc/http/getInflationGovernor.mdx | 71 + docs/uk/rpc/http/getInflationRate.mdx | 56 + docs/uk/rpc/http/getInflationReward.mdx | 96 ++ docs/uk/rpc/http/getLargestAccounts.mdx | 146 ++ docs/uk/rpc/http/getLatestBlockhash.mdx | 90 ++ docs/uk/rpc/http/getLeaderSchedule.mdx | 93 ++ docs/uk/rpc/http/getMaxRetransmitSlot.mdx | 42 + docs/uk/rpc/http/getMaxShredInsertSlot.mdx | 42 + .../getMinimumBalanceForRentExemption.mdx | 61 + docs/uk/rpc/http/getMultipleAccounts.mdx | 154 ++ docs/uk/rpc/http/getProgramAccounts.mdx | 179 +++ .../rpc/http/getRecentPerformanceSamples.mdx | 100 ++ .../rpc/http/getRecentPrioritizationFees.mdx | 93 ++ docs/uk/rpc/http/getSignatureStatuses.mdx | 115 ++ docs/uk/rpc/http/getSignaturesForAddress.mdx | 115 ++ docs/uk/rpc/http/getSlot.mdx | 58 + docs/uk/rpc/http/getSlotLeader.mdx | 61 + docs/uk/rpc/http/getSlotLeaders.mdx | 73 + .../uk/rpc/http/getStakeMinimumDelegation.mdx | 67 + docs/uk/rpc/http/getSupply.mdx | 84 + docs/uk/rpc/http/getTokenAccountBalance.mdx | 90 ++ .../rpc/http/getTokenAccountsByDelegate.mdx | 189 +++ docs/uk/rpc/http/getTokenAccountsByOwner.mdx | 209 +++ docs/uk/rpc/http/getTokenLargestAccounts.mdx | 97 ++ docs/uk/rpc/http/getTokenSupply.mdx | 86 + docs/uk/rpc/http/getTransaction.mdx | 213 +++ docs/uk/rpc/http/getTransactionCount.mdx | 57 + docs/uk/rpc/http/getVersion.mdx | 50 + docs/uk/rpc/http/getVoteAccounts.mdx | 113 ++ docs/uk/rpc/http/index.mdx | 105 ++ docs/uk/rpc/http/isBlockhashValid.mdx | 84 + docs/uk/rpc/http/minimumLedgerSlot.mdx | 47 + docs/uk/rpc/http/requestAirdrop.mdx | 72 + docs/uk/rpc/http/sendTransaction.mdx | 125 ++ docs/uk/rpc/http/simulateTransaction.mdx | 197 +++ docs/uk/rpc/index.mdx | 99 ++ docs/uk/rpc/json-structures.mdx | 110 ++ docs/uk/rpc/websocket/accountSubscribe.mdx | 160 ++ docs/uk/rpc/websocket/accountUnsubscribe.mdx | 47 + docs/uk/rpc/websocket/blockSubscribe.mdx | 386 +++++ docs/uk/rpc/websocket/blockUnsubscribe.mdx | 47 + docs/uk/rpc/websocket/index.mdx | 23 + docs/uk/rpc/websocket/logsSubscribe.mdx | 138 ++ docs/uk/rpc/websocket/logsUnsubscribe.mdx | 47 + docs/uk/rpc/websocket/programSubscribe.mdx | 211 +++ docs/uk/rpc/websocket/programUnsubscribe.mdx | 47 + docs/uk/rpc/websocket/rootSubscribe.mdx | 55 + docs/uk/rpc/websocket/rootUnsubscribe.mdx | 47 + docs/uk/rpc/websocket/signatureSubscribe.mdx | 149 ++ .../uk/rpc/websocket/signatureUnsubscribe.mdx | 47 + docs/uk/rpc/websocket/slotSubscribe.mdx | 65 + docs/uk/rpc/websocket/slotUnsubscribe.mdx | 47 + .../rpc/websocket/slotsUpdatesSubscribe.mdx | 87 + .../rpc/websocket/slotsUpdatesUnsubscribe.mdx | 47 + docs/uk/rpc/websocket/voteSubscribe.mdx | 75 + docs/uk/rpc/websocket/voteUnsubscribe.mdx | 47 + docs/uk/terminology.md | 438 +++++ 290 files changed, 26485 insertions(+) rename docs/{ => en}/advanced/actions.md (100%) rename docs/{ => en}/advanced/confirmation.md (100%) rename docs/{ => en}/advanced/index.md (100%) rename docs/{ => en}/advanced/lookup-tables.md (100%) rename docs/{ => en}/advanced/retry.md (100%) rename docs/{ => en}/advanced/state-compression.md (100%) rename docs/{ => en}/advanced/versions.md (100%) rename docs/{ => en}/clients/index.md (100%) rename docs/{ => en}/clients/javascript-reference.md (100%) rename docs/{ => en}/clients/javascript.md (100%) rename docs/{ => en}/clients/rust.md (100%) rename docs/{ => en}/core/accounts.md (100%) rename docs/{ => en}/core/clusters.md (100%) rename docs/{ => en}/core/cpi.md (100%) rename docs/{ => en}/core/fees.md (100%) rename docs/{ => en}/core/index.md (100%) rename docs/{ => en}/core/pda.md (100%) rename docs/{ => en}/core/programs.md (100%) rename docs/{ => en}/core/tokens.md (100%) rename docs/{ => en}/core/transactions.md (100%) rename docs/{ => en}/economics/index.md (100%) rename docs/{ => en}/economics/inflation/_adjusted_staking_yield.md (100%) rename docs/{ => en}/economics/inflation/inflation-schedule.md (100%) rename docs/{ => en}/economics/inflation/terminology.md (100%) rename docs/{ => en}/economics/staking/index.md (100%) rename docs/{ => en}/economics/staking/stake-accounts.md (100%) rename docs/{ => en}/economics/staking/stake-programming.md (100%) rename docs/{ => en}/index.md (100%) rename docs/{ => en}/intro/dev.md (100%) rename docs/{ => en}/intro/index.md (100%) rename docs/{ => en}/intro/installation.md (100%) rename docs/{ => en}/intro/quick-start/cross-program-invocation.md (100%) rename docs/{ => en}/intro/quick-start/deploying-programs.md (100%) rename docs/{ => en}/intro/quick-start/index.md (100%) rename docs/{ => en}/intro/quick-start/program-derived-address.md (100%) rename docs/{ => en}/intro/quick-start/reading-from-network.md (100%) rename docs/{ => en}/intro/quick-start/writing-to-network.md (100%) rename docs/{ => en}/intro/wallets.md (100%) rename docs/{ => en}/more/exchange.md (100%) rename docs/{ => en}/more/index.md (100%) rename docs/{ => en}/programs/anchor/client-typescript.md (100%) rename docs/{ => en}/programs/anchor/cpi.md (100%) rename docs/{ => en}/programs/anchor/idl.md (100%) rename docs/{ => en}/programs/anchor/index.md (100%) rename docs/{ => en}/programs/anchor/pda.md (100%) rename docs/{ => en}/programs/anchor/program-structure.md (100%) rename docs/{ => en}/programs/deploying.md (100%) rename docs/{ => en}/programs/examples.md (100%) rename docs/{ => en}/programs/faq.md (100%) rename docs/{ => en}/programs/index.md (100%) rename docs/{ => en}/programs/limitations.md (100%) rename docs/{ => en}/programs/rust/index.md (100%) rename docs/{ => en}/programs/rust/program-structure.md (100%) rename docs/{ => en}/programs/testing.md (100%) rename docs/{ => en}/rpc.md (100%) rename docs/{ => en}/rpc/deprecated/confirmTransaction.mdx (100%) rename docs/{ => en}/rpc/deprecated/getConfirmedBlock.mdx (100%) rename docs/{ => en}/rpc/deprecated/getConfirmedBlocks.mdx (100%) rename docs/{ => en}/rpc/deprecated/getConfirmedBlocksWithLimit.mdx (100%) rename docs/{ => en}/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx (100%) rename docs/{ => en}/rpc/deprecated/getConfirmedTransaction.mdx (100%) rename docs/{ => en}/rpc/deprecated/getFeeCalculatorForBlockhash.mdx (100%) rename docs/{ => en}/rpc/deprecated/getFeeRateGovernor.mdx (100%) rename docs/{ => en}/rpc/deprecated/getFees.mdx (100%) rename docs/{ => en}/rpc/deprecated/getRecentBlockhash.mdx (100%) rename docs/{ => en}/rpc/deprecated/getSignatureConfirmation.mdx (100%) rename docs/{ => en}/rpc/deprecated/getSignatureStatus.mdx (100%) rename docs/{ => en}/rpc/deprecated/getSnapshotSlot.mdx (100%) rename docs/{ => en}/rpc/deprecated/getStakeActivation.mdx (100%) rename docs/{ => en}/rpc/deprecated/index.mdx (100%) rename docs/{ => en}/rpc/http/getAccountInfo.mdx (100%) rename docs/{ => en}/rpc/http/getBalance.mdx (100%) rename docs/{ => en}/rpc/http/getBlock.mdx (100%) rename docs/{ => en}/rpc/http/getBlockCommitment.mdx (100%) rename docs/{ => en}/rpc/http/getBlockHeight.mdx (100%) rename docs/{ => en}/rpc/http/getBlockProduction.mdx (100%) rename docs/{ => en}/rpc/http/getBlockTime.mdx (100%) rename docs/{ => en}/rpc/http/getBlocks.mdx (100%) rename docs/{ => en}/rpc/http/getBlocksWithLimit.mdx (100%) rename docs/{ => en}/rpc/http/getClusterNodes.mdx (100%) rename docs/{ => en}/rpc/http/getEpochInfo.mdx (100%) rename docs/{ => en}/rpc/http/getEpochSchedule.mdx (100%) rename docs/{ => en}/rpc/http/getFeeForMessage.mdx (100%) rename docs/{ => en}/rpc/http/getFirstAvailableBlock.mdx (100%) rename docs/{ => en}/rpc/http/getGenesisHash.mdx (100%) rename docs/{ => en}/rpc/http/getHealth.mdx (100%) rename docs/{ => en}/rpc/http/getHighestSnapshotSlot.mdx (100%) rename docs/{ => en}/rpc/http/getIdentity.mdx (100%) rename docs/{ => en}/rpc/http/getInflationGovernor.mdx (100%) rename docs/{ => en}/rpc/http/getInflationRate.mdx (100%) rename docs/{ => en}/rpc/http/getInflationReward.mdx (100%) rename docs/{ => en}/rpc/http/getLargestAccounts.mdx (100%) rename docs/{ => en}/rpc/http/getLatestBlockhash.mdx (100%) rename docs/{ => en}/rpc/http/getLeaderSchedule.mdx (100%) rename docs/{ => en}/rpc/http/getMaxRetransmitSlot.mdx (100%) rename docs/{ => en}/rpc/http/getMaxShredInsertSlot.mdx (100%) rename docs/{ => en}/rpc/http/getMinimumBalanceForRentExemption.mdx (100%) rename docs/{ => en}/rpc/http/getMultipleAccounts.mdx (100%) rename docs/{ => en}/rpc/http/getProgramAccounts.mdx (100%) rename docs/{ => en}/rpc/http/getRecentPerformanceSamples.mdx (100%) rename docs/{ => en}/rpc/http/getRecentPrioritizationFees.mdx (100%) rename docs/{ => en}/rpc/http/getSignatureStatuses.mdx (100%) rename docs/{ => en}/rpc/http/getSignaturesForAddress.mdx (100%) rename docs/{ => en}/rpc/http/getSlot.mdx (100%) rename docs/{ => en}/rpc/http/getSlotLeader.mdx (100%) rename docs/{ => en}/rpc/http/getSlotLeaders.mdx (100%) rename docs/{ => en}/rpc/http/getStakeMinimumDelegation.mdx (100%) rename docs/{ => en}/rpc/http/getSupply.mdx (100%) rename docs/{ => en}/rpc/http/getTokenAccountBalance.mdx (100%) rename docs/{ => en}/rpc/http/getTokenAccountsByDelegate.mdx (100%) rename docs/{ => en}/rpc/http/getTokenAccountsByOwner.mdx (100%) rename docs/{ => en}/rpc/http/getTokenLargestAccounts.mdx (100%) rename docs/{ => en}/rpc/http/getTokenSupply.mdx (100%) rename docs/{ => en}/rpc/http/getTransaction.mdx (100%) rename docs/{ => en}/rpc/http/getTransactionCount.mdx (100%) rename docs/{ => en}/rpc/http/getVersion.mdx (100%) rename docs/{ => en}/rpc/http/getVoteAccounts.mdx (100%) rename docs/{ => en}/rpc/http/index.mdx (100%) rename docs/{ => en}/rpc/http/isBlockhashValid.mdx (100%) rename docs/{ => en}/rpc/http/minimumLedgerSlot.mdx (100%) rename docs/{ => en}/rpc/http/requestAirdrop.mdx (100%) rename docs/{ => en}/rpc/http/sendTransaction.mdx (100%) rename docs/{ => en}/rpc/http/simulateTransaction.mdx (100%) rename docs/{ => en}/rpc/index.mdx (100%) rename docs/{ => en}/rpc/json-structures.mdx (100%) rename docs/{ => en}/rpc/websocket/accountSubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/accountUnsubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/blockSubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/blockUnsubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/index.mdx (100%) rename docs/{ => en}/rpc/websocket/logsSubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/logsUnsubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/programSubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/programUnsubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/rootSubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/rootUnsubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/signatureSubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/signatureUnsubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/slotSubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/slotUnsubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/slotsUpdatesSubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/slotsUpdatesUnsubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/voteSubscribe.mdx (100%) rename docs/{ => en}/rpc/websocket/voteUnsubscribe.mdx (100%) rename docs/{ => en}/terminology.md (100%) create mode 100644 docs/uk/advanced/actions.md create mode 100644 docs/uk/advanced/confirmation.md create mode 100644 docs/uk/advanced/index.md create mode 100644 docs/uk/advanced/lookup-tables.md create mode 100644 docs/uk/advanced/retry.md create mode 100644 docs/uk/advanced/state-compression.md create mode 100644 docs/uk/advanced/versions.md create mode 100644 docs/uk/clients/index.md create mode 100644 docs/uk/clients/javascript-reference.md create mode 100644 docs/uk/clients/javascript.md create mode 100644 docs/uk/clients/rust.md create mode 100644 docs/uk/core/accounts.md create mode 100644 docs/uk/core/clusters.md create mode 100644 docs/uk/core/cpi.md create mode 100644 docs/uk/core/fees.md create mode 100644 docs/uk/core/index.md create mode 100644 docs/uk/core/pda.md create mode 100644 docs/uk/core/programs.md create mode 100644 docs/uk/core/tokens.md create mode 100644 docs/uk/core/transactions.md create mode 100644 docs/uk/economics/index.md create mode 100644 docs/uk/economics/inflation/_adjusted_staking_yield.md create mode 100644 docs/uk/economics/inflation/inflation-schedule.md create mode 100644 docs/uk/economics/inflation/terminology.md create mode 100644 docs/uk/economics/staking/index.md create mode 100644 docs/uk/economics/staking/stake-accounts.md create mode 100644 docs/uk/economics/staking/stake-programming.md create mode 100644 docs/uk/index.md create mode 100644 docs/uk/intro/dev.md create mode 100644 docs/uk/intro/index.md create mode 100644 docs/uk/intro/installation.md create mode 100644 docs/uk/intro/quick-start/cross-program-invocation.md create mode 100644 docs/uk/intro/quick-start/deploying-programs.md create mode 100644 docs/uk/intro/quick-start/index.md create mode 100644 docs/uk/intro/quick-start/program-derived-address.md create mode 100644 docs/uk/intro/quick-start/reading-from-network.md create mode 100644 docs/uk/intro/quick-start/writing-to-network.md create mode 100644 docs/uk/intro/wallets.md create mode 100644 docs/uk/more/exchange.md create mode 100644 docs/uk/more/index.md create mode 100644 docs/uk/programs/anchor/client-typescript.md create mode 100644 docs/uk/programs/anchor/cpi.md create mode 100644 docs/uk/programs/anchor/idl.md create mode 100644 docs/uk/programs/anchor/index.md create mode 100644 docs/uk/programs/anchor/pda.md create mode 100644 docs/uk/programs/anchor/program-structure.md create mode 100644 docs/uk/programs/deploying.md create mode 100644 docs/uk/programs/examples.md create mode 100644 docs/uk/programs/faq.md create mode 100644 docs/uk/programs/index.md create mode 100644 docs/uk/programs/limitations.md create mode 100644 docs/uk/programs/rust/index.md create mode 100644 docs/uk/programs/rust/program-structure.md create mode 100644 docs/uk/programs/testing.md create mode 100644 docs/uk/rpc.md create mode 100644 docs/uk/rpc/deprecated/confirmTransaction.mdx create mode 100644 docs/uk/rpc/deprecated/getConfirmedBlock.mdx create mode 100644 docs/uk/rpc/deprecated/getConfirmedBlocks.mdx create mode 100644 docs/uk/rpc/deprecated/getConfirmedBlocksWithLimit.mdx create mode 100644 docs/uk/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx create mode 100644 docs/uk/rpc/deprecated/getConfirmedTransaction.mdx create mode 100644 docs/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx create mode 100644 docs/uk/rpc/deprecated/getFeeRateGovernor.mdx create mode 100644 docs/uk/rpc/deprecated/getFees.mdx create mode 100644 docs/uk/rpc/deprecated/getRecentBlockhash.mdx create mode 100644 docs/uk/rpc/deprecated/getSignatureConfirmation.mdx create mode 100644 docs/uk/rpc/deprecated/getSignatureStatus.mdx create mode 100644 docs/uk/rpc/deprecated/getSnapshotSlot.mdx create mode 100644 docs/uk/rpc/deprecated/getStakeActivation.mdx create mode 100644 docs/uk/rpc/deprecated/index.mdx create mode 100644 docs/uk/rpc/http/getAccountInfo.mdx create mode 100644 docs/uk/rpc/http/getBalance.mdx create mode 100644 docs/uk/rpc/http/getBlock.mdx create mode 100644 docs/uk/rpc/http/getBlockCommitment.mdx create mode 100644 docs/uk/rpc/http/getBlockHeight.mdx create mode 100644 docs/uk/rpc/http/getBlockProduction.mdx create mode 100644 docs/uk/rpc/http/getBlockTime.mdx create mode 100644 docs/uk/rpc/http/getBlocks.mdx create mode 100644 docs/uk/rpc/http/getBlocksWithLimit.mdx create mode 100644 docs/uk/rpc/http/getClusterNodes.mdx create mode 100644 docs/uk/rpc/http/getEpochInfo.mdx create mode 100644 docs/uk/rpc/http/getEpochSchedule.mdx create mode 100644 docs/uk/rpc/http/getFeeForMessage.mdx create mode 100644 docs/uk/rpc/http/getFirstAvailableBlock.mdx create mode 100644 docs/uk/rpc/http/getGenesisHash.mdx create mode 100644 docs/uk/rpc/http/getHealth.mdx create mode 100644 docs/uk/rpc/http/getHighestSnapshotSlot.mdx create mode 100644 docs/uk/rpc/http/getIdentity.mdx create mode 100644 docs/uk/rpc/http/getInflationGovernor.mdx create mode 100644 docs/uk/rpc/http/getInflationRate.mdx create mode 100644 docs/uk/rpc/http/getInflationReward.mdx create mode 100644 docs/uk/rpc/http/getLargestAccounts.mdx create mode 100644 docs/uk/rpc/http/getLatestBlockhash.mdx create mode 100644 docs/uk/rpc/http/getLeaderSchedule.mdx create mode 100644 docs/uk/rpc/http/getMaxRetransmitSlot.mdx create mode 100644 docs/uk/rpc/http/getMaxShredInsertSlot.mdx create mode 100644 docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx create mode 100644 docs/uk/rpc/http/getMultipleAccounts.mdx create mode 100644 docs/uk/rpc/http/getProgramAccounts.mdx create mode 100644 docs/uk/rpc/http/getRecentPerformanceSamples.mdx create mode 100644 docs/uk/rpc/http/getRecentPrioritizationFees.mdx create mode 100644 docs/uk/rpc/http/getSignatureStatuses.mdx create mode 100644 docs/uk/rpc/http/getSignaturesForAddress.mdx create mode 100644 docs/uk/rpc/http/getSlot.mdx create mode 100644 docs/uk/rpc/http/getSlotLeader.mdx create mode 100644 docs/uk/rpc/http/getSlotLeaders.mdx create mode 100644 docs/uk/rpc/http/getStakeMinimumDelegation.mdx create mode 100644 docs/uk/rpc/http/getSupply.mdx create mode 100644 docs/uk/rpc/http/getTokenAccountBalance.mdx create mode 100644 docs/uk/rpc/http/getTokenAccountsByDelegate.mdx create mode 100644 docs/uk/rpc/http/getTokenAccountsByOwner.mdx create mode 100644 docs/uk/rpc/http/getTokenLargestAccounts.mdx create mode 100644 docs/uk/rpc/http/getTokenSupply.mdx create mode 100644 docs/uk/rpc/http/getTransaction.mdx create mode 100644 docs/uk/rpc/http/getTransactionCount.mdx create mode 100644 docs/uk/rpc/http/getVersion.mdx create mode 100644 docs/uk/rpc/http/getVoteAccounts.mdx create mode 100644 docs/uk/rpc/http/index.mdx create mode 100644 docs/uk/rpc/http/isBlockhashValid.mdx create mode 100644 docs/uk/rpc/http/minimumLedgerSlot.mdx create mode 100644 docs/uk/rpc/http/requestAirdrop.mdx create mode 100644 docs/uk/rpc/http/sendTransaction.mdx create mode 100644 docs/uk/rpc/http/simulateTransaction.mdx create mode 100644 docs/uk/rpc/index.mdx create mode 100644 docs/uk/rpc/json-structures.mdx create mode 100644 docs/uk/rpc/websocket/accountSubscribe.mdx create mode 100644 docs/uk/rpc/websocket/accountUnsubscribe.mdx create mode 100644 docs/uk/rpc/websocket/blockSubscribe.mdx create mode 100644 docs/uk/rpc/websocket/blockUnsubscribe.mdx create mode 100644 docs/uk/rpc/websocket/index.mdx create mode 100644 docs/uk/rpc/websocket/logsSubscribe.mdx create mode 100644 docs/uk/rpc/websocket/logsUnsubscribe.mdx create mode 100644 docs/uk/rpc/websocket/programSubscribe.mdx create mode 100644 docs/uk/rpc/websocket/programUnsubscribe.mdx create mode 100644 docs/uk/rpc/websocket/rootSubscribe.mdx create mode 100644 docs/uk/rpc/websocket/rootUnsubscribe.mdx create mode 100644 docs/uk/rpc/websocket/signatureSubscribe.mdx create mode 100644 docs/uk/rpc/websocket/signatureUnsubscribe.mdx create mode 100644 docs/uk/rpc/websocket/slotSubscribe.mdx create mode 100644 docs/uk/rpc/websocket/slotUnsubscribe.mdx create mode 100644 docs/uk/rpc/websocket/slotsUpdatesSubscribe.mdx create mode 100644 docs/uk/rpc/websocket/slotsUpdatesUnsubscribe.mdx create mode 100644 docs/uk/rpc/websocket/voteSubscribe.mdx create mode 100644 docs/uk/rpc/websocket/voteUnsubscribe.mdx create mode 100644 docs/uk/terminology.md diff --git a/docs/advanced/actions.md b/docs/en/advanced/actions.md similarity index 100% rename from docs/advanced/actions.md rename to docs/en/advanced/actions.md diff --git a/docs/advanced/confirmation.md b/docs/en/advanced/confirmation.md similarity index 100% rename from docs/advanced/confirmation.md rename to docs/en/advanced/confirmation.md diff --git a/docs/advanced/index.md b/docs/en/advanced/index.md similarity index 100% rename from docs/advanced/index.md rename to docs/en/advanced/index.md diff --git a/docs/advanced/lookup-tables.md b/docs/en/advanced/lookup-tables.md similarity index 100% rename from docs/advanced/lookup-tables.md rename to docs/en/advanced/lookup-tables.md diff --git a/docs/advanced/retry.md b/docs/en/advanced/retry.md similarity index 100% rename from docs/advanced/retry.md rename to docs/en/advanced/retry.md diff --git a/docs/advanced/state-compression.md b/docs/en/advanced/state-compression.md similarity index 100% rename from docs/advanced/state-compression.md rename to docs/en/advanced/state-compression.md diff --git a/docs/advanced/versions.md b/docs/en/advanced/versions.md similarity index 100% rename from docs/advanced/versions.md rename to docs/en/advanced/versions.md diff --git a/docs/clients/index.md b/docs/en/clients/index.md similarity index 100% rename from docs/clients/index.md rename to docs/en/clients/index.md diff --git a/docs/clients/javascript-reference.md b/docs/en/clients/javascript-reference.md similarity index 100% rename from docs/clients/javascript-reference.md rename to docs/en/clients/javascript-reference.md diff --git a/docs/clients/javascript.md b/docs/en/clients/javascript.md similarity index 100% rename from docs/clients/javascript.md rename to docs/en/clients/javascript.md diff --git a/docs/clients/rust.md b/docs/en/clients/rust.md similarity index 100% rename from docs/clients/rust.md rename to docs/en/clients/rust.md diff --git a/docs/core/accounts.md b/docs/en/core/accounts.md similarity index 100% rename from docs/core/accounts.md rename to docs/en/core/accounts.md diff --git a/docs/core/clusters.md b/docs/en/core/clusters.md similarity index 100% rename from docs/core/clusters.md rename to docs/en/core/clusters.md diff --git a/docs/core/cpi.md b/docs/en/core/cpi.md similarity index 100% rename from docs/core/cpi.md rename to docs/en/core/cpi.md diff --git a/docs/core/fees.md b/docs/en/core/fees.md similarity index 100% rename from docs/core/fees.md rename to docs/en/core/fees.md diff --git a/docs/core/index.md b/docs/en/core/index.md similarity index 100% rename from docs/core/index.md rename to docs/en/core/index.md diff --git a/docs/core/pda.md b/docs/en/core/pda.md similarity index 100% rename from docs/core/pda.md rename to docs/en/core/pda.md diff --git a/docs/core/programs.md b/docs/en/core/programs.md similarity index 100% rename from docs/core/programs.md rename to docs/en/core/programs.md diff --git a/docs/core/tokens.md b/docs/en/core/tokens.md similarity index 100% rename from docs/core/tokens.md rename to docs/en/core/tokens.md diff --git a/docs/core/transactions.md b/docs/en/core/transactions.md similarity index 100% rename from docs/core/transactions.md rename to docs/en/core/transactions.md diff --git a/docs/economics/index.md b/docs/en/economics/index.md similarity index 100% rename from docs/economics/index.md rename to docs/en/economics/index.md diff --git a/docs/economics/inflation/_adjusted_staking_yield.md b/docs/en/economics/inflation/_adjusted_staking_yield.md similarity index 100% rename from docs/economics/inflation/_adjusted_staking_yield.md rename to docs/en/economics/inflation/_adjusted_staking_yield.md diff --git a/docs/economics/inflation/inflation-schedule.md b/docs/en/economics/inflation/inflation-schedule.md similarity index 100% rename from docs/economics/inflation/inflation-schedule.md rename to docs/en/economics/inflation/inflation-schedule.md diff --git a/docs/economics/inflation/terminology.md b/docs/en/economics/inflation/terminology.md similarity index 100% rename from docs/economics/inflation/terminology.md rename to docs/en/economics/inflation/terminology.md diff --git a/docs/economics/staking/index.md b/docs/en/economics/staking/index.md similarity index 100% rename from docs/economics/staking/index.md rename to docs/en/economics/staking/index.md diff --git a/docs/economics/staking/stake-accounts.md b/docs/en/economics/staking/stake-accounts.md similarity index 100% rename from docs/economics/staking/stake-accounts.md rename to docs/en/economics/staking/stake-accounts.md diff --git a/docs/economics/staking/stake-programming.md b/docs/en/economics/staking/stake-programming.md similarity index 100% rename from docs/economics/staking/stake-programming.md rename to docs/en/economics/staking/stake-programming.md diff --git a/docs/index.md b/docs/en/index.md similarity index 100% rename from docs/index.md rename to docs/en/index.md diff --git a/docs/intro/dev.md b/docs/en/intro/dev.md similarity index 100% rename from docs/intro/dev.md rename to docs/en/intro/dev.md diff --git a/docs/intro/index.md b/docs/en/intro/index.md similarity index 100% rename from docs/intro/index.md rename to docs/en/intro/index.md diff --git a/docs/intro/installation.md b/docs/en/intro/installation.md similarity index 100% rename from docs/intro/installation.md rename to docs/en/intro/installation.md diff --git a/docs/intro/quick-start/cross-program-invocation.md b/docs/en/intro/quick-start/cross-program-invocation.md similarity index 100% rename from docs/intro/quick-start/cross-program-invocation.md rename to docs/en/intro/quick-start/cross-program-invocation.md diff --git a/docs/intro/quick-start/deploying-programs.md b/docs/en/intro/quick-start/deploying-programs.md similarity index 100% rename from docs/intro/quick-start/deploying-programs.md rename to docs/en/intro/quick-start/deploying-programs.md diff --git a/docs/intro/quick-start/index.md b/docs/en/intro/quick-start/index.md similarity index 100% rename from docs/intro/quick-start/index.md rename to docs/en/intro/quick-start/index.md diff --git a/docs/intro/quick-start/program-derived-address.md b/docs/en/intro/quick-start/program-derived-address.md similarity index 100% rename from docs/intro/quick-start/program-derived-address.md rename to docs/en/intro/quick-start/program-derived-address.md diff --git a/docs/intro/quick-start/reading-from-network.md b/docs/en/intro/quick-start/reading-from-network.md similarity index 100% rename from docs/intro/quick-start/reading-from-network.md rename to docs/en/intro/quick-start/reading-from-network.md diff --git a/docs/intro/quick-start/writing-to-network.md b/docs/en/intro/quick-start/writing-to-network.md similarity index 100% rename from docs/intro/quick-start/writing-to-network.md rename to docs/en/intro/quick-start/writing-to-network.md diff --git a/docs/intro/wallets.md b/docs/en/intro/wallets.md similarity index 100% rename from docs/intro/wallets.md rename to docs/en/intro/wallets.md diff --git a/docs/more/exchange.md b/docs/en/more/exchange.md similarity index 100% rename from docs/more/exchange.md rename to docs/en/more/exchange.md diff --git a/docs/more/index.md b/docs/en/more/index.md similarity index 100% rename from docs/more/index.md rename to docs/en/more/index.md diff --git a/docs/programs/anchor/client-typescript.md b/docs/en/programs/anchor/client-typescript.md similarity index 100% rename from docs/programs/anchor/client-typescript.md rename to docs/en/programs/anchor/client-typescript.md diff --git a/docs/programs/anchor/cpi.md b/docs/en/programs/anchor/cpi.md similarity index 100% rename from docs/programs/anchor/cpi.md rename to docs/en/programs/anchor/cpi.md diff --git a/docs/programs/anchor/idl.md b/docs/en/programs/anchor/idl.md similarity index 100% rename from docs/programs/anchor/idl.md rename to docs/en/programs/anchor/idl.md diff --git a/docs/programs/anchor/index.md b/docs/en/programs/anchor/index.md similarity index 100% rename from docs/programs/anchor/index.md rename to docs/en/programs/anchor/index.md diff --git a/docs/programs/anchor/pda.md b/docs/en/programs/anchor/pda.md similarity index 100% rename from docs/programs/anchor/pda.md rename to docs/en/programs/anchor/pda.md diff --git a/docs/programs/anchor/program-structure.md b/docs/en/programs/anchor/program-structure.md similarity index 100% rename from docs/programs/anchor/program-structure.md rename to docs/en/programs/anchor/program-structure.md diff --git a/docs/programs/deploying.md b/docs/en/programs/deploying.md similarity index 100% rename from docs/programs/deploying.md rename to docs/en/programs/deploying.md diff --git a/docs/programs/examples.md b/docs/en/programs/examples.md similarity index 100% rename from docs/programs/examples.md rename to docs/en/programs/examples.md diff --git a/docs/programs/faq.md b/docs/en/programs/faq.md similarity index 100% rename from docs/programs/faq.md rename to docs/en/programs/faq.md diff --git a/docs/programs/index.md b/docs/en/programs/index.md similarity index 100% rename from docs/programs/index.md rename to docs/en/programs/index.md diff --git a/docs/programs/limitations.md b/docs/en/programs/limitations.md similarity index 100% rename from docs/programs/limitations.md rename to docs/en/programs/limitations.md diff --git a/docs/programs/rust/index.md b/docs/en/programs/rust/index.md similarity index 100% rename from docs/programs/rust/index.md rename to docs/en/programs/rust/index.md diff --git a/docs/programs/rust/program-structure.md b/docs/en/programs/rust/program-structure.md similarity index 100% rename from docs/programs/rust/program-structure.md rename to docs/en/programs/rust/program-structure.md diff --git a/docs/programs/testing.md b/docs/en/programs/testing.md similarity index 100% rename from docs/programs/testing.md rename to docs/en/programs/testing.md diff --git a/docs/rpc.md b/docs/en/rpc.md similarity index 100% rename from docs/rpc.md rename to docs/en/rpc.md diff --git a/docs/rpc/deprecated/confirmTransaction.mdx b/docs/en/rpc/deprecated/confirmTransaction.mdx similarity index 100% rename from docs/rpc/deprecated/confirmTransaction.mdx rename to docs/en/rpc/deprecated/confirmTransaction.mdx diff --git a/docs/rpc/deprecated/getConfirmedBlock.mdx b/docs/en/rpc/deprecated/getConfirmedBlock.mdx similarity index 100% rename from docs/rpc/deprecated/getConfirmedBlock.mdx rename to docs/en/rpc/deprecated/getConfirmedBlock.mdx diff --git a/docs/rpc/deprecated/getConfirmedBlocks.mdx b/docs/en/rpc/deprecated/getConfirmedBlocks.mdx similarity index 100% rename from docs/rpc/deprecated/getConfirmedBlocks.mdx rename to docs/en/rpc/deprecated/getConfirmedBlocks.mdx diff --git a/docs/rpc/deprecated/getConfirmedBlocksWithLimit.mdx b/docs/en/rpc/deprecated/getConfirmedBlocksWithLimit.mdx similarity index 100% rename from docs/rpc/deprecated/getConfirmedBlocksWithLimit.mdx rename to docs/en/rpc/deprecated/getConfirmedBlocksWithLimit.mdx diff --git a/docs/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx b/docs/en/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx similarity index 100% rename from docs/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx rename to docs/en/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx diff --git a/docs/rpc/deprecated/getConfirmedTransaction.mdx b/docs/en/rpc/deprecated/getConfirmedTransaction.mdx similarity index 100% rename from docs/rpc/deprecated/getConfirmedTransaction.mdx rename to docs/en/rpc/deprecated/getConfirmedTransaction.mdx diff --git a/docs/rpc/deprecated/getFeeCalculatorForBlockhash.mdx b/docs/en/rpc/deprecated/getFeeCalculatorForBlockhash.mdx similarity index 100% rename from docs/rpc/deprecated/getFeeCalculatorForBlockhash.mdx rename to docs/en/rpc/deprecated/getFeeCalculatorForBlockhash.mdx diff --git a/docs/rpc/deprecated/getFeeRateGovernor.mdx b/docs/en/rpc/deprecated/getFeeRateGovernor.mdx similarity index 100% rename from docs/rpc/deprecated/getFeeRateGovernor.mdx rename to docs/en/rpc/deprecated/getFeeRateGovernor.mdx diff --git a/docs/rpc/deprecated/getFees.mdx b/docs/en/rpc/deprecated/getFees.mdx similarity index 100% rename from docs/rpc/deprecated/getFees.mdx rename to docs/en/rpc/deprecated/getFees.mdx diff --git a/docs/rpc/deprecated/getRecentBlockhash.mdx b/docs/en/rpc/deprecated/getRecentBlockhash.mdx similarity index 100% rename from docs/rpc/deprecated/getRecentBlockhash.mdx rename to docs/en/rpc/deprecated/getRecentBlockhash.mdx diff --git a/docs/rpc/deprecated/getSignatureConfirmation.mdx b/docs/en/rpc/deprecated/getSignatureConfirmation.mdx similarity index 100% rename from docs/rpc/deprecated/getSignatureConfirmation.mdx rename to docs/en/rpc/deprecated/getSignatureConfirmation.mdx diff --git a/docs/rpc/deprecated/getSignatureStatus.mdx b/docs/en/rpc/deprecated/getSignatureStatus.mdx similarity index 100% rename from docs/rpc/deprecated/getSignatureStatus.mdx rename to docs/en/rpc/deprecated/getSignatureStatus.mdx diff --git a/docs/rpc/deprecated/getSnapshotSlot.mdx b/docs/en/rpc/deprecated/getSnapshotSlot.mdx similarity index 100% rename from docs/rpc/deprecated/getSnapshotSlot.mdx rename to docs/en/rpc/deprecated/getSnapshotSlot.mdx diff --git a/docs/rpc/deprecated/getStakeActivation.mdx b/docs/en/rpc/deprecated/getStakeActivation.mdx similarity index 100% rename from docs/rpc/deprecated/getStakeActivation.mdx rename to docs/en/rpc/deprecated/getStakeActivation.mdx diff --git a/docs/rpc/deprecated/index.mdx b/docs/en/rpc/deprecated/index.mdx similarity index 100% rename from docs/rpc/deprecated/index.mdx rename to docs/en/rpc/deprecated/index.mdx diff --git a/docs/rpc/http/getAccountInfo.mdx b/docs/en/rpc/http/getAccountInfo.mdx similarity index 100% rename from docs/rpc/http/getAccountInfo.mdx rename to docs/en/rpc/http/getAccountInfo.mdx diff --git a/docs/rpc/http/getBalance.mdx b/docs/en/rpc/http/getBalance.mdx similarity index 100% rename from docs/rpc/http/getBalance.mdx rename to docs/en/rpc/http/getBalance.mdx diff --git a/docs/rpc/http/getBlock.mdx b/docs/en/rpc/http/getBlock.mdx similarity index 100% rename from docs/rpc/http/getBlock.mdx rename to docs/en/rpc/http/getBlock.mdx diff --git a/docs/rpc/http/getBlockCommitment.mdx b/docs/en/rpc/http/getBlockCommitment.mdx similarity index 100% rename from docs/rpc/http/getBlockCommitment.mdx rename to docs/en/rpc/http/getBlockCommitment.mdx diff --git a/docs/rpc/http/getBlockHeight.mdx b/docs/en/rpc/http/getBlockHeight.mdx similarity index 100% rename from docs/rpc/http/getBlockHeight.mdx rename to docs/en/rpc/http/getBlockHeight.mdx diff --git a/docs/rpc/http/getBlockProduction.mdx b/docs/en/rpc/http/getBlockProduction.mdx similarity index 100% rename from docs/rpc/http/getBlockProduction.mdx rename to docs/en/rpc/http/getBlockProduction.mdx diff --git a/docs/rpc/http/getBlockTime.mdx b/docs/en/rpc/http/getBlockTime.mdx similarity index 100% rename from docs/rpc/http/getBlockTime.mdx rename to docs/en/rpc/http/getBlockTime.mdx diff --git a/docs/rpc/http/getBlocks.mdx b/docs/en/rpc/http/getBlocks.mdx similarity index 100% rename from docs/rpc/http/getBlocks.mdx rename to docs/en/rpc/http/getBlocks.mdx diff --git a/docs/rpc/http/getBlocksWithLimit.mdx b/docs/en/rpc/http/getBlocksWithLimit.mdx similarity index 100% rename from docs/rpc/http/getBlocksWithLimit.mdx rename to docs/en/rpc/http/getBlocksWithLimit.mdx diff --git a/docs/rpc/http/getClusterNodes.mdx b/docs/en/rpc/http/getClusterNodes.mdx similarity index 100% rename from docs/rpc/http/getClusterNodes.mdx rename to docs/en/rpc/http/getClusterNodes.mdx diff --git a/docs/rpc/http/getEpochInfo.mdx b/docs/en/rpc/http/getEpochInfo.mdx similarity index 100% rename from docs/rpc/http/getEpochInfo.mdx rename to docs/en/rpc/http/getEpochInfo.mdx diff --git a/docs/rpc/http/getEpochSchedule.mdx b/docs/en/rpc/http/getEpochSchedule.mdx similarity index 100% rename from docs/rpc/http/getEpochSchedule.mdx rename to docs/en/rpc/http/getEpochSchedule.mdx diff --git a/docs/rpc/http/getFeeForMessage.mdx b/docs/en/rpc/http/getFeeForMessage.mdx similarity index 100% rename from docs/rpc/http/getFeeForMessage.mdx rename to docs/en/rpc/http/getFeeForMessage.mdx diff --git a/docs/rpc/http/getFirstAvailableBlock.mdx b/docs/en/rpc/http/getFirstAvailableBlock.mdx similarity index 100% rename from docs/rpc/http/getFirstAvailableBlock.mdx rename to docs/en/rpc/http/getFirstAvailableBlock.mdx diff --git a/docs/rpc/http/getGenesisHash.mdx b/docs/en/rpc/http/getGenesisHash.mdx similarity index 100% rename from docs/rpc/http/getGenesisHash.mdx rename to docs/en/rpc/http/getGenesisHash.mdx diff --git a/docs/rpc/http/getHealth.mdx b/docs/en/rpc/http/getHealth.mdx similarity index 100% rename from docs/rpc/http/getHealth.mdx rename to docs/en/rpc/http/getHealth.mdx diff --git a/docs/rpc/http/getHighestSnapshotSlot.mdx b/docs/en/rpc/http/getHighestSnapshotSlot.mdx similarity index 100% rename from docs/rpc/http/getHighestSnapshotSlot.mdx rename to docs/en/rpc/http/getHighestSnapshotSlot.mdx diff --git a/docs/rpc/http/getIdentity.mdx b/docs/en/rpc/http/getIdentity.mdx similarity index 100% rename from docs/rpc/http/getIdentity.mdx rename to docs/en/rpc/http/getIdentity.mdx diff --git a/docs/rpc/http/getInflationGovernor.mdx b/docs/en/rpc/http/getInflationGovernor.mdx similarity index 100% rename from docs/rpc/http/getInflationGovernor.mdx rename to docs/en/rpc/http/getInflationGovernor.mdx diff --git a/docs/rpc/http/getInflationRate.mdx b/docs/en/rpc/http/getInflationRate.mdx similarity index 100% rename from docs/rpc/http/getInflationRate.mdx rename to docs/en/rpc/http/getInflationRate.mdx diff --git a/docs/rpc/http/getInflationReward.mdx b/docs/en/rpc/http/getInflationReward.mdx similarity index 100% rename from docs/rpc/http/getInflationReward.mdx rename to docs/en/rpc/http/getInflationReward.mdx diff --git a/docs/rpc/http/getLargestAccounts.mdx b/docs/en/rpc/http/getLargestAccounts.mdx similarity index 100% rename from docs/rpc/http/getLargestAccounts.mdx rename to docs/en/rpc/http/getLargestAccounts.mdx diff --git a/docs/rpc/http/getLatestBlockhash.mdx b/docs/en/rpc/http/getLatestBlockhash.mdx similarity index 100% rename from docs/rpc/http/getLatestBlockhash.mdx rename to docs/en/rpc/http/getLatestBlockhash.mdx diff --git a/docs/rpc/http/getLeaderSchedule.mdx b/docs/en/rpc/http/getLeaderSchedule.mdx similarity index 100% rename from docs/rpc/http/getLeaderSchedule.mdx rename to docs/en/rpc/http/getLeaderSchedule.mdx diff --git a/docs/rpc/http/getMaxRetransmitSlot.mdx b/docs/en/rpc/http/getMaxRetransmitSlot.mdx similarity index 100% rename from docs/rpc/http/getMaxRetransmitSlot.mdx rename to docs/en/rpc/http/getMaxRetransmitSlot.mdx diff --git a/docs/rpc/http/getMaxShredInsertSlot.mdx b/docs/en/rpc/http/getMaxShredInsertSlot.mdx similarity index 100% rename from docs/rpc/http/getMaxShredInsertSlot.mdx rename to docs/en/rpc/http/getMaxShredInsertSlot.mdx diff --git a/docs/rpc/http/getMinimumBalanceForRentExemption.mdx b/docs/en/rpc/http/getMinimumBalanceForRentExemption.mdx similarity index 100% rename from docs/rpc/http/getMinimumBalanceForRentExemption.mdx rename to docs/en/rpc/http/getMinimumBalanceForRentExemption.mdx diff --git a/docs/rpc/http/getMultipleAccounts.mdx b/docs/en/rpc/http/getMultipleAccounts.mdx similarity index 100% rename from docs/rpc/http/getMultipleAccounts.mdx rename to docs/en/rpc/http/getMultipleAccounts.mdx diff --git a/docs/rpc/http/getProgramAccounts.mdx b/docs/en/rpc/http/getProgramAccounts.mdx similarity index 100% rename from docs/rpc/http/getProgramAccounts.mdx rename to docs/en/rpc/http/getProgramAccounts.mdx diff --git a/docs/rpc/http/getRecentPerformanceSamples.mdx b/docs/en/rpc/http/getRecentPerformanceSamples.mdx similarity index 100% rename from docs/rpc/http/getRecentPerformanceSamples.mdx rename to docs/en/rpc/http/getRecentPerformanceSamples.mdx diff --git a/docs/rpc/http/getRecentPrioritizationFees.mdx b/docs/en/rpc/http/getRecentPrioritizationFees.mdx similarity index 100% rename from docs/rpc/http/getRecentPrioritizationFees.mdx rename to docs/en/rpc/http/getRecentPrioritizationFees.mdx diff --git a/docs/rpc/http/getSignatureStatuses.mdx b/docs/en/rpc/http/getSignatureStatuses.mdx similarity index 100% rename from docs/rpc/http/getSignatureStatuses.mdx rename to docs/en/rpc/http/getSignatureStatuses.mdx diff --git a/docs/rpc/http/getSignaturesForAddress.mdx b/docs/en/rpc/http/getSignaturesForAddress.mdx similarity index 100% rename from docs/rpc/http/getSignaturesForAddress.mdx rename to docs/en/rpc/http/getSignaturesForAddress.mdx diff --git a/docs/rpc/http/getSlot.mdx b/docs/en/rpc/http/getSlot.mdx similarity index 100% rename from docs/rpc/http/getSlot.mdx rename to docs/en/rpc/http/getSlot.mdx diff --git a/docs/rpc/http/getSlotLeader.mdx b/docs/en/rpc/http/getSlotLeader.mdx similarity index 100% rename from docs/rpc/http/getSlotLeader.mdx rename to docs/en/rpc/http/getSlotLeader.mdx diff --git a/docs/rpc/http/getSlotLeaders.mdx b/docs/en/rpc/http/getSlotLeaders.mdx similarity index 100% rename from docs/rpc/http/getSlotLeaders.mdx rename to docs/en/rpc/http/getSlotLeaders.mdx diff --git a/docs/rpc/http/getStakeMinimumDelegation.mdx b/docs/en/rpc/http/getStakeMinimumDelegation.mdx similarity index 100% rename from docs/rpc/http/getStakeMinimumDelegation.mdx rename to docs/en/rpc/http/getStakeMinimumDelegation.mdx diff --git a/docs/rpc/http/getSupply.mdx b/docs/en/rpc/http/getSupply.mdx similarity index 100% rename from docs/rpc/http/getSupply.mdx rename to docs/en/rpc/http/getSupply.mdx diff --git a/docs/rpc/http/getTokenAccountBalance.mdx b/docs/en/rpc/http/getTokenAccountBalance.mdx similarity index 100% rename from docs/rpc/http/getTokenAccountBalance.mdx rename to docs/en/rpc/http/getTokenAccountBalance.mdx diff --git a/docs/rpc/http/getTokenAccountsByDelegate.mdx b/docs/en/rpc/http/getTokenAccountsByDelegate.mdx similarity index 100% rename from docs/rpc/http/getTokenAccountsByDelegate.mdx rename to docs/en/rpc/http/getTokenAccountsByDelegate.mdx diff --git a/docs/rpc/http/getTokenAccountsByOwner.mdx b/docs/en/rpc/http/getTokenAccountsByOwner.mdx similarity index 100% rename from docs/rpc/http/getTokenAccountsByOwner.mdx rename to docs/en/rpc/http/getTokenAccountsByOwner.mdx diff --git a/docs/rpc/http/getTokenLargestAccounts.mdx b/docs/en/rpc/http/getTokenLargestAccounts.mdx similarity index 100% rename from docs/rpc/http/getTokenLargestAccounts.mdx rename to docs/en/rpc/http/getTokenLargestAccounts.mdx diff --git a/docs/rpc/http/getTokenSupply.mdx b/docs/en/rpc/http/getTokenSupply.mdx similarity index 100% rename from docs/rpc/http/getTokenSupply.mdx rename to docs/en/rpc/http/getTokenSupply.mdx diff --git a/docs/rpc/http/getTransaction.mdx b/docs/en/rpc/http/getTransaction.mdx similarity index 100% rename from docs/rpc/http/getTransaction.mdx rename to docs/en/rpc/http/getTransaction.mdx diff --git a/docs/rpc/http/getTransactionCount.mdx b/docs/en/rpc/http/getTransactionCount.mdx similarity index 100% rename from docs/rpc/http/getTransactionCount.mdx rename to docs/en/rpc/http/getTransactionCount.mdx diff --git a/docs/rpc/http/getVersion.mdx b/docs/en/rpc/http/getVersion.mdx similarity index 100% rename from docs/rpc/http/getVersion.mdx rename to docs/en/rpc/http/getVersion.mdx diff --git a/docs/rpc/http/getVoteAccounts.mdx b/docs/en/rpc/http/getVoteAccounts.mdx similarity index 100% rename from docs/rpc/http/getVoteAccounts.mdx rename to docs/en/rpc/http/getVoteAccounts.mdx diff --git a/docs/rpc/http/index.mdx b/docs/en/rpc/http/index.mdx similarity index 100% rename from docs/rpc/http/index.mdx rename to docs/en/rpc/http/index.mdx diff --git a/docs/rpc/http/isBlockhashValid.mdx b/docs/en/rpc/http/isBlockhashValid.mdx similarity index 100% rename from docs/rpc/http/isBlockhashValid.mdx rename to docs/en/rpc/http/isBlockhashValid.mdx diff --git a/docs/rpc/http/minimumLedgerSlot.mdx b/docs/en/rpc/http/minimumLedgerSlot.mdx similarity index 100% rename from docs/rpc/http/minimumLedgerSlot.mdx rename to docs/en/rpc/http/minimumLedgerSlot.mdx diff --git a/docs/rpc/http/requestAirdrop.mdx b/docs/en/rpc/http/requestAirdrop.mdx similarity index 100% rename from docs/rpc/http/requestAirdrop.mdx rename to docs/en/rpc/http/requestAirdrop.mdx diff --git a/docs/rpc/http/sendTransaction.mdx b/docs/en/rpc/http/sendTransaction.mdx similarity index 100% rename from docs/rpc/http/sendTransaction.mdx rename to docs/en/rpc/http/sendTransaction.mdx diff --git a/docs/rpc/http/simulateTransaction.mdx b/docs/en/rpc/http/simulateTransaction.mdx similarity index 100% rename from docs/rpc/http/simulateTransaction.mdx rename to docs/en/rpc/http/simulateTransaction.mdx diff --git a/docs/rpc/index.mdx b/docs/en/rpc/index.mdx similarity index 100% rename from docs/rpc/index.mdx rename to docs/en/rpc/index.mdx diff --git a/docs/rpc/json-structures.mdx b/docs/en/rpc/json-structures.mdx similarity index 100% rename from docs/rpc/json-structures.mdx rename to docs/en/rpc/json-structures.mdx diff --git a/docs/rpc/websocket/accountSubscribe.mdx b/docs/en/rpc/websocket/accountSubscribe.mdx similarity index 100% rename from docs/rpc/websocket/accountSubscribe.mdx rename to docs/en/rpc/websocket/accountSubscribe.mdx diff --git a/docs/rpc/websocket/accountUnsubscribe.mdx b/docs/en/rpc/websocket/accountUnsubscribe.mdx similarity index 100% rename from docs/rpc/websocket/accountUnsubscribe.mdx rename to docs/en/rpc/websocket/accountUnsubscribe.mdx diff --git a/docs/rpc/websocket/blockSubscribe.mdx b/docs/en/rpc/websocket/blockSubscribe.mdx similarity index 100% rename from docs/rpc/websocket/blockSubscribe.mdx rename to docs/en/rpc/websocket/blockSubscribe.mdx diff --git a/docs/rpc/websocket/blockUnsubscribe.mdx b/docs/en/rpc/websocket/blockUnsubscribe.mdx similarity index 100% rename from docs/rpc/websocket/blockUnsubscribe.mdx rename to docs/en/rpc/websocket/blockUnsubscribe.mdx diff --git a/docs/rpc/websocket/index.mdx b/docs/en/rpc/websocket/index.mdx similarity index 100% rename from docs/rpc/websocket/index.mdx rename to docs/en/rpc/websocket/index.mdx diff --git a/docs/rpc/websocket/logsSubscribe.mdx b/docs/en/rpc/websocket/logsSubscribe.mdx similarity index 100% rename from docs/rpc/websocket/logsSubscribe.mdx rename to docs/en/rpc/websocket/logsSubscribe.mdx diff --git a/docs/rpc/websocket/logsUnsubscribe.mdx b/docs/en/rpc/websocket/logsUnsubscribe.mdx similarity index 100% rename from docs/rpc/websocket/logsUnsubscribe.mdx rename to docs/en/rpc/websocket/logsUnsubscribe.mdx diff --git a/docs/rpc/websocket/programSubscribe.mdx b/docs/en/rpc/websocket/programSubscribe.mdx similarity index 100% rename from docs/rpc/websocket/programSubscribe.mdx rename to docs/en/rpc/websocket/programSubscribe.mdx diff --git a/docs/rpc/websocket/programUnsubscribe.mdx b/docs/en/rpc/websocket/programUnsubscribe.mdx similarity index 100% rename from docs/rpc/websocket/programUnsubscribe.mdx rename to docs/en/rpc/websocket/programUnsubscribe.mdx diff --git a/docs/rpc/websocket/rootSubscribe.mdx b/docs/en/rpc/websocket/rootSubscribe.mdx similarity index 100% rename from docs/rpc/websocket/rootSubscribe.mdx rename to docs/en/rpc/websocket/rootSubscribe.mdx diff --git a/docs/rpc/websocket/rootUnsubscribe.mdx b/docs/en/rpc/websocket/rootUnsubscribe.mdx similarity index 100% rename from docs/rpc/websocket/rootUnsubscribe.mdx rename to docs/en/rpc/websocket/rootUnsubscribe.mdx diff --git a/docs/rpc/websocket/signatureSubscribe.mdx b/docs/en/rpc/websocket/signatureSubscribe.mdx similarity index 100% rename from docs/rpc/websocket/signatureSubscribe.mdx rename to docs/en/rpc/websocket/signatureSubscribe.mdx diff --git a/docs/rpc/websocket/signatureUnsubscribe.mdx b/docs/en/rpc/websocket/signatureUnsubscribe.mdx similarity index 100% rename from docs/rpc/websocket/signatureUnsubscribe.mdx rename to docs/en/rpc/websocket/signatureUnsubscribe.mdx diff --git a/docs/rpc/websocket/slotSubscribe.mdx b/docs/en/rpc/websocket/slotSubscribe.mdx similarity index 100% rename from docs/rpc/websocket/slotSubscribe.mdx rename to docs/en/rpc/websocket/slotSubscribe.mdx diff --git a/docs/rpc/websocket/slotUnsubscribe.mdx b/docs/en/rpc/websocket/slotUnsubscribe.mdx similarity index 100% rename from docs/rpc/websocket/slotUnsubscribe.mdx rename to docs/en/rpc/websocket/slotUnsubscribe.mdx diff --git a/docs/rpc/websocket/slotsUpdatesSubscribe.mdx b/docs/en/rpc/websocket/slotsUpdatesSubscribe.mdx similarity index 100% rename from docs/rpc/websocket/slotsUpdatesSubscribe.mdx rename to docs/en/rpc/websocket/slotsUpdatesSubscribe.mdx diff --git a/docs/rpc/websocket/slotsUpdatesUnsubscribe.mdx b/docs/en/rpc/websocket/slotsUpdatesUnsubscribe.mdx similarity index 100% rename from docs/rpc/websocket/slotsUpdatesUnsubscribe.mdx rename to docs/en/rpc/websocket/slotsUpdatesUnsubscribe.mdx diff --git a/docs/rpc/websocket/voteSubscribe.mdx b/docs/en/rpc/websocket/voteSubscribe.mdx similarity index 100% rename from docs/rpc/websocket/voteSubscribe.mdx rename to docs/en/rpc/websocket/voteSubscribe.mdx diff --git a/docs/rpc/websocket/voteUnsubscribe.mdx b/docs/en/rpc/websocket/voteUnsubscribe.mdx similarity index 100% rename from docs/rpc/websocket/voteUnsubscribe.mdx rename to docs/en/rpc/websocket/voteUnsubscribe.mdx diff --git a/docs/terminology.md b/docs/en/terminology.md similarity index 100% rename from docs/terminology.md rename to docs/en/terminology.md diff --git a/docs/uk/advanced/actions.md b/docs/uk/advanced/actions.md new file mode 100644 index 000000000..0debc4c69 --- /dev/null +++ b/docs/uk/advanced/actions.md @@ -0,0 +1,1038 @@ +--- +sidebarLabel: "Дії та Блінки" +title: "Дії та Блінки" +seoTitle: "Дії та Блінки" +description: + "Дії Solana — це API, які повертають транзакції для попереднього перегляду і + підпису користувачами. Посилання на блокчейн — або блінки — перетворюють дії + в зручні, багаті на метадані посилання для спільного використання." +altRoutes: + - /docs/actions + - /docs/blinks + - /docs/advanced/blinks +--- + +[Дії Solana](#actions) — це API, які відповідають специфікації і повертають +транзакції в блокчейні Solana для попереднього перегляду, підпису та відправки. +Вони можуть використовуватися в різних контекстах, таких як QR-коди, кнопки, +віджети та вебсайти. Дії дозволяють розробникам легко інтегрувати функціонал +екосистеми Solana у свій додаток, дозволяючи виконувати блокчейн-транзакції +без необхідності переходу на інші сторінки або додатки. + +[Посилання на блокчейн](#blinks) — або блінки — перетворюють будь-яку дію Solana +в зручне посилання, багате метаданими. Блінки дозволяють клієнтам, які +підтримують їх, (таким як гаманці або боти) відображати додаткові функціональні +можливості. Наприклад, на вебсайті блінк може негайно відкрити попередній +перегляд транзакції у гаманці, а в Discord бот може перетворити блінк на +інтерактивні кнопки. Це забезпечує взаємодію з блокчейном на будь-якій платформі, +що підтримує URL. + +## Початок роботи + +Щоб швидко почати створювати власні дії Solana: + +```shell +npm install @solana/actions +``` + +- встановіть [Solana Actions SDK](https://www.npmjs.com/package/@solana/actions) у вашому додатку +- створіть API-ендпойнт для [GET-запиту](#get-request), який повертає метадані + про вашу дію +- створіть API-ендпойнт для [POST-запиту](#post-request), який повертає + транзакцію для підпису користувачем + +> Перегляньте цей відеоурок про +> [створення дії Solana](https://www.youtube.com/watch?v=kCht01Ycif0) за допомогою +> `@solana/actions` SDK. +> +> Ви також можете знайти +> [вихідний код дії](https://github.com/solana-developers/solana-actions/blob/main/examples/next-js/src/app/api/actions/transfer-sol/route.ts), +> яка виконує нативний переказ SOL, а також інші приклади дій у +> [цьому репозиторії](https://github.com/solana-developers/solana-actions/tree/main/examples). + +Під час розгортання власних дій Solana у продакшн: + +- переконайтеся, що ваш додаток має дійсний файл [actions.json](#actionsjson) у + корені вашого домену +- переконайтеся, що ваш додаток відповідає + [необхідним заголовкам CORS](#options-response) для всіх ендпойнтів дій, + включаючи файл `actions.json` +- тестуйте та налагоджуйте свої блінки/дії за допомогою + [Blinks Inspector](https://www.blinks.xyz/inspector) + +Якщо ви шукаєте натхнення для створення дій та блінків, перегляньте +[Awesome Blinks](https://github.com/solana-developers/awesome-blinks) — +репозиторій із прикладами створених спільнотою блінків та +[ідеями для нових](https://github.com/solana-developers/awesome-blinks/discussions/categories/ideas-for-blinks). + +## Дії + +Специфікація дій Solana використовує набір стандартних API для передачі +транзакцій (та, зрештою, повідомлень) для підпису безпосередньо користувачам. +Ці API доступні за публічними URL, які можуть взаємодіяти з будь-якими клієнтами. + +> Дії можна уявити як API-ендпойнт, який повертає метадані та об'єкт для +> підпису користувачем (транзакцію або повідомлення для аутентифікації) за +> допомогою їх блокчейн-гаманця. + +API дій складається з простих `GET` і `POST` запитів до URL-ендпойнтів дій та +обробки відповідей, які відповідають інтерфейсу дій. + +1. [GET-запит](#get-request) повертає метадані, які надають клієнту + інформацію про доступні дії за цим URL, а також список пов’язаних дій (за + бажанням). +2. [POST-запит](#post-request) повертає транзакцію або повідомлення для + підпису, які клієнт відображає в гаманці користувача для підпису та виконання + у блокчейні або іншому офчейн-сервісі. + +### Виконання дії та життєвий цикл + +На практиці взаємодія з діями нагадує роботу зі стандартним REST API: + +- клієнт надсилає початковий `GET`-запит до URL дії для отримання метаданих про + доступні дії +- ендпойнт повертає відповідь, яка включає метадані (наприклад, заголовок + програми та іконку) і перелік доступних дій +- клієнтський додаток (наприклад, мобільний гаманець, чат-бот або вебсайт) + відображає інтерфейс для виконання однієї з дій +- після вибору дії користувачем (натискання кнопки) клієнт надсилає `POST`-запит + до ендпойнта, щоб отримати транзакцію для підпису +- гаманець допомагає користувачеві підписати транзакцію і зрештою надсилає її в + блокчейн для підтвердження + +![Життєвий цикл виконання дій Solana](/public/assets/docs/action-execution-and-lifecycle.png) + +Під час отримання транзакцій із URL дій клієнти повинні обробляти надсилання цих +транзакцій у блокчейн і управляти їхнім станом. + +Дії також підтримують певний рівень недійсності перед виконанням. `GET`- та +`POST`-запити можуть повертати метадані, які вказують, чи можливо виконати дію +(наприклад, через поле `disabled`). + +Наприклад, якщо ендпойнт дії підтримує голосування за пропозицію DAO, термін +голосування за якою закінчився, початковий [GET-запит](#get-request) може +повернути повідомлення про помилку "Цю пропозицію більше не можна обговорювати", +а кнопки "Проголосувати за" та "Проголосувати проти" — як "вимкнені". + +## Блінки + +Блінки (посилання на блокчейн) — це клієнтські програми, які аналізують API +дій і створюють інтерфейси користувача для взаємодії з діями та їх виконання. + +Клієнтські програми, що підтримують блінки, виявляють URL, сумісні з діями, +аналізують їх і дозволяють користувачам взаємодіяти з ними у стандартизованих +інтерфейсах. + +> Будь-яка клієнтська програма, яка повністю аналізує API дій для створення +> повноцінного інтерфейсу, є _блінком_. Отже, не всі клієнти, які +> використовують API дій, є блінками. + +### Специфікація URL блінків + +URL блінка описує клієнтську програму, яка дозволяє користувачеві завершити +повний [життєвий цикл виконання дії](#action-execution-and-lifecycle), включаючи +підписання у гаманці. + +```text +https://example.domain/?action= +``` + +Для того, щоб будь-яка клієнтська програма могла стати блінком: + +- URL блінка повинен містити параметр запиту `action`, значення якого має бути + [URL-кодованим](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) + [URL дії](#url-scheme). Це значення має бути закодоване, щоб уникнути конфліктів з іншими параметрами протоколу. + +- Клієнтська програма повинна + [декодувати URL](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent) + параметр запиту `action` і аналізувати наданий посилання API дій (див. + [Схему URL дії](#url-scheme)). + +- Клієнт повинен відобразити багатий інтерфейс користувача, який дозволяє + завершити повний [життєвий цикл виконання дії](#action-execution-and-lifecycle), + включаючи підписання у гаманці. + +> Не всі клієнтські програми-блінки (наприклад, вебсайти або децентралізовані +> додатки) підтримуватимуть усі дії. Розробники додатків можуть обирати, які дії +> вони хочуть підтримувати у своїх інтерфейсах блінків. + +Наступний приклад демонструє дійсний URL блінка зі значенням параметра `action` +`solana-action:https://actions.alice.com/donate`, яке закодовано у форматі URL: + +```text +https://example.domain/?action=solana-action%3Ahttps%3A%2F%2Factions.alice.com%2Fdonate +``` + +### Виявлення дій через блінки + +Блінки можуть бути пов’язані з діями щонайменше трьома способами: + +1. Поширення явного URL дії: + `solana-action:https://actions.alice.com/donate` + + У цьому випадку лише клієнти, які підтримують блінки, можуть відобразити + блінк. Не буде доступного попереднього перегляду посилання або сайту, який + можна відвідати поза клієнтами, що не підтримують блінки. + +2. Поширення посилання на вебсайт, пов’язаний із API дій через файл + [`actions.json`](#actionsjson) у кореневій директорії домену вебсайту. + + Наприклад, `https://alice.com/actions.json` зіставляє + `https://alice.com/donate`, URL вебсайту, на якому користувачі можуть + зробити пожертву для Alice, з API URL `https://actions.alice.com/donate`, на + якому хостяться дії для пожертвування Alice. + +3. Вбудовування URL дії у "перехідний" URL сайту, який розуміє, як аналізувати + дії. + + ```text + https://example.domain/?action= + ``` + +Клієнти, які підтримують блінки, повинні мати можливість працювати з будь-яким +із зазначених форматів і правильно відображати інтерфейс для виконання дії +безпосередньо в клієнті. + +Для клієнтів, які не підтримують блінки, повинен бути доступний основний +вебсайт, що робить браузер універсальним варіантом резервного доступу. + +Якщо користувач натискає на будь-яку область клієнта, яка не є кнопкою дії або +полем для введення тексту, він повинен бути перенаправлений на основний сайт. + +### Тестування та перевірка блінків + +Хоча Solana Actions і блінки є протоколом/специфікацією без дозволів, клієнтські +додатки та гаманці повинні забезпечити можливість користувачам підписувати +транзакцію. + +> Використовуйте інструмент [Blinks Inspector](https://www.blinks.xyz/inspector) +> для перевірки, налагодження та тестування ваших блінків і дій безпосередньо в +> браузері. Ви можете переглядати GET і POST відповіді, заголовки та тестувати +> всі введення для кожної з ваших пов'язаних дій. + +Кожен клієнтський додаток або гаманець може мати різні вимоги щодо того, які +ендпойнти дій будуть автоматично розгортатися й негайно відображатися користувачам +на платформах соціальних мереж. + +Наприклад, деякі клієнти можуть працювати за підходом "список дозволених" і +вимагати верифікації перед розгортанням дії для користувачів, як це робить +реєстр дій Dialect (докладно описано нижче). + +Усі блінки все одно будуть відображатися й дозволять підписання на сайті Dialect +[dial.to](https://dial.to), де їхній статус у реєстрі буде показаний у блінку. + +### Реєстр дій Dialect + +Як загальне благо для екосистеми Solana, [Dialect](https://dialect.to) +підтримує публічний реєстр — разом із допомогою Solana Foundation та інших +членів спільноти — для посилань на блокчейн, які попередньо перевірені й +походять із відомих джерел. На момент запуску лише дії, зареєстровані в реєстрі +Dialect, будуть автоматично розгортатися у Twitter, коли їх публікують. + +Клієнтські програми та гаманці можуть вільно використовувати цей публічний +реєстр або інші рішення, щоб забезпечити безпеку користувачів. Якщо посилання +на блокчейн не верифіковане через реєстр Dialect, воно не оброблятиметься +клієнтом блінків і буде відображатися як звичайне URL. + +Розробники можуть подати заявку на верифікацію у Dialect тут: +[dial.to/register](https://dial.to/register) + +## Специфікація + +Специфікація Solana Actions складається з ключових розділів, які є частиною +процесу взаємодії запит/відповідь: + +- Схема URL [Solana Action](#url-scheme), яка надає URL дії +- [OPTIONS-відповідь](#options-response) на URL дії для відповідності вимогам CORS +- [GET-запит](#get-request) до URL дії +- [GET-відповідь](#get-response) із сервера +- [POST-запит](#post-request) до URL дії +- [POST-відповідь](#post-response) із сервера + +Кожен із цих запитів надсилається _клієнтом дій_ (наприклад, гаманець, розширення +для браузера, децентралізований додаток, вебсайт тощо) для збору специфічних +метаданих для багатого інтерфейсу користувача та забезпечення вводу користувачем +до API дій. + +Кожна з відповідей створюється додатком (наприклад, вебсайтом, серверним +додатком тощо) і повертається _клієнту дій_. Зрештою, це забезпечує транзакцію +або повідомлення для підпису гаманцем, щоб користувач міг підтвердити, підписати +та надіслати їх до блокчейну. + +> Типи та інтерфейси, описані в цьому файлі readme, часто спрощені для +> полегшення читання. +> +> Для кращої безпеки типів і покращеного досвіду розробників пакет +> `@solana/actions-spec` містить більш складні визначення типів. Ви можете знайти +> [вихідний код тут](https://github.com/solana-developers/solana-actions/blob/main/packages/actions-spec/index.d.ts). + +### Схема URL + +URL дії Solana описує інтерактивний запит на підписання транзакції або +повідомлення в Solana за допомогою протоколу `solana-action`. + +Запит є інтерактивним, оскільки параметри в URL використовуються клієнтом для +надсилання серії стандартизованих HTTP-запитів для складання транзакції або +повідомлення для підписання користувачем у його гаманці. + +```text +solana-action: +``` + +- Єдине поле `link` обов’язкове як шлях. Значення повинно бути + [URL-кодованим](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) + абсолютним HTTPS URL. + +- Якщо URL містить параметри запиту, він повинен бути закодований у форматі URL. + Це допомагає уникнути конфліктів із будь-якими параметрами протоколу дій, які + можуть бути додані через специфікацію протоколу. + +- Якщо URL не містить параметрів запиту, він не повинен бути закодованим у + форматі URL. Це забезпечує коротший URL і менш щільний QR-код. + +У будь-якому випадку клієнти повинні +[декодувати URL](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent) +значення. Це не матиме жодного ефекту, якщо значення вже не було закодовано. +Якщо декодоване значення не є абсолютним HTTPS URL, гаманець повинен відхилити +його як **пошкоджене**. + +### OPTIONS-відповідь + +Для забезпечення крос-доменного доступу (CORS) у клієнтах дій (включаючи +блінки), усі ендпойнти дій повинні відповідати на HTTP-запити методу `OPTIONS` +з дійсними заголовками, які дозволять клієнтам проходити CORS-перевірки для всіх +подальших запитів із їхнього домену. + +Клієнт дій може виконувати +"[префлайт-запити](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests)" +до ендпойнта URL дії, щоб перевірити, чи пройде наступний GET-запит до цього URL +всі CORS-перевірки. Ці перевірки виконуються за допомогою HTTP-методу `OPTIONS` +і повинні відповідати з усіма необхідними HTTP-заголовками, які дозволяють +клієнтам дій (наприклад, блінкам) правильно виконувати всі подальші запити. + +Мінімальний набір обов’язкових HTTP-заголовків: + +- `Access-Control-Allow-Origin` зі значенням `*` + - забезпечує можливість усім клієнтам дій безпечно проходити CORS-перевірки + для виконання всіх необхідних запитів. +- `Access-Control-Allow-Methods` зі значенням `GET,POST,PUT,OPTIONS` + - забезпечує підтримку всіх необхідних HTTP-методів запитів для дій. +- `Access-Control-Allow-Headers` з мінімальним значенням + `Content-Type, Authorization, Content-Encoding, Accept-Encoding`. + +Для спрощення розробникам слід розглянути можливість повернення однакової +відповіді та заголовків на запити `OPTIONS`, що і для їхнього +[GET-відповіді](#get-response). + + + +Відповідь файлу `actions.json` також повинна повертати дійсні заголовки +крос-доменного доступу для запитів `GET` і `OPTIONS`, зокрема заголовок +`Access-Control-Allow-Origin` зі значенням `*`. + +Докладніше дивіться у розділі [actions.json](#actionsjson). + + + +### GET-запит + +Клієнт дій (наприклад, гаманець, розширення браузера тощо) повинен надсилати +HTTP `GET` JSON-запит до URL-ендпойнта дії. + +- Запит не повинен ідентифікувати гаманець або користувача. +- Клієнт повинен виконувати запит із заголовком + [`Accept-Encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding). +- Клієнт повинен відображати домен URL під час виконання запиту. + +### GET-відповідь + +URL-ендпойнт дії (наприклад, додаток або серверний бекенд) повинен відповідати +HTTP `OK` JSON-відповіддю (з дійсним вмістом у тілі) або відповідною помилкою HTTP. + +- Клієнт повинен обробляти HTTP + [помилки клієнта](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses), + [помилки сервера](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses) + та + [редиректи](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). +- Ендпойнт повинен відповідати із заголовком + [`Content-Encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding) + для HTTP-компресії. +- Ендпойнт повинен відповідати із заголовком + [`Content-Type`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) + зі значенням `application/json`. + +- Клієнт не повинен кешувати відповідь, окрім випадків, коли це вказано у + [HTTP-заголовках кешування](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching#controlling_caching). +- Клієнт повинен відображати `title` і рендерити іконку `icon` для користувача. + +Помилкові відповіді (тобто статуси HTTP 4xx та 5xx) повинні повертати JSON-тіло +відповіді, яке відповідає `ActionError`, щоб представити користувачам корисне +повідомлення про помилку. Дивіться [Помилки дій](#action-errors). + +#### Тіло GET-відповіді + +`GET`-відповідь зі статусом HTTP `OK` повинна включати тіло з вмістом, що +відповідає специфікації інтерфейсу: + +```ts filename="ActionGetResponse" +export type ActionType = "action" | "completed"; + +export type ActionGetResponse = Action<"action">; + +export interface Action { + /** type of Action to present to the user */ + type: T; + /** image url that represents the source of the action request */ + icon: string; + /** describes the source of the action request */ + title: string; + /** brief summary of the action to be performed */ + description: string; + /** button text rendered to the user */ + label: string; + /** UI state for the button being rendered to the user */ + disabled?: boolean; + links?: { + /** list of related Actions a user could perform */ + actions: LinkedAction[]; + }; + /** non-fatal error message to be displayed to the user */ + error?: ActionError; +} +``` + +- `type` - Тип дії, що надається користувачеві. За замовчуванням встановлено значення `action`. Початковий `ActionGetResponse` повинен мати тип `action`. + + - `action` - Стандартна дія, яка дозволяє користувачеві взаємодіяти з будь-якими `LinkedActions`. + - `completed` - Використовується для позначення стану "завершено" у ланцюжку дій. + +- `icon` - Значення має бути абсолютним HTTP або HTTPS URL іконки. Файл повинен бути формату SVG, PNG або WebP, інакше клієнт/гаманець повинен відхилити його як **пошкоджений**. + +- `title` - Значення має бути рядком UTF-8, що представляє джерело запиту дії. Наприклад, це може бути назва бренду, магазину, програми або особи, яка робить запит. + +- `description` - Значення має бути рядком UTF-8, що надає інформацію про дію. Опис повинен бути відображений користувачеві. + +- `label` - Значення має бути рядком UTF-8, який буде відображено на кнопці для натискання користувачем. Усі мітки не повинні перевищувати 5 слів і повинні починатися з дієслова, щоб закріпити дію, яку ви хочете, щоб користувач виконав. Наприклад, "Mint NFT", "Vote Yes" або "Stake 1 SOL". + +- `disabled` - Значення має бути логічним (boolean), щоб представляти стан вимкнення кнопки (яка відображає рядок `label`). Якщо значення не надано, `disabled` має за замовчуванням бути `false` (тобто увімкнено). Наприклад, якщо кінцева точка дії використовується для голосування, яке вже закрите, встановіть `disabled=true`, а мітка може бути "Vote Closed". + +- `error` - Необов'язковий індикатор помилки для нефатальних помилок. Якщо присутній, клієнт повинен відобразити це користувачеві. Якщо встановлено, це не повинно заважати клієнту інтерпретувати дію або відображати її користувачеві (див. [Помилки дій](#action-errors)). Наприклад, помилка може використовуватися разом із `disabled`, щоб показати причину, як-от бізнес-обмеження, авторизація, стан або помилка зовнішнього ресурсу. + +- `links.actions` - Необов'язковий масив пов'язаних дій для кінцевої точки. Користувачам повинен бути відображений інтерфейс для кожної зі вказаних дій, і очікується, що вони виконають лише одну. Наприклад, кінцева точка дії для голосування в управлінні DAO може повернути три варіанти для користувача: "Vote Yes", "Vote No" і "Abstain from Vote". + + - Якщо `links.actions` не надано, клієнт повинен відобразити одну кнопку, використовуючи кореневий рядок `label`, і виконати POST-запит до тієї самої кінцевої точки URL дії, що й початковий GET-запит. + + - Якщо будь-які `links.actions` надані, клієнт повинен відображати лише кнопки та поля введення на основі елементів, перелічених у полі `links.actions`. Клієнт не повинен відображати кнопку для вмісту кореневого `label`. + +```ts filename="LinkedAction" +export interface LinkedAction { + /** URL endpoint for an action */ + href: string; + /** button text rendered to the user */ + label: string; + /** + * Parameters to accept user input within an action + * @see {ActionParameter} + * @see {ActionParameterSelectable} + */ + parameters?: Array; +} +``` + +`ActionParameter` дозволяє визначити, яке саме введення API дій запитує у користувача: + +```ts filename="ActionParameter" +/** + * Parameter to accept user input within an action + * note: for ease of reading, this is a simplified type of the actual + */ +export interface ActionParameter { + /** input field type */ + type?: ActionParameterType; + /** parameter name in url */ + name: string; + /** placeholder text for the user input field */ + label?: string; + /** declare if this field is required (defaults to `false`) */ + required?: boolean; + /** regular expression pattern to validate user input client side */ + pattern?: string; + /** human-readable description of the `type` and/or `pattern`, represents a caption and error, if value doesn't match */ + patternDescription?: string; + /** the minimum value allowed based on the `type` */ + min?: string | number; + /** the maximum value allowed based on the `type` */ + max?: string | number; +} +``` + +`pattern` повинен бути рядком, еквівалентним дійсному регулярному виразу. Цей регулярний вираз має використовуватися клієнтами-блінками для перевірки введення користувача перед виконанням POST-запиту. Якщо `pattern` не є дійсним регулярним виразом, клієнт повинен його ігнорувати. + +`patternDescription` — це опис, зрозумілий для людини, який пояснює очікуване введення користувача. Якщо надано `pattern`, то `patternDescription` також обов’язково має бути надано. + +Значення `min` та `max` дозволяють встановити нижню та/або верхню межу введення, запитуваного у користувача (наприклад, мінімальне/максимальне число або мінімальну/максимальну довжину рядка). Вони повинні використовуватися для клієнтської валідації. Для типів введення `date` або `datetime-local` ці значення мають бути рядками, що представляють дати. Для інших типів введення на основі рядків значення повинні бути числами, що представляють їх мінімальну/максимальну довжину символів. + +Якщо введене значення користувача не відповідає `pattern`, користувач має отримати повідомлення про помилку на стороні клієнта, що вказує на недійсність поля введення, і відображати рядок `patternDescription`. + +Поле `type` дозволяє API дій визначати більш конкретні поля введення користувача, забезпечуючи кращу валідацію на стороні клієнта та покращуючи користувацький досвід. У багатьох випадках цей тип буде подібний до стандартного +[елемента введення HTML](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). + +Тип `ActionParameterType` можна спростити до такого формату: + +```ts filename="ActionParameterType" +/** + * Input field type to present to the user + * @default `text` + */ +export type ActionParameterType = + | "text" + | "email" + | "url" + | "number" + | "date" + | "datetime-local" + | "checkbox" + | "radio" + | "textarea" + | "select"; +``` + +Кожне зі значень `type` зазвичай має відповідати полю введення користувача, яке нагадує стандартний HTML-елемент `input` відповідного типу (наприклад, ``), щоб забезпечити кращу валідацію на стороні клієнта та покращити користувацький досвід: + +- `text` - еквівалент HTML + [елемента введення типу "text"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/text) +- `email` - еквівалент HTML + [елемента введення типу "email"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email) +- `url` - еквівалент HTML + [елемента введення типу "url"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/url) +- `number` - еквівалент HTML + [елемента введення типу "number"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number) +- `date` - еквівалент HTML + [елемента введення типу "date"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date) +- `datetime-local` - еквівалент HTML + [елемента введення типу "datetime-local"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local) +- `checkbox` - еквівалент групи стандартних HTML + [елементів введення типу "checkbox"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox). + API дій має повертати `options`, як описано нижче. Користувач повинен мати змогу вибрати кілька запропонованих варіантів. +- `radio` - еквівалент групи стандартних HTML + [елементів введення типу "radio"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio). + API дій має повертати `options`, як описано нижче. Користувач повинен мати змогу вибрати лише один із запропонованих варіантів. +- Інші еквіваленти HTML-типів введення, не зазначені вище (`hidden`, `button`, `submit`, `file` тощо), наразі не підтримуються. + +Окрім елементів, схожих на HTML-типи введення, також підтримуються наступні елементи введення користувача: + +- `textarea` - еквівалент HTML + [елемента "textarea"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea), + що дозволяє користувачеві вводити багаторядковий текст. +- `select` - еквівалент HTML + [елемента "select"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select), + що надає користувачеві досвід вибору з випадаючого списку. API дій має повертати `options`, як описано нижче. + +Коли `type` встановлено як `select`, `checkbox` або `radio`, API дій має включати масив `options`, кожен із яких надає `label` та `value` принаймні. Кожна опція також може мати значення `selected`, яке інформує клієнт-блінк, яка опція має бути обрана за замовчуванням для користувача (див. відмінності для `checkbox` і `radio`). + +Цей `ActionParameterSelectable` можна спростити до такого визначення типу: + +```ts filename="ActionParameterSelectable" +/** + * note: for ease of reading, this is a simplified type of the actual + */ +interface ActionParameterSelectable extends ActionParameter { + options: Array<{ + /** displayed UI label of this selectable option */ + label: string; + /** value of this selectable option */ + value: string; + /** whether or not this option should be selected by default */ + selected?: boolean; + }>; +} +``` + +Якщо `type` не встановлено або задано невідоме/непідтримуване значення, клієнти-блінки мають за замовчуванням використовувати `text` і відображати просте текстове поле введення. + +API дій все одно відповідає за валідацію та санітизацію всіх даних, отриманих від параметрів введення користувача, забезпечуючи виконання всіх обов’язкових ("required") полів введення за необхідності. + +Для платформ, які не базуються на HTML/веб (наприклад, для нативних мобільних додатків), слід використовувати еквівалентні нативні компоненти введення, щоб забезпечити аналогічний досвід та валідацію на стороні клієнта, як описано для HTML/веб. + +#### Приклад відповіді на GET-запит + +Наступний приклад відповіді забезпечує єдину "кореневу" дію, яка очікує, що користувачеві буде представлена одна кнопка з міткою "Отримати токен доступу": + +```json +{ + "title": "HackerHouse Events", + "icon": "", + "description": "Claim your Hackerhouse access token.", + "label": "Claim Access Token" // button text +} +``` + +Наступний приклад відповіді забезпечує 3 пов’язані посилання на дії, що дозволяють користувачеві натиснути одну з трьох кнопок для голосування за пропозицію DAO: + +```json +{ + "title": "Realms DAO Platform", + "icon": "", + "description": "Vote on DAO governance proposals #1234.", + "label": "Vote", + "links": { + "actions": [ + { + "label": "Vote Yes", // button text + "href": "/api/proposal/1234/vote?choice=yes" + }, + { + "label": "Vote No", // button text + "href": "/api/proposal/1234/vote?choice=no" + }, + { + "label": "Abstain from Vote", // button text + "href": "/api/proposal/1234/vote?choice=abstain" + } + ] + } +} +``` + +#### Приклад відповіді на GET-запит з параметрами + +Наступні приклади відповіді демонструють, як приймати текстове введення від користувача (через `parameters`) і включати це введення у кінцеву кінцеву точку запиту `POST` (через поле `href` у `LinkedAction`): + +Наступний приклад відповіді забезпечує користувачеві 3 пов’язані дії для стейкінгу SOL: кнопку з міткою "Stake 1 SOL", іншу кнопку з міткою "Stake 5 SOL" та текстове поле введення, яке дозволяє користувачеві ввести конкретне значення "amount", що буде надіслано до API дій: + +```json +{ + "title": "Stake-o-matic", + "icon": "", + "description": "Stake SOL to help secure the Solana network.", + "label": "Stake SOL", // not displayed since `links.actions` are provided + "links": { + "actions": [ + { + "label": "Stake 1 SOL", // button text + "href": "/api/stake?amount=1" + // no `parameters` therefore not a text input field + }, + { + "label": "Stake 5 SOL", // button text + "href": "/api/stake?amount=5" + // no `parameters` therefore not a text input field + }, + { + "label": "Stake", // button text + "href": "/api/stake?amount={amount}", + "parameters": [ + { + "name": "amount", // field name + "label": "SOL amount" // text input placeholder + } + ] + } + ] + } +} +``` + +Наступний приклад відповіді забезпечує одне поле введення для користувача, щоб ввести `amount`, яке буде надіслано з запитом `POST` (може бути використано як параметр запиту або як підшлях): + +```json +{ + "icon": "", + "label": "Donate SOL", + "title": "Donate to GoodCause Charity", + "description": "Help support this charity by donating SOL.", + "links": { + "actions": [ + { + "label": "Donate", // button text + "href": "/api/donate/{amount}", // or /api/donate?amount={amount} + "parameters": [ + // {amount} input field + { + "name": "amount", // input field name + "label": "SOL amount" // text input placeholder + } + ] + } + ] + } +} +``` + +### POST Запит + +Наступний приклад відповіді забезпечує одне поле введення для користувача, щоб ввести `amount`, яке буде надіслано з запитом `POST` (може бути використано як параметр запиту або як підшлях): + +```json +{ + "account": "" +} +``` + +- `account` - Значення повинно бути відкритим ключем облікового запису у форматі base58, який може підписувати транзакцію. + +Клієнт має виконати запит із заголовком +[Accept-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding), +а застосунок може відповісти заголовком +[Content-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding) +для HTTP-компресії. + +Клієнт повинен відобразити домен URL дії під час виконання запиту. Якщо був виконаний `GET`-запит, клієнт також повинен відобразити `title` та відрендерити зображення `icon` з відповіді GET. + +### Відповідь на POST-запит + +Кінцева точка `POST` для дії повинна відповідати HTTP-відповіддю `OK` у форматі JSON (з дійсним тілом відповіді) або відповідною HTTP-помилкою. + +- Клієнт повинен обробляти + [помилки клієнта](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses), + [помилки сервера](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses), + та + [відповіді-перенаправлення](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). +- Кінцева точка повинна відповідати з + заголовком [`Content-Type`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) + значенням `application/json`. + +Помилкові відповіді (тобто HTTP-коди стану 4xx і 5xx) повинні повертати JSON-відповідь, що відповідає структурі `ActionError`, для відображення корисного повідомлення про помилку користувачам. Див. [Помилки дій](#action-errors). + +#### Тіло відповіді на POST-запит + +Відповідь `POST` з HTTP-відповіддю `OK` у форматі JSON повинна включати тіло відповіді наступного вигляду: + + +```ts filename="ActionPostResponse" +/** + * Response body payload returned from the Action POST Request + */ +export interface ActionPostResponse { + /** base64 encoded serialized transaction */ + transaction: string; + /** describes the nature of the transaction */ + message?: string; + links?: { + /** + * The next action in a successive chain of actions to be obtained after + * the previous was successful. + */ + next: NextActionLink; + }; +} +``` +- `transaction` - Значення повинно бути серіалізованою транзакцією, закодованою в base64 + ([документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#serialize)). + Клієнт повинен декодувати транзакцію з base64 і + [десеріалізувати її](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#from). + +- `message` - Значення повинно бути рядком у форматі UTF-8, який описує суть транзакції, + включеної у відповідь. Клієнт повинен відобразити це значення користувачу. + Наприклад, це може бути назва товару, який купується, застосована знижка, + або подяка. + +- `links.next` - Необов'язкове значення, яке використовується для "зчеплення" кількох дій + у послідовності. Після підтвердження включеної `transaction` у блокчейні + клієнт може отримати та відобразити наступну дію. Дивіться + [Зчеплення дій](#action-chaining) для отримання додаткової інформації. + +- Клієнт та застосунок повинні дозволяти додаткові поля у тілі запиту + та відповіді, які можуть бути додані у майбутніх оновленнях специфікацій. + +> Застосунок може відповідати частково або повністю підписаною транзакцією. +> Клієнт та гаманець повинні перевіряти транзакцію як **ненадійну**. + +#### Відповідь POST - Транзакція + +Якщо у транзакції +[`signatures`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#signatures) +відсутні або транзакція ще не підписана частково: + +- Клієнт повинен ігнорувати + [`feePayer`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#feePayer) + у транзакції та встановити `feePayer` як `account` з запиту. +- Клієнт повинен ігнорувати + [`recentBlockhash`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#recentBlockhash) + у транзакції та встановити `recentBlockhash` на + [останній blockhash](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getLatestBlockhash). +- Клієнт повинен серіалізувати та десеріалізувати транзакцію перед її підписанням. + Це забезпечує послідовний порядок ключів облікових записів як рішення для + [цієї проблеми](https://github.com/solana-labs/solana/issues/21722). + +Якщо транзакція вже частково підписана: + +- Клієнт не повинен змінювати + [`feePayer`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#feePayer) + або + [`recentBlockhash`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#recentBlockhash), + оскільки це зробить існуючі підписи недійсними. +- Клієнт повинен перевірити існуючі підписи, і якщо будь-який з них недійсний, + клієнт повинен відхилити транзакцію як **пошкоджену**. + +Клієнт повинен підписати транзакцію лише за допомогою `account`, зазначеного у запиті, +і зробити це лише у випадку, якщо очікується підпис для цього `account`. + +Якщо очікується будь-який підпис, окрім підпису для `account` у запиті, +клієнт повинен відхилити транзакцію як **шкідливу**. + +### Помилки дій + +API для дій повинні повертати помилки у форматі `ActionError`, щоб надати +корисні повідомлення про помилки для користувачів. Залежно від контексту, ця помилка +може бути фатальною або нефатальною. + + +```ts filename="ActionError" +export interface ActionError { + /** simple error message to be displayed to the user */ + message: string; +} +``` +Коли API для дій відповідає HTTP-кодом помилки (тобто 4xx і 5xx), тіло відповіді має бути JSON-навантаженням, яке відповідає формату `ActionError`. Помилка вважається фатальною, і повідомлення, яке міститься в ній, має бути представлене користувачеві. + +Для відповідей API, які підтримують необов'язковий атрибут `error` (наприклад, [`ActionGetResponse`](#get-response)), помилка вважається нефатальною, і повідомлення, яке міститься в ній, також має бути представлене користувачеві. + +## Зчеплення дій + +Дії Solana можуть бути "зчеплені" разом у послідовну серію. Після підтвердження транзакції дії у блокчейні можна отримати наступну дію та представити її користувачеві. + +Зчеплення дій дозволяє розробникам створювати більш складний і динамічний досвід у рамках blinks, включаючи: + +- надання декількох транзакцій (і в майбутньому повідомлень для підпису) користувачу; +- налаштування метаданих дії залежно від адреси гаманця користувача; +- оновлення метаданих blink після успішної транзакції; +- отримання API-зворотного виклику з підписом транзакції для додаткової перевірки та логіки на сервері API для дій; +- налаштовані повідомлення про успіх, шляхом оновлення відображуваних метаданих (наприклад, нове зображення або опис). + +Для зчеплення кількох дій разом, у будь-якому `ActionPostResponse` включіть `links.next` одного з наступних типів: + +- `PostNextActionLink` — Посилання POST-запиту з URL зворотного виклику того самого походження для отримання `signature` і `account` користувача у тілі. Цей URL зворотного виклику повинен відповідати `NextAction`. +- `InlineNextActionLink` — Вбудовані метадані для наступної дії, які мають бути представлені користувачеві негайно після підтвердження транзакції. Ніякий зворотний виклик не буде виконано. + +```ts +export type NextActionLink = PostNextActionLink | InlineNextActionLink; + +/** @see {NextActionPostRequest} */ +export interface PostNextActionLink { + /** Indicates the type of the link. */ + type: "post"; + /** Relative or same origin URL to which the POST request should be made. */ + href: string; +} + +/** + * Represents an inline next action embedded within the current context. + */ +export interface InlineNextActionLink { + /** Indicates the type of the link. */ + type: "inline"; + /** The next action to be performed */ + action: NextAction; +} +``` +### NextAction + +Після того як транзакція, включена в `ActionPostResponse`, підписана користувачем і підтверджена у блокчейні, blink-клієнт повинен або: + +- виконати запит зворотного виклику, щоб отримати і відобразити `NextAction`, або +- якщо `NextAction` вже надана через `links.next`, blink-клієнт повинен оновити відображувані метадані і не робити запит зворотного виклику. + +Якщо URL зворотного виклику не має того ж походження, що і початковий POST-запит, запит зворотного виклику не повинен виконуватися. Blink-клієнти повинні відобразити помилку, що повідомляє користувача. + + +```ts filename="NextAction" +/** The next action to be performed */ +export type NextAction = Action<"action"> | CompletedAction; + +/** The completed action, used to declare the "completed" state within action chaining. */ +export type CompletedAction = Omit, "links">; +``` + +### Відповідно до `type`, наступна дія повинна бути представлена користувачеві через blink-клієнти одним із наступних способів: + +- `action` - (за замовчуванням) Стандартна дія, яка дозволяє користувачеві переглядати включені метадані Action, взаємодіяти з наданими `LinkedActions` і продовжувати виконувати будь-які наступні дії в ланцюжку. + +- `completed` - Завершальний стан ланцюжка дій, який може оновлювати інтерфейс blink із включеними метаданими Action, але не дозволяє користувачеві виконувати подальші дії. + +Якщо `links.next` не надано, blink-клієнти повинні припустити, що поточна дія є фінальною у ланцюжку, і представити свій інтерфейс "завершеної" дії після підтвердження транзакції. + +## actions.json + +Файл [`actions.json`](#actionsjson) використовується для того, щоб додаток міг інструктувати клієнтів про те, які URL-адреси вебсайту підтримують Solana Actions, і надавати мапінг, який може бути використаний для виконання [GET запитів](#get-request) до серверу API дій. + + + +Відповідь файлу `actions.json` також повинна повертати дійсні заголовки Cross-Origin для запитів `GET` і `OPTIONS`, зокрема заголовок `Access-Control-Allow-Origin` із значенням `*`. + +Детальніше див. у розділі [OPTIONS response](#options-response) вище. + + + +Файл `actions.json` повинен бути збережений і загальнодоступний у кореневій директорії домену. + +Наприклад, якщо ваш вебдодаток розгорнуто на `my-site.com`, тоді файл `actions.json` має бути доступний за адресою `https://my-site.com/actions.json`. Цей файл також має бути доступний через будь-який браузер за допомогою заголовка `Access-Control-Allow-Origin` із значенням `*`. + +### Правила + +Поле `rules` дозволяє додатку мапувати набір відносних маршрутів вебсайту на інші шляхи. + +**Тип:** `Array` з `ActionRuleObject`. + +```ts filename="ActionRuleObject" +interface ActionRuleObject { + /** relative (preferred) or absolute path to perform the rule mapping from */ + pathPattern: string; + /** relative (preferred) or absolute path that supports Action requests */ + apiPath: string; +} +``` +- [`pathPattern`](#rules-pathpattern) - Шаблон, який відповідає кожному вхідному шляху. + +- [`apiPath`](#rules-apipath) - Місце призначення, визначене як абсолютний шлях або зовнішній URL. + +#### Правила - pathPattern + +Шаблон, який відповідає кожному вхідному шляху. Це може бути абсолютний або відносний шлях, який підтримує наступні формати: + +- **Точне співпадіння**: Відповідає точному URL-шляху. + + - Приклад: `/exact-path` + - Приклад: `https://website.com/exact-path` + +- **Співпадіння з використанням шаблону**: Використовує символи підстановки для відповідності будь-якій послідовності символів у шляху URL. Це може відповідати одному (за допомогою `*`) або кільком сегментам (за допомогою `**`). (Див. [Path Matching](#rules-path-matching) нижче). + + - Приклад: `/trade/*` відповідатиме `/trade/123` і `/trade/abc`, захоплюючи лише перший сегмент після `/trade/`. + - Приклад: `/category/*/item/**` відповідатиме `/category/123/item/456` і `/category/abc/item/def`. + - Приклад: `/api/actions/trade/*/confirm` відповідатиме `/api/actions/trade/123/confirm`. + +#### Правила - apiPath + +Шлях призначення для запиту дії. Він може бути визначений як абсолютний шлях або зовнішній URL. + +- Приклад: `/api/exact-path` +- Приклад: `https://api.example.com/v1/donate/*` +- Приклад: `/api/category/*/item/*` +- Приклад: `/api/swap/**` + +#### Правила - Query Parameters + +Параметри запиту з оригінального URL завжди зберігаються та додаються до мапованого URL. + +#### Правила - Path Matching + +Наступна таблиця описує синтаксис для шаблонів відповідності шляхів: + +| Оператор | Відповідає | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `*` | Один сегмент шляху, що не включає оточуючі символи розділювача шляху `/`. | +| `**` | Відповідає нулю або більшій кількості символів, включаючи будь-які символи розділювача шляху `/` між декількома сегментами шляху. Якщо включені інші оператори, оператор `**` повинен бути останнім. | +| `?` | Непідтримуваний шаблон. | + +### Приклади Правил + +Наступний приклад демонструє правило точного співпадіння для мапування запитів до `/buy` з кореня вашого сайту на точний шлях `/api/buy`, відносно кореня вашого сайту: + +```json filename="actions.json" +{ + "rules": [ + { + "pathPattern": "/buy", + "apiPath": "/api/buy" + } + ] +} +``` + +Наступний приклад використовує шаблонне співставлення шляху для відображення запитів до будь-якого шляху (за винятком підкаталогів) під `/actions/` від кореня вашого сайту до відповідного шляху під `/api/actions/`, відносно кореня вашого сайту: + +```json filename="actions.json" +{ + "rules": [ + { + "pathPattern": "/actions/*", + "apiPath": "/api/actions/*" + } + ] +} +``` + +Наступний приклад використовує зіставлення шляхів із використанням символів підстановки для перенаправлення запитів до будь-якого шляху (за винятком підкаталогів) під `/donate/` у кореневій директорії вашого сайту до відповідного абсолютного шляху `https://api.dialect.com/api/v1/donate/` на зовнішньому сайті: + +```json filename="actions.json" +{ + "rules": [ + { + "pathPattern": "/donate/*", + "apiPath": "https://api.dialect.com/api/v1/donate/*" + } + ] +} +``` + +Наступний приклад використовує зіставлення шляхів із використанням символів підстановки для ідемпотентного правила, щоб перенаправляти запити до будь-якого шляху (включаючи підкаталоги) під `/api/actions/` у кореневій директорії вашого сайту до самого себе: + +> Ідемпотентні правила дозволяють клієнтам blink легше визначати, чи підтримує даний шлях запити API дій, без необхідності: +> +> - додавання префіксу `solana-action:` URI, +> - виконання додаткового тестування відповіді, +> - або будь-яких інших спеціальних перевірок. + +```json filename="actions.json" +{ + "rules": [ + { + "pathPattern": "/api/actions/**", + "apiPath": "/api/actions/**" + } + ] +} +``` + +## Ідентифікація Дії (Action Identity) + +Кінцеві точки дій (Action endpoints) можуть включати _Ідентифікацію Дії_ у транзакціях, які повертаються у [POST-відповіді](#post-response) для підпису користувачем. Це дозволяє індексаторам та аналітичним платформам легко та достовірно приписувати активність у блокчейні конкретному провайдеру дій (тобто сервісу). + +[Ідентифікація Дії](#action-identity) — це пара ключів (keypair), яка використовується для підпису спеціально форматованого повідомлення, що включається до транзакції за допомогою інструкції Memo. Це _Повідомлення Ідентифікатора_ (_Identifier Message_) може бути достовірно приписане до конкретної Ідентифікації Дії, а отже, до конкретного провайдера дій. + +Пара ключів не вимагається для підписання самої транзакції. Це дозволяє гаманцям та додаткам покращити доставку транзакції, якщо у транзакції, поверненій користувачу, немає інших підписів (див. [POST-відповідь транзакції](#post-response-transaction)). + +Якщо сценарій використання провайдера дій вимагає, щоб їх бекенд-сервіси попередньо підписували транзакцію перед тим, як це зробить користувач, вони мають використовувати цю пару ключів як Ідентифікацію Дії. Це дозволить зменшити кількість облікових записів у транзакції, скоротивши її загальний розмір на 32 байти. + +### Повідомлення Ідентифікатора Дії (Action Identifier Message) + +Повідомлення Ідентифікатора Дії — це UTF-8 рядок, розділений двокрапками, який включається до транзакції за допомогою однієї [інструкції SPL Memo](https://spl.solana.com/memo). + +```shell +protocol:identity:reference:signature +``` +- `protocol` - Значення протоколу, який використовується (встановлено як `solana-action` відповідно до [URL-схеми](#url-scheme) вище). +- `identity` - Значення має бути публічним ключем у форматі base58, який відповідає парі ключів Ідентифікації Дії. +- `reference` - Значення має бути масивом байтів довжиною 32 у форматі base58. Це можуть бути як публічні ключі, так і інші дані, які можуть або не можуть відповідати обліковим записам у Solana. +- `signature` - Підпис у форматі base58, створений парою ключів Ідентифікації Дії, що підписує лише значення `reference`. + +Значення `reference` має використовуватися тільки один раз і в одній транзакції. Для приписування транзакцій провайдеру дій, лише перше використання значення `reference` вважається дійсним. + +Транзакції можуть містити кілька інструкцій Memo. Під час виконання [`getSignaturesForAddress`](https://solana.com/docs/rpc/http/getsignaturesforaddress) поле `memo` у результатах повертає повідомлення кожної інструкції Memo як єдиний рядок, розділений крапкою з комою. + +Жодні інші дані не повинні включатися до інструкції Memo Повідомлення Ідентифікатора. + +Облікові записи `identity` та `reference` повинні бути включені як доступні тільки для читання, але без можливості підпису ([ключі](https://solana-labs.github.io/solana-web3.js/v1.x/classes/TransactionInstruction.html#keys)) у транзакції в інструкції, яка не є Інструкцією Memo Повідомлення Ідентифікатора. + +Інструкція Memo Повідомлення Ідентифікатора не повинна містити жодних облікових записів. Якщо облікові записи надаються, програма Memo вимагає, щоб ці облікові записи були дійсними підписувачами. Це обмежує гнучкість і може погіршити досвід користувача, тому це вважається антипатерном і має бути уникнуто. + +### Перевірка Ідентифікації Дії (Action Identity Verification) + +Будь-яка транзакція, що включає обліковий запис `identity`, може бути достовірно пов'язана з провайдером дій за допомогою багатоступінчастого процесу: + +1. Отримайте всі транзакції для заданого `identity`. +2. Розберіть і перевірте рядок memo кожної транзакції, переконавшись, що підпис `signature` дійсний для збереженого значення `reference`. +3. Перевірте, чи є ця транзакція першим випадком використання `reference` у блокчейні: + - Якщо ця транзакція є першим випадком, вона вважається підтвердженою і може бути достовірно приписана провайдеру дій. + - Якщо ця транзакція НЕ є першим випадком, вона вважається недійсною і, відповідно, не може бути приписана провайдеру дій. + +Оскільки валідатори Solana індексують транзакції за обліковими записами, метод RPC [`getSignaturesForAddress`](https://solana.com/docs/rpc/http/getsignaturesforaddress) може бути використаний для визначення всіх транзакцій, що включають обліковий запис `identity`. + +Відповідь цього методу RPC включає всі дані Memo у полі `memo`. Якщо в транзакції було використано кілька інструкцій Memo, кожне повідомлення Memo буде включено в це поле `memo` і має бути відповідним чином розібране перевіряючою стороною для отримання _Повідомлення Ідентифікації_. + +Ці транзакції спочатку мають вважатися **НЕПЕРЕВІРЕНИМИ**. Це пов'язано з тим, що `identity` не вимагається для підписання транзакції, що дозволяє будь-якій транзакції включати цей обліковий запис як не-підписувач. Це потенційно може штучно збільшити статистику приписування та використання. + +Повідомлення Ідентифікації має бути перевірене для забезпечення того, що `signature` було створено `identity`, підписуючи `reference`. Якщо ця перевірка підпису не вдається, транзакція вважається недійсною. + +Якщо перевірка підпису успішна, перевіряюча сторона має забезпечити, що ця транзакція є першим випадком використання `reference`. Якщо це не так, транзакція вважається недійсною. + diff --git a/docs/uk/advanced/confirmation.md b/docs/uk/advanced/confirmation.md new file mode 100644 index 000000000..a4d1ae3bc --- /dev/null +++ b/docs/uk/advanced/confirmation.md @@ -0,0 +1,402 @@ +--- +sidebarSortOrder: 1 +sidebarLabel: "Confirmation & Expiration" +title: "Transaction Confirmation & Expiration" +seoTitle: "Transaction Confirmation & Expiration" +description: + "Understand how Solana transaction confirmation and when a transaction expires + (including recent blockhash checks)." +altRoutes: + - /docs/advanced + - /docs/core/transactions/confirmation +--- + +Problems relating to +[transaction confirmation](/docs/terminology.md#transaction-confirmations) are +common with many newer developers while building applications. This article aims +to boost the overall understanding of the confirmation mechanism used on the +Solana blockchain, including some recommended best practices. + +## Brief background on transactions + +Before diving into how Solana transaction confirmation and expiration works, +let's briefly set the base understanding of a few things: + +- what a transaction is +- the lifecycle of a transaction +- what a blockhash is +- and a brief understanding of Proof of History (PoH) and how it relates to + blockhashes + +### What is a transaction? + +Transactions consist of two components: a +[message](/docs/terminology.md#message) and a +[list of signatures](/docs/terminology.md#signature). The transaction message is +where the magic happens and at a high level it consists of four components: + +- a **header** with metadata about the transaction, +- a **list of instructions** to invoke, +- a **list of accounts** to load, and +- a **“recent blockhash.”** + +In this article, we're going to be focusing a lot on a transaction's +[recent blockhash](/docs/terminology.md#blockhash) because it plays a big role +in transaction confirmation. + +### Transaction lifecycle refresher + +Below is a high level view of the lifecycle of a transaction. This article will +touch on everything except steps 1 and 4. + +1. Create a header and a list of instructions along with the list of accounts + that instructions need to read and write +2. Fetch a recent blockhash and use it to prepare a transaction message +3. Simulate the transaction to ensure it behaves as expected +4. Prompt user to sign the prepared transaction message with their private key +5. Send the transaction to an RPC node which attempts to forward it to the + current block producer +6. Hope that a block producer validates and commits the transaction into their + produced block +7. Confirm the transaction has either been included in a block or detect when it + has expired + +### What is a Blockhash? + +A [“blockhash”](/docs/terminology.md#blockhash) refers to the last Proof of +History (PoH) hash for a [“slot”](/docs/terminology.md#slot) (description +below). Since Solana uses PoH as a trusted clock, a transaction's recent +blockhash can be thought of as a **timestamp**. + +### Proof of History refresher + +Solana's Proof of History mechanism uses a very long chain of recursive SHA-256 +hashes to build a trusted clock. The “history” part of the name comes from the +fact that block producers hash transaction id's into the stream to record which +transactions were processed in their block. + +[PoH hash calculation](https://github.com/anza-xyz/agave/blob/aa0922d6845e119ba466f88497e8209d1c82febc/entry/src/poh.rs#L79): +`next_hash = hash(prev_hash, hash(transaction_ids))` + +PoH can be used as a trusted clock because each hash must be produced +sequentially. Each produced block contains a blockhash and a list of hash +checkpoints called “ticks” so that validators can verify the full chain of +hashes in parallel and prove that some amount of time has actually passed. + +## Transaction Expiration + +By default, all Solana transactions will expire if not committed to a block in a +certain amount of time. The **vast majority** of transaction confirmation issues +are related to how RPC nodes and validators detect and handle **expired** +transactions. A solid understanding of how transaction expiration works should +help you diagnose the bulk of your transaction confirmation issues. + +### How does transaction expiration work? + +Each transaction includes a “recent blockhash” which is used as a PoH clock +timestamp and expires when that blockhash is no longer “recent enough”. + +As each block is finalized (i.e. the maximum tick height +[is reached](https://github.com/anza-xyz/agave/blob/0588ecc6121ba026c65600d117066dbdfaf63444/runtime/src/bank.rs#L3269-L3271), +reaching the "block boundary"), the final hash of the block is added to the +`BlockhashQueue` which stores a maximum of the +[300 most recent blockhashes](https://github.com/anza-xyz/agave/blob/e0b0bcc80380da34bb63364cc393801af1e1057f/sdk/program/src/clock.rs#L123-L126). +During transaction processing, Solana Validators will check if each +transaction's recent blockhash is recorded within the most recent 151 stored +hashes (aka "max processing age"). If the transaction's recent blockhash is +[older than this](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/runtime/src/bank.rs#L3570-L3571) +max processing age, the transaction is not processed. + +> Due to the current +> [max processing age of 150](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L129-L131) +> and the "age" of a blockhash in the queue being +> [0-indexed](https://github.com/anza-xyz/agave/blob/992a398fe8ea29ec4f04d081ceef7664960206f4/accounts-db/src/blockhash_queue.rs#L248-L274), +> there are actually 151 blockhashes that are considered "recent enough" and +> valid for processing. + +Since [slots](/docs/terminology.md#slot) (aka the time period a validator can +produce a block) are configured to last about +[400ms](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L107-L109), +but may fluctuate between 400ms and 600ms, a given blockhash can only be used by +transactions for about 60 to 90 seconds before it will be considered expired by +the runtime. + +### Example of transaction expiration + +Let's walk through a quick example: + +1. A validator is actively producing a new block for the current slot +2. The validator receives a transaction from a user with the recent blockhash + `abcd...` +3. The validator checks this blockhash `abcd...` against the list of recent + blockhashes in the `BlockhashQueue` and discovers that it was created 151 + blocks ago +4. Since it is exactly 151 blockhashes old, the transaction has not expired yet + and can still be processed! +5. But wait: before actually processing the transaction, the validator finished + creating the next block and added it to the `BlockhashQueue`. The validator + then starts producing the block for the next slot (validators get to produce + blocks for 4 consecutive slots) +6. The validator checks that same transaction again and finds it is now 152 + blockhashes old and rejects it because it's too old :( + +## Why do transactions expire? + +There's a very good reason for this actually, it's to help validators avoid +processing the same transaction twice. + +A naive brute force approach to prevent double processing could be to check +every new transaction against the blockchain's entire transaction history. But +by having transactions expire after a short amount of time, validators only need +to check if a new transaction is in a relatively small set of _recently_ +processed transactions. + +### Other blockchains + +Solana's approach to prevent double processing is quite different from other +blockchains. For example, Ethereum tracks a counter (nonce) for each transaction +sender and will only process transactions that use the next valid nonce. + +Ethereum's approach is simple for validators to implement, but it can be +problematic for users. Many people have encountered situations when their +Ethereum transactions got stuck in a _pending_ state for a long time and all the +later transactions, which used higher nonce values, were blocked from +processing. + +### Advantages on Solana + +There are a few advantages to Solana's approach: + +1. A single fee payer can submit multiple transactions at the same time that are + allowed to be processed in any order. This might happen if you're using + multiple applications at the same time. +2. If a transaction doesn't get committed to a block and expires, users can try + again knowing that their previous transaction will NOT ever be processed. + +By not using counters, the Solana wallet experience may be easier for users to +understand because they can get to success, failure, or expiration states +quickly and avoid annoying pending states. + +### Disadvantages on Solana + +Of course there are some disadvantages too: + +1. Validators have to actively track a set of all processed transaction id's to + prevent double processing. +2. If the expiration time period is too short, users might not be able to submit + their transaction before it expires. + +These disadvantages highlight a tradeoff in how transaction expiration is +configured. If the expiration time of a transaction is increased, validators +need to use more memory to track more transactions. If expiration time is +decreased, users don't have enough time to submit their transaction. + +Currently, Solana clusters require that transactions use blockhashes that are no +more than 151 blocks old. + +> This [Github issue](https://github.com/solana-labs/solana/issues/23582) +> contains some calculations that estimate that mainnet-beta validators need +> about 150MB of memory to track transactions. This could be slimmed down in the +> future if necessary without decreasing expiration time as are detailed in that +> issue. + +## Transaction confirmation tips + +As mentioned before, blockhashes expire after a time period of only 151 blocks +which can pass as quickly as **one minute** when slots are processed within the +target time of 400ms. + +One minute is not a lot of time considering that a client needs to fetch a +recent blockhash, wait for the user to sign, and finally hope that the +broadcasted transaction reaches a leader that is willing to accept it. Let's go +through some tips to help avoid confirmation failures due to transaction +expiration! + +### Fetch blockhashes with the appropriate commitment level + +Given the short expiration time frame, it's imperative that clients and +applications help users create transactions with a blockhash that is as recent +as possible. + +When fetching blockhashes, the current recommended RPC API is called +[`getLatestBlockhash`](/docs/rpc/http/getLatestBlockhash.mdx). By default, this +API uses the `finalized` commitment level to return the most recently finalized +block's blockhash. However, you can override this behavior by +[setting the `commitment` parameter](/docs/rpc/index.mdx#configuring-state-commitment) +to a different commitment level. + +**Recommendation** + +The `confirmed` commitment level should almost always be used for RPC requests +because it's usually only a few slots behind the `processed` commitment and has +a very low chance of belonging to a dropped +[fork](https://docs.anza.xyz/consensus/fork-generation). + +But feel free to consider the other options: + +- Choosing `processed` will let you fetch the most recent blockhash compared to + other commitment levels and therefore gives you the most time to prepare and + process a transaction. But due to the prevalence of forking in the Solana + blockchain, roughly 5% of blocks don't end up being finalized by the cluster + so there's a real chance that your transaction uses a blockhash that belongs + to a dropped fork. Transactions that use blockhashes for abandoned blocks + won't ever be considered recent by any blocks that are in the finalized + blockchain. +- Using the [default commitment](/docs/rpc#default-commitment) level `finalized` + will eliminate any risk that the blockhash you choose will belong to a dropped + fork. The tradeoff is that there is typically at least a 32 slot difference + between the most recent confirmed block and the most recent finalized block. + This tradeoff is pretty severe and effectively reduces the expiration of your + transactions by about 13 seconds but this could be even more during unstable + cluster conditions. + +### Use an appropriate preflight commitment level + +If your transaction uses a blockhash that was fetched from one RPC node then you +send, or simulate, that transaction with a different RPC node, you could run +into issues due to one node lagging behind the other. + +When RPC nodes receive a `sendTransaction` request, they will attempt to +determine the expiration block of your transaction using the most recent +finalized block or with the block selected by the `preflightCommitment` +parameter. A **VERY** common issue is that a received transaction's blockhash +was produced after the block used to calculate the expiration for that +transaction. If an RPC node can't determine when your transaction expires, it +will only forward your transaction **one time** and afterwards will then +**drop** the transaction. + +Similarly, when RPC nodes receive a `simulateTransaction` request, they will +simulate your transaction using the most recent finalized block or with the +block selected by the `preflightCommitment` parameter. If the block chosen for +simulation is older than the block used for your transaction's blockhash, the +simulation will fail with the dreaded “blockhash not found” error. + +**Recommendation** + +Even if you use `skipPreflight`, **ALWAYS** set the `preflightCommitment` +parameter to the same commitment level used to fetch your transaction's +blockhash for both `sendTransaction` and `simulateTransaction` requests. + +### Be wary of lagging RPC nodes when sending transactions + +When your application uses an RPC pool service or when the RPC endpoint differs +between creating a transaction and sending a transaction, you need to be wary of +situations where one RPC node is lagging behind the other. For example, if you +fetch a transaction blockhash from one RPC node then you send that transaction +to a second RPC node for forwarding or simulation, the second RPC node might be +lagging behind the first. + +**Recommendation** + +For `sendTransaction` requests, clients should keep resending a transaction to a +RPC node on a frequent interval so that if an RPC node is slightly lagging +behind the cluster, it will eventually catch up and detect your transaction's +expiration properly. + +For `simulateTransaction` requests, clients should use the +[`replaceRecentBlockhash`](/docs/rpc/http/simulateTransaction.mdx) parameter to +tell the RPC node to replace the simulated transaction's blockhash with a +blockhash that will always be valid for simulation. + +### Avoid reusing stale blockhashes + +Even if your application has fetched a very recent blockhash, be sure that +you're not reusing that blockhash in transactions for too long. The ideal +scenario is that a recent blockhash is fetched right before a user signs their +transaction. + +**Recommendation for applications** + +Poll for new recent blockhashes on a frequent basis to ensure that whenever a +user triggers an action that creates a transaction, your application already has +a fresh blockhash that's ready to go. + +**Recommendation for wallets** + +Poll for new recent blockhashes on a frequent basis and replace a transaction's +recent blockhash right before they sign the transaction to ensure the blockhash +is as fresh as possible. + +### Use healthy RPC nodes when fetching blockhashes + +By fetching the latest blockhash with the `confirmed` commitment level from an +RPC node, it's going to respond with the blockhash for the latest confirmed +block that it's aware of. Solana's block propagation protocol prioritizes +sending blocks to staked nodes so RPC nodes naturally lag about a block behind +the rest of the cluster. They also have to do more work to handle application +requests and can lag a lot more under heavy user traffic. + +Lagging RPC nodes can therefore respond to +[`getLatestBlockhash`](/docs/rpc/http/getLatestBlockhash.mdx) requests with +blockhashes that were confirmed by the cluster quite awhile ago. By default, a +lagging RPC node detects that it is more than 150 slots behind the cluster will +stop responding to requests, but just before hitting that threshold they can +still return a blockhash that is just about to expire. + +**Recommendation** + +Monitor the health of your RPC nodes to ensure that they have an up-to-date view +of the cluster state with one of the following methods: + +1. Fetch your RPC node's highest processed slot by using the + [`getSlot`](/docs/rpc/http/getSlot.mdx) RPC API with the `processed` + commitment level and then call the + [`getMaxShredInsertSlot`](/docs/rpc/http/getMaxShredInsertSlot.mdx) RPC API + to get the highest slot that your RPC node has received a “shred” of a block + for. If the difference between these responses is very large, the cluster is + producing blocks far ahead of what the RPC node has processed. +2. Call the `getLatestBlockhash` RPC API with the `confirmed` commitment level + on a few different RPC API nodes and use the blockhash from the node that + returns the highest slot for its + [context slot](/docs/rpc/index.mdx#rpcresponse-structure). + +### Wait long enough for expiration + +**Recommendation** + +When calling the [`getLatestBlockhash`](/docs/rpc/http/getLatestBlockhash.mdx) +RPC API to get a recent blockhash for your transaction, take note of the +`lastValidBlockHeight` in the response. + +Then, poll the [`getBlockHeight`](/docs/rpc/http/getBlockHeight.mdx) RPC API +with the `confirmed` commitment level until it returns a block height greater +than the previously returned last valid block height. + +### Consider using “durable” transactions + +Sometimes transaction expiration issues are really hard to avoid (e.g. offline +signing, cluster instability). If the previous tips are still not sufficient for +your use-case, you can switch to using durable transactions (they just require a +bit of setup). + +To start using durable transactions, a user first needs to submit a transaction +that +[invokes instructions that create a special on-chain “nonce” account](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.create_nonce_account.html) +and stores a “durable blockhash” inside of it. At any point in the future (as +long as the nonce account hasn't been used yet), the user can create a durable +transaction by following these 2 rules: + +1. The instruction list must start with an + [“advance nonce” system instruction](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.advance_nonce_account.html) + which loads their on-chain nonce account +2. The transaction's blockhash must be equal to the durable blockhash stored by + the on-chain nonce account + +Here's how these durable transactions are processed by the Solana runtime: + +1. If the transaction's blockhash is no longer “recent”, the runtime checks if + the transaction's instruction list begins with an “advance nonce” system + instruction +2. If so, it then loads the nonce account specified by the “advance nonce” + instruction +3. Then it checks that the stored durable blockhash matches the transaction's + blockhash +4. Lastly it makes sure to advance the nonce account's stored blockhash to the + latest recent blockhash to ensure that the same transaction can never be + processed again + +For more details about how these durable transactions work, you can read the +[original proposal](https://docs.anza.xyz/implemented-proposals/durable-tx-nonces) +and +[check out an example](/content/guides/advanced/introduction-to-durable-nonces.md) +in the Solana docs. diff --git a/docs/uk/advanced/index.md b/docs/uk/advanced/index.md new file mode 100644 index 000000000..11ae9d7f4 --- /dev/null +++ b/docs/uk/advanced/index.md @@ -0,0 +1,5 @@ +--- +metaOnly: true +title: Advanced Topics +sidebarSortOrder: 3 +--- diff --git a/docs/uk/advanced/lookup-tables.md b/docs/uk/advanced/lookup-tables.md new file mode 100644 index 000000000..3b997c6c8 --- /dev/null +++ b/docs/uk/advanced/lookup-tables.md @@ -0,0 +1,192 @@ +--- +sidebarSortOrder: 4 +title: Address Lookup Tables +description: + Learn how to use Solana Address Lookup Tables (ALTs) to efficiently handle up + to 64 addresses per transaction. Create, extend, and utilize lookup tables + using web3.js. +--- + +Address Lookup Tables, commonly referred to as "_lookup tables_" or "_ALTs_" for +short, allow developers to create a collection of related addresses to +efficiently load more addresses in a single transaction. + +Since each transaction on the Solana blockchain requires a listing of every +address that is interacted with as part of the transaction, this listing would +effectively be capped at 32 addresses per transaction. With the help of +[Address Lookup Tables](/docs/advanced/lookup-tables.md), a transaction would +now be able to raise that limit to 64 addresses per transaction. + +## Compressing onchain addresses + +After all the desired addresses have been stored onchain in an Address Lookup +Table, each address can be referenced inside a transaction by its 1-byte index +within the table (instead of their full 32-byte address). This lookup method +effectively "_compresses_" a 32-byte address into a 1-byte index value. + +This "_compression_" enables storing up to 256 addresses in a single lookup +table for use inside any given transaction. + +## Versioned Transactions + +To utilize an Address Lookup Table inside a transaction, developers must use v0 +transactions that were introduced with the new +[Versioned Transaction format](/docs/advanced/versions.md). + +## How to create an address lookup table + +Creating a new lookup table with the `@solana/web3.js` library is similar to the +older `legacy` transactions, but with some differences. + +Using the `@solana/web3.js` library, you can use the +[`createLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#createLookupTable) +function to construct the instruction needed to create a new lookup table, as +well as determine its address: + +```js +const web3 = require("@solana/web3.js"); + +// connect to a cluster and get the current `slot` +const connection = new web3.Connection(web3.clusterApiUrl("devnet")); +const slot = await connection.getSlot(); + +// Assumption: +// `payer` is a valid `Keypair` with enough SOL to pay for the execution + +const [lookupTableInst, lookupTableAddress] = + web3.AddressLookupTableProgram.createLookupTable({ + authority: payer.publicKey, + payer: payer.publicKey, + recentSlot: slot, + }); + +console.log("lookup table address:", lookupTableAddress.toBase58()); + +// To create the Address Lookup Table onchain: +// send the `lookupTableInst` instruction in a transaction +``` + +> NOTE: Address lookup tables can be **created** with either a `v0` transaction +> or a `legacy` transaction. But the Solana runtime can only retrieve and handle +> the additional addresses within a lookup table while using +> [v0 Versioned Transactions](/docs/advanced/versions.md#current-transaction-versions). + +## Add addresses to a lookup table + +Adding addresses to a lookup table is known as "_extending_". Using the +`@solana/web3.js` library, you can create a new _extend_ instruction using the +[`extendLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#extendLookupTable) +method: + +```js +// add addresses to the `lookupTableAddress` table via an `extend` instruction +const extendInstruction = web3.AddressLookupTableProgram.extendLookupTable({ + payer: payer.publicKey, + authority: payer.publicKey, + lookupTable: lookupTableAddress, + addresses: [ + payer.publicKey, + web3.SystemProgram.programId, + // list more `publicKey` addresses here + ], +}); + +// Send this `extendInstruction` in a transaction to the cluster +// to insert the listing of `addresses` into your lookup table with address `lookupTableAddress` +``` + +> NOTE: Due to the same memory limits of `legacy` transactions, any transaction +> used to _extend_ an Address Lookup Table is also limited in how many addresses +> can be added at a time. Because of this, you will need to use multiple +> transactions to _extend_ any table with more addresses (~20) that can fit +> within a single transaction's memory limits. + +Once these addresses have been inserted into the table, and stored onchain, you +will be able to utilize the Address Lookup Table in future transactions. +Enabling up to 64 addresses in those future transactions. + +## Fetch an Address Lookup Table + +Similar to requesting another account (or PDA) from the cluster, you can fetch a +complete Address Lookup Table with the +[`getAddressLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getAddressLookupTable) +method: + +```js +// define the `PublicKey` of the lookup table to fetch +const lookupTableAddress = new web3.PublicKey(""); + +// get the table from the cluster +const lookupTableAccount = ( + await connection.getAddressLookupTable(lookupTableAddress) +).value; + +// `lookupTableAccount` will now be a `AddressLookupTableAccount` object + +console.log("Table address from cluster:", lookupTableAccount.key.toBase58()); +``` + +Our `lookupTableAccount` variable will now be a `AddressLookupTableAccount` +object which we can parse to read the listing of all the addresses stored on +chain in the lookup table: + +```js +// loop through and parse all the addresses stored in the table +for (let i = 0; i < lookupTableAccount.state.addresses.length; i++) { + const address = lookupTableAccount.state.addresses[i]; + console.log(i, address.toBase58()); +} +``` + +## How to use an address lookup table in a transaction + +After you have created your lookup table, and stored your needed address on +chain (via extending the lookup table), you can create a `v0` transaction to +utilize the onchain lookup capabilities. + +Just like older `legacy` transactions, you can create all the +[instructions](/docs/terminology.md#instruction) your transaction will execute +onchain. You can then provide an array of these instructions to the +[Message](/docs/terminology.md#message) used in the `v0` transaction. + +> NOTE: The instructions used inside a `v0` transaction can be constructed using +> the same methods and functions used to create the instructions in the past. +> There is no required change to the instructions used involving an Address +> Lookup Table. + +```js +// Assumptions: +// - `arrayOfInstructions` has been created as an `array` of `TransactionInstruction` +// - we are using the `lookupTableAccount` obtained above + +// construct a v0 compatible transaction `Message` +const messageV0 = new web3.TransactionMessage({ + payerKey: payer.publicKey, + recentBlockhash: blockhash, + instructions: arrayOfInstructions, // note this is an array of instructions +}).compileToV0Message([lookupTableAccount]); + +// create a v0 transaction from the v0 message +const transactionV0 = new web3.VersionedTransaction(messageV0); + +// sign the v0 transaction using the file system wallet we created named `payer` +transactionV0.sign([payer]); + +// send and confirm the transaction +// (NOTE: There is NOT an array of Signers here; see the note below...) +const txid = await web3.sendAndConfirmTransaction(connection, transactionV0); + +console.log( + `Transaction: https://explorer.solana.com/tx/${txid}?cluster=devnet`, +); +``` + +> NOTE: When sending a `VersionedTransaction` to the cluster, it must be signed +> BEFORE calling the `sendAndConfirmTransaction` method. If you pass an array of +> `Signer` (like with `legacy` transactions) the method will trigger an error! + +## More Resources + +- Read the [proposal](https://docs.anza.xyz/proposals/versioned-transactions) + for Address Lookup Tables and Versioned transactions +- [Example Rust program using Address Lookup Tables](https://github.com/TeamRaccoons/address-lookup-table-multi-swap) diff --git a/docs/uk/advanced/retry.md b/docs/uk/advanced/retry.md new file mode 100644 index 000000000..be27ecefa --- /dev/null +++ b/docs/uk/advanced/retry.md @@ -0,0 +1,329 @@ +--- +sidebarSortOrder: 2 +title: Retrying Transactions +altRoutes: + - /docs/core/transactions/retry +description: + Learn how to handle dropped transactions and implement custom retry logic on + Solana. This guide covers transaction rebroadcasting, preflight checks, and + best practices for managing transaction retries to ensure reliable transaction + processing on the Solana blockchain. +--- + +# Retrying Transactions + +On some occasions, a seemingly valid transaction may be dropped before it is +included in a block. This most often occurs during periods of network +congestion, when an RPC node fails to rebroadcast the transaction to the +[leader](/docs/terminology.md#leader). To an end-user, it may appear as if their +transaction disappears entirely. While RPC nodes are equipped with a generic +rebroadcasting algorithm, application developers are also capable of developing +their own custom rebroadcasting logic. + +## TLDR; + +- RPC nodes will attempt to rebroadcast transactions using a generic algorithm +- Application developers can implement their own custom rebroadcasting logic +- Developers should take advantage of the `maxRetries` parameter on the + `sendTransaction` JSON-RPC method +- Developers should enable preflight checks to raise errors before transactions + are submitted +- Before re-signing any transaction, it is **very important** to ensure that the + initial transaction's blockhash has expired + +## The Journey of a Transaction + +### How Clients Submit Transactions + +In Solana, there is no concept of a mempool. All transactions, whether they are +initiated programmatically or by an end-user, are efficiently routed to leaders +so that they can be processed into a block. There are two main ways in which a +transaction can be sent to leaders: + +1. By proxy via an RPC server and the + [sendTransaction](/docs/rpc/http/sendTransaction.mdx) JSON-RPC method +2. Directly to leaders via a + [TPU Client](https://docs.rs/solana-client/latest/solana_client/tpu_client/index.html) + +The vast majority of end-users will submit transactions via an RPC server. When +a client submits a transaction, the receiving RPC node will in turn attempt to +broadcast the transaction to both the current and next leaders. Until the +transaction is processed by a leader, there is no record of the transaction +outside of what the client and the relaying RPC nodes are aware of. In the case +of a TPU client, rebroadcast and leader forwarding is handled entirely by the +client software. + +![Overview of a transactions journey, from client to leader](/assets/docs/rt-tx-journey.png) + +### How RPC Nodes Broadcast Transactions + +After an RPC node receives a transaction via `sendTransaction`, it will convert +the transaction into a +[UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol) packet before +forwarding it to the relevant leaders. UDP allows validators to quickly +communicate with one another, but does not provide any guarantees regarding +transaction delivery. + +Because Solana's leader schedule is known in advance of every +[epoch](/docs/terminology.md#epoch) (~2 days), an RPC node will broadcast its +transaction directly to the current and next leaders. This is in contrast to +other gossip protocols such as Ethereum that propagate transactions randomly and +broadly across the entire network. By default, RPC nodes will try to forward +transactions to leaders every two seconds until either the transaction is +finalized or the transaction's blockhash expires (150 blocks or ~1 minute 19 +seconds as of the time of this writing). If the outstanding rebroadcast queue +size is greater than +[10,000 transactions](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/send-transaction-service/src/send_transaction_service.rs#L20), +newly submitted transactions are dropped. There are command-line +[arguments](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/validator/src/main.rs#L1172) +that RPC operators can adjust to change the default behavior of this retry +logic. + +When an RPC node broadcasts a transaction, it will attempt to forward the +transaction to a leader's +[Transaction Processing Unit (TPU)](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/validator.rs#L867). +The TPU processes transactions in five distinct phases: + +- [Fetch Stage](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/fetch_stage.rs#L21) +- [SigVerify Stage](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/tpu.rs#L91) +- [Banking Stage](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/banking_stage.rs#L249) +- [Proof of History Service](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/poh/src/poh_service.rs) +- [Broadcast Stage](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/tpu.rs#L136) + +![Overview of the Transaction Processing Unit (TPU)](/assets/docs/rt-tpu-jito-labs.png) + +Of these five phases, the Fetch Stage is responsible for receiving transactions. +Within the Fetch Stage, validators will categorize incoming transactions +according to three ports: + +- [tpu](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/gossip/src/contact_info.rs#L27) + handles regular transactions such as token transfers, NFT mints, and program + instructions +- [tpu_vote](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/gossip/src/contact_info.rs#L31) + focuses exclusively on voting transactions +- [tpu_forwards](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/gossip/src/contact_info.rs#L29) + forwards unprocessed packets to the next leader if the current leader is + unable to process all transactions + +For more information on the TPU, please refer to +[this excellent writeup by Jito Labs](https://jito-labs.medium.com/solana-validator-101-transaction-processing-90bcdc271143). + +## How Transactions Get Dropped + +Throughout a transaction's journey, there are a few scenarios in which the +transaction can be unintentionally dropped from the network. + +### Before a transaction is processed + +If the network drops a transaction, it will most likely do so before the +transaction is processed by a leader. UDP +[packet loss](https://en.wikipedia.org/wiki/Packet_loss) is the simplest reason +why this might occur. During times of intense network load, it's also possible +for validators to become overwhelmed by the sheer number of transactions +required for processing. While validators are equipped to forward surplus +transactions via `tpu_forwards`, there is a limit to the amount of data that can +be +[forwarded](https://github.com/solana-labs/solana/blob/master/core/src/banking_stage.rs#L389). +Furthermore, each forward is limited to a single hop between validators. That +is, transactions received on the `tpu_forwards` port are not forwarded on to +other validators. + +There are also two lesser known reasons why a transaction may be dropped before +it is processed. The first scenario involves transactions that are submitted via +an RPC pool. Occasionally, part of the RPC pool can be sufficiently ahead of the +rest of the pool. This can cause issues when nodes within the pool are required +to work together. In this example, the transaction's +[recentBlockhash](/docs/core/transactions.md#recent-blockhash) is queried from +the advanced part of the pool (Backend A). When the transaction is submitted to +the lagging part of the pool (Backend B), the nodes will not recognize the +advanced blockhash and will drop the transaction. This can be detected upon +transaction submission if developers enable +[preflight checks](/docs/rpc/http/sendTransaction.mdx) on `sendTransaction`. + +![Transaction dropped via an RPC Pool](/assets/docs/rt-dropped-via-rpc-pool.png) + +Temporary network forks can also result in dropped transactions. If a validator +is slow to replay its blocks within the Banking Stage, it may end up creating a +minority fork. When a client builds a transaction, it's possible for the +transaction to reference a `recentBlockhash` that only exists on the minority +fork. After the transaction is submitted, the cluster can then switch away from +its minority fork before the transaction is processed. In this scenario, the +transaction is dropped due to the blockhash not being found. + +![Transaction dropped due to minority fork (before processed)](/assets/docs/rt-dropped-minority-fork-pre-process.png) + +### After a transaction is processed and before it is finalized + +In the event a transaction references a `recentBlockhash` from a minority fork, +it's still possible for the transaction to be processed. In this case, however, +it would be processed by the leader on the minority fork. When this leader +attempts to share its processed transactions with the rest of the network, it +would fail to reach consensus with the majority of validators that do not +recognize the minority fork. At this time, the transaction would be dropped +before it could be finalized. + +![Transaction dropped due to minority fork (after processed)](/assets/docs/rt-dropped-minority-fork-post-process.png) + +## Handling Dropped Transactions + +While RPC nodes will attempt to rebroadcast transactions, the algorithm they +employ is generic and often ill-suited for the needs of specific applications. +To prepare for times of network congestion, application developers should +customize their own rebroadcasting logic. + +### An In-Depth Look at sendTransaction + +When it comes to submitting transactions, the `sendTransaction` RPC method is +the primary tool available to developers. `sendTransaction` is only responsible +for relaying a transaction from a client to an RPC node. If the node receives +the transaction, `sendTransaction` will return the transaction id that can be +used to track the transaction. A successful response does not indicate whether +the transaction will be processed or finalized by the cluster. + +### Request Parameters + +- `transaction`: `string` - fully-signed Transaction, as encoded string +- (optional) `configuration object`: `object` + - `skipPreflight`: `boolean` - if true, skip the preflight transaction checks + (default: false) + - (optional) `preflightCommitment`: `string` - + [Commitment](/docs/rpc/index.mdx#configuring-state-commitment) level to use + for preflight simulations against the bank slot (default: "finalized"). + - (optional) `encoding`: `string` - Encoding used for the transaction data. + Either "base58" (slow), or "base64". (default: "base58"). + - (optional) `maxRetries`: `usize` - Maximum number of times for the RPC node + to retry sending the transaction to the leader. If this parameter is not + provided, the RPC node will retry the transaction until it is finalized or + until the blockhash expires. + +**Response:** + +- `transaction id`: `string` - First transaction signature embedded in the + transaction, as base-58 encoded string. This transaction id can be used with + [`getSignatureStatuses`](/docs/rpc/http/getSignatureStatuses.mdx) to poll for + status updates. + +## Customizing Rebroadcast Logic + +In order to develop their own rebroadcasting logic, developers should take +advantage of `sendTransaction`'s `maxRetries` parameter. If provided, +`maxRetries` will override an RPC node's default retry logic, allowing +developers to manually control the retry process +[within reasonable bounds](https://github.com/solana-labs/solana/blob/98707baec2385a4f7114d2167ef6dfb1406f954f/validator/src/main.rs#L1258-L1274). + +A common pattern for manually retrying transactions involves temporarily storing +the `lastValidBlockHeight` that comes from +[getLatestBlockhash](/docs/rpc/http/getLatestBlockhash.mdx). Once stashed, an +application can then +[poll the cluster's blockheight](/docs/rpc/http/getBlockHeight.mdx) and manually +retry the transaction at an appropriate interval. In times of network +congestion, it's advantageous to set `maxRetries` to 0 and manually rebroadcast +via a custom algorithm. While some applications may employ an +[exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff) +algorithm, others such as [Mango](https://www.mango.markets/) opt to +[continuously resubmit](https://github.com/blockworks-foundation/mango-ui/blob/b6abfc6c13b71fc17ebbe766f50b8215fa1ec54f/src/utils/send.tsx#L713) +transactions at a constant interval until some timeout has occurred. + +```ts +import { + Keypair, + Connection, + LAMPORTS_PER_SOL, + SystemProgram, + Transaction, +} from "@solana/web3.js"; +import * as nacl from "tweetnacl"; + +const sleep = async (ms: number) => { + return new Promise(r => setTimeout(r, ms)); +}; + +(async () => { + const payer = Keypair.generate(); + const toAccount = Keypair.generate().publicKey; + + const connection = new Connection("http://127.0.0.1:8899", "confirmed"); + + const airdropSignature = await connection.requestAirdrop( + payer.publicKey, + LAMPORTS_PER_SOL, + ); + + await connection.confirmTransaction({ signature: airdropSignature }); + + const blockhashResponse = await connection.getLatestBlockhash(); + const lastValidBlockHeight = blockhashResponse.lastValidBlockHeight - 150; + + const transaction = new Transaction({ + feePayer: payer.publicKey, + blockhash: blockhashResponse.blockhash, + lastValidBlockHeight: lastValidBlockHeight, + }).add( + SystemProgram.transfer({ + fromPubkey: payer.publicKey, + toPubkey: toAccount, + lamports: 1000000, + }), + ); + const message = transaction.serializeMessage(); + const signature = nacl.sign.detached(message, payer.secretKey); + transaction.addSignature(payer.publicKey, Buffer.from(signature)); + const rawTransaction = transaction.serialize(); + let blockheight = await connection.getBlockHeight(); + + while (blockheight < lastValidBlockHeight) { + connection.sendRawTransaction(rawTransaction, { + skipPreflight: true, + }); + await sleep(500); + blockheight = await connection.getBlockHeight(); + } +})(); +``` + +When polling via `getLatestBlockhash`, applications should specify their +intended [commitment](/docs/rpc/index.mdx#configuring-state-commitment) level. +By setting its commitment to `confirmed` (voted on) or `finalized` (~30 blocks +after `confirmed`), an application can avoid polling a blockhash from a minority +fork. + +If an application has access to RPC nodes behind a load balancer, it can also +choose to divide its workload amongst specific nodes. RPC nodes that serve +data-intensive requests such as +[getProgramAccounts](/content/guides/javascript/get-program-accounts.md) may be +prone to falling behind and can be ill-suited for also forwarding transactions. +For applications that handle time-sensitive transactions, it may be prudent to +have dedicated nodes that only handle `sendTransaction`. + +### The Cost of Skipping Preflight + +By default, `sendTransaction` will perform three preflight checks prior to +submitting a transaction. Specifically, `sendTransaction` will: + +- Verify that all signatures are valid +- Check that the referenced blockhash is within the last 150 blocks +- Simulate the transaction against the bank slot specified by the + `preflightCommitment` + +In the event that any of these three preflight checks fail, `sendTransaction` +will raise an error prior to submitting the transaction. Preflight checks can +often be the difference between losing a transaction and allowing a client to +gracefully handle an error. To ensure that these common errors are accounted +for, it is recommended that developers keep `skipPreflight` set to `false`. + +### When to Re-Sign Transactions + +Despite all attempts to rebroadcast, there may be times in which a client is +required to re-sign a transaction. Before re-signing any transaction, it is +**very important** to ensure that the initial transaction's blockhash has +expired. If the initial blockhash is still valid, it is possible for both +transactions to be accepted by the network. To an end-user, this would appear as +if they unintentionally sent the same transaction twice. + +In Solana, a dropped transaction can be safely discarded once the blockhash it +references is older than the `lastValidBlockHeight` received from +`getLatestBlockhash`. Developers should keep track of this +`lastValidBlockHeight` by querying +[`getEpochInfo`](/docs/rpc/http/getEpochInfo.mdx) and comparing with +`blockHeight` in the response. Once a blockhash is invalidated, clients may +re-sign with a newly-queried blockhash. diff --git a/docs/uk/advanced/state-compression.md b/docs/uk/advanced/state-compression.md new file mode 100644 index 000000000..5e01a602e --- /dev/null +++ b/docs/uk/advanced/state-compression.md @@ -0,0 +1,339 @@ +--- +sidebarSortOrder: 4 +title: State Compression +description: + 'State Compression is the method of cheaply and securely storing + "fingerprints" of offchain data in the Solana leger, instead of expensive + accounts.' +--- + +On Solana, [State Compression](/docs/advanced/state-compression.md) is the +method of creating a "fingerprint" (or hash) of offchain data and storing this +fingerprint on-chain for secure verification. Effectively using the security of +the Solana ledger to securely validate offchain data, verifying it has not been +tampered with. + +This method of "compression" allows Solana programs and dApps to use cheap +blockchain [ledger](/docs/terminology.md#ledger) space, instead of the more +expensive [account](/docs/terminology.md#account) space, to securely store data. + +This is accomplished by using a special binary tree structure, known as a +[concurrent merkle tree](#what-is-a-concurrent-merkle-tree), to create a hash of +each piece of data (called a `leaf`), hashing those together, and only storing +this final hash on-chain. + +## What is State Compression? + +In simple terms, state compression uses "**_tree_**" structures to +cryptographically hash offchain data together, in a deterministic way, to +compute a single final hash that gets stored on-chain. + +These _trees_ are created in this "_deterministic_" process by: + +- taking any piece of data +- creating a hash of this data +- storing this hash as a `leaf` at the bottom of the tree +- each `leaf` pair is then hashed together, creating a `branch` +- each `branch` is then hashed together +- continually climbing the tree and hashing adjacent branches together +- once at the top of the tree, a final `root hash` is produced + +This `root hash` is then stored onchain, as a verifiable **_proof_** of all of +the data within every leaf. Allowing anyone to cryptographically verify all the +offchain data within the tree, while only actually storing a **minimal** amount +of data on-chain. Therefore, significantly reducing the cost to store/prove +large amounts of data due to this "state compression". + +## Merkle trees and concurrent merkle trees + +Solana's state compression used a special type of +[merkle tree](#what-is-a-merkle-tree) that allows for multiple changes to any +given tree to happen, while still maintaining the integrity and validity of the +tree. + +This special tree, known as a +"[concurrent merkle tree](#what-is-a-concurrent-merkle-tree)", effectively +retains a "changelog" of the tree on-chain. Allowing for multiple rapid changes +to the same tree (i.e. all in the same block), before a proof is invalidated. + +### What is a merkle tree? + +A [merkle tree](https://en.wikipedia.org/wiki/merkle_tree), sometimes called a +"hash tree", is a hash based binary tree structure where each `leaf` node is +represented as a cryptographic hash of its inner data. And every node that is +**not** a leaf, called a `branch`, is represented as a hash of its child leaf +hashes. + +Each branch is then also hashed together, climbing the tree, until eventually +only a single hash remains. This final hash, called the `root hash` or "root", +can then be used in combination with a "proof path" to verify any piece of data +stored within a leaf node. + +Once a final `root hash` has been computed, any piece of data stored within a +`leaf` node can be verified by rehashing the specific leaf's data and the hash +label of each adjacent branch climbing the tree (known as the `proof` or "proof +path"). Comparing this "rehash" to the `root hash` is the verification of the +underlying leaf data. If they match, the data is verified accurate. If they do +not match, the leaf data was changed. + +Whenever desired, the original leaf data can be changed by simply hashing the +**new leaf** data and recomputing the root hash in the same manner of the +original root. This **new root hash** is then used to verify any of the data, +and effectively invalidates the previous root hash and previous proof. +Therefore, each change to these _traditional merkle trees_ are required to be +performed in series. + +> This process of changing leaf data, and computing a new root hash can be a +> **very common** thing when using merkle trees! While it is one of the design +> points of the tree, it can result in one of the most notable drawbacks: rapid +> changes. + +### What is a Concurrent merkle tree? + +In high throughput applications, like within the +[Solana runtime](/docs/core/fees.md), requests to change an on-chain +_traditional merkle tree_ could be received by validators in relatively rapid +succession (e.g. within the same slot). Each leaf data change would still be +required to be performed in series. Resulting in each subsequent request for +change to fail, due to the root hash and proof being invalidated by the previous +change request in the slot. + +Enter, Concurrent merkle trees. + +A **Concurrent merkle tree** stores a **secure changelog** of the most recent +changes, their root hash, and the proof to derive it. This changelog "buffer" is +stored on-chain in an account specific to each tree, with a maximum number of +changelog "records" (aka `maxBufferSize`). + +When multiple leaf data change requests are received by validators in the same +slot, the on-chain _concurrent merkle tree_ can use this "changelog buffer" as a +source of truth for more acceptable proofs. Effectively allowing for up to +`maxBufferSize` changes to the same tree in the same slot. Significantly +boosting throughput. + +## Sizing a concurrent merkle tree + +When creating one of these on-chain trees, there are 3 values that will +determine the size of your tree, the cost to create your tree, and the number of +concurrent changes to your tree: + +1. max depth +2. max buffer size +3. canopy depth + +### Max depth + +The "max depth" of a tree is the **maximum number** of hops to get from any data +`leaf` to the `root` of the tree. + +Since merkle trees are binary trees, every leaf is connected to **only one** +other leaf; existing as a `leaf pair`. + +Therefore, the `maxDepth` of a tree is used to determine the maximum number of +nodes (aka pieces of data or `leafs`) to store within the tree using a simple +calculation: + +```text +nodes_count = 2 ^ maxDepth +``` + +Since a trees depth must be set at tree creation, you must decide how many +pieces of data you want your tree to store. Then using the simple calculation +above, you can determine the lowest `maxDepth` to store your data. + +#### Example 1: minting 100 nfts + +If you wanted to create a tree to store 100 compressed nfts, we will need a +minimum of "100 leafs" or "100 nodes". + +```text +// maxDepth=6 -> 64 nodes +2^6 = 64 + +// maxDepth=7 -> 128 nodes +2^7 = 128 +``` + +We must use a `maxDepth` of `7` to ensure we can store all of our data. + +#### Example 2: minting 15000 nfts + +If you wanted to create a tree to store 15000 compressed nfts, we will need a +minimum of "15000 leafs" or "15000 nodes". + +```text +// maxDepth=13 -> 8192 nodes +2^13 = 8192 + +// maxDepth=14 -> 16384 nodes +2^14 = 16384 +``` + +We must use a `maxDepth` of `14` to ensure we can store all of our data. + +#### The higher the max depth, the higher the cost + +The `maxDepth` value will be one of the primary drivers of cost when creating a +tree since you will pay this cost upfront at tree creation. The higher the max +tree depth, the more data fingerprints (aka hashes) you can store, the higher +the cost. + +### Max buffer size + +The "max buffer size" is effectively the maximum number of changes that can +occur on a tree, with the `root hash` still being valid. + +Due to the root hash effectively being a single hash of all leaf data, changing +any single leaf would invalidate the proof needed for all subsequent attempts to +change any leaf of a regular tree. + +But with a [concurrent tree](#what-is-a-concurrent-merkle-tree), there is +effectively a changelog of updates for these proofs. This changelog buffer is +sized and set at tree creation via this `maxBufferSize` value. + +### Canopy depth + +The "canopy depth," also known as the canopy size, refers to the number of proof +node levels that are cached or stored onchain for a given proof path. + +When performing an update action on a `leaf`, like transferring ownership (e.g. +selling a compressed NFT), the **complete** proof path must be used to verify +original ownership of the leaf and therefore allow for the update action. This +verification is performed using the **complete** proof path to correctly compute +the current `root hash` (or any cached `root hash` via the onchain "concurrent +buffer"). + +The larger a tree's max depth is, the more proof nodes are required to perform +this verification. For example, if your max depth is `14`, there are `14` total +proof nodes required to be used to verify. As a tree gets larger, the complete +proof path gets larger. + +Normally, each of these proof nodes would be required to be included within each +tree update transaction. Since each proof node value takes up `32 bytes` in a +transaction (similar to providing a Public Key), larger trees would very quickly +exceed the maximum transaction size limit. + +Enter the canopy. The canopy enables storing a set number of proof nodes on +chain (for any given proof path). Allowing for less proof nodes to be included +within each update transactions, therefore keeping the overall transaction size +below the limit. + +For example, a tree with a max depth of `14` would require `14` total proof +nodes. With a canopy of `10`, only `4` proof nodes are required to be submitted +per update transaction. + +![Canopy depth of 1 for a Concurrent Merkle Tree of max depth of 3](/assets/docs/compression/canopy-depth-1.png) + +Consider another example, this time with a tree of max depth `3`. If we want to +apply an action to one of the tree’s leaves—such as updating `R4`—we need to +provide proofs for `L4` and `R2`. However, we can omit `R1` since it is already +cached/stored onchain due to our canopy depth of `1`, which ensures that all +nodes at level 1 (`L1` and `R1`) are stored onchain. This results in a total of +2 required proofs. + +Therefore, the number of proofs required to update a leaf is equal to the max +depth minus the canopy depth. In this example, `3 - 1 = 2`. + +#### The larger the canopy depth value, the higher the cost + +The `canopyDepth` value is also a primary factor of cost when creating a tree +since you will pay this cost upfront at tree creation. The higher the canopy +depth, the more data proof nodes are stored onchain, the higher the cost. + +#### Smaller canopy limits composability + +While a tree's creation costs are higher with a higher canopy, having a lower +`canopyDepth` will require more proof nodes to be included within each update +transaction. The more nodes required to be submitted, the larger the transaction +size, and therefore the easier it is to exceed the transaction size limits. + +This will also be the case for any other Solana program or dApp that attempts to +interact with your tree/leafs. If your tree requires too many proof nodes +(because of a low canopy depth), then any other additional actions another +on-chain program **could** offer will be **limited** by their specific +instruction size plus your proof node list size. Limiting composability, and +potential additional utility for your specific tree. + +For example, if your tree is being used for compressed NFTs and has a very low +canopy depth, an NFT marketplace may only be able to support simple NFTs +transfers. And not be able to support an on-chain bidding system. + +## Cost of creating a tree + +The cost of creating a concurrent merkle tree is based on the tree's size +parameters: `maxDepth`, `maxBufferSize`, and `canopyDepth`. These values are all +used to calculate the on-chain storage (in bytes) required for a tree to exist +onchain. + +Once the required space (in bytes) has been calculated, and using the +[`getMinimumBalanceForRentExemption`](/docs/rpc/http/getminimumbalanceforrentexemption) +RPC method, request the cost (in lamports) to allocate this amount of bytes +on-chain. + +### Calculate tree cost in JavaScript + +Within the +[`@solana/spl-account-compression`](https://www.npmjs.com/package/@solana/spl-account-compression) +package, developers can use the +[`getConcurrentMerkleTreeAccountSize`](https://solana-labs.github.io/solana-program-library/account-compression/sdk/docs/modules/index.html#getConcurrentMerkleTreeAccountSize) +function to calculate the required space for a given tree size parameters. + +Then using the +[`getMinimumBalanceForRentExemption`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getMinimumBalanceForRentExemption) +function to get the final cost (in lamports) to allocate the required space for +the tree on-chain. + +Then determine the cost in lamports to make an account of this size rent exempt, +similar to any other account creation. + +```ts +// calculate the space required for the tree +const requiredSpace = getConcurrentMerkleTreeAccountSize( + maxDepth, + maxBufferSize, + canopyDepth, +); + +// get the cost (in lamports) to store the tree on-chain +const storageCost = + await connection.getMinimumBalanceForRentExemption(requiredSpace); +``` + +### Example costs + +Listed below are several example costs, for different tree sizes, including how +many leaf nodes are possible for each: + +**Example #1: 16,384 nodes costing 0.222 SOL** + +- max depth of `14` and max buffer size of `64` +- maximum number of leaf nodes: `16,384` +- canopy depth of `0` costs approximately `0.222 SOL` to create + +**Example #2: 16,384 nodes costing 1.134 SOL** + +- max depth of `14` and max buffer size of `64` +- maximum number of leaf nodes: `16,384` +- canopy depth of `11` costs approximately `1.134 SOL` to create + +**Example #3: 1,048,576 nodes costing 1.673 SOL** + +- max depth of `20` and max buffer size of `256` +- maximum number of leaf nodes: `1,048,576` +- canopy depth of `10` costs approximately `1.673 SOL` to create + +**Example #4: 1,048,576 nodes costing 15.814 SOL** + +- max depth of `20` and max buffer size of `256` +- maximum number of leaf nodes: `1,048,576` +- canopy depth of `15` costs approximately `15.814 SOL` to create + +## Compressed NFTs + +Compressed NFTs are one of the most popular use cases for State Compression on +Solana. With compression, a one million NFT collection could be minted for +`~50 SOL`, vice `~12,000 SOL` for its uncompressed equivalent collection. + +If you are interested in creating compressed NFTs yourself, read our developer +guide for +[minting and transferring compressed NFTs](/content/guides/javascript/compressed-nfts.md). diff --git a/docs/uk/advanced/versions.md b/docs/uk/advanced/versions.md new file mode 100644 index 000000000..c94013997 --- /dev/null +++ b/docs/uk/advanced/versions.md @@ -0,0 +1,191 @@ +--- +sidebarSortOrder: 3 +title: Versioned Transactions +description: + "Explore the core Solana concepts: transactions, versioned transactions, + enabling additional functionality in the Solana runtime, address lookup + tables, and more." +altRoutes: + - /docs/core/transactions/versions +--- + +Versioned Transactions are the new transaction format that allow for additional +functionality in the Solana runtime, including +[Address Lookup Tables](/docs/advanced/lookup-tables.md). + +While changes to onchain programs are **NOT** required to support the new +functionality of versioned transactions (or for backwards compatibility), +developers **WILL** need update their client side code to prevent +[errors due to different transaction versions](#max-supported-transaction-version). + +## Current Transaction Versions + +The Solana runtime supports two transaction versions: + +- `legacy` - older transaction format with no additional benefit +- `0` - added support for + [Address Lookup Tables](/docs/advanced/lookup-tables.md) + +## Max supported transaction version + +All RPC requests that return a transaction **_should_** specify the highest +version of transactions they will support in their application using the +`maxSupportedTransactionVersion` option, including +[`getBlock`](/docs/rpc/http/getBlock.mdx) and +[`getTransaction`](/docs/rpc/http/getTransaction.mdx). + +An RPC request will fail if a Versioned Transaction is returned that is higher +than the set `maxSupportedTransactionVersion`. (i.e. if a version `0` +transaction is returned when `legacy` is selected) + +> WARNING: If no `maxSupportedTransactionVersion` value is set, then only +> `legacy` transactions will be allowed in the RPC response. Therefore, your RPC +> requests **WILL** fail if any version `0` transactions are returned. + +## How to set max supported version + +You can set the `maxSupportedTransactionVersion` using both the +[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/) library +and JSON formatted requests directly to an RPC endpoint. + +### Using web3.js + +Using the +[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/) library, +you can retrieve the most recent block or get a specific transaction: + +```js +// connect to the `devnet` cluster and get the current `slot` +const connection = new web3.Connection(web3.clusterApiUrl("devnet")); +const slot = await connection.getSlot(); + +// get the latest block (allowing for v0 transactions) +const block = await connection.getBlock(slot, { + maxSupportedTransactionVersion: 0, +}); + +// get a specific transaction (allowing for v0 transactions) +const getTx = await connection.getTransaction( + "3jpoANiFeVGisWRY5UP648xRXs3iQasCHABPWRWnoEjeA93nc79WrnGgpgazjq4K9m8g2NJoyKoWBV1Kx5VmtwHQ", + { + maxSupportedTransactionVersion: 0, + }, +); +``` + +### JSON requests to the RPC + +Using a standard JSON formatted POST request, you can set the +`maxSupportedTransactionVersion` when retrieving a specific block: + +```shell +curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d \ +'{"jsonrpc": "2.0", "id":1, "method": "getBlock", "params": [430, { + "encoding":"json", + "maxSupportedTransactionVersion":0, + "transactionDetails":"full", + "rewards":false +}]}' +``` + +## How to create a Versioned Transaction + +Versioned transactions can be created similar to the older method of creating +transactions. There are differences in using certain libraries that should be +noted. + +Below is an example of how to create a Versioned Transaction, using the +`@solana/web3.js` library, to send perform a SOL transfer between two accounts. + +#### Notes: + +- `payer` is a valid `Keypair` wallet, funded with SOL +- `toAccount` a valid `Keypair` + +Firstly, import the web3.js library and create a `connection` to your desired +cluster. + +We then define the recent `blockhash` and `minRent` we will need for our +transaction and the account: + +```js +const web3 = require("@solana/web3.js"); + +// connect to the cluster and get the minimum rent for rent exempt status +const connection = new web3.Connection(web3.clusterApiUrl("devnet")); +let minRent = await connection.getMinimumBalanceForRentExemption(0); +let blockhash = await connection + .getLatestBlockhash() + .then(res => res.blockhash); +``` + +Create an `array` of all the `instructions` you desire to send in your +transaction. In this example below, we are creating a simple SOL transfer +instruction: + +```js +// create an array with your desired `instructions` +const instructions = [ + web3.SystemProgram.transfer({ + fromPubkey: payer.publicKey, + toPubkey: toAccount.publicKey, + lamports: minRent, + }), +]; +``` + +Next, construct a `MessageV0` formatted transaction message with your desired +`instructions`: + +```js +// create v0 compatible message +const messageV0 = new web3.TransactionMessage({ + payerKey: payer.publicKey, + recentBlockhash: blockhash, + instructions, +}).compileToV0Message(); +``` + +Then, create a new `VersionedTransaction`, passing in our v0 compatible message: + +```js +const transaction = new web3.VersionedTransaction(messageV0); + +// sign your transaction with the required `Signers` +transaction.sign([payer]); +``` + +You can sign the transaction by either: + +- passing an array of `signatures` into the `VersionedTransaction` method, or +- call the `transaction.sign()` method, passing an array of the required + `Signers` + +> NOTE: After calling the `transaction.sign()` method, all the previous +> transaction `signatures` will be fully replaced by new signatures created from +> the provided in `Signers`. + +After your `VersionedTransaction` has been signed by all required accounts, you +can send it to the cluster and `await` the response: + +```js +// send our v0 transaction to the cluster +const txId = await connection.sendTransaction(transaction); +console.log(`https://explorer.solana.com/tx/${txId}?cluster=devnet`); +``` + +> NOTE: Unlike `legacy` transactions, sending a `VersionedTransaction` via +> `sendTransaction` does **NOT** support transaction signing via passing in an +> array of `Signers` as the second parameter. You will need to sign the +> transaction before calling `connection.sendTransaction()`. + +## More Resources + +- using + [Versioned Transactions for Address Lookup Tables](/docs/advanced/lookup-tables.md#how-to-create-an-address-lookup-table) +- view an + [example of a v0 transaction](https://explorer.solana.com/tx/h9WQsqSUYhFvrbJWKFPaXximJpLf6Z568NW1j6PBn3f7GPzQXe9PYMYbmWSUFHwgnUmycDNbEX9cr6WjUWkUFKx/?cluster=devnet) + on Solana Explorer +- read the + [accepted proposal](https://docs.anza.xyz/proposals/versioned-transactions) + for Versioned Transaction and Address Lookup Tables diff --git a/docs/uk/clients/index.md b/docs/uk/clients/index.md new file mode 100644 index 000000000..bdafa7921 --- /dev/null +++ b/docs/uk/clients/index.md @@ -0,0 +1,5 @@ +--- +metaOnly: true +title: Solana Clients +sidebarSortOrder: 4 +--- diff --git a/docs/uk/clients/javascript-reference.md b/docs/uk/clients/javascript-reference.md new file mode 100644 index 000000000..cfa80f396 --- /dev/null +++ b/docs/uk/clients/javascript-reference.md @@ -0,0 +1,861 @@ +--- +title: Web3.js API Examples +description: + Learn how to interact with the Solana blockchain using the @solana/web3.js + library through practical code samples and explanations. +--- + +## Web3 API Reference Guide + +The `@solana/web3.js` library is a package that has coverage over the +[Solana JSON RPC API](/docs/rpc). + +You can find the full documentation for the `@solana/web3.js` library +[here](https://solana-labs.github.io/solana-web3.js/v1.x/). + +## General + +### Connection + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html) + +Connection is used to interact with the [Solana JSON RPC](/docs/rpc). You can +use Connection to confirm transactions, get account info, and more. + +You create a connection by defining the JSON RPC cluster endpoint and the +desired commitment. Once this is complete, you can use this connection object to +interact with any of the Solana JSON RPC API. + +#### Example Usage + +```javascript +const web3 = require("@solana/web3.js"); + +let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); + +let slot = await connection.getSlot(); +console.log(slot); +// 93186439 + +let blockTime = await connection.getBlockTime(slot); +console.log(blockTime); +// 1630747045 + +let block = await connection.getBlock(slot); +console.log(block); + +/* +{ + blockHeight: null, + blockTime: 1630747045, + blockhash: 'AsFv1aV5DGip9YJHHqVjrGg6EKk55xuyxn2HeiN9xQyn', + parentSlot: 93186438, + previousBlockhash: '11111111111111111111111111111111', + rewards: [], + transactions: [] +} +*/ + +let slotLeader = await connection.getSlotLeader(); +console.log(slotLeader); +//49AqLYbpJYc2DrzGUAH1fhWJy62yxBxpLEkfJwjKy2jr +``` + +The above example shows only a few of the methods on Connection. Please see the +[source generated docs](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html) +for the full list. + +### Transaction + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html) + +A transaction is used to interact with programs on the Solana blockchain. These +transactions are constructed with TransactionInstructions, containing all the +accounts possible to interact with, as well as any needed data or program +addresses. Each TransactionInstruction consists of keys, data, and a programId. +You can do multiple instructions in a single transaction, interacting with +multiple programs at once. + +#### Example Usage + +```javascript +const web3 = require("@solana/web3.js"); +const nacl = require("tweetnacl"); + +// Airdrop SOL for paying transactions +let payer = web3.Keypair.generate(); +let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); + +let airdropSignature = await connection.requestAirdrop( + payer.publicKey, + web3.LAMPORTS_PER_SOL, +); + +await connection.confirmTransaction({ signature: airdropSignature }); + +let toAccount = web3.Keypair.generate(); + +// Create Simple Transaction +let transaction = new web3.Transaction(); + +// Add an instruction to execute +transaction.add( + web3.SystemProgram.transfer({ + fromPubkey: payer.publicKey, + toPubkey: toAccount.publicKey, + lamports: 1000, + }), +); + +// Send and confirm transaction +// Note: feePayer is by default the first signer, or payer, if the parameter is not set +await web3.sendAndConfirmTransaction(connection, transaction, [payer]); + +// Alternatively, manually construct the transaction +let recentBlockhash = await connection.getLatestBlockhash(); +let manualTransaction = new web3.Transaction({ + recentBlockhash: recentBlockhash.blockhash, + feePayer: payer.publicKey, +}); +manualTransaction.add( + web3.SystemProgram.transfer({ + fromPubkey: payer.publicKey, + toPubkey: toAccount.publicKey, + lamports: 1000, + }), +); + +let transactionBuffer = manualTransaction.serializeMessage(); +let signature = nacl.sign.detached(transactionBuffer, payer.secretKey); + +manualTransaction.addSignature(payer.publicKey, signature); + +let isVerifiedSignature = manualTransaction.verifySignatures(); +console.log(`The signatures were verified: ${isVerifiedSignature}`); + +// The signatures were verified: true + +let rawTransaction = manualTransaction.serialize(); + +await web3.sendAndConfirmRawTransaction(connection, rawTransaction); +``` + +### Keypair + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Keypair.html) + +The keypair is used to create an account with a public key and secret key within +Solana. You can either generate, generate from a seed, or create from a secret +key. + +#### Example Usage + +```javascript +const { Keypair } = require("@solana/web3.js"); + +let account = Keypair.generate(); + +console.log(account.publicKey.toBase58()); +console.log(account.secretKey); + +// 2DVaHtcdTf7cm18Zm9VV8rKK4oSnjmTkKE6MiXe18Qsb +// Uint8Array(64) [ +// 152, 43, 116, 211, 207, 41, 220, 33, 193, 168, 118, +// 24, 176, 83, 206, 132, 47, 194, 2, 203, 186, 131, +// 197, 228, 156, 170, 154, 41, 56, 76, 159, 124, 18, +// 14, 247, 32, 210, 51, 102, 41, 43, 21, 12, 170, +// 166, 210, 195, 188, 60, 220, 210, 96, 136, 158, 6, +// 205, 189, 165, 112, 32, 200, 116, 164, 234 +// ] + +let seed = Uint8Array.from([ + 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, + 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, +]); +let accountFromSeed = Keypair.fromSeed(seed); + +console.log(accountFromSeed.publicKey.toBase58()); +console.log(accountFromSeed.secretKey); + +// 3LDverZtSC9Duw2wyGC1C38atMG49toPNW9jtGJiw9Ar +// Uint8Array(64) [ +// 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, +// 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, +// 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 34, +// 164, 6, 12, 9, 193, 196, 30, 148, 122, 175, 11, +// 28, 243, 209, 82, 240, 184, 30, 31, 56, 223, 236, +// 227, 60, 72, 215, 47, 208, 209, 162, 59 +// ] + +let accountFromSecret = Keypair.fromSecretKey(account.secretKey); + +console.log(accountFromSecret.publicKey.toBase58()); +console.log(accountFromSecret.secretKey); + +// 2DVaHtcdTf7cm18Zm9VV8rKK4oSnjmTkKE6MiXe18Qsb +// Uint8Array(64) [ +// 152, 43, 116, 211, 207, 41, 220, 33, 193, 168, 118, +// 24, 176, 83, 206, 132, 47, 194, 2, 203, 186, 131, +// 197, 228, 156, 170, 154, 41, 56, 76, 159, 124, 18, +// 14, 247, 32, 210, 51, 102, 41, 43, 21, 12, 170, +// 166, 210, 195, 188, 60, 220, 210, 96, 136, 158, 6, +// 205, 189, 165, 112, 32, 200, 116, 164, 234 +// ] +``` + +Using `generate` generates a random Keypair for use as an account on Solana. +Using `fromSeed`, you can generate a Keypair using a deterministic constructor. +`fromSecret` creates a Keypair from a secret Uint8array. You can see that the +publicKey for the `generate` Keypair and `fromSecret` Keypair are the same +because the secret from the `generate` Keypair is used in `fromSecret`. + +**Warning**: Do not use `fromSeed` unless you are creating a seed with high +entropy. Do not share your seed. Treat the seed like you would a private key. + +### PublicKey + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/PublicKey.html) + +PublicKey is used throughout `@solana/web3.js` in transactions, keypairs, and +programs. You require publickey when listing each account in a transaction and +as a general identifier on Solana. + +A PublicKey can be created with a base58 encoded string, buffer, Uint8Array, +number, and an array of numbers. + +#### Example Usage + +```javascript +const { Buffer } = require("buffer"); +const web3 = require("@solana/web3.js"); +const crypto = require("crypto"); + +// Create a PublicKey with a base58 encoded string +let base58publicKey = new web3.PublicKey( + "5xot9PVkphiX2adznghwrAuxGs2zeWisNSxMW6hU6Hkj", +); +console.log(base58publicKey.toBase58()); + +// 5xot9PVkphiX2adznghwrAuxGs2zeWisNSxMW6hU6Hkj + +// Create a Program Address +let highEntropyBuffer = crypto.randomBytes(31); +let programAddressFromKey = await web3.PublicKey.createProgramAddress( + [highEntropyBuffer.slice(0, 31)], + base58publicKey, +); +console.log(`Generated Program Address: ${programAddressFromKey.toBase58()}`); + +// Generated Program Address: 3thxPEEz4EDWHNxo1LpEpsAxZryPAHyvNVXJEJWgBgwJ + +// Find Program address given a PublicKey +let validProgramAddress = await web3.PublicKey.findProgramAddress( + [Buffer.from("", "utf8")], + programAddressFromKey, +); +console.log(`Valid Program Address: ${validProgramAddress}`); + +// Valid Program Address: C14Gs3oyeXbASzwUpqSymCKpEyccfEuSe8VRar9vJQRE,253 +``` + +### SystemProgram + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/SystemProgram.html) + +The SystemProgram grants the ability to create accounts, allocate account data, +assign an account to programs, work with nonce accounts, and transfer lamports. +You can use the SystemInstruction class to help with decoding and reading +individual instructions + +#### Example Usage + +```javascript +const web3 = require("@solana/web3.js"); + +// Airdrop SOL for paying transactions +let payer = web3.Keypair.generate(); +let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); + +let airdropSignature = await connection.requestAirdrop( + payer.publicKey, + web3.LAMPORTS_PER_SOL, +); + +await connection.confirmTransaction({ signature: airdropSignature }); + +// Allocate Account Data +let allocatedAccount = web3.Keypair.generate(); +let allocateInstruction = web3.SystemProgram.allocate({ + accountPubkey: allocatedAccount.publicKey, + space: 100, +}); +let transaction = new web3.Transaction().add(allocateInstruction); + +await web3.sendAndConfirmTransaction(connection, transaction, [ + payer, + allocatedAccount, +]); + +// Create Nonce Account +let nonceAccount = web3.Keypair.generate(); +let minimumAmountForNonceAccount = + await connection.getMinimumBalanceForRentExemption(web3.NONCE_ACCOUNT_LENGTH); +let createNonceAccountTransaction = new web3.Transaction().add( + web3.SystemProgram.createNonceAccount({ + fromPubkey: payer.publicKey, + noncePubkey: nonceAccount.publicKey, + authorizedPubkey: payer.publicKey, + lamports: minimumAmountForNonceAccount, + }), +); + +await web3.sendAndConfirmTransaction( + connection, + createNonceAccountTransaction, + [payer, nonceAccount], +); + +// Advance nonce - Used to create transactions as an account custodian +let advanceNonceTransaction = new web3.Transaction().add( + web3.SystemProgram.nonceAdvance({ + noncePubkey: nonceAccount.publicKey, + authorizedPubkey: payer.publicKey, + }), +); + +await web3.sendAndConfirmTransaction(connection, advanceNonceTransaction, [ + payer, +]); + +// Transfer lamports between accounts +let toAccount = web3.Keypair.generate(); + +let transferTransaction = new web3.Transaction().add( + web3.SystemProgram.transfer({ + fromPubkey: payer.publicKey, + toPubkey: toAccount.publicKey, + lamports: 1000, + }), +); +await web3.sendAndConfirmTransaction(connection, transferTransaction, [payer]); + +// Assign a new account to a program +let programId = web3.Keypair.generate(); +let assignedAccount = web3.Keypair.generate(); + +let assignTransaction = new web3.Transaction().add( + web3.SystemProgram.assign({ + accountPubkey: assignedAccount.publicKey, + programId: programId.publicKey, + }), +); + +await web3.sendAndConfirmTransaction(connection, assignTransaction, [ + payer, + assignedAccount, +]); +``` + +### Secp256k1Program + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Secp256k1Program.html) + +The Secp256k1Program is used to verify Secp256k1 signatures, which are used by +both Bitcoin and Ethereum. + +#### Example Usage + +```javascript +const { keccak_256 } = require("js-sha3"); +const web3 = require("@solana/web3.js"); +const secp256k1 = require("secp256k1"); + +// Create a Ethereum Address from secp256k1 +let secp256k1PrivateKey; +do { + secp256k1PrivateKey = web3.Keypair.generate().secretKey.slice(0, 32); +} while (!secp256k1.privateKeyVerify(secp256k1PrivateKey)); + +let secp256k1PublicKey = secp256k1 + .publicKeyCreate(secp256k1PrivateKey, false) + .slice(1); + +let ethAddress = + web3.Secp256k1Program.publicKeyToEthAddress(secp256k1PublicKey); +console.log(`Ethereum Address: 0x${ethAddress.toString("hex")}`); + +// Ethereum Address: 0xadbf43eec40694eacf36e34bb5337fba6a2aa8ee + +// Fund a keypair to create instructions +let fromPublicKey = web3.Keypair.generate(); +let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); + +let airdropSignature = await connection.requestAirdrop( + fromPublicKey.publicKey, + web3.LAMPORTS_PER_SOL, +); + +await connection.confirmTransaction({ signature: airdropSignature }); + +// Sign Message with Ethereum Key +let plaintext = Buffer.from("string address"); +let plaintextHash = Buffer.from(keccak_256.update(plaintext).digest()); +let { signature, recid: recoveryId } = secp256k1.ecdsaSign( + plaintextHash, + secp256k1PrivateKey, +); + +// Create transaction to verify the signature +let transaction = new Transaction().add( + web3.Secp256k1Program.createInstructionWithEthAddress({ + ethAddress: ethAddress.toString("hex"), + plaintext, + signature, + recoveryId, + }), +); + +// Transaction will succeed if the message is verified to be signed by the address +await web3.sendAndConfirmTransaction(connection, transaction, [fromPublicKey]); +``` + +### Message + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Message.html) + +Message is used as another way to construct transactions. You can construct a +message using the accounts, header, instructions, and recentBlockhash that are a +part of a transaction. A [Transaction](/docs/clients/javascript.md#Transaction) +is a Message plus the list of required signatures required to execute the +transaction. + +#### Example Usage + +```javascript +const { Buffer } = require("buffer"); +const bs58 = require("bs58"); +const web3 = require("@solana/web3.js"); + +let toPublicKey = web3.Keypair.generate().publicKey; +let fromPublicKey = web3.Keypair.generate(); + +let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); + +let airdropSignature = await connection.requestAirdrop( + fromPublicKey.publicKey, + web3.LAMPORTS_PER_SOL, +); + +await connection.confirmTransaction({ signature: airdropSignature }); + +let type = web3.SYSTEM_INSTRUCTION_LAYOUTS.Transfer; +let data = Buffer.alloc(type.layout.span); +let layoutFields = Object.assign({ instruction: type.index }); +type.layout.encode(layoutFields, data); + +let recentBlockhash = await connection.getRecentBlockhash(); + +let messageParams = { + accountKeys: [ + fromPublicKey.publicKey.toString(), + toPublicKey.toString(), + web3.SystemProgram.programId.toString(), + ], + header: { + numReadonlySignedAccounts: 0, + numReadonlyUnsignedAccounts: 1, + numRequiredSignatures: 1, + }, + instructions: [ + { + accounts: [0, 1], + data: bs58.encode(data), + programIdIndex: 2, + }, + ], + recentBlockhash, +}; + +let message = new web3.Message(messageParams); + +let transaction = web3.Transaction.populate(message, [ + fromPublicKey.publicKey.toString(), +]); + +await web3.sendAndConfirmTransaction(connection, transaction, [fromPublicKey]); +``` + +### Struct + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Struct.html) + +The struct class is used to create Rust compatible structs in javascript. This +class is only compatible with Borsh encoded Rust structs. + +#### Example Usage + +Struct in Rust: + +```rust +pub struct Fee { + pub denominator: u64, + pub numerator: u64, +} +``` + +Using web3: + +```javascript +import BN from "bn.js"; +import { Struct } from "@solana/web3.js"; + +export class Fee extends Struct { + denominator: BN; + numerator: BN; +} +``` + +### Enum + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Enum.html) + +The Enum class is used to represent a Rust compatible Enum in javascript. The +enum will just be a string representation if logged but can be properly +encoded/decoded when used in conjunction with +[Struct](/docs/clients/javascript.md#Struct). This class is only compatible with +Borsh encoded Rust enumerations. + +#### Example Usage + +Rust: + +```rust +pub enum AccountType { + Uninitialized, + StakePool, + ValidatorList, +} +``` + +Web3: + +```javascript +import { Enum } from "@solana/web3.js"; + +export class AccountType extends Enum {} +``` + +### NonceAccount + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/NonceAccount.html) + +Normally a transaction is rejected if a transaction's `recentBlockhash` field is +too old. To provide for certain custodial services, Nonce Accounts are used. +Transactions which use a `recentBlockhash` captured on-chain by a Nonce Account +do not expire as long at the Nonce Account is not advanced. + +You can create a nonce account by first creating a normal account, then using +`SystemProgram` to make the account a Nonce Account. + +#### Example Usage + +```javascript +const web3 = require("@solana/web3.js"); + +// Create connection +let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); + +// Generate accounts +let account = web3.Keypair.generate(); +let nonceAccount = web3.Keypair.generate(); + +// Fund account +let airdropSignature = await connection.requestAirdrop( + account.publicKey, + web3.LAMPORTS_PER_SOL, +); + +await connection.confirmTransaction({ signature: airdropSignature }); + +// Get Minimum amount for rent exemption +let minimumAmount = await connection.getMinimumBalanceForRentExemption( + web3.NONCE_ACCOUNT_LENGTH, +); + +// Form CreateNonceAccount transaction +let transaction = new web3.Transaction().add( + web3.SystemProgram.createNonceAccount({ + fromPubkey: account.publicKey, + noncePubkey: nonceAccount.publicKey, + authorizedPubkey: account.publicKey, + lamports: minimumAmount, + }), +); +// Create Nonce Account +await web3.sendAndConfirmTransaction(connection, transaction, [ + account, + nonceAccount, +]); + +let nonceAccountData = await connection.getNonce( + nonceAccount.publicKey, + "confirmed", +); + +console.log(nonceAccountData); +// NonceAccount { +// authorizedPubkey: PublicKey { +// _bn: +// }, +// nonce: '93zGZbhMmReyz4YHXjt2gHsvu5tjARsyukxD4xnaWaBq', +// feeCalculator: { lamportsPerSignature: 5000 } +// } + +let nonceAccountInfo = await connection.getAccountInfo( + nonceAccount.publicKey, + "confirmed", +); + +let nonceAccountFromInfo = web3.NonceAccount.fromAccountData( + nonceAccountInfo.data, +); + +console.log(nonceAccountFromInfo); +// NonceAccount { +// authorizedPubkey: PublicKey { +// _bn: +// }, +// nonce: '93zGZbhMmReyz4YHXjt2gHsvu5tjARsyukxD4xnaWaBq', +// feeCalculator: { lamportsPerSignature: 5000 } +// } +``` + +The above example shows both how to create a `NonceAccount` using +`SystemProgram.createNonceAccount`, as well as how to retrieve the +`NonceAccount` from accountInfo. Using the nonce, you can create transactions +offline with the nonce in place of the `recentBlockhash`. + +### VoteAccount + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/VoteAccount.html) + +Vote account is an object that grants the capability of decoding vote accounts +from the native vote account program on the network. + +#### Example Usage + +```javascript +const web3 = require("@solana/web3.js"); + +let voteAccountInfo = await connection.getProgramAccounts(web3.VOTE_PROGRAM_ID); +let voteAccountFromData = web3.VoteAccount.fromAccountData( + voteAccountInfo[0].account.data, +); +console.log(voteAccountFromData); +/* +VoteAccount { + nodePubkey: PublicKey { + _bn: + }, + authorizedWithdrawer: PublicKey { + _bn: + }, + commission: 10, + rootSlot: 104570885, + votes: [ + { slot: 104570886, confirmationCount: 31 }, + { slot: 104570887, confirmationCount: 30 }, + { slot: 104570888, confirmationCount: 29 }, + { slot: 104570889, confirmationCount: 28 }, + { slot: 104570890, confirmationCount: 27 }, + { slot: 104570891, confirmationCount: 26 }, + { slot: 104570892, confirmationCount: 25 }, + { slot: 104570893, confirmationCount: 24 }, + { slot: 104570894, confirmationCount: 23 }, + ... + ], + authorizedVoters: [ { epoch: 242, authorizedVoter: [PublicKey] } ], + priorVoters: [ + [Object], [Object], [Object], + [Object], [Object], [Object], + [Object], [Object], [Object], + [Object], [Object], [Object], + [Object], [Object], [Object], + [Object], [Object], [Object], + [Object], [Object], [Object], + [Object], [Object], [Object], + [Object], [Object], [Object], + [Object], [Object], [Object], + [Object], [Object] + ], + epochCredits: [ + { epoch: 179, credits: 33723163, prevCredits: 33431259 }, + { epoch: 180, credits: 34022643, prevCredits: 33723163 }, + { epoch: 181, credits: 34331103, prevCredits: 34022643 }, + { epoch: 182, credits: 34619348, prevCredits: 34331103 }, + { epoch: 183, credits: 34880375, prevCredits: 34619348 }, + { epoch: 184, credits: 35074055, prevCredits: 34880375 }, + { epoch: 185, credits: 35254965, prevCredits: 35074055 }, + { epoch: 186, credits: 35437863, prevCredits: 35254965 }, + { epoch: 187, credits: 35672671, prevCredits: 35437863 }, + { epoch: 188, credits: 35950286, prevCredits: 35672671 }, + { epoch: 189, credits: 36228439, prevCredits: 35950286 }, + ... + ], + lastTimestamp: { slot: 104570916, timestamp: 1635730116 } +} +*/ +``` + +## Staking + +### StakeProgram + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/StakeProgram.html) + +The StakeProgram facilitates staking SOL and delegating them to any validators +on the network. You can use StakeProgram to create a stake account, stake some +SOL, authorize accounts for withdrawal of your stake, deactivate your stake, and +withdraw your funds. The StakeInstruction class is used to decode and read more +instructions from transactions calling the StakeProgram + +#### Example Usage + +```javascript +const web3 = require("@solana/web3.js"); + +// Fund a key to create transactions +let fromPublicKey = web3.Keypair.generate(); +let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); + +let airdropSignature = await connection.requestAirdrop( + fromPublicKey.publicKey, + web3.LAMPORTS_PER_SOL, +); +await connection.confirmTransaction({ signature: airdropSignature }); + +// Create Account +let stakeAccount = web3.Keypair.generate(); +let authorizedAccount = web3.Keypair.generate(); +/* Note: This is the minimum amount for a stake account -- Add additional Lamports for staking + For example, we add 50 lamports as part of the stake */ +let lamportsForStakeAccount = + (await connection.getMinimumBalanceForRentExemption( + web3.StakeProgram.space, + )) + 50; + +let createAccountTransaction = web3.StakeProgram.createAccount({ + fromPubkey: fromPublicKey.publicKey, + authorized: new web3.Authorized( + authorizedAccount.publicKey, + authorizedAccount.publicKey, + ), + lamports: lamportsForStakeAccount, + lockup: new web3.Lockup(0, 0, fromPublicKey.publicKey), + stakePubkey: stakeAccount.publicKey, +}); +await web3.sendAndConfirmTransaction(connection, createAccountTransaction, [ + fromPublicKey, + stakeAccount, +]); + +// Check that stake is available +let stakeBalance = await connection.getBalance(stakeAccount.publicKey); +console.log(`Stake balance: ${stakeBalance}`); +// Stake balance: 2282930 + +// We can verify the state of our stake. This may take some time to become active +let stakeState = await connection.getStakeActivation(stakeAccount.publicKey); +console.log(`Stake state: ${stakeState.state}`); +// Stake state: inactive + +// To delegate our stake, we get the current vote accounts and choose the first +let voteAccounts = await connection.getVoteAccounts(); +let voteAccount = voteAccounts.current.concat(voteAccounts.delinquent)[0]; +let votePubkey = new web3.PublicKey(voteAccount.votePubkey); + +// We can then delegate our stake to the voteAccount +let delegateTransaction = web3.StakeProgram.delegate({ + stakePubkey: stakeAccount.publicKey, + authorizedPubkey: authorizedAccount.publicKey, + votePubkey: votePubkey, +}); +await web3.sendAndConfirmTransaction(connection, delegateTransaction, [ + fromPublicKey, + authorizedAccount, +]); + +// To withdraw our funds, we first have to deactivate the stake +let deactivateTransaction = web3.StakeProgram.deactivate({ + stakePubkey: stakeAccount.publicKey, + authorizedPubkey: authorizedAccount.publicKey, +}); +await web3.sendAndConfirmTransaction(connection, deactivateTransaction, [ + fromPublicKey, + authorizedAccount, +]); + +// Once deactivated, we can withdraw our funds +let withdrawTransaction = web3.StakeProgram.withdraw({ + stakePubkey: stakeAccount.publicKey, + authorizedPubkey: authorizedAccount.publicKey, + toPubkey: fromPublicKey.publicKey, + lamports: stakeBalance, +}); + +await web3.sendAndConfirmTransaction(connection, withdrawTransaction, [ + fromPublicKey, + authorizedAccount, +]); +``` + +### Authorized + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Authorized.html) + +Authorized is an object used when creating an authorized account for staking +within Solana. You can designate a `staker` and `withdrawer` separately, +allowing for a different account to withdraw other than the staker. + +You can find more usage of the `Authorized` object under +[`StakeProgram`](/docs/clients/javascript.md#StakeProgram) + +### Lockup + +[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Lockup.html) + +Lockup is used in conjunction with the +[StakeProgram](/docs/clients/javascript.md#StakeProgram) to create an account. +The Lockup is used to determine how long the stake will be locked, or unable to +be retrieved. If the Lockup is set to 0 for both epoch and the Unix timestamp, +the lockup will be disabled for the stake account. + +#### Example Usage + +```javascript +const { + Authorized, + Keypair, + Lockup, + StakeProgram, +} = require("@solana/web3.js"); + +let account = Keypair.generate(); +let stakeAccount = Keypair.generate(); +let authorized = new Authorized(account.publicKey, account.publicKey); +let lockup = new Lockup(0, 0, account.publicKey); + +let createStakeAccountInstruction = StakeProgram.createAccount({ + fromPubkey: account.publicKey, + authorized: authorized, + lamports: 1000, + lockup: lockup, + stakePubkey: stakeAccount.publicKey, +}); +``` + +The above code creates a `createStakeAccountInstruction` to be used when +creating an account with the `StakeProgram`. The Lockup is set to 0 for both the +epoch and Unix timestamp, disabling lockup for the account. + +See [StakeProgram](/docs/clients/javascript.md#StakeProgram) for more. diff --git a/docs/uk/clients/javascript.md b/docs/uk/clients/javascript.md new file mode 100644 index 000000000..6d4932896 --- /dev/null +++ b/docs/uk/clients/javascript.md @@ -0,0 +1,409 @@ +--- +sidebarLabel: JavaScript / TypeScript +title: JavaScript Client for Solana +sidebarSortOrder: 2 +description: + Learn how to interact with Solana using the JavaScript/TypeScript client + library (@solana/web3.js). This guide covers wallet connections, transactions, + and custom program interactions with code examples. +--- + +## What is Solana-Web3.js? + +The Solana-Web3.js library aims to provide complete coverage of Solana. The +library was built on top of the [Solana JSON RPC API](/docs/rpc). + +You can find the full documentation for the `@solana/web3.js` library +[here](https://solana-labs.github.io/solana-web3.js/v1.x/). + +## Common Terminology + +| Term | Definition | +| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Program | Stateless executable code written to interpret instructions. Programs are capable of performing actions based on the instructions provided. | +| Instruction | The smallest unit of a program that a client can include in a transaction. Within its processing code, an instruction may contain one or more cross-program invocations. | +| Transaction | One or more instructions signed by the client using one or more Keypairs and executed atomically with only two possible outcomes: success or failure. | + +For the full list of terms, see +[Solana terminology](/docs/terminology.md#cross-program-invocation-cpi) + +## Getting Started + +### Installation + +#### yarn + +```shell +yarn add @solana/web3.js@1 +``` + +#### npm + +```shell +npm install --save @solana/web3.js@1 +``` + +#### Bundle + +```html + + + + + +``` + +### Usage + +#### Javascript + +```javascript +const solanaWeb3 = require("@solana/web3.js"); +console.log(solanaWeb3); +``` + +#### ES6 + +```javascript +import * as solanaWeb3 from "@solana/web3.js"; +console.log(solanaWeb3); +``` + +#### Browser Bundle + +```javascript +// solanaWeb3 is provided in the global namespace by the bundle script +console.log(solanaWeb3); +``` + +## Quickstart + +### Connecting to a Wallet + +To allow users to use your dApp or application on Solana, they will need to get +access to their Keypair. A Keypair is a private key with a matching public key, +used to sign transactions. + +There are two ways to obtain a Keypair: + +1. Generate a new Keypair +2. Obtain a Keypair using the secret key + +You can obtain a new Keypair with the following: + +```javascript +const { Keypair } = require("@solana/web3.js"); + +let keypair = Keypair.generate(); +``` + +This will generate a brand new Keypair for a user to fund and use within your +application. + +You can allow entry of the secretKey using a textbox, and obtain the Keypair +with `Keypair.fromSecretKey(secretKey)`. + +```javascript +const { Keypair } = require("@solana/web3.js"); + +let secretKey = Uint8Array.from([ + 202, 171, 192, 129, 150, 189, 204, 241, 142, 71, 205, 2, 81, 97, 2, 176, 48, + 81, 45, 1, 96, 138, 220, 132, 231, 131, 120, 77, 66, 40, 97, 172, 91, 245, 84, + 221, 157, 190, 9, 145, 176, 130, 25, 43, 72, 107, 190, 229, 75, 88, 191, 136, + 7, 167, 109, 91, 170, 164, 186, 15, 142, 36, 12, 23, +]); + +let keypair = Keypair.fromSecretKey(secretKey); +``` + +Many wallets today allow users to bring their Keypair using a variety of +extensions or web wallets. The general recommendation is to use wallets, not +Keypairs, to sign transactions. The wallet creates a layer of separation between +the dApp and the Keypair, ensuring that the dApp never has access to the secret +key. You can find ways to connect to external wallets with the +[wallet-adapter](https://github.com/solana-labs/wallet-adapter) library. + +### Creating and Sending Transactions + +To interact with programs on Solana, you create, sign, and send transactions to +the network. Transactions are collections of instructions with signatures. The +order that instructions exist in a transaction determines the order they are +executed. + +A transaction in Solana-Web3.js is created using the +[`Transaction`](/docs/clients/javascript.md#Transaction) object and adding +desired messages, addresses, or instructions. + +Take the example of a transfer transaction: + +```javascript +const { + Keypair, + Transaction, + SystemProgram, + LAMPORTS_PER_SOL, +} = require("@solana/web3.js"); + +let fromKeypair = Keypair.generate(); +let toKeypair = Keypair.generate(); +let transaction = new Transaction(); + +transaction.add( + SystemProgram.transfer({ + fromPubkey: fromKeypair.publicKey, + toPubkey: toKeypair.publicKey, + lamports: LAMPORTS_PER_SOL, + }), +); +``` + +The above code achieves creating a transaction ready to be signed and +broadcasted to the network. The `SystemProgram.transfer` instruction was added +to the transaction, containing the amount of lamports to send, and the `to` and +`from` public keys. + +All that is left is to sign the transaction with keypair and send it over the +network. You can accomplish sending a transaction by using +`sendAndConfirmTransaction` if you wish to alert the user or do something after +a transaction is finished, or use `sendTransaction` if you don't need to wait +for the transaction to be confirmed. + +```javascript +const { + sendAndConfirmTransaction, + clusterApiUrl, + Connection, +} = require("@solana/web3.js"); + +let keypair = Keypair.generate(); +let connection = new Connection(clusterApiUrl("testnet")); + +sendAndConfirmTransaction(connection, transaction, [keypair]); +``` + +The above code takes in a `TransactionInstruction` using `SystemProgram`, +creates a `Transaction`, and sends it over the network. You use `Connection` in +order to define which Solana network you are connecting to, namely +`mainnet-beta`, `testnet`, or `devnet`. + +### Interacting with Custom Programs + +The previous section visits sending basic transactions. In Solana everything you +do interacts with different programs, including the previous section's transfer +transaction. At the time of writing programs on Solana are either written in +Rust or C. + +Let's look at the `SystemProgram`. The method signature for allocating space in +your account on Solana in Rust looks like this: + +```rust +pub fn allocate( + pubkey: &Pubkey, + space: u64 +) -> Instruction +``` + +In Solana when you want to interact with a program you must first know all the +accounts you will be interacting with. + +You must always provide every account that the program will be interacting +within the instruction. Not only that, but you must provide whether or not the +account is `isSigner` or `isWritable`. + +In the `allocate` method above, a single account `pubkey` is required, as well +as an amount of `space` for allocation. We know that the `allocate` method +writes to the account by allocating space within it, making the `pubkey` +required to be `isWritable`. `isSigner` is required when you are designating the +account that is running the instruction. In this case, the signer is the account +calling to allocate space within itself. + +Let's look at how to call this instruction using solana-web3.js: + +```javascript +let keypair = web3.Keypair.generate(); +let payer = web3.Keypair.generate(); +let connection = new web3.Connection(web3.clusterApiUrl("testnet")); + +let airdropSignature = await connection.requestAirdrop( + payer.publicKey, + web3.LAMPORTS_PER_SOL, +); + +await connection.confirmTransaction({ signature: airdropSignature }); +``` + +First, we set up the account Keypair and connection so that we have an account +to make allocate on the testnet. We also create a payer Keypair and airdrop some +SOL so we can pay for the allocate transaction. + +```javascript +let allocateTransaction = new web3.Transaction({ + feePayer: payer.publicKey, +}); +let keys = [{ pubkey: keypair.publicKey, isSigner: true, isWritable: true }]; +let params = { space: 100 }; +``` + +We create the transaction `allocateTransaction`, keys, and params objects. +`feePayer` is an optional field when creating a transaction that specifies who +is paying for the transaction, defaulting to the pubkey of the first signer in +the transaction. `keys` represents all accounts that the program's `allocate` +function will interact with. Since the `allocate` function also required space, +we created `params` to be used later when invoking the `allocate` function. + +```javascript +let allocateStruct = { + index: 8, + layout: struct([u32("instruction"), ns64("space")]), +}; +``` + +The above is created using `u32` and `ns64` from `@solana/buffer-layout` to +facilitate the payload creation. The `allocate` function takes in the parameter +`space`. To interact with the function we must provide the data as a Buffer +format. The `buffer-layout` library helps with allocating the buffer and +encoding it correctly for Rust programs on Solana to interpret. + +Let's break down this struct. + +```javascript +{ + index: 8, /* <-- */ + layout: struct([ + u32('instruction'), + ns64('space'), + ]) +} +``` + +`index` is set to 8 because the function `allocate` is in the 8th position in +the instruction enum for `SystemProgram`. + +```rust +/* https://github.com/solana-labs/solana/blob/21bc43ed58c63c827ba4db30426965ef3e807180/sdk/program/src/system_instruction.rs#L142-L305 */ +pub enum SystemInstruction { + /** 0 **/CreateAccount {/**/}, + /** 1 **/Assign {/**/}, + /** 2 **/Transfer {/**/}, + /** 3 **/CreateAccountWithSeed {/**/}, + /** 4 **/AdvanceNonceAccount, + /** 5 **/WithdrawNonceAccount(u64), + /** 6 **/InitializeNonceAccount(Pubkey), + /** 7 **/AuthorizeNonceAccount(Pubkey), + /** 8 **/Allocate {/**/}, + /** 9 **/AllocateWithSeed {/**/}, + /** 10 **/AssignWithSeed {/**/}, + /** 11 **/TransferWithSeed {/**/}, + /** 12 **/UpgradeNonceAccount, +} +``` + +Next up is `u32('instruction')`. + +```javascript +{ + index: 8, + layout: struct([ + u32('instruction'), /* <-- */ + ns64('space'), + ]) +} +``` + +The `layout` in the allocate struct must always have `u32('instruction')` first +when you are using it to call an instruction. + +```javascript +{ + index: 8, + layout: struct([ + u32('instruction'), + ns64('space'), /* <-- */ + ]) +} +``` + +`ns64('space')` is the argument for the `allocate` function. You can see in the +original `allocate` function in Rust that space was of the type `u64`. `u64` is +an unsigned 64bit integer. Javascript by default only provides up to 53bit +integers. `ns64` comes from `@solana/buffer-layout` to help with type +conversions between Rust and Javascript. You can find more type conversions +between Rust and Javascript at +[solana-labs/buffer-layout](https://github.com/solana-labs/buffer-layout). + +```javascript +let data = Buffer.alloc(allocateStruct.layout.span); +let layoutFields = Object.assign({ instruction: allocateStruct.index }, params); +allocateStruct.layout.encode(layoutFields, data); +``` + +Using the previously created bufferLayout, we can allocate a data buffer. We +then assign our params `{ space: 100 }` so that it maps correctly to the layout, +and encode it to the data buffer. Now the data is ready to be sent to the +program. + +```javascript +allocateTransaction.add( + new web3.TransactionInstruction({ + keys, + programId: web3.SystemProgram.programId, + data, + }), +); + +await web3.sendAndConfirmTransaction(connection, allocateTransaction, [ + payer, + keypair, +]); +``` + +Finally, we add the transaction instruction with all the account keys, payer, +data, and programId and broadcast the transaction to the network. + +The full code can be found below. + +```javascript +const { struct, u32, ns64 } = require("@solana/buffer-layout"); +const { Buffer } = require("buffer"); +const web3 = require("@solana/web3.js"); + +let keypair = web3.Keypair.generate(); +let payer = web3.Keypair.generate(); + +let connection = new web3.Connection(web3.clusterApiUrl("testnet")); + +let airdropSignature = await connection.requestAirdrop( + payer.publicKey, + web3.LAMPORTS_PER_SOL, +); + +await connection.confirmTransaction({ signature: airdropSignature }); + +let allocateTransaction = new web3.Transaction({ + feePayer: payer.publicKey, +}); +let keys = [{ pubkey: keypair.publicKey, isSigner: true, isWritable: true }]; +let params = { space: 100 }; + +let allocateStruct = { + index: 8, + layout: struct([u32("instruction"), ns64("space")]), +}; + +let data = Buffer.alloc(allocateStruct.layout.span); +let layoutFields = Object.assign({ instruction: allocateStruct.index }, params); +allocateStruct.layout.encode(layoutFields, data); + +allocateTransaction.add( + new web3.TransactionInstruction({ + keys, + programId: web3.SystemProgram.programId, + data, + }), +); + +await web3.sendAndConfirmTransaction(connection, allocateTransaction, [ + payer, + keypair, +]); +``` diff --git a/docs/uk/clients/rust.md b/docs/uk/clients/rust.md new file mode 100644 index 000000000..7dd221995 --- /dev/null +++ b/docs/uk/clients/rust.md @@ -0,0 +1,53 @@ +--- +sidebarLabel: Rust +title: Rust Client for Solana +sidebarSortOrder: 1 +description: Learn how to use Solana's Rust crates for development. +--- + +Solana's Rust crates are +[published to crates.io](https://crates.io/search?q=solana-) and can be found +[on docs.rs](https://docs.rs/releases/search?query=solana-) with the `solana-` +prefix. + + + +To quickly get started with Solana development and build your first Rust +program, take a look at these detailed quick start guides: + +- [Build and deploy your first Solana program using only your browser](/content/guides/getstarted/hello-world-in-your-browser.md). + No installation needed. +- [Setup your local environment](/docs/intro/installation) and use the local + test validator. + + + +## Rust Crates + +The following are the most important and commonly used Rust crates for Solana +development: + +- [`solana-program`] — Imported by programs running on Solana, compiled to + SBF. This crate contains many fundamental data types and is re-exported from + [`solana-sdk`], which cannot be imported from a Solana program. + +- [`solana-sdk`] — The basic offchain SDK, it re-exports + [`solana-program`] and adds more APIs on top of that. Most Solana programs + that do not run on-chain will import this. + +- [`solana-client`] — For interacting with a Solana node via the + [JSON RPC API](/docs/rpc). + +- [`solana-cli-config`] — Loading and saving the Solana CLI configuration + file. + +- [`solana-clap-utils`] — Routines for setting up a CLI, using [`clap`], + as used by the main Solana CLI. Includes functions for loading all types of + signers supported by the CLI. + +[`solana-program`]: https://docs.rs/solana-program +[`solana-sdk`]: https://docs.rs/solana-sdk +[`solana-client`]: https://docs.rs/solana-client +[`solana-cli-config`]: https://docs.rs/solana-cli-config +[`solana-clap-utils`]: https://docs.rs/solana-clap-utils +[`clap`]: https://docs.rs/clap diff --git a/docs/uk/core/accounts.md b/docs/uk/core/accounts.md new file mode 100644 index 000000000..7cc886308 --- /dev/null +++ b/docs/uk/core/accounts.md @@ -0,0 +1,197 @@ +--- +sidebarSortOrder: 1 +sidebarLabel: Solana Account Model +title: Solana Account Model +description: + Learn about Solana's account model, including how accounts store data and + programs, rent mechanics, account ownership, and the relationship between + programs and data accounts. Understand the core concepts of Solana's key-value + storage system. +--- + +On Solana, all data is stored in what are referred to as "accounts”. The way +data is organized on Solana resembles a +[key-value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), +where each entry in the database is called an "account". + +![Accounts](/assets/docs/core/accounts/accounts.svg) + +## Key Points + +- Accounts can store up to 10MB of data, which can consist of either executable + program code or program state. + +- Accounts require a rent deposit in SOL, proportional to the amount of data + stored, which is fully refundable when the account is closed. + +- Every account has a program "owner". Only the program that owns an account can + modify its data or deduct its lamport balance. However, anyone can increase + the balance. + +- Programs (smart contracts) are stateless accounts that store executable code. + +- Data accounts are created by programs to store and manage program state. + +- Native programs are built-in programs included with the Solana runtime. + +- Sysvar accounts are special accounts that store network cluster state. + +## Account + +Each account is identifiable by its unique address, represented as 32 bytes in +the format of an [Ed25519](https://ed25519.cr.yp.to/) `PublicKey`. You can think +of the address as the unique identifier for the account. + +![Account Address](/assets/docs/core/accounts/account-address.svg) + +This relationship between the account and its address can be thought of as a +key-value pair, where the address serves as the key to locate the corresponding +on-chain data of the account. + +### AccountInfo + +Accounts have a +[max size of 10MB](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L85) +(10 Mega Bytes) and the data stored on every account on Solana has the following +structure known as the +[AccountInfo](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/account_info.rs#L19). + +![AccountInfo](/assets/docs/core/accounts/accountinfo.svg) + +The `AccountInfo` for each account includes the following fields: + +- `data`: A byte array that stores the state of an account. If the account is a + program (smart contract), this stores executable program code. This field is + often referred to as the "account data". +- `executable`: A boolean flag that indicates if the account is a program. +- `lamports`: A numeric representation of the account's balance in + [lamports](/docs/terminology.md#lamport), the smallest unit of SOL (1 SOL = 1 + billion lamports). +- `owner`: Specifies the public key (program ID) of the program that owns the + account. + +As a key part of the Solana Account Model, every account on Solana has a +designated "owner", specifically a program. Only the program designated as the +owner of an account can modify the data stored on the account or deduct the +lamport balance. It's important to note that while only the owner may deduct the +balance, anyone can increase the balance. + +> To store data on-chain, a certain amount of SOL must be transferred to an +> account. The amount transferred is proportional to the size of the data stored +> on the account. This concept is commonly referred to as “rent”. However, you +> can think of "rent" more like a "deposit" because the SOL allocated to an +> account can be fully recovered when the account is closed. + +## Native Programs + +Solana contains a small handful of native programs that are part of the +validator implementation and provide various core functionalities for the +network. You can find the full list of native programs +[here](https://docs.anza.xyz/runtime/programs). + +When developing custom programs on Solana, you will commonly interact with two +native programs, the System Program and the BPF Loader. + +### System Program + +By default, all new accounts are owned by the +[System Program](https://github.com/solana-labs/solana/tree/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src). +The System Program performs several key tasks such as: + +- [New Account Creation](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L145): + Only the System Program can create new accounts. +- [Space Allocation](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L70): + Sets the byte capacity for the data field of each account. +- [Assign Program Ownership](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L112): + Once the System Program creates an account, it can reassign the designated + program owner to a different program account. This is how custom programs take + ownership of new accounts created by the System Program. + +On Solana, a "wallet" is simply an account owned by the System Program. The +lamport balance of the wallet is the amount of SOL owned by the account. + +![System Account](/assets/docs/core/accounts/system-account.svg) + +> Only accounts owned by the System Program can be used as transaction fee +> payers. + +### BPFLoader Program + +The +[BPF Loader](https://github.com/solana-labs/solana/tree/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src) +is the program designated as the "owner" of all other programs on the network, +excluding Native Programs. It is responsible for deploying, upgrading, and +executing custom programs. + +## Sysvar Accounts + +Sysvar accounts are special accounts located at predefined addresses that +provide access to cluster state data. These accounts are dynamically updated +with data about the network cluster. You can find the full list of Sysvar +Accounts [here](https://docs.anza.xyz/runtime/sysvars). + +## Custom Programs + +On Solana, “smart contracts” are referred to as +[programs](/docs/core/programs.md). A program is an account that contains +executable code and is indicated by an “executable” flag that is set to true. + +For a more detailed explanation of the program deployment process, refer to the +[Deploying Programs](/docs/programs/deploying.md) page of this documentation. + +### Program Account + +When new programs are +[deployed](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L498) +on Solana, technically three separate accounts are created: + +- **Program Account**: The main account representing an on-chain program. This + account stores the address of an executable data account (which stores the + compiled program code) and the update authority for the program (address + authorized to make changes to the program). +- **Program Executable Data Account**: An account that contains the executable + byte code of the program. +- **Buffer Account**: A temporary account that stores byte code while a program + is being actively deployed or upgraded. Once the process is complete, the data + is transferred to the Program Executable Data Account and the buffer account + is closed. + +For example, here are links to the Solana Explorer for the Token Extensions +[Program Account](https://explorer.solana.com/address/TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb) +and its corresponding +[Program Executable Data Account](https://explorer.solana.com/address/DoU57AYuPFu2QU514RktNPG22QhApEjnKxnBcu4BHDTY). + +![Program and Executable Data Accounts](/assets/docs/core/accounts/program-account-expanded.svg) + +For simplicity, you can think of the "Program Account" as the program itself. + +![Program Account](/assets/docs/core/accounts/program-account-simple.svg) + +> The address of the "Program Account" is commonly referred to as the “Program +> ID”, which is used to invoke the program. + +### Data Account + +Solana programs are "stateless", meaning that program accounts only contain the +program's executable byte code. To store and modify additional data, new +accounts must be created. These accounts are commonly referred to as “data +accounts”. + +Data accounts can store any arbitrary data as defined in the owner program's +code. + +![Data Account](/assets/docs/core/accounts/data-account.svg) + +Note that only the [System Program](/docs/core/accounts.md#system-program) can +create new accounts. Once the System Program creates an account, it can then +transfer ownership of the new account to another program. + +In other words, creating a data account for a custom program requires two steps: + +1. Invoke the System Program to create an account, which then transfers + ownership to a custom program +2. Invoke the custom program, which now owns the account, to then initialize the + account data as defined in the program code + +This data account creation process is often abstracted as a single step, but +it's helpful to understand the underlying process. diff --git a/docs/uk/core/clusters.md b/docs/uk/core/clusters.md new file mode 100644 index 000000000..4134ff06c --- /dev/null +++ b/docs/uk/core/clusters.md @@ -0,0 +1,169 @@ +--- +sidebarLabel: Clusters & Endpoints +title: Clusters and Public RPC Endpoints +sidebarSortOrder: 8 +description: + Learn about Solana's network clusters (Devnet, Testnet, and Mainnet Beta), + their public RPC endpoints, rate limits, and use cases. Learn how to connect + to different Solana networks for development, testing, and production. +--- + +The Solana blockchain has several different groups of validators, known as +[Clusters](/docs/core/clusters.md). Each serving different purposes within the +overall ecosystem and containing dedicated API nodes to fulfill +[JSON-RPC](/docs/rpc/index.mdx) requests for their respective Cluster. + +The individual nodes within a Cluster are owned and operated by third parties, +with a public endpoint available for each. + +## Solana public RPC endpoints + +The Solana Labs organization operates a public RPC endpoint for each Cluster. +Each of these public endpoints are subject to rate limits, but are available for +users and developers to interact with the Solana blockchain. + +> Public endpoint rate limits are subject to change. The specific rate limits +> listed on this document are not guaranteed to be the most up-to-date. + +### Using explorers with different Clusters + +Many of the popular Solana blockchain explorers support selecting any of the +Clusters, often allowing advanced users to add a custom/private RPC endpoint as +well. + +An example of some of these Solana blockchain explorers include: + +- [http://explorer.solana.com/](https://explorer.solana.com/). +- [http://solana.fm/](https://solana.fm/). +- [http://solscan.io/](https://solscan.io/). +- [http://solanabeach.io/](http://solanabeach.io/). +- [http://validators.app/](http://validators.app/). + +## On a high level + +- Mainnet: Live production environment for deployed applications. +- Devnet: Testing with public accessibility for developers experimenting with + their applications. +- Testnet: Stress-testing for network upgrades and validator performance. + +**Example use cases**: You may want to debug a new program on Devnet or verify +performance metrics on Testnet before Mainnet deployment. + +| **Cluster** | **Endpoint** | **Purpose** | **Notes** | +| ----------- | ------------------------------------- | ------------------------------ | ------------------------------ | +| Mainnet | `https://api.mainnet-beta.solana.com` | Live production environment | Requires SOL for transactions | +| Devnet | `https://api.devnet.solana.com` | Public testing and development | Free SOL airdrop for testing | +| Testnet | `https://api.testnet.solana.com` | Validator and stress testing | May have intermittent downtime | + +## Devnet + +Devnet serves as a playground for anyone who wants to take Solana for a test +drive, as a user, token holder, app developer, or validator. + +- Application developers should target Devnet. +- Potential validators should first target Devnet. +- Key differences between Devnet and Mainnet Beta: + - Devnet tokens are **not real** + - Devnet includes a token faucet for airdrops for application testing + - Devnet may be subject to ledger resets + - Devnet typically runs the same software release branch version as Mainnet + Beta, but may run a newer minor release version than Mainnet Beta. +- Gossip entrypoint for Devnet: `entrypoint.devnet.solana.com:8001` + +### Devnet endpoint + +- `https://api.devnet.solana.com` - single Solana Labs hosted API node; + rate-limited + +#### Example `solana` command-line configuration + +To connect to the `devnet` Cluster using the Solana CLI: + +```shell +solana config set --url https://api.devnet.solana.com +``` + +### Devnet rate limits + +- Maximum number of requests per 10 seconds per IP: 100 +- Maximum number of requests per 10 seconds per IP for a single RPC: 40 +- Maximum concurrent connections per IP: 40 +- Maximum connection rate per 10 seconds per IP: 40 +- Maximum amount of data per 30 second: 100 MB + +## Testnet + +Testnet is where the Solana core contributors stress test recent release +features on a live cluster, particularly focused on network performance, +stability and validator behavior. + +- Testnet tokens are **not real** +- Testnet may be subject to ledger resets. +- Testnet includes a token faucet for airdrops for application testing +- Testnet typically runs a newer software release branch than both Devnet and + Mainnet Beta +- Gossip entrypoint for Testnet: `entrypoint.testnet.solana.com:8001` + +### Testnet endpoint + +- `https://api.testnet.solana.com` - single Solana Labs API node; rate-limited + +#### Example `solana` command-line configuration + +To connect to the `testnet` Cluster using the Solana CLI: + +```shell +solana config set --url https://api.testnet.solana.com +``` + +### Testnet rate limits + +- Maximum number of requests per 10 seconds per IP: 100 +- Maximum number of requests per 10 seconds per IP for a single RPC: 40 +- Maximum concurrent connections per IP: 40 +- Maximum connection rate per 10 seconds per IP: 40 +- Maximum amount of data per 30 second: 100 MB + +## Mainnet beta + +A permissionless, persistent cluster for Solana users, builders, validators and +token holders. + +- Tokens that are issued on Mainnet Beta are **real** SOL +- Gossip entrypoint for Mainnet Beta: `entrypoint.mainnet-beta.solana.com:8001` + +### Mainnet beta endpoint + +- `https://api.mainnet-beta.solana.com` - Solana Labs hosted API node cluster, + backed by a load balancer; rate-limited + +#### Example `solana` command-line configuration + +To connect to the `mainnet-beta` Cluster using the Solana CLI: + +```shell +solana config set --url https://api.mainnet-beta.solana.com +``` + +### Mainnet beta rate limits + +- Maximum number of requests per 10 seconds per IP: 100 +- Maximum number of requests per 10 seconds per IP for a single RPC: 40 +- Maximum concurrent connections per IP: 40 +- Maximum connection rate per 10 seconds per IP: 40 +- Maximum amount of data per 30 seconds: 100 MB + +> The public RPC endpoints are not intended for production applications. Please +> use dedicated/private RPC servers when you launch your application, drop NFTs, +> etc. The public services are subject to abuse and rate limits may change +> without prior notice. Likewise, high-traffic websites may be blocked without +> prior notice. + +## Common HTTP Error Codes + +- 403 -- Your IP address or website has been blocked. It is time to run your own + RPC server(s) or find a private service. +- 429 -- Your IP address is exceeding the rate limits. Slow down! Use the + [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) + HTTP response header to determine how long to wait before making another + request. diff --git a/docs/uk/core/cpi.md b/docs/uk/core/cpi.md new file mode 100644 index 000000000..6a6add62b --- /dev/null +++ b/docs/uk/core/cpi.md @@ -0,0 +1,134 @@ +--- +title: Cross Program Invocation (CPI) +sidebarLabel: Cross Program Invocation +sidebarSortOrder: 6 +description: + Learn about Cross Program Invocation (CPI) on Solana - how programs can call + instructions on other programs, handle PDA signers, and compose functionality + across the Solana network. +--- + +A Cross Program Invocation (CPI) refers to when one program invokes the +instructions of another program. This mechanism allows for the composability of +Solana programs. + +You can think of instructions as API endpoints that a program exposes to the +network and a CPI as one API internally invoking another API. + +![Cross Program Invocation](/assets/docs/core/cpi/cpi.svg) + +When a program initiates a Cross Program Invocation (CPI) to another program: + +- The signer privileges from the initial transaction invoking the caller program + (A) extend to the callee (B) program +- The callee (B) program can make further CPIs to other programs, up to a + maximum depth of 4 (ex. B->C, C->D) +- The programs can "sign" on behalf of the [PDAs](/docs/core/pda.md) derived + from its program ID + +> The Solana program runtime defines a constant called +> [`max_invoke_stack_height`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/program-runtime/src/compute_budget.rs#L31-L35), +> which is set to a +> [value of 5](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/program-runtime/src/compute_budget.rs#L138). +> This represents the maximum height of the program instruction invocation +> stack. The stack height begins at 1 for transaction instructions, increases by +> 1 each time a program invokes another instruction. This setting effectively +> limits invocation depth for CPIs to 4. + +## Key Points + +- CPIs enable Solana program instructions to directly invoke instructions on + another program. + +- Signer privileges from a caller program are extended to the callee program. + +- When making a CPI, programs can "sign" on behalf of PDAs derived from their + own program ID. + +- The callee program can make additional CPIs to other programs, up to a maximum + depth of 4. + +## How to write a CPI + +Writing an instruction for a CPI follows the same pattern as building an +[instruction](/docs/core/transactions.md#instruction) to add to a transaction. +Under the hood, each CPI instruction must specify the following information: + +- **Program address**: Specifies the program being invoked +- **Accounts**: Lists every account the instruction reads from or writes to, + including other programs +- **Instruction Data**: Specifies which instruction on the program to invoke, + plus any additional data required by the instruction (function arguments) + +Depending on the program you are making the call to, there may be crates +available with helper functions for building the instruction. Programs then +execute CPIs using either one of the following functions from the +`solana_program` crate: + +- `invoke` - used when there are no PDA signers +- `invoke_signed` - used when the caller program needs to sign with a PDA + derived from its program ID + +### Basic CPI + +The +[`invoke`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/program.rs#L132) +function is used when making a CPI that does not require PDA signers. When +making CPIs, signers provided to the caller program automatically extend to the +callee program. + +```rust +pub fn invoke( + instruction: &Instruction, + account_infos: &[AccountInfo<'_>] +) -> Result<(), ProgramError> +``` + +Here is an example program on +[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi-invoke) +that makes a CPI using the `invoke` function to call the transfer instruction on +the System Program. You can also reference the +[Basic CPI guide](/content/guides/getstarted/how-to-cpi.md) for further details. + +### CPI with PDA Signer + +The +[`invoke_signed`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/program.rs#L247) +function is used when making a CPI that requires PDA signers. The seeds used to +derive the signer PDAs are passed into the `invoke_signed` function as +`signer_seeds`. + +You can reference the [Program Derived Address](/docs/core/pda.md) page for +details on how PDAs are derived. + +```rust +pub fn invoke_signed( + instruction: &Instruction, + account_infos: &[AccountInfo<'_>], + signers_seeds: &[&[&[u8]]] +) -> Result<(), ProgramError> +``` + +The runtime uses the privileges granted to the caller program to determine what +privileges can be extended to the callee. Privileges in this context refer to +signers and writable accounts. For example, if the instruction the caller is +processing contains a signer or writable account, then the caller can invoke an +instruction that also contains that signer and/or writable account. + +While PDAs have [no private keys](/docs/core/pda.md#what-is-a-pda), they can +still act as a signer in an instruction via a CPI. To verify that a PDA is +derived from the calling program, the seeds used to generate the PDA must be +included as `signers_seeds`. + +When the CPI is processed, the Solana runtime +[internally calls `create_program_address`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/syscalls/cpi.rs#L550) +using the `signers_seeds` and the `program_id` of the calling program. If a +valid PDA is found, the address is +[added as a valid signer](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/syscalls/cpi.rs#L552). + +Here is an example program on +[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi-invoke-signed) +that makes a CPI using the `invoke_signed` function to call the transfer +instruction on the System Program with a PDA signer. You can reference the +[CPI with PDA Signer guide](/content/guides/getstarted/how-to-cpi-with-signer.md) +for further details. diff --git a/docs/uk/core/fees.md b/docs/uk/core/fees.md new file mode 100644 index 000000000..8192694fa --- /dev/null +++ b/docs/uk/core/fees.md @@ -0,0 +1,496 @@ +--- +title: Fees on Solana +sidebarSortOrder: 3 +description: + Learn about Solana's fee structure including transaction fees, prioritization + fees, and rent costs. Understand how fees are calculated, collected and + distributed across the network. +keywords: + - instruction fee + - processing fee + - storage fee + - rent + - gas + - gwei +altRoutes: + - /docs/core/rent + - /docs/intro/rent + - /docs/intro/transaction_fees + - /docs/intro/transaction-fees + - /docs/core/runtime +--- + +The Solana blockchain has a few different types of fees and costs that are +incurred to use the permissionless network. These can be segmented into a few +specific types: + +- Transaction Fees - A fee to have validators process transactions/instructions +- Prioritization Fees - An optional fee to boost transactions processing order +- Rent - A withheld balance to keep data stored on-chain + +## Transaction Fees + +The small fee paid to process logic (instruction) within an on-chain program on +the Solana blockchain is known as a "_transaction fee_". + +As each [transaction](/docs/core/transactions.md#transaction) (which contains +one or more [instructions](/docs/core/transactions.md#instruction)) is sent +through the network, it gets processed by the current validator leader. Once +confirmed as a global state transaction, this _transaction fee_ is paid to the +network to help support the economic design of the Solana blockchain. + +> Transaction fees are different from account data storage deposit fee of +> [rent](#rent). While transaction fees are paid to process instructions on the +> Solana network, a rent deposit is withheld in an account to store its data on +> the blockchain and reclaimable. + +Currently, the base Solana transaction fee is set at a static value of 5k +lamports per signature. On top of this base fee, any additional +[prioritization fees](#prioritization-fee) can be added. + +### Why pay transaction fees? + +Transaction fees offer many benefits in the Solana +[economic design](#basic-economic-design), mainly they: + +- provide compensation to the validator network for the expended CPU/GPU compute + resources necessary to process transactions +- reduce network spam by introducing a real cost to transactions +- provide long-term economic stability to the network through a + protocol-captured minimum fee amount per transaction + +### Basic economic design + +Many blockchain networks (including Bitcoin and Ethereum), rely on inflationary +_protocol-based rewards_ to secure the network in the short-term. Over the +long-term, these networks will increasingly rely on _transaction fees_ to +sustain security. + +The same is true on Solana. Specifically: + +- A fixed proportion (initially 50%) of each transaction fee is _burned_ + (destroyed), with the remaining going to the current + [leader](/docs/terminology.md#leader) processing the transaction. +- A scheduled global inflation rate provides a source for + [rewards](https://docs.anza.xyz/implemented-proposals/staking-rewards) + distributed to [Solana Validators](https://docs.anza.xyz/operations). + +### Fee collection + +Transactions are required to have at least one account which has signed the +transaction and is writable. These _writable signer accounts_ are serialized +first in the list of accounts and the first of these is always used as the "_fee +payer_". + +Before any transaction instructions are processed, the fee payer account +[balance will be deducted](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank.rs#L4045-L4064) +to pay for transaction fees. If the fee payer balance is not sufficient to cover +transaction fees, the transaction processing will halt and result in a failed +transaction. + +If the balance was sufficient, the fees will be deducted and the transaction's +instructions will begin execution. Should any of the instructions result in an +error, transaction processing will halt and ultimately be recorded as a failed +transaction in the Solana ledger. The fee is still collected by the runtime for +these failed transactions. + +Should any of the instructions return an error or violate runtime restrictions, +all account changes **_except_** the transaction fee deduction will be rolled +back. This is because the validator network has already expended computational +resources to collect transactions and begin the initial processing. + +### Fee distribution + +Transaction fees are +[partially burned](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank/fee_distribution.rs#L55-L64) +and the remaining fees are collected by the validator that produced the block +that the corresponding transactions were included in. Specifically, +[50% are burned](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/fee_calculator.rs#L79) +and +[50% percent are distributed](https://github.com/anza-xyz/agave/blob/e621336acad4f5d6e5b860eaa1b074b01c99253c/runtime/src/bank/fee_distribution.rs#L58-L62) +to the validator that produced the block. + +### Why burn some fees? + +As mentioned above, a fixed proportion of each transaction fee is _burned_ +(destroyed). This is intended to cement the economic value of SOL and thus +sustain the network's security. Unlike a scheme where transactions fees are +completely burned, leaders are still incentivized to include as many +transactions as possible in their slots (opportunity to create a block). + +Burnt fees can also help prevent malicious validators from censoring +transactions by being considered in [fork](/docs/terminology.md#fork) selection. + +#### Example of an attack: + +In the case of a +[Proof of History (PoH)](/docs/terminology.md#proof-of-history-poh) fork with a +malicious or censoring leader: + +- due to the fees lost from censoring, we would expect the total fees burned to + be **_less than_** a comparable honest fork +- if the censoring leader is to compensate for these lost protocol fees, they + would have to replace the burnt fees on their fork themselves +- thus potentially reducing the incentive to censor in the first place + +### Calculating transaction fees + +The complete fee for a given transaction is calculated based on two main parts: + +- a statically set base fee per signature, and +- the computational resources used during the transaction, measured in + "[_compute units_](/docs/terminology.md#compute-units)" + +Since each transaction may require a different amount of computational +resources, each is allotted a maximum number of _compute units_ per transaction +as part of the _compute budget_. + +## Compute Budget + +To prevent abuse of computational resources, each transaction is allocated a +"_compute budget_". This budget specifies details about +[compute units](#compute-units) and includes: + +- the compute costs associated with different types of operations the + transaction may perform (compute units consumed per operation), +- the maximum number of compute units that a transaction can consume (compute + unit limit), +- and the operational bounds the transaction must adhere to (like account data + size limits) + +When the transaction consumes its entire compute budget (compute budget +exhaustion), or exceeds a bound such as attempting to exceed the +[max call stack depth](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L138) +or [max loaded account](#accounts-data-size-limit) data size limit, the runtime +halts the transaction processing and returns an error. Resulting in a failed +transaction and no state changes (aside from the transaction fee being +[collected](#fee-collection)). + +### Accounts data size limit + +A transaction may specify the maximum bytes of account data it is allowed to +load by including a `SetLoadedAccountsDataSizeLimit` instruction (not to exceed +the runtime's absolute max). If no `SetLoadedAccountsDataSizeLimit` is provided, +the transaction defaults to use the runtime's +[`MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L137-L139) +value. + +The `ComputeBudgetInstruction::set_loaded_accounts_data_size_limit` function can +be used to create this instruction: + +```rust +let instruction = ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(100_000); +``` + +### Compute units + +All the operations performed on-chain within a transaction require different +amounts of computation resources be expended by validators when processing +(compute cost). The smallest unit of measure for the consumption of these +resources is called a _"compute unit"_. + +As a transaction is processed, compute units are incrementally consumed by each +of its instructions being executed on-chain (consuming the budget). Since each +instruction is executing different logic (writing to accounts, cpi, performing +syscalls, etc), each may consume a +[different amount](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L133-L178) +of compute units. + +> A program can log details about its compute usage, including how much remains +> in its allotted compute budget. You can also find more information in this +> guide for +> [optimizing your compute usage](/content/guides/advanced/how-to-optimize-compute.md). + +Each transaction is allotted a [compute unit limit](#compute-unit-limit), either +with the default limit set by the runtime or by explicitly requesting a higher +limit. After a transaction exceeds its compute unit limit, its processing is +halted resulting in a transaction failure. + +The following are some common operations that incur a compute cost: + +- executing instructions +- passing data between programs +- performing syscalls +- using sysvars +- logging with the `msg!` macro +- logging pubkeys +- creating program addresses (PDAs) +- cross-program invocations (CPI) +- cryptographic operations + +> For [cross-program invocations](/docs/core/cpi.md), the instruction invoked +> inherits the compute budget and limits of their parent. If an invoked +> instruction consumes the transaction's remaining budget, or exceeds a bound, +> the entire invocation chain and the top level transaction processing are +> halted. + +You can find more details about all the operations that consume compute units +within the Solana runtime's +[`ComputeBudget`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L19-L123). + +### Compute unit limit + +Each transaction has a maximum number of compute units (CU) it can consume +called the _"compute unit limit"_. Per transaction, the Solana runtime has an +absolute max compute unit limit of +[1.4 million CU](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L19) +and sets a default requested max limit of +[200k CU per instruction](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L18). + +A transaction can request a more specific and optimal compute unit limit by +including a single `SetComputeUnitLimit` instruction. Either a higher or lower +limit. But it may never request higher than the absolute max limit per +transaction. + +While a transaction's default compute unit limit will work in most cases for +simple transactions, they are often less than optimal (both for the runtime and +the user). For more complex transactions, like invoking programs that perform +multiple CPIs, you may need to request a higher compute unit limit for the +transaction. + +Requesting the optimal compute unit limits for your transaction is essential to +help you pay less for your transaction and to help schedule your transaction +better on the network. Wallets, dApps, and other services should ensure their +compute unit requests are optimal to provide the best experience possible for +their users. + +> For more details and best practices, read this guide on +> [requesting optimal compute limits](/content/guides/advanced/how-to-request-optimal-compute.md). + +### Compute unit price + +When a transaction desires to pay a higher fee to boost its processing +prioritization, it can set a _"compute unit price"_. This price, used in +combination with [compute unit limit](#compute-unit-limit), will be used to +determine a transaction's prioritization fee. + +By default, there is +[no compute unit price set](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L38) +resulting in no additional prioritization fee. + +## Prioritization Fees + +As part of the [Compute Budget](#compute-budget), the runtime supports +transactions paying an **optional** fee known as a _"prioritization fee"_. +Paying this additional fee helps boost how a transaction is prioritized against +others when processing, resulting in faster execution times. + +### How the prioritization fee is calculated + +A transaction's prioritization fee is calculated by multiplying its **_compute +unit limit_** by the **_compute unit price_** (measured in _micro-lamports_). +These values can be set once per transaction by including the following Compute +Budget instructions: + +- [`SetComputeUnitLimit`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L47-L50) - + setting the maximum number of compute units the transaction can consume +- [`SetComputeUnitPrice`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L52-L55) - + setting the desired additional fee the transaction is willing to pay to boost + its prioritization + +If no `SetComputeUnitLimit` instruction is provided, the +[default compute unit limit](#compute-unit-limit) will be used. + +If no `SetComputeUnitPrice` instruction is provided, the transaction will +default to no additional elevated fee and the lowest priority (i.e. no +prioritization fee). + +### How to set the prioritization fee + +A transaction's prioritization fee is set by including a `SetComputeUnitPrice` +instruction, and optionally a `SetComputeUnitLimit` instruction. The runtime +will use these values to calculate the prioritization fee, which will be used to +prioritize the given transaction within the block. + +You can craft each of these instructions via their Rust or `@solana/web3.js` +functions. Each instruction can then be included in the transaction and sent to +the cluster like normal. See also the +[best practices](#prioritization-fee-best-practices) below. + +Unlike other instructions inside a Solana transaction, Compute Budget +instructions do **NOT** require any accounts. A transaction with multiple of +either of the instructions will fail. + + + +Transactions can only contain **one of each type** of compute budget +instruction. Duplicate instruction types will result in an +[`TransactionError::DuplicateInstruction`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/transaction/error.rs#L143-L145) +error, and ultimately transaction failure. + + + +#### Rust + +The rust `solana-sdk` crate includes functions within +[`ComputeBudgetInstruction`](https://docs.rs/solana-sdk/latest/solana_sdk/compute_budget/enum.ComputeBudgetInstruction.html) +to craft instructions for setting the _compute unit limit_ and _compute unit +price_: + +```rust +let instruction = ComputeBudgetInstruction::set_compute_unit_limit(300_000); +``` + +```rust +let instruction = ComputeBudgetInstruction::set_compute_unit_price(1); +``` + +#### Javascript + +The `@solana/web3.js` library includes functions within the +[`ComputeBudgetProgram`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/ComputeBudgetProgram.html) +class to craft instructions for setting the _compute unit limit_ and _compute +unit price_: + +```js +const instruction = ComputeBudgetProgram.setComputeUnitLimit({ + units: 300_000, +}); +``` + +```js +const instruction = ComputeBudgetProgram.setComputeUnitPrice({ + microLamports: 1, +}); +``` + +### Prioritization fee best practices + +Below you can find general information on the best practices for prioritization +fees. You can also find more detailed information in this guide on +[how to request optimal compute](/content/guides/advanced/how-to-request-optimal-compute.md), +including how to simulate a transaction to determine its approximate compute +usage. + +#### Request the minimum compute units + +Transactions should request the minimum amount of compute units required for +execution to minimize fees. Also note that fees are not adjusted when the number +of requested compute units exceeds the number of compute units actually consumed +by an executed transaction. + +#### Get recent prioritization fees + +Prior to sending a transaction to the cluster, you can use the +[`getRecentPrioritizationFees`](/docs/rpc/http/getRecentPrioritizationFees.mdx) +RPC method to get a list of the recent paid prioritization fees within the +recent blocks processed by the node. + +You could then use this data to estimate an appropriate prioritization fee for +your transaction to both (a) better ensure it gets processed by the cluster and +(b) minimize the fees paid. + +## Rent + +The fee deposited into every [Solana Account](/docs/core/accounts.md) to keep +its associated data available on-chain is called "_rent_". This fee is withheld +in the normal lamport balance on every account and reclaimable when the account +is closed. + +> Rent is different from [transaction fees](#transaction-fees). Rent is "paid" +> (withheld in an Account) to keep data stored on the Solana blockchain and can +> be reclaimed. Whereas transaction fees are paid to process +> [instructions](/docs/core/transactions.md#instructions) on the network. + +All accounts are required to maintain a high enough lamport balance (relative to +its allocated space) to become [rent exempt](#rent-exempt) and remain on the +Solana blockchain. Any transaction that attempts to reduce an account's balance +below its respective minimum balance for rent exemption will fail (unless the +balance is reduced to exactly zero). + +When an account's owner no longer desires to keep this data on-chain and +available in the global state, the owner can close the account and reclaim the +rent deposit. + +This is accomplished by withdrawing (transferring) the account's entire lamport +balance to another account (i.e. your wallet). By reducing the account's balance +to exactly `0`, the runtime will remove the account and its associated data from +the network in the process of _"[garbage collection](#garbage-collection)"_. + +### Rent rate + +The Solana rent rate is set on a network wide basis, primarily based on a +runtime set +"[lamports _per_ byte _per_ year](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/rent.rs#L27-L34)". +Currently, the rent rate is a static amount and stored in the +[Rent sysvar](https://docs.anza.xyz/runtime/sysvars#rent). + +This rent rate is used to calculate the exact amount of rent required to be +withheld inside an account for the space allocated to the account (i.e. the +amount of data that can be stored in the account). The more space an account +allocates, the higher the withheld rent deposit will be. + +### Rent exempt + +Accounts must maintain a lamport balance greater than the minimum required to +store its respective data on-chain. This is called "_rent exempt_" and that +balance is called the "_minimum balance for rent exemption_". + +> New accounts (and programs) on Solana are **REQUIRED** to be initialized with +> enough lamports to become _rent exempt_. This was not always the case. +> Previously, the runtime would periodically and automatically collect a fee +> from each account below its _minimum balance for rent exemption_. Eventually +> reducing those accounts to a balance of zero and garbage collecting them from +> the global state (unless manually topped up). + +In the process of creating a new account, you must ensure you deposit enough +lamports to be above this minimum balance. Anything lower that this minimum +threshold will result in a failed transaction. + +Every time an account's balance is reduced, the runtime performs a check to see +if the account will still be above this minimum balance for rent exemption. +Unless they reduce the final balance to exactly `0` (closing the account), +transactions that would cause an account's balance to drop below the rent exempt +threshold will fail. + +The specific minimum balance for an account to become rent exempt is dependant +on the blockchain's current [rent rate](#rent-rate) and the desired amount of +storage space an account wants to allocate (account size). Therefore, it is +recommended to use the +[`getMinimumBalanceForRentExemption`](/docs/rpc/http/getMinimumBalanceForRentExemption.mdx) +RPC endpoint to calculate the specific balance for a given account size. + +The required rent deposit amount can also be estimated via the +[`solana rent` CLI subcommand](https://docs.anza.xyz/cli/usage#solana-rent): + +```shell +solana rent 15000 + +# output +Rent per byte-year: 0.00000348 SOL +Rent per epoch: 0.000288276 SOL +Rent-exempt minimum: 0.10529088 SOL +``` + +### Garbage collection + +Accounts that do not maintain a lamport balance greater than zero are removed +from the network in a process known as _garbage collection_. This process is +done to help reduce the network wide storage of no longer used/maintained data. + +After a transaction successfully reduces an accounts balance to exactly `0`, +garbage collection happens automatically by the runtime. Any transaction that +attempts to reduce an accounts balance lower that its minimum balance for rent +exemption (that is not exactly zero) will fail. + + + +It's important to note that garbage collection happens **after** the transaction +execution is completed. If there is an instruction to "close" an account by +reducing the account balance to zero, the account can be "reopened" within the +same transaction via a later instruction. If the account state was not cleared +in the "close" instruction, the later "reopen" instruction will have the same +account state. It's a security concern, so it's good to know the exact timing +garbage collection takes effect. + + + +Even after an account has been removed from the network (via garbage +collection), it may still have transactions associated with it's address (either +past history or in the future). Even though a Solana block explorer may display +an "account not found" type of message, you may still be able to view +transaction history associated with that account. + +You can read the validator +[implemented proposal](https://docs.anza.xyz/implemented-proposals/persistent-account-storage#garbage-collection) +for garbage collection to learn more. diff --git a/docs/uk/core/index.md b/docs/uk/core/index.md new file mode 100644 index 000000000..7bf9fd62a --- /dev/null +++ b/docs/uk/core/index.md @@ -0,0 +1,117 @@ +--- +title: Core Concepts +sidebarSortOrder: 2 +description: + Learn essential Solana blockchain concepts including accounts, transactions, + programs, program derived addresses, cross program invocations, and how tokens + work on Solana. +--- + +Build a strong understanding of the core concepts that make Solana different +from other blockchains. Understanding the "Solana programming model" through +these core concepts is very important to maximize your success as a Solana +blockchain developer. + +## Solana Account Model + +On Solana, all data is stored in what are referred to as "accounts”. The way +data is organized on the Solana blockchain resembles a +[key-value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), +where each entry in the database is called an "account". + +Learn more about [Accounts](/docs/core/accounts.md) here. + +## Transactions and Instructions + +On Solana, we send [transactions](/docs/core/transactions#transaction) to +interact with the network. Transactions include one or more +[instructions](/docs/core/transactions#instruction), each representing a +specific operation to be processed. The execution logic for instructions is +stored on [programs](/docs/core/programs) deployed to the Solana network, where +each program stores its own set of instructions. + +Learn more about [Transactions](/docs/core/transactions.md) and +[Instructions](/docs/core/transactions.md#instruction) here. + +## Fees on Solana + +The Solana blockchain has a few different types of fees and costs that are +incurred to use the permissionless network. These can be segmented into a few +specific types: + +- [Transaction Fees](/docs/core/fees.md#transaction-fees) - A fee to have + validators process transactions/instructions +- [Prioritization Fees](/docs/core/fees.md#prioritization-fees) - An optional + fee to boost transactions processing order +- [Rent](/docs/core/fees.md#rent) - A withheld balance to keep data stored + on-chain + +Learn more about [Fees on Solana](/docs/core/fees.md) here. + +## Programs on Solana + +In the Solana ecosystem, "smart contracts" are called programs. Each program is +an on-chain account that stores executable logic, organized into specific +functions referred to as _instructions_ and called via _instruction handler_ +functions within the respective deployed program. + +Learn more about [Programs on Solana](/docs/core/programs.md) here. + +## Program Derived Address + +Program Derived Addresses (PDAs) provide developers on Solana with two main use +cases: + +- **Deterministic Account Addresses**: PDAs provide a mechanism to + deterministically derive an address using a combination of optional "seeds" + (predefined inputs) and a specific program ID. +- **Enable Program Signing**: The Solana runtime enables programs to "sign" for + PDAs which are derived from its program ID. + +You can think of PDAs as a way to create hashmap-like structures on-chain from a +predefined set of inputs (e.g. strings, numbers, and other account addresses). + +Learn more about [Program Derived Address](/docs/core/pda.md) here. + +## Cross Program Invocation + +A Cross Program Invocation (CPI) refers to when one program invokes the +instructions of another program. This mechanism allows for the composability of +Solana programs. + +You can think of instructions as API endpoints that a program exposes to the +network and a CPI as one API internally invoking another API. + +Learn more about [Cross Program Invocation](/docs/core/cpi.md) here. + +## Tokens on Solana + +Tokens are digital assets that represent ownership over diverse categories of +assets. Tokenization enables the digitalization of property rights, serving as a +fundamental component for managing both fungible and non-fungible assets. + +- Fungible Tokens represent interchangeable and divisible assets of the same + type and value (ex. USDC). +- Non-fungible Tokens (NFT) represent ownership of indivisible assets (e.g. + artwork). + +Learn more about [Tokens on Solana](/docs/core/tokens.md) here. + +## Clusters and Endpoints + +The Solana blockchain has several different groups of validators, known as +[Clusters](/docs/core/clusters.md). Each serving different purposes within the +overall ecosystem and containing dedicated api nodes to fulfill +[JSON-RPC](/docs/rpc/index.mdx) requests for their respective Cluster. + +The individual nodes within a Cluster are owned and operated by third parties, +with a public endpoint available for each. + +There are three primary clusters on the Solana network, each with a different +public endpoint: + +- Mainnet - `https://api.mainnet-beta.solana.com` +- Devnet - `https://api.devnet.solana.com` +- Testnet - `https://api.testnet.solana.com` + +Learn more about [Clusters and Endpoints](/docs/core/clusters.md) here. diff --git a/docs/uk/core/pda.md b/docs/uk/core/pda.md new file mode 100644 index 000000000..2d0330554 --- /dev/null +++ b/docs/uk/core/pda.md @@ -0,0 +1,394 @@ +--- +title: Program Derived Address (PDA) +sidebarLabel: Program Derived Address +sidebarSortOrder: 5 +description: + Learn about Program Derived Addresses (PDAs) on Solana - deterministic account + addresses that enable secure program signing. Understand PDA derivation, + canonical bumps, and how to create PDA accounts. +--- + +Program Derived Addresses (PDAs) provide developers on Solana with two main use +cases: + +- **Deterministic Account Addresses**: PDAs provide a mechanism to + deterministically derive an address using a combination of optional "seeds" + (predefined inputs) and a specific program ID. +- **Enable Program Signing**: The Solana runtime enables programs to "sign" for + PDAs which are derived from its program ID. + +You can think of PDAs as a way to create hashmap-like structures on-chain from a +predefined set of inputs (e.g. strings, numbers, and other account addresses). + +The benefit of this approach is that it eliminates the need to keep track of an +exact address. Instead, you simply need to recall the specific inputs used for +its derivation. + +![Program Derived Address](/assets/docs/core/pda/pda.svg) + +It's important to understand that simply deriving a Program Derived Address +(PDA) does not automatically create an on-chain account at that address. +Accounts with a PDA as the on-chain address must be explicitly created through +the program used to derive the address. You can think of deriving a PDA as +finding an address on a map. Just having an address does not mean there is +anything built at that location. + +> This section will cover the details of deriving PDAs. The details on how +> programs use PDAs for signing will be addressed in the section on +> [Cross Program Invocations (CPIs)](/docs/core/cpi.md) as it requires context +> for both concepts. + +## Key Points + +- PDAs are addresses derived deterministically using a combination of + user-defined seeds, a bump seed, and a program's ID. + +- PDAs are addresses that fall off the Ed25519 curve and have no corresponding + private key. + +- Solana programs can programmatically "sign" on behalf of PDAs that are derived + using its program ID. + +- Deriving a PDA does not automatically create an on-chain account. + +- An account using a PDA as its address must be explicitly created through a + dedicated instruction within a Solana program. + +## What is a PDA + +PDAs are addresses that are deterministically derived and look like standard +public keys, but have no associated private keys. This means that no external +user can generate a valid signature for the address. However, the Solana runtime +enables programs to programmatically "sign" for PDAs without needing a private +key. + +For context, Solana +[Keypairs](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/signer/keypair.rs#L25) +are points on the Ed25519 curve (elliptic-curve cryptography) which have a +public key and corresponding private key. We often use public keys as the unique +IDs for new on-chain accounts and private keys for signing. + +![On Curve Address](/assets/docs/core/pda/address-on-curve.svg) + +A PDA is a point that is intentionally derived to fall off the Ed25519 curve +using a predefined set of inputs. A point that is not on the Ed25519 curve does +not have a valid corresponding private key and cannot be used for cryptographic +operations (signing). + +A PDA can then be used as the address (unique identifier) for an on-chain +account, providing a method to easily store, map, and fetch program state. + +![Off Curve Address](/assets/docs/core/pda/address-off-curve.svg) + +## How to derive a PDA + +The derivation of a PDA requires 3 inputs. + +- **Optional seeds**: Predefined inputs (e.g. string, number, other account + addresses) used to derive a PDA. These inputs are converted to a buffer of + bytes. +- **Bump seed**: An additional input (with a value between 255-0) that is used + to guarantee that a valid PDA (off curve) is generated. This bump seed + (starting with 255) is appended to the optional seeds when generating a PDA to + "bump" the point off the Ed25519 curve. The bump seed is sometimes referred to + as a "nonce". +- **Program ID**: The address of the program the PDA is derived from. This is + also the program that can "sign" on behalf of the PDA + +![PDA Derivation](/assets/docs/core/pda/pda-derivation.svg) + +The examples below include links to Solana Playground, where you can run the +examples in an in-browser editor. + +### FindProgramAddress + +To derive a PDA, we can use the +[`findProgramAddressSync`](https://github.com/solana-labs/solana-web3.js/blob/ca9da583a39cdf8fd874a2e03fccdc849e29de34/packages/library-legacy/src/publickey.ts#L212) +method from [`@solana/web3.js`](https://www.npmjs.com/package/@solana/web3.js). +There are equivalents of this function in other programming languages (e.g. +[Rust](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/pubkey.rs#L484)), +but in this section, we will walk through examples using Javascript. + +When using the `findProgramAddressSync` method, we pass in: + +- the predefined optional seeds converted to a buffer of bytes, and +- the program ID (address) used to derive the PDA + +Once a valid PDA is found, `findProgramAddressSync` returns both the address +(PDA) and bump seed used to derive the PDA. + +The example below derives a PDA without providing any optional seeds. + +```ts /[]/ +import { PublicKey } from "@solana/web3.js"; + +const programId = new PublicKey("11111111111111111111111111111111"); + +const [PDA, bump] = PublicKey.findProgramAddressSync([], programId); + +console.log(`PDA: ${PDA}`); +console.log(`Bump: ${bump}`); +``` + +You can run this example on +[Solana Playground](https://beta.solpg.io/66031e5acffcf4b13384cfef). The PDA and +bump seed output will always be the same: + +``` +PDA: Cu7NwqCXSmsR5vgGA3Vw9uYVViPi3kQvkbKByVQ8nPY9 +Bump: 255 +``` + +The next example below adds an optional seed "helloWorld". + +```ts /string/ +import { PublicKey } from "@solana/web3.js"; + +const programId = new PublicKey("11111111111111111111111111111111"); +const string = "helloWorld"; + +const [PDA, bump] = PublicKey.findProgramAddressSync( + [Buffer.from(string)], + programId, +); + +console.log(`PDA: ${PDA}`); +console.log(`Bump: ${bump}`); +``` + +You can also run this example on +[Solana Playground](https://beta.solpg.io/66031ee5cffcf4b13384cff0). The PDA and +bump seed output will always be the same: + +``` +PDA: 46GZzzetjCURsdFPb7rcnspbEMnCBXe9kpjrsZAkKb6X +Bump: 254 +``` + +Note that the bump seed is 254. This means that 255 derived a point on the +Ed25519 curve, and is not a valid PDA. + +The bump seed returned by `findProgramAddressSync` is the first value (between +255-0) for the given combination of optional seeds and program ID that derives a +valid PDA. + +> This first valid bump seed is referred to as the "canonical bump". For program +> security, it is recommended to only use the canonical bump when working with +> PDAs. + +### CreateProgramAddress + +Under the hood, `findProgramAddressSync` will iteratively append an additional +bump seed (nonce) to the seeds buffer and call the +[`createProgramAddressSync`](https://github.com/solana-labs/solana-web3.js/blob/ca9da583a39cdf8fd874a2e03fccdc849e29de34/packages/library-legacy/src/publickey.ts#L168) +method. The bump seed starts with a value of 255 and is decreased by 1 until a +valid PDA (off curve) is found. + +You can replicate the previous example by using `createProgramAddressSync` and +explicitly passing in the bump seed of 254. + +```ts /bump/ +import { PublicKey } from "@solana/web3.js"; + +const programId = new PublicKey("11111111111111111111111111111111"); +const string = "helloWorld"; +const bump = 254; + +const PDA = PublicKey.createProgramAddressSync( + [Buffer.from(string), Buffer.from([bump])], + programId, +); + +console.log(`PDA: ${PDA}`); +``` + +Run this example above on +[Solana Playground](https://beta.solpg.io/66031f8ecffcf4b13384cff1). Given the +same seeds and program ID, the PDA output will match the previous one: + +``` +PDA: 46GZzzetjCURsdFPb7rcnspbEMnCBXe9kpjrsZAkKb6X +``` + +### Canonical Bump + +The "canonical bump" refers to the first bump seed (starting from 255 and +decrementing by 1) that derives a valid PDA. For program security, it is +recommended to only use PDAs derived from a canonical bump. + +Using the previous example as a reference, the example below attempts to derive +a PDA using every bump seed from 255-0. + +```ts +import { PublicKey } from "@solana/web3.js"; + +const programId = new PublicKey("11111111111111111111111111111111"); +const string = "helloWorld"; + +// Loop through all bump seeds for demonstration +for (let bump = 255; bump >= 0; bump--) { + try { + const PDA = PublicKey.createProgramAddressSync( + [Buffer.from(string), Buffer.from([bump])], + programId, + ); + console.log("bump " + bump + ": " + PDA); + } catch (error) { + console.log("bump " + bump + ": " + error); + } +} +``` + +Run the example on +[Solana Playground](https://beta.solpg.io/66032009cffcf4b13384cff2) and you +should see the following output: + +``` +bump 255: Error: Invalid seeds, address must fall off the curve +bump 254: 46GZzzetjCURsdFPb7rcnspbEMnCBXe9kpjrsZAkKb6X +bump 253: GBNWBGxKmdcd7JrMnBdZke9Fumj9sir4rpbruwEGmR4y +bump 252: THfBMgduMonjaNsCisKa7Qz2cBoG1VCUYHyso7UXYHH +bump 251: EuRrNqJAofo7y3Jy6MGvF7eZAYegqYTwH2dnLCwDDGdP +bump 250: Error: Invalid seeds, address must fall off the curve +... +// remaining bump outputs +``` + +As expected, the bump seed 255 throws an error and the first bump seed to derive +a valid PDA is 254. + +However, note that bump seeds 253-251 all derive valid PDAs with different +addresses. This means that given the same optional seeds and `programId`, a bump +seed with a different value can still derive a valid PDA. + + + When building Solana programs, it is recommended to include security checks that + validate a PDA passed to the program is derived using the canonical bump. + Failing to do so may introduce vulnerabilities that allow for unexpected + accounts to be provided to a program. + + +## Create PDA Accounts + +This example program on +[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/pda-account) +demonstrates how to create an account using a PDA as the address of the new +account. The example program is written using the Anchor framework. + +In the `lib.rs` file, you will find the following program which includes a +single instruction to create a new account using a PDA as the address of the +account. The new account stores the address of the `user` and the `bump` seed +used to derive the PDA. + +```rust filename="lib.rs" {11-14,26-29} +use anchor_lang::prelude::*; + +declare_id!("75GJVCJNhaukaa2vCCqhreY31gaphv7XTScBChmr1ueR"); + +#[program] +pub mod pda_account { + use super::*; + + pub fn initialize(ctx: Context) -> Result<()> { + let account_data = &mut ctx.accounts.pda_account; + // store the address of the `user` + account_data.user = *ctx.accounts.user.key; + // store the canonical bump + account_data.bump = ctx.bumps.pda_account; + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(mut)] + pub user: Signer<'info>, + + #[account( + init, + // set the seeds to derive the PDA + seeds = [b"data", user.key().as_ref()], + // use the canonical bump + bump, + payer = user, + space = 8 + DataAccount::INIT_SPACE + )] + pub pda_account: Account<'info, DataAccount>, + pub system_program: Program<'info, System>, +} + +#[account] + +#[derive(InitSpace)] +pub struct DataAccount { + pub user: Pubkey, + pub bump: u8, +} +``` + +The seeds used to derive the PDA include the hardcoded string `data` and the +address of the `user` account provided in the instruction. The Anchor framework +automatically derives the canonical `bump` seed. + +```rust /data/ /user.key()/ /bump/ +#[account( + init, + seeds = [b"data", user.key().as_ref()], + bump, + payer = user, + space = 8 + DataAccount::INIT_SPACE +)] +pub pda_account: Account<'info, DataAccount>, +``` + +The `init` constraint instructs Anchor to invoke the System Program to create a +new account using the PDA as the address. Under the hood, this is done through a +[CPI](/docs/core/cpi.md). + +```rust /init/ +#[account( + init, + seeds = [b"data", user.key().as_ref()], + bump, + payer = user, + space = 8 + DataAccount::INIT_SPACE +)] +pub pda_account: Account<'info, DataAccount>, +``` + +In the test file (`pda-account.test.ts`) located within the Solana Playground +link provided above, you will find the Javascript equivalent to derive the PDA. + +```ts /data/ /user.publicKey/ +const [PDA] = PublicKey.findProgramAddressSync( + [Buffer.from("data"), user.publicKey.toBuffer()], + program.programId, +); +``` + +A transaction is then sent to invoke the `initialize` instruction to create a +new on-chain account using the PDA as the address. Once the transaction is sent, +the PDA is used to fetch the on-chain account that was created at the address. + +```ts /initialize()/ /PDA/ {14} +it("Is initialized!", async () => { + const transactionSignature = await program.methods + .initialize() + .accounts({ + user: user.publicKey, + pdaAccount: PDA, + }) + .rpc(); + + console.log("Transaction Signature:", transactionSignature); +}); + +it("Fetch Account", async () => { + const pdaAccount = await program.account.dataAccount.fetch(PDA); + console.log(JSON.stringify(pdaAccount, null, 2)); +}); +``` + +Note that if you invoke the `initialize` instruction more than once using the +same `user` address as a seed, then the transaction will fail. This is because +an account will already exist at the derived address. diff --git a/docs/uk/core/programs.md b/docs/uk/core/programs.md new file mode 100644 index 000000000..89e34cdad --- /dev/null +++ b/docs/uk/core/programs.md @@ -0,0 +1,95 @@ +--- +title: Programs +sidebarLabel: Programs on Solana +sidebarSortOrder: 4 +description: + Learn about Solana programs (smart contracts) and how to develop them using + Rust or the Anchor framework. Understand program deployment, upgrades, and + verification on the Solana network. +--- + +In the Solana ecosystem, "smart contracts" are called programs. Each +[program](/docs/core/accounts.md#program-account) is an on-chain account that +stores executable logic, organized into specific functions referred to as +[instructions](/docs/core/transactions.md#instruction). + +## Key Points + +- Programs are on-chain accounts that contain executable code. This code is + organized into distinct functions known as instructions. + +- Programs are stateless but can include instructions to create new accounts, + which are used to store and manage program state. + +- Programs can be updated by an upgrade authority. A program becomes immutable + when the upgrade authority is set to null. + +- Verifiable builds enable users to verify that onchain programs match the + publicly available source code. + +## Writing Solana Programs + +Solana programs are predominantly written in the +[Rust](https://doc.rust-lang.org/book/) programming language, with two common +approaches for development: + +- [Anchor](/docs/programs/anchor): A framework designed for Solana program + development. It provides a faster and simpler way to write programs, using + Rust macros to significantly reduce boilerplate code. For beginners, it is + recommended to start with the Anchor framework. + +- [Native Rust](/content/guides/getstarted/intro-to-native-rust.md): This + approach involves writing Solana programs in Rust without leveraging any + frameworks. It offers more flexibility but comes with increased complexity. + +## Updating Solana Programs + +On-chain programs can be +[directly modified](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L675) +by an account designated as the "upgrade authority", which is typically the +account that originally deployed the program. + +If the +[upgrade authority](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L865) +is revoked and set to `None`, the program becomes immutable and can no longer be +updated. + +## Verifiable Programs + +Ensuring the integrity and verifiability of on-chain code is essential. A +verifiable build ensures that the executable code deployed on-chain can be +independently verified to match its public source code by any third party. This +process enhances transparency and trust, making it possible to detect +discrepancies between the source code and the deployed program. + +The Solana developer community has introduced tools to support verifiable +builds, enabling both developers and users to verify that onchain programs +accurately reflect their publicly shared source code. + +- **Searching for Verified Programs**: To quickly check for verified programs, + users can search for a program address on the [SolanaFM](https://solana.fm/) + Explorer and navigate to the "Verification" tab. View an example of a verified + program + [here](https://solana.fm/address/PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY). + +- **Verification Tools**: The + [Solana Verifiable Build CLI](https://github.com/Ellipsis-Labs/solana-verifiable-build) + by Ellipsis Labs enables users to independently verify onchain programs + against published source code. + +- **Support for Verifiable Builds in Anchor**: Anchor provides built-in support + for verifiable builds. Details can be found in the + [Anchor documentation](https://www.anchor-lang.com/docs/verifiable-builds). + +## Berkeley Packet Filter (BPF) + +Solana leverages the [LLVM compiler infrastructure](https://llvm.org/) to +compile programs into +[Executable and Linkable Format (ELF)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) +files. These files include a modified version of +[Berkeley Packet Filter (eBPF)](https://en.wikipedia.org/wiki/EBPF) bytecode for +Solana programs, known as "Solana Bytecode Format" (sBPF). + +The use of LLVM enables Solana to potentially support any programming language +that can compile to LLVM's BPF backend. This significantly enhances the +flexibility of Solana as a development platform. diff --git a/docs/uk/core/tokens.md b/docs/uk/core/tokens.md new file mode 100644 index 000000000..0cbd5cf23 --- /dev/null +++ b/docs/uk/core/tokens.md @@ -0,0 +1,580 @@ +--- +title: "Tokens on Solana" +sidebarSortOrder: 7 +description: + Learn about Solana tokens (SPL Tokens) including fungible and non-fungible + tokens, Token Program, Token Extensions Program, mint accounts, token + accounts, and practical examples for creating and managing tokens on Solana. +--- + +Tokens are digital assets that represent ownership over diverse categories of +assets. Tokenization enables the digitalization of property rights, serving as a +fundamental component for managing both fungible and non-fungible assets. + +- Fungible Tokens represent interchangeable and divisible assets of the same + type and value (ex. USDC). +- Non-fungible Tokens (NFT) represent ownership of indivisible assets (e.g. + artwork). + +This section will cover the basics of how tokens are represented on Solana. +These are referred to as SPL +([Solana Program Library](https://github.com/solana-labs/solana-program-library)) +Tokens. + +- The [Token Program](#token-program) contains all the instruction logic for + interacting with tokens on the network (both fungible and non-fungible). + +- A [Mint Account](#mint-account) represents a specific type of token and stores + global metadata about the token such as the total supply and mint authority + (address authorized to create new units of a token). + +- A [Token Account](#token-account) keeps track of individual ownership of how + many units of a specific type of token (mint account) are owned by a specific + address. + +> There are currently two versions of the Token Program. The original +> [Token Program](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) +> and the +> [Token Extensions Program](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program-2022) +> (Token2022). The Token Extensions Program functions the same as the original +> Token Program, but with additional features and improvements. The Token +> Extensions Program is the recommended version to use for creating new tokens +> (mint accounts). + +## Key Points + +- Tokens represent ownership over either fungible (interchangeable) or + non-fungible (unique) assets. + +- The Token Program contains all instruction for interacting with both fungible + and non-fungible tokens on the network. + +- The Token Extensions Program is a new version of the Token Program that + includes additional features while maintaining the same core functionalities. + +- A Mint Account represents a unique token on the network and stores global + metadata such as total supply. + +- A Token Account tracks individual ownership of tokens for a specific mint + account. + +- An Associated Token Account is a Token Account created with an address derived + from the owner's and mint account's addresses. + +## Token Program + +The +[Token Program](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) +contains all the instruction logic for interacting with tokens on the network +(both fungible and non-fungible). All tokens on Solana are effectively +[data accounts](/docs/core/accounts.md#data-account) owned by the Token Program. + +You can find the full list of Token Program instructions +[here](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/instruction.rs). + +![Token Program](/assets/docs/core/tokens/token-program.svg) + +A few commonly used instructions include: + +- [`InitializeMint`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L29): + Create a new mint account to represent a new type of token. +- [`InitializeAccount`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L84): + Create a new token account to hold units of a specific type of token (mint). +- [`MintTo`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L522): + Create new units of a specific type of token and add them to a token account. + This increases the supply of the token and can only be done by the mint + authority of the mint account. +- [`Transfer`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L228): + Transfer units of a specific type of token from one token account to another. + +### Mint Account + +Tokens on Solana are uniquely identified by the address of a +[Mint Account](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32) +owned by the Token Program. This account is effectively a global counter for a +specific token, and stores data such as: + +- Supply: Total supply of the token +- Decimals: Decimal precision of the token +- Mint authority: The account authorized to create new units of the token, thus + increasing the supply +- Freeze authority: The account authorized to freeze tokens from being + transferred from "token accounts" + +![Mint Account](/assets/docs/core/tokens/mint-account.svg) + +The full details stored on each Mint Account include the following: + +```rust +pub struct Mint { + /// Optional authority used to mint new tokens. The mint authority may only + /// be provided during mint creation. If no mint authority is present + /// then the mint has a fixed supply and no further tokens may be + /// minted. + pub mint_authority: COption, + /// Total supply of tokens. + pub supply: u64, + /// Number of base 10 digits to the right of the decimal place. + pub decimals: u8, + /// Is `true` if this structure has been initialized + pub is_initialized: bool, + /// Optional authority to freeze token accounts. + pub freeze_authority: COption, +} +``` + +For reference, here is a Solana Explorer link to the +[USDC Mint Account](https://explorer.solana.com/address/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v). + +### Token Account + +To track the individual ownership of each unit of a specific token, another type +of data account owned by the Token Program must be created. This account is +referred to as a +[Token Account](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L89-L110). + +The most commonly referenced data stored on the Token Account include the +following: + +- Mint: The type of token the Token Account holds units of +- Owner: The account authorized to transfer tokens out of the Token Account +- Amount: Units of the token the Token Account currently holds + +![Token Account](/assets/docs/core/tokens/token-account.svg) + +The full details stored on each Token Account includes the following: + +```rust +pub struct Account { + /// The mint associated with this account + pub mint: Pubkey, + /// The owner of this account. + pub owner: Pubkey, + /// The amount of tokens this account holds. + pub amount: u64, + /// If `delegate` is `Some` then `delegated_amount` represents + /// the amount authorized by the delegate + pub delegate: COption, + /// The account's state + pub state: AccountState, + /// If is_native.is_some, this is a native token, and the value logs the + /// rent-exempt reserve. An Account is required to be rent-exempt, so + /// the value is used by the Processor to ensure that wrapped SOL + /// accounts do not drop below this threshold. + pub is_native: COption, + /// The amount delegated + pub delegated_amount: u64, + /// Optional authority to close the account. + pub close_authority: COption, +} +``` + +For a wallet to own units of a certain token, it needs to create a token account +for a specific type of token (mint) that designates the wallet as the owner of +the token account. A wallet can create multiple token accounts for the same type +of token, but each token account can only be owned by one wallet and hold units +of one type of token. + +![Account Relationship](/assets/docs/core/tokens/token-account-relationship.svg) + +> Note that each Token Account's data includes an `owner` field used to identify +> who has authority over that specific Token Account. This is separate from the +> program owner specified in the +> [AccountInfo](/docs/core/accounts.md#accountinfo), which is the Token Program +> for all Token Accounts. + +### Associated Token Account + +To simplify the process of locating a token account's address for a specific +mint and owner, we often use Associated Token Accounts. + +An Associated Token Account is a token account whose address is +deterministically derived using the owner's address and the mint account's +address. You can think of the Associated Token Account as the "default" token +account for a specific mint and owner. + +It's important to understand that an Associated Token Account isn't a different +type of token account. It's just a token account with a specific address. + +![Associated Token Account](/assets/docs/core/tokens/associated-token-account.svg) + +This introduces a key concept in Solana development: +[Program Derived Address (PDA)](/docs/core/pda.md). Conceptually, a PDA provides +a deterministic way to generate an address using some predefined inputs. This +enables us to easily find the address of an account at a later time. + +Here is a [Solana Playground](https://beta.solpg.io/656a2dd0fb53fa325bfd0c41) +example that derives the USDC Associated Token Account address and owner. It +will always generate the +[same address](https://explorer.solana.com/address/4kokFKCFMxpCpG41yLYkLEqXW8g1WPfCt2NC9KGivY6N) +for the same mint and owner. + +```ts +import { getAssociatedTokenAddressSync } from "@solana/spl-token"; + +const associatedTokenAccountAddress = getAssociatedTokenAddressSync( + USDC_MINT_ADDRESS, + OWNER_ADDRESS, +); +``` + +Specifically, the address for an Associated Token Account is derived using the +following inputs. Here is a +[Solana Playground](https://beta.solpg.io/656a31d0fb53fa325bfd0c42) example that +generates the same address as the previous example. + +```ts +import { PublicKey } from "@solana/web3.js"; + +const [PDA, bump] = PublicKey.findProgramAddressSync( + [ + OWNER_ADDRESS.toBuffer(), + TOKEN_PROGRAM_ID.toBuffer(), + USDC_MINT_ADDRESS.toBuffer(), + ], + ASSOCIATED_TOKEN_PROGRAM_ID, +); +``` + +For two wallets to hold units of the same type of token, each wallet needs its +own token account for the specific mint account. The image below demonstrates +what this account relationship looks like. + +![Accounts Relationship Expanded](/assets/docs/core/tokens/token-account-relationship-ata.svg) + +## Token Examples + +The [`spl-token` CLI](https://docs.anza.xyz/cli) can be used to experiment with +SPL tokens. In the examples below, we'll use the +[Solana Playground](https://beta.solpg.io/) terminal to run the CLI commands +directly in the browser without having to install the CLI locally. + +Creating tokens and accounts requires SOL for account rent deposits and +transaction fees. If it is your first time using Solana Playground, created a +Playground wallet and run the `solana airdrop` command in the Playground +terminal. You can also get devnet SOL using the public +[web faucet](https://faucet.solana.com/). + +```sh +solana airdrop 2 +``` + +Run `spl-token --help` for a full description of available commands. + +```sh +spl-token --help +``` + +Alternatively, you can install the spl-token CLI locally using the following +command. This requires first [installing Rust](https://rustup.rs/). + +> In the following sections, the account addresses displayed when you run the +> CLI command will differ from the example output shown below. Please use the +> address shown in your Playground terminal when following along. For example, +> the address output from the `create-token` is the mint account where your +> Playground wallet is set as the mint authority. + +### Create a New Token + +To create a new token ([mint account](#mint-account)) run the following command +in the Solana Playground terminal. + +```sh +spl-token create-token +``` + +You should see an output similar to the following below. You can inspect both +the token and transaction details on +[Solana Explorer](https://explorer.solana.com/?cluster=devnet) using the +`Address` and `Signature`. + +In the example output below, the unique identifier (address) of the new token is +`99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg`. + +```shell filename="Terminal Output" /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ +Creating token 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg + +Address: 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg +Decimals: 9 + +Signature: 44fvKfT1ezBUwdzrCys3fvCdFxbLMnNvBstds76QZyE6cXag5NupBprSXwxPTzzjrC3cA6nvUZaLFTvmcKyzxrm1 +``` + +New tokens initially have no supply. You can check the current supply of a token +using the following command: + +```sh +spl-token supply +``` + +Running the `supply` command for a newly created token will return a value of +`0`: + +```sh /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ +spl-token supply 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg +``` + +Under the hood, creating a new Mint Account requires sending a transaction with +two instructions. Here is a Javascript example on +[Solana Playground](https://beta.solpg.io/660ce32ecffcf4b13384d00f). + +1. Invoke the System Program to create a new account with enough space for the + Mint Account data and then transfer ownership to the Token Program. + +2. Invoke the Token Program to initialize the data of the new account as a Mint + Account + +### Create Token Account + +To hold units of a particular token, you must first create a +[token account](#token-account). To create a new token account, use the +following command: + +```sh +spl-token create-account [OPTIONS] +``` + +For example, running the following command in the Solana Playground terminal: + +```sh /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ +spl-token create-account 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg +``` + +Returns the following output: + +- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` is the address of the token + account created to hold units of the token specified in the `create-account` + command. + +```shell filename="Terminal Output" /AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9/ +Creating account AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9 + +Signature: 2BtrynuCLX9CNofFiaw6Yzbx6hit66pup9Sk7aFjwU2NEbFz7NCHD9w9sWhrCfEd73XveAGK1DxFpJoQZPXU9tS1 +``` + +By default the `create-account` command creates an +[associated token account](#associated-token-account) with your wallet address +as the token account owner. + +You can create a token account with a different owner using the following +command: + +```sh +spl-token create-account --owner +``` + +For example, running the following command: + +```sh /2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR/ +spl-token create-account --owner 2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg +``` + +Returns the following output: + +- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` is the address of the token + account created to hold units of the token specified in the `create-account` + command (`99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg`) and owned by the + address specified following the `--owner` flag + (`2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR`). This is useful when you need + to create a token account for another user. + +```shell filename="Terminal Output" /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ +Creating account Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt + +Signature: 44vqKdfzspT592REDPY4goaRJH3uJ3Ce13G4BCuUHg35dVUbHuGTHvqn4ZjYF9BGe9QrjMfe9GmuLkQhSZCBQuEt +``` + +Under the hood, creating an Associated Token Account requires a single +instruction that invokes the +[Associated Token Program](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src). +Here is a Javascript example on +[Solana Playground](https://beta.solpg.io/660ce868cffcf4b13384d011). + +The Associated Token Program uses [Cross Program Invocations](/docs/core/cpi.md) +to handle: + +- [Invoking the System Program](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src/tools/account.rs#L19) + to create a new account using the provided PDA as the address of the new + account +- [Invoking the Token Program](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src/processor.rs#L138-L161) + to initialize the Token Account data for the new account. + +Alternatively, creating a new Token Account using a randomly generated keypair +(not an Associated Token Account) requires sending a transaction with two +instructions. Here is a Javascript example on +[Solana Playground](https://beta.solpg.io/660ce716cffcf4b13384d010). + +1. Invoke the System Program to create a new account with enough space for the + Token Account data and then transfer ownership to the Token Program. + +2. Invoke the Token Program to initialize the data of the new account as a Token + Account + +### Mint Tokens + +To create new units of a token, use the following command: + +```sh +spl-token mint [OPTIONS] [--] [RECIPIENT_TOKEN_ACCOUNT_ADDRESS] +``` + +For example, running the following command: + +```sh +spl-token mint 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 +``` + +Returns the following output: + +- `99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg` is the address of the mint + account that tokens are being minted for (increasing total supply). + +- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` is the address of your wallet's + token account that units of the token are being minted to (increasing amount). + +```shell filename="Terminal Output" /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ /AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9/ +Minting 100 tokens + Token: 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg + Recipient: AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9 + +Signature: 2NJ1m7qCraPSBAVxbr2ssmWZmBU9Jc8pDtJAnyZsZJRcaYCYMqq1oRY1gqA4ddQno3g3xcnny5fzr1dvsnFKMEqG +``` + +To mint tokens to a different token account, specify the address of the intended +recipient token account. For example, running the following command: + +```sh /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ +spl-token mint 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 -- Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt +``` + +Returns the following output: + +- `99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg` is the address of the mint + account that tokens are being minted for (increasing total supply). + +- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` is the address of the token + account that units of the token are being minted to (increasing amount). + +```shell filename="Terminal Output" /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ +Minting 100 tokens + Token: 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg + Recipient: Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt + +Signature: 3SQvNM3o9DsTiLwcEkSPT1Edr14RgE2wC54TEjonEP2swyVCp2jPWYWdD6RwXUGpvDNUkKWzVBZVFShn5yntxVd7 +``` + +Under the hood, creating new units of a token requires invoking the `MintTo` +instruction on the Token Program. This instruction must be signed by the mint +authority. The instruction mints new units of the token to a Token Account and +increases the total supply on the Mint Account. Here is a Javascript example on +[Solana Playground](https://beta.solpg.io/660cea45cffcf4b13384d012). + +### Transfer Tokens + +To transfer units of a token between two token accounts, use the following +command: + +```sh +spl-token transfer [OPTIONS] +``` + +For example, running the following command: + +```sh +spl-token transfer 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt +``` + +Returns the following output: + +- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` is the address of the token + account that tokens are being transferred from. This would be the address of + your token account for the specified token being transferred. + +- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` is the address of the token + account that tokens are being transferred to. + +```shell filename="Terminal Output" /AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9/ /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ +Transfer 100 tokens + Sender: AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9 + Recipient: Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt + +Signature: 5y6HVwV8V2hHGLTVmTmdySRiEUCZnWmkasAvJ7J6m7JR46obbGKCBqUFgLpZu5zQGwM4Xy6GZ4M5LKd1h6Padx3o +``` + +Under the hood, transferring tokens requires invoking the `Transfer` instruction +on the Token Program. This instruction must be signed by the owner of the +sender's Token Account. The instruction transfers units of a token from one +Token Account to another Token Account. Here is a Javascript example on +[Solana Playground](https://beta.solpg.io/660ced84cffcf4b13384d013). + +It's important to understand that both the sender and recipient must have +existing token accounts for the specific type of token being transferred. The +sender can include additional instructions on the transaction to create the +recipient's token account, which generally is the Associated Token Account. + +### Create Token Metadata + +The Token Extensions Program enables additional customizable metadata (such as +name, symbol, link to image) to be stored directly on the Mint Account. + + + To use the Token Extensions CLI flags, ensure you have a local installation of the CLI, version 3.4.0 or later: + + `cargo install --version 3.4.0 spl-token-cli` + + +To create a new token with the metadata extension enabled, using the following +command: + +```sh +spl-token create-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb +--enable-metadata +``` + +The command returns the following output: + +- `BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP` is the address of the new token + created with the metadata extension enabled. + +```shell filename="Terminal Output" /BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP/ +Creating token BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP under program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb +To initialize metadata inside the mint, please run `spl-token initialize-metadata BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP `, and sign with the mint authority. + +Address: BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP +Decimals: 9 + +Signature: 5iQofFeXdYhMi9uTzZghcq8stAaa6CY6saUwcdnELST13eNSifiuLbvR5DnRt311frkCTUh5oecj8YEvZSB3wfai +``` + +Once a new token is created with the metadata extension enabled, use the +following command to initialize the metadata. + +```sh +spl-token initialize-metadata + +``` + +The token URI is normally a link to offchain metadata you want to associate with +the token. You can find an example of the JSON format +[here](https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json). + +For example, running the following command will store the additional metadata +directly on the specified mint account: + +```sh /BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP/ +spl-token initialize-metadata BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP "TokenName" "TokenSymbol" "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json" +``` + +You can then look up the address of the mint account on an explorer to inspect +the metadata. For example, here is a token created with the metadata extension +enabled on the +[SolanaFm](https://solana.fm/address/BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP?cluster=devnet-solana) +explorer. + +You can learn more on the +[Metadata Extension Guide](https://solana.com/developers/guides/token-extensions/metadata-pointer). +For more details related to various Token Extensions, refer to the Token +Extensions +[Getting Started Guide](https://solana.com/developers/guides/token-extensions/getting-started) +and the [SPL documentation](https://spl.solana.com/token-2022/extensions). diff --git a/docs/uk/core/transactions.md b/docs/uk/core/transactions.md new file mode 100644 index 000000000..4cf2554fa --- /dev/null +++ b/docs/uk/core/transactions.md @@ -0,0 +1,415 @@ +--- +title: "Transactions and Instructions" +sidebarSortOrder: 2 +description: + Learn about Solana transactions and instructions - the fundamental building + blocks for interacting with the Solana blockchain. Understand transaction + structure and instruction composition with practical examples. +--- + +On Solana, we send [transactions](/docs/core/transactions#transaction) to +interact with the network. Transactions include one or more +[instructions](/docs/core/transactions#instruction), each representing a +specific operation to be processed. The execution logic for instructions is +stored on [programs](/docs/core/programs) deployed to the Solana network, where +each program stores its own set of instructions. + +Below are key details about how transactions are executed: + +- Execution Order: If a transaction includes multiple instructions, the + instructions are processed in the order they are added to the transaction. +- Atomicity: A transaction is atomic, meaning it either fully completes with all + instructions successfully processed, or fails altogether. If any instruction + within the transaction fails, none of the instructions are executed. + +For simplicity, a transaction can be thought of as a request to process one or +multiple instructions. + +![Transaction Simplified](/assets/docs/core/transactions/transaction-simple.svg) + +You can imagine a transaction as an envelope, where each instruction is a +document that you fill out and place inside the envelope. We then mail out the +envelope to process the documents, just like sending a transaction on the +network to process our instructions. + +## Key Points + +- Solana transactions consist of instructions that interact with various + programs on the network, where each instruction represents a specific + operation. + +- Each instruction specifies the program to execute the instruction, the + accounts required by the instruction, and the data required for the + instruction's execution. + +- Instructions within a transaction are processed in the order they are listed. + +- Transactions are atomic, meaning either all instructions process successfully, + or the entire transaction fails. + +- The maximum size of a transaction is 1232 bytes. + +## Basic Example + +Below is a diagram representing a transaction with a single instruction to +transfer SOL from a sender to a receiver. + +Individual "wallets" on Solana are accounts owned by the +[System Program](/docs/core/accounts#system-program). As part of the +[Solana Account Model](/docs/core/accounts), only the program that owns an +account is allowed to modify the data on the account. + +Therefore, transferring SOL from a "wallet" account requires sending a +transaction to invoke the transfer instruction on the System Program. + +![SOL Transfer](/assets/docs/core/transactions/sol-transfer.svg) + +The sender account must be included as a signer (`is_signer`) on the transaction +to approve the deduction of their lamport balance. Both the sender and recipient +accounts must be mutable (`is_writable`) because the instruction modifies the +lamport balance for both accounts. + +Once the transaction is sent, the System Program is invoked to process the +transfer instruction. The System Program then updates the lamport balances of +both the sender and recipient accounts accordingly. + +![SOL Transfer Process](/assets/docs/core/transactions/sol-transfer-process.svg) + +### Simple SOL Transfer + +Here is a [Solana Playground](https://beta.solpg.io/656a0ea7fb53fa325bfd0c3e) +example of how to build a SOL transfer instruction using the +`SystemProgram.transfer` method: + +```typescript +// Define the amount to transfer +const transferAmount = 0.01; // 0.01 SOL + +// Create a transfer instruction for transferring SOL from wallet_1 to wallet_2 +const transferInstruction = SystemProgram.transfer({ + fromPubkey: sender.publicKey, + toPubkey: receiver.publicKey, + lamports: transferAmount * LAMPORTS_PER_SOL, // Convert transferAmount to lamports +}); + +// Add the transfer instruction to a new transaction +const transaction = new Transaction().add(transferInstruction); +``` + +Run the script and inspect the transaction details logged to the console. In the +sections below, we'll walk through the details of what's happening under the +hood. + +## Transaction + +A Solana +[transaction](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/transaction/mod.rs#L173) +consists of: + +1. [Signatures](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/signature.rs#L27): + An array of signatures included on the transaction. +2. [Message](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L110): + List of instructions to be processed atomically. + +![Transaction Format](/assets/docs/core/transactions/tx_format.png) + +The structure of a transaction message comprises of: + +- [Message Header](/docs/core/transactions#message-header): Specifies the number + of signer and read-only account. +- [Account Addresses](/docs/core/transactions#array-of-account-addresses): An + array of account addresses required by the instructions on the transaction. +- [Recent Blockhash](/docs/core/transactions#recent-blockhash): Acts as a + timestamp for the transaction. +- [Instructions](/docs/core/transactions#array-of-instructions): An array of + instructions to be executed. + +![Transaction Message](/assets/docs/core/transactions/legacy_message.png) + +### Transaction Size + +The Solana network adheres to a maximum transmission unit (MTU) size of 1280 +bytes, consistent with the [IPv6 MTU](https://en.wikipedia.org/wiki/IPv6_packet) +size constraints to ensure fast and reliable transmission of cluster information +over UDP. After accounting for the necessary headers (40 bytes for IPv6 and 8 +bytes for the fragment header), +[1232 bytes remain available for packet data](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/packet.rs#L16-L21), +such as serialized transactions. + +This means that the total size of a Solana transaction is limited to 1232 bytes. +The combination of the signatures and the message cannot exceed this limit. + +- Signatures: Each signature requires 64 bytes. The number of signatures can + vary, depending on the transaction's requirements. +- Message: The message includes instructions, accounts, and additional metadata, + with each account requiring 32 bytes. The combined size of the accounts plus + metadata can vary, depending on the instructions included in the transaction. + +![Transaction Format](/assets/docs/core/transactions/issues_with_legacy_txs.png) + +### Message Header + +The +[message header](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/mod.rs#L96) +specifies the privileges of accounts included in the transaction's account +address array. It is comprised of three bytes, each containing a u8 integer, +which collectively specify: + +1. The number of required signatures for the transaction. +2. The number of read-only account addresses that require signatures. +3. The number of read-only account addresses that do not require signatures. + +![Message Header](/assets/docs/core/transactions/message_header.png) + +### Compact-Array Format + +A compact array in the context of a transaction message refers to an array +serialized in the following format: + +1. The length of the array, encoded as + [compact-u16](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/short_vec.rs). +2. The individual items of the array listed sequentially after the encoded + length. + +![Compact array format](/assets/docs/core/transactions/compact_array_format.png) + +This encoding method is used to specify the lengths of both the +[Account Addresses](/docs/core/transactions#array-of-account-addresses) and +[Instructions](/docs/core/transactions#array-of-instructions) arrays within a +transaction message. + +### Array of Account Addresses + +A transaction message includes an array containing all the +[account addresses](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L119) +needed for the instructions within the transaction. + +This array starts with a +[compact-u16](/docs/core/transactions#compact-array-format) encoding of the +number of account addresses, followed by the addresses ordered by the privileges +for the accounts. The metadata in the message header is used to determine the +number of accounts in each section. + +- Accounts that are writable and signers +- Accounts that are read-only and signers +- Accounts that are writable and not signers +- Accounts that are read-only and not signers + +![Compact array of account addresses](/assets/docs/core/transactions/compat_array_of_account_addresses.png) + +### Recent Blockhash + +All transactions include a +[recent blockhash](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L122) +to act as a timestamp for the transaction. The blockhash is used to prevent +duplications and eliminate stale transactions. + +The maximum age of a transaction's blockhash is 150 blocks (~1 minute assuming +400ms block times). If a transaction's blockhash is 150 blocks older than the +latest blockhash, it is considered expired. This means that transactions not +processed within a specific timeframe will never be executed. + +You can use the [`getLatestBlockhash`](/docs/rpc/http/getlatestblockhash) RPC +method to get the current blockhash and last block height at which the blockhash +will be valid. Here is an example on +[Solana Playground](https://beta.solpg.io/661a06e1cffcf4b13384d046). + +### Array of Instructions + +A transaction message includes an array of all +[instructions](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L128) +requesting to be processed. Instructions within a transaction message are in the +format of +[CompiledInstruction](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L633). + +Much like the array of account addresses, this compact array starts with a +[compact-u16](/docs/core/transactions#compact-array-format) encoding of the +number of instructions, followed by an array of instructions. Each instruction +in the array specifies the following information: + +1. **Program ID**: Identifies an on-chain program that will process the + instruction. This is represented as an u8 index pointing to an account + address within the account addresses array. +2. **Compact array of account address indexes**: Array of u8 indexes pointing to + the account addresses array for each account required by the instruction. +3. **Compact array of opaque u8 data**: A u8 byte array specific to the program + invoked. This data specifies the instruction to invoke on the program along + with any additional data that the instruction requires (such as function + arguments). + +![Compact array of Instructions](/assets/docs/core/transactions/compact_array_of_ixs.png) + +### Example Transaction Structure + +Below is an example of the structure of a transaction including a single +[SOL transfer](/docs/core/transactions#basic-example) instruction. It shows the +message details including the header, account keys, blockhash, and the +instructions, along with the signature for the transaction. + +- `header`: Includes data used to specify the read/write and signer privileges + in the `accountKeys` array. + +- `accountKeys`: Array including account addresses for all instructions on the + transaction. + +- `recentBlockhash`: The blockhash included on the transaction when the + transaction was created. + +- `instructions`: Array including all the instructions on the transaction. Each + `account` and `programIdIndex` in an instruction references the `accountKeys` + array by index. + +- `signatures`: Array including signatures for all accounts required as signers + by the instructions on the transaction. A signature is created by signing the + transaction message using the corresponding private key for an account. + +```json +"transaction": { + "message": { + "header": { + "numReadonlySignedAccounts": 0, + "numReadonlyUnsignedAccounts": 1, + "numRequiredSignatures": 1 + }, + "accountKeys": [ + "3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R", + "5snoUseZG8s8CDFHrXY2ZHaCrJYsW457piktDmhyb5Jd", + "11111111111111111111111111111111" + ], + "recentBlockhash": "DzfXchZJoLMG3cNftcf2sw7qatkkuwQf4xH15N5wkKAb", + "instructions": [ + { + "accounts": [ + 0, + 1 + ], + "data": "3Bxs4NN8M2Yn4TLb", + "programIdIndex": 2, + "stackHeight": null + } + ], + "indexToProgramIds": {} + }, + "signatures": [ + "5LrcE2f6uvydKRquEJ8xp19heGxSvqsVbcqUeFoiWbXe8JNip7ftPQNTAVPyTK7ijVdpkzmKKaAQR7MWMmujAhXD" + ] + } +``` + +## Instruction + +An +[instruction](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L329) +is a request to process a specific action on-chain and is the smallest +contiguous unit of execution logic in a +[program](/docs/core/accounts#program-account). + +When building an instruction to add to a transaction, each instruction must +include the following information: + +- **Program address**: Specifies the program being invoked. +- **Accounts**: Lists every account the instruction reads from or writes to, + including other programs, using the `AccountMeta` struct. +- **Instruction Data**: A byte array that specifies which + [instruction handler](/docs/terminology#instruction-handler) on the program to + invoke, plus any additional data required by the instruction handler (function + arguments). + +![Transaction Instruction](/assets/docs/core/transactions/instruction.svg) + +### AccountMeta + +For every account required by an instruction, the following info must be +specified: + +- `pubkey`: The on-chain address of an account +- `is_signer`: Specify if the account is required as a signer on the transaction +- `is_writable`: Specify if the account data will be modified + +This information is referred to as the +[AccountMeta](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L539). + +![AccountMeta](/assets/docs/core/transactions/accountmeta.svg) + +By specifying all accounts required by an instruction, and whether each account +is writable, transactions can be processed in parallel. + +For example, two transactions that do not include any accounts that write to the +same state can be executed at the same time. + +### Example Instruction Structure + +Below is an example of the structure of a +[SOL transfer](/docs/core/transactions#basic-examples) instruction which details +the account keys, program ID, and data required by the instruction. + +- `keys`: Includes the `AccountMeta` for each account required by an + instruction. +- `programId`: The address of the program which contains the execution logic for + the instruction invoked. +- `data`: The instruction data for the instruction as a buffer of bytes + +``` +{ + "keys": [ + { + "pubkey": "3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R", + "isSigner": true, + "isWritable": true + }, + { + "pubkey": "BpvxsLYKQZTH42jjtWHZpsVSa7s6JVwLKwBptPSHXuZc", + "isSigner": false, + "isWritable": true + } + ], + "programId": "11111111111111111111111111111111", + "data": [2,0,0,0,128,150,152,0,0,0,0,0] +} +``` + +## Expanded Example + +The details for building program instructions are often abstracted away by +client libraries. However, if one is not available, you can always fall back to +manually building the instruction. + +### Manual SOL Transfer + +Here is a [Solana Playground](https://beta.solpg.io/656a102efb53fa325bfd0c3f) +example of how to manually build a SOL transfer instruction: + +```typescript +// Define the amount to transfer +const transferAmount = 0.01; // 0.01 SOL + +// Instruction index for the SystemProgram transfer instruction +const transferInstructionIndex = 2; + +// Create a buffer for the data to be passed to the transfer instruction +const instructionData = Buffer.alloc(4 + 8); // uint32 + uint64 +// Write the instruction index to the buffer +instructionData.writeUInt32LE(transferInstructionIndex, 0); +// Write the transfer amount to the buffer +instructionData.writeBigUInt64LE(BigInt(transferAmount * LAMPORTS_PER_SOL), 4); + +// Manually create a transfer instruction for transferring SOL from sender to receiver +const transferInstruction = new TransactionInstruction({ + keys: [ + { pubkey: sender.publicKey, isSigner: true, isWritable: true }, + { pubkey: receiver.publicKey, isSigner: false, isWritable: true }, + ], + programId: SystemProgram.programId, + data: instructionData, +}); + +// Add the transfer instruction to a new transaction +const transaction = new Transaction().add(transferInstruction); +``` + +Under the hood, the +[simple example](/docs/core/transactions#simple-sol-transfer) using the +`SystemProgram.transfer` method is functionally equivalent to the more verbose +example above. The `SystemProgram.transfer` method simply abstracts away the +details of creating the instruction data buffer and `AccountMeta` for each +account required by the instruction. diff --git a/docs/uk/economics/index.md b/docs/uk/economics/index.md new file mode 100644 index 000000000..55444a801 --- /dev/null +++ b/docs/uk/economics/index.md @@ -0,0 +1,52 @@ +--- +sidebarLabel: Economics +title: Solana Economics Overview +altRoutes: + - /docs/intro/economics +sidebarSortOrder: 5 +--- + +**Subject to change.** + +Solana's crypto-economic system is designed to promote a healthy, long term +self-sustaining economy with participant incentives aligned to the security and +decentralization of the network. The main participants in this economy are +validation-clients. Their contributions to the network, state validation, and +their requisite incentive mechanisms are discussed below. + +The main channels of participant remittances are referred to as protocol-based +rewards and transaction fees. Protocol-based rewards are generated from +inflationary issuances from a protocol-defined inflation schedule. These rewards +will constitute the total protocol-based reward delivered to validation clients, +the remaining sourced from transaction fees. In the early days of the network, +it is likely that protocol-based rewards, deployed based on predefined issuance +schedule, will drive the majority of participant incentives to participate in +the network. + +These protocol-based rewards are calculated per epoch and distributed across the +active delegated stake and validator set (per validator commission). As +discussed further below, the per annum inflation rate is based on a +pre-determined disinflationary schedule. This provides the network with supply +predictability which supports long term economic stability and security. + +Transaction fees are participant-to-participant transfers, attached to network +interactions as a motivation and compensation for the inclusion and execution of +a proposed transaction. A mechanism for long-term economic stability and forking +protection through partial burning of each transaction fee is also discussed +below. + +First, an overview of the inflation design is presented. This section starts +with defining and clarifying +[Terminology](/docs/economics/inflation/terminology.md) commonly used +subsequently in the discussion of inflation and the related components. +Following that, we outline Solana's proposed +[Inflation Schedule](/docs/economics/inflation/inflation_schedule.md), i.e. the +specific parameters that uniquely parameterize the protocol-driven inflationary +issuance over time. Next is a brief section on +[Adjusted Staking Yield](/docs/economics/inflation/_adjusted_staking_yield.md), +and how token dilution might influence staking behavior. + +An overview of [Transaction Fees](/docs/core/fees.md#transaction-fees) on Solana +is followed by a discussion of [Storage Rent Economics](/docs/core/fees.md#rent) +in which we describe an implementation of storage rent to account for the +externality costs of maintaining the active state of the ledger. diff --git a/docs/uk/economics/inflation/_adjusted_staking_yield.md b/docs/uk/economics/inflation/_adjusted_staking_yield.md new file mode 100644 index 000000000..33abf65a9 --- /dev/null +++ b/docs/uk/economics/inflation/_adjusted_staking_yield.md @@ -0,0 +1,170 @@ +--- +title: Adjusted Staking Yield +--- + +### Token Dilution + +Similarly we can look at the expected _Staked Dilution_ (i.e. _Adjusted Staking +Yield_) and _Un-staked Dilution_ as previously defined. Again, _dilution_ in +this context is defined as the change in fractional representation (i.e. +ownership) of a set of tokens within a larger set. In this sense, dilution can +be a positive value: an increase in fractional ownership (staked dilution / +_Adjusted Staking Yield_), or a negative value: a decrease in fractional +ownership (un-staked dilution). + +We are interested in the relative change in ownership of staked vs un-staked +tokens as the overall token pool increases with inflation issuance. As +discussed, this issuance is distributed only to staked token holders, increasing +the staked token fractional representation of the _Total Current Supply_. + +Continuing with the same _Inflation Schedule_ parameters as above, we see the +fraction of staked supply grow as shown below. + +![Graph of example growth of staked supply](/assets/docs/economics/example_staked_supply_w_range_initial_stake.png) + +Due to this relative change in representation, the proportion of stake of any +token holder will also change as a function of the _Inflation Schedule_ and the +proportion of all tokens that are staked. + +Of initial interest, however, is the _dilution of **un-staked** tokens_, or +$D_{us}$. In the case of un-staked tokens, token dilution is only a function of +the _Inflation Schedule_ because the amount of un-staked tokens doesn't change +over time. + +This can be seen by explicitly calculating un-staked dilution as $D_{us}$. The +un-staked proportion of the token pool at time $t$ is $P_{us}(t_{N})$ and +$I_{t}$ is the incremental inflation rate applied between any two consecutive +time points. $SOL_{us}(t)$ and $SOL_{total}(t)$ is the amount of un-staked and +total SOL on the network, respectively, at time $t$. Therefore +$P_{us}(t) = SOL_{us}(t)/SOL_{total}(t)$. + +$$ +\begin{aligned} + D_{us} &= \left( \frac{P_{us}(t_{1}) - P_{us}(t_{0})}{P_{us}(t_{0})} \right)\\ + &= \left( \frac{ \left( \frac{SOL_{us}(t_{2})}{SOL_{total}(t_{2})} \right) - \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})} \right)}{ \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})} \right) } \right)\\ + +\end{aligned} +$$ + +However, because inflation issuance only increases the total amount and the +un-staked supply doesn't change: + +$$ +\begin{aligned} + SOL_{us}(t_2) &= SOL_{us}(t_1)\\ + SOL_{total}(t_2) &= SOL_{total}(t_1)\times (1 + I_{t_1})\\ +\end{aligned} +$$ + +So $D_{us}$ becomes: + +$$ +\begin{aligned} + D_{us} &= \left( \frac{ \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})\times (1 + I_{1})} \right) - \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})} \right)}{ \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})} \right) } \right)\\ + D_{us} &= \frac{1}{(1 + I_{1})} - 1\\ +\end{aligned} +$$ + +Or generally, dilution for un-staked tokens over any time frame undergoing +inflation $I$: + +$$ +D_{us} = -\frac{I}{I + 1} \\ +$$ + +So as guessed, this dilution is independent of the total proportion of staked +tokens and only depends on inflation rate. This can be seen with our example +_Inflation Schedule_ here: + +![Graph of an example dilution of unstaked SOL](/assets/docs/economics/example_unstaked_dilution.png) + +### Estimated Adjusted Staked Yield + +We can do a similar calculation to determine the _dilution_ of staked token +holders, or as we've defined here as the **_Adjusted Staked Yield_**, keeping in +mind that dilution in this context is an _increase_ in proportional ownership +over time. We'll use the terminology _Adjusted Staked Yield_ to avoid confusion +going forward. + +To see the functional form, we calculate, $Y_{adj}$, or the _Adjusted Staked +Yield_ (to be compared to _D\_{us}_ the dilution of un-staked tokens above), +where $P_{s}(t)$ is the staked proportion of token pool at time $t$ and $I_{t}$ +is the incremental inflation rate applied between any two consecutive time +points. The definition of $Y_{adj}$ is therefore: + +$$ + Y_{adj} = \frac{P_s(t_2) - P_s(t_1)}{P_s(t_1)}\\ +$$ + +As seen in the plot above, the proportion of staked tokens increases with +inflation issuance. Letting $SOL_s(t)$ and $SOL_{\text{total}}(t)$ represent the +amount of staked and total SOL at time $t$ respectively: + +$$ + P_s(t_2) = \frac{SOL_s(t_1) + SOL_{\text{total}}(t_1)\times I(t_1)}{SOL_{\text{total}}(t_1)\times (1 + I(t_1))}\\ +$$ + +Where $SOL_{\text{total}}(t_1)\times I(t_1)$ is the additional inflation +issuance added to the staked token pool. Now we can write $Y_{adj}$ in common +terms $t_1 = t$: + +$$ +\begin{aligned} +Y_{adj} &= \frac{\frac{SOL_s(t) + SOL_{\text{total}}(t)\times I(t)}{SOL_{\text{total}}(t)\times (1 + I(t))} - \frac{SOL_s(t)}{SOL_{\text{total}}(t)} }{ \frac{SOL_s(t)}{SOL_{\text{total}}(t)} } \\ + &= \frac{ SOL_{\text{total}}(t)\times (SOL_s(t) + SOL_{\text{total}}(t)\times I(t)) }{ SOL_s(t)\times SOL_{\text{total}}\times (1 + I(t)) } -1 \\ +\end{aligned} +$$ + +which simplifies to: + +$$ +Y_{adj} = \frac{ 1 + I(t)/P_s(t) }{ 1 + I(t) } - 1\\ +$$ + +So we see that the _Adjusted Staked Yield_ is a function of the inflation rate +and the percent of staked tokens on the network. We can see this plotted for +various staking fractions here: + +![Graph of example adjusted staking yields](/assets/docs/economics/example_adjusted_staking_yields.png) + +It is also clear that in all cases, dilution of un-staked tokens $>$ adjusted +staked yield (i.e. dilution of staked tokens). Explicitly we can look at the +_relative dilution of un-staked tokens to staked tokens:_ $D_{us}/Y_{adj}$. Here +the relationship to inflation drops out and the relative dilution, i.e. the +impact of staking tokens vs not staking tokens, is purely a function of the % of +the total token supply staked. From above + +$$ +\begin{aligned} +Y_{adj} &= \frac{ 1 + I/P_s }{ 1 + I } - 1,~\text{and}\\ +D_{us} &= -\frac{I}{I + 1},~\text{so} \\ +\frac{D_{us}}{Y_{adj}} &= \frac{ \frac{I}{I + 1} }{ \frac{ 1 + I/P_s }{ 1 + I } - 1 } \\ +\end{aligned} +$$ + +which simplifies as, + +$$ + \begin{aligned} + \frac{D_{us}}{Y_{adj}} &= \frac{ I }{ 1 + \frac{I}{P_s} - (1 + I)}\\ + &= \frac{ I }{ \frac{I}{P_s} - I}\\ + \frac{D_{us}}{Y_{adj}}&= \frac{ P_s }{ 1 - P_s}\\ + \end{aligned} +$$ + +Where we can see a primary dependence of the relative dilution of un-staked +tokens to staked tokens is on the function of the proportion of total tokens +staked. As shown above, the proportion of total tokens staked changes over time +(i.e. $P_s = P_s(t)$ due to the re-staking of inflation issuance thus we see +relative dilution grow over time as: + +![Graph of example relative un-staked vs staked SOL dilution](/assets/docs/economics/example_relative_dilution.png) + +As might be intuitive, as the total fraction of staked tokens increases the +relative dilution of un-staked tokens grows dramatically. E.g. with $80\%$ of +the network tokens staked, an un-staked token holder will experience ~$400\%$ +more dilution than a staked holder. + +Again, this represents the change in fractional change in ownership of staked +tokens and illustrates the built-in incentive for token holder to stake their +tokens to earn _Staked Yield_ and avoid _Un-staked Dilution_. diff --git a/docs/uk/economics/inflation/inflation-schedule.md b/docs/uk/economics/inflation/inflation-schedule.md new file mode 100644 index 000000000..e3ae311c8 --- /dev/null +++ b/docs/uk/economics/inflation/inflation-schedule.md @@ -0,0 +1,88 @@ +--- +sidebarLabel: Proposed Inflation Schedule +title: Proposed Inflation Schedule +altRoutes: + - /docs/economics/inflation/inflation_schedule + - /docs/intro/economics +--- + +As mentioned above, the network's _Inflation Schedule_ is uniquely described by +three parameters: _Initial Inflation Rate_, _Disinflation Rate_ and _Long-term +Inflation Rate_. When considering these numbers, there are many factors to take +into account: + +- A large portion of the SOL issued via inflation will be distributed to + stake-holders in proportion to the SOL they have staked. We want to ensure + that the _Inflation Schedule_ design results in reasonable _Staking Yields_ + for token holders who delegate SOL and for validation service providers (via + commissions taken from _Staking Yields_). +- The primary driver of _Staked Yield_ is the amount of SOL staked divided by + the total amount of SOL (% of total SOL staked). Therefore the distribution + and delegation of tokens across validators are important factors to understand + when determining initial inflation parameters. +- Yield throttling is a current area of research that would impact + _staking-yields_. This is not taken into consideration in the discussion here + or the modeling below. +- Overall token issuance - i.e. what do we expect the Current Total Supply to be + in 10 years, or 20 years? +- Long-term, steady-state inflation is an important consideration not only for + sustainable support for the validator ecosystem and the Solana Foundation + grant programs, but also should be tuned in consideration with expected token + losses and burning over time. +- The rate at which we expect network usage to grow, as a consideration to the + disinflationary rate. Over time, we plan for inflation to drop and expect that + usage will grow. + +Based on these considerations and the community discussions following the +initial design, the Solana Foundation proposes the following Inflation Schedule +parameters: + +- Initial Inflation Rate: 8% +- Disinflation Rate: -15% +- Long-term Inflation Rate: 1.5% + +These parameters define the proposed _Inflation Schedule_. Below we show +implications of these parameters. These plots only show the impact of inflation +issuances given the Inflation Schedule as parameterized above. They _do not +account_ for other factors that may impact the Total Supply such as fee/rent +burning, slashing or other unforeseen future token destruction events. +Therefore, what is presented here is an **upper limit** on the amount of SOL +issued via inflation. + +![Example proposed inflation schedule graph](/assets/docs/economics/proposed_inflation_schedule.png) + +In the above graph we see the annual inflation rate percentage over time, given +the inflation parameters proposed above. + +![Example proposed total supply graph](/assets/docs/economics/proposed_total_supply.png) + +Similarly, here we see the _Total Current Supply_ of SOL [MM] over time, +assuming an initial _Total Current Supply_ of `488,587,349 SOL` (i.e. for this +example, taking the _Total Current Supply_ as of `2020-01-25` and simulating +inflation starting from that day). + +Setting aside validator uptime and commissions, the expected Staking Yield and +Adjusted Staking Yield metrics are then primarily a function of the % of total +SOL staked on the network. Therefore we can model _Staking Yield_, if we +introduce an additional parameter _% of Staked SOL_: + + + +This parameter must be estimated because it is a dynamic property of the token +holders and staking incentives. The values of _% of Staked SOL_ presented here +range from 60% - 90%, which we feel covers the likely range we expect to +observe, based on feedback from the investor and validator communities as well +as what is observed on comparable Proof-of-Stake protocols. + +![Example staked yields graph](/assets/docs/economics/example_staked_yields.png) + +Again, the above shows an example _Staked Yield_ that a staker might expect over +time on the Solana network with the _Inflation Schedule_ as specified. This is +an idealized _Staked Yield_ as it neglects validator uptime impact on rewards, +validator commissions, potential yield throttling and potential slashing +incidents. It additionally ignores that _% of Staked SOL_ is dynamic by design - +the economic incentives set up by this _Inflation Schedule_ are more clearly +seen when _Token Dilution_ is taken into account (see the **Adjusted Staking +Yield** section below). diff --git a/docs/uk/economics/inflation/terminology.md b/docs/uk/economics/inflation/terminology.md new file mode 100644 index 000000000..c6d6503f9 --- /dev/null +++ b/docs/uk/economics/inflation/terminology.md @@ -0,0 +1,112 @@ +--- +sidebarLabel: Inflation Terminology +title: Inflation Related Terminology +--- + +Many terms are thrown around when discussing inflation and the related +components (e.g. rewards/yield/interest), we try to define and clarify some +commonly used concept here: + +### Total Current Supply [SOL] + +The total amount of tokens (locked or unlocked) that have been generated (via +genesis block or protocol inflation) minus any tokens that have been burnt (via +transaction fees or other mechanism) or slashed. At network launch, 500,000,000 +SOL were instantiated in the genesis block. Since then the Total Current Supply +has been reduced by the burning of transaction fees and a planned token +reduction event. Solana's _Total Current Supply_ can be found at +https://explorer.solana.com/supply + +### Inflation Rate [%] + +The Solana protocol will automatically create new tokens on a predetermined +inflation schedule (discussed below). The _Inflation Rate [%]_ is the annualized +growth rate of the _Total Current Supply_ at any point in time. + +### Inflation Schedule + +A deterministic description of token issuance over time. The Solana Foundation +is proposing a disinflationary _Inflation Schedule_. I.e. Inflation starts at +its highest value, the rate reduces over time until stabilizing at a +predetermined long-term inflation rate (see discussion below). This schedule is +completely and uniquely parameterized by three numbers: + +- **Initial Inflation Rate [%]**: The starting _Inflation Rate_ for when + inflation is first enabled. Token issuance rate can only decrease from this + point. +- **Disinflation Rate [%]**: The rate at which the _Inflation Rate_ is reduced. +- **Long-term Inflation Rate [%]**: The stable, long-term _Inflation Rate_ to be + expected. + +### Effective Inflation Rate [%] + +The inflation rate actually observed on the Solana network after accounting for +other factors that might decrease the _Total Current Supply_. Note that it is +not possible for tokens to be created outside of what is described by the +_Inflation Schedule_. + +- While the _Inflation Schedule_ determines how the protocol issues SOL, this + neglects the concurrent elimination of tokens in the ecosystem due to various + factors. The primary token burning mechanism is the burning of a portion of + each transaction fee. 50% of each transaction fee is burned, with the + remaining fee retained by the validator that processes the transaction. +- Additional factors such as loss of private keys and slashing events should + also be considered in a holistic analysis of the _Effective Inflation Rate_. + For example, it's estimated that 10-20% of all BTC have been lost and are + unrecoverable and that networks may experience similar yearly losses at the + rate of 1-2%. + +### Staking Yield [%] + +The rate of return (aka _interest_) earned on SOL staked on the network. It is +often quoted as an annualized rate (e.g. "the network _staking yield_ is +currently 10% per year"). + +- _Staking yield_ is of great interest to validators and token holders who wish + to delegate their tokens to avoid token dilution due to inflation (the extent + of which is discussed below). +- 100% of inflationary issuances are to be distributed to staked token-holders + in proportion to their staked SOL and to validators who charge a commission on + the rewards earned by their delegated SOL. + - There may be future consideration for an additional split of inflation + issuance with the introduction of _Archivers_ into the economy. _Archivers_ + are network participants who provide a decentralized storage service and + should also be incentivized with token distribution from inflation issuances + for this service. - Similarly, early designs specified a fixed percentage of + inflationary issuance to be delivered to the Foundation treasury for + operational expenses and future grants. However, inflation will be launching + without any portion allocated to the Foundation. +- _Staking yield_ can be calculated from the _Inflation Schedule_ along with the + fraction of the _Total Current Supply_ that is staked at any given time. The + explicit relationship is given by: + + + +### Token Dilution [%] + +Dilution is defined here as the change in proportional representation of a set +of tokens within a larger set due to the introduction of new tokens. In +practical terms, we discuss the dilution of staked or un-staked tokens due to +the introduction and distribution of inflation issuance across the network. As +will be shown below, while dilution impacts every token holder, the _relative_ +dilution between staked and un-staked tokens should be the primary concern to +un-staked token holders. Staking tokens, which will receive their proportional +distribution of inflation issuance, should assuage any dilution concerns for +staked token holders. I.e. dilution from 'inflation' is offset by the +distribution of new tokens to staked token holders, nullifying the 'dilutive' +effects of the inflation for that group. + +### Adjusted Staking Yield [%] + +A complete appraisal of earning potential from staking tokens should take into +account staked _Token Dilution_ and its impact on the _Staking Yield_. For this, +we define the _Adjusted Staking Yield_ as the change in fractional token supply +ownership of staked tokens due to the distribution of inflation issuance. I.e. +the positive dilutive effects of inflation. diff --git a/docs/uk/economics/staking/index.md b/docs/uk/economics/staking/index.md new file mode 100644 index 000000000..b4e741f43 --- /dev/null +++ b/docs/uk/economics/staking/index.md @@ -0,0 +1,98 @@ +--- +sidebarLabel: Staking +title: Staking on Solana +--- + +_Note before reading: All references to increases in values are in absolute +terms with regards to balance of SOL. This document makes no suggestion as to +the monetary value of SOL at any time._ + +By staking your SOL tokens, you help secure the network and +[earn rewards](https://docs.anza.xyz/implemented-proposals/staking-rewards) +while doing so. + +You can stake by delegating your tokens to validators who process transactions +and run the network. + +Delegating stake is a shared-risk shared-reward financial model that may provide +returns to holders of tokens delegated for a long period. This is achieved by +aligning the financial incentives of the token-holders (delegators) and the +validators to whom they delegate. + +The more stake delegated to a validator, the more often this validator is chosen +to write new transactions to the ledger. The more transactions the validator +writes, the more rewards the validator and its delegators earn. Validators who +configure their systems to be able to process more transactions earn +proportionally more rewards and because they keep the network running as fast +and as smoothly as possible. + +Validators incur costs by running and maintaining their systems, and this is +passed on to delegators in the form of a fee collected as a percentage of +rewards earned. This fee is known as a _commission_. Since validators earn more +rewards the more stake is delegated to them, they may compete with one another +to offer the lowest commission for their services. + +Although this is not implemented in the Solana protocol today, in the future, +delegators could risk losing tokens when staking through a process known as +_slashing_. Slashing involves the removal and destruction of a portion of a +validator's SOL in response to intentional malicious behavior, such as creating +invalid transactions or censoring certain types of transactions or network +participants. + +There is no in protocol implementation of slashing currently. For more +information on slashing see the +[slashing roadmap](https://docs.anza.xyz/proposals/optimistic-confirmation-and-slashing#slashing-roadmap). + +## How do I stake my SOL tokens? + +You can stake SOL by moving your tokens into a wallet that supports staking. The +wallet provides steps to create a stake account and do the delegation. + +#### Supported Wallets + +Many web and mobile wallets support Solana staking operations. Please check with +your favorite wallet's maintainers regarding status + +#### Solana command line tools + +- Solana command line tools can perform all stake operations in conjunction with + a CLI-generated keypair file wallet, a paper wallet, or with a connected + Ledger Nano. + [Staking commands using the Solana Command Line Tools](https://docs.anza.xyz/cli/examples/delegate-stake). + +#### Create a Stake Account + +Follow the wallet's instructions for creating a staking account. This account +will be of a different type than one used to simply send and receive tokens. + +#### Select a Validator + +Follow the wallet's instructions for selecting a validator. You can get +information about potentially performant validators from the links below. The +Solana Foundation does not recommend any particular validator. + +The site solanabeach.io is built and maintained by one of our validators, +Staking Facilities. It provides a some high-level graphical information about +the network as a whole, as well as a list of each validator and some recent +performance statistics about each one. + +- https://solanabeach.io + +To view block production statistics, use the Solana command-line tools: + +- `solana validators` +- `solana block-production` + +The Solana team does not make recommendations on how to interpret this +information. Do your own due diligence. + +#### Delegate your Stake + +Follow the wallet's instructions for delegating your stake to your chosen +validator. + +## Stake Account Details + +For more information about the operations and permissions associated with a +stake account, please see +[Stake Accounts](/docs/economics/staking/stake-accounts.md) diff --git a/docs/uk/economics/staking/stake-accounts.md b/docs/uk/economics/staking/stake-accounts.md new file mode 100644 index 000000000..972458007 --- /dev/null +++ b/docs/uk/economics/staking/stake-accounts.md @@ -0,0 +1,146 @@ +--- +sidebarLabel: Stake Accounts +title: Stake Accounts +--- + +A stake account on Solana can be used to delegate tokens to validators on the +network to potentially earn rewards for the owner of the stake account. Stake +accounts are created and managed differently than a traditional wallet address, +known as a _system account_. A system account is only able to send and receive +SOL from other accounts on the network, whereas a stake account supports more +complex operations needed to manage a delegation of tokens. + +Stake accounts on Solana also work differently than those of other +Proof-of-Stake blockchain networks that you may be familiar with. This document +describes the high-level structure and functions of a Solana stake account. + +#### Account Address + +Each stake account has a unique address which can be used to look up the account +information in the command line or in any network explorer tools. However, +unlike a wallet address in which the holder of the address's keypair controls +the wallet, the keypair associated with a stake account address does not +necessarily have any control over the account. In fact, a keypair or private key +may not even exist for a stake account's address. + +The only time a stake account's address has a keypair file is when +[creating a stake account using the command line tools](https://docs.anza.xyz/cli/examples/delegate-stake#create-a-stake-account). +A new keypair file is created first only to ensure that the stake account's +address is new and unique. + +#### Understanding Account Authorities + +Certain types of accounts may have one or more _signing authorities_ associated +with a given account. An account authority is used to sign certain transactions +for the account it controls. This is different from some other blockchain +networks where the holder of the keypair associated with the account's address +controls all of the account's activity. + +Each stake account has two signing authorities specified by their respective +address, each of which is authorized to perform certain operations on the stake +account. + +The _stake authority_ is used to sign transactions for the following operations: + +- Delegating stake +- Deactivating the stake delegation +- Splitting the stake account, creating a new stake account with a portion of + the funds in the first account +- Merging two stake accounts into one +- Setting a new stake authority + +The _withdraw authority_ signs transactions for the following: + +- Withdrawing un-delegated stake into a wallet address +- Setting a new withdraw authority +- Setting a new stake authority + +The stake authority and withdraw authority are set when the stake account is +created, and they can be changed to authorize a new signing address at any time. +The stake and withdraw authority can be the same address or two different +addresses. + +The withdraw authority keypair holds more control over the account as it is +needed to liquidate the tokens in the stake account, and can be used to reset +the stake authority if the stake authority keypair becomes lost or compromised. + +Securing the withdraw authority against loss or theft is of utmost importance +when managing a stake account. + +#### Multiple Delegations + +Each stake account may only be used to delegate to one validator at a time. All +of the tokens in the account are either delegated or un-delegated, or in the +process of becoming delegated or un-delegated. To delegate a fraction of your +tokens to a validator, or to delegate to multiple validators, you must create +multiple stake accounts. + +This can be accomplished by creating multiple stake accounts from a wallet +address containing some tokens, or by creating a single large stake account and +using the stake authority to split the account into multiple accounts with token +balances of your choosing. + +The same stake and withdraw authorities can be assigned to multiple stake +accounts. + +#### Merging stake accounts + +Two stake accounts that have the same authorities and lockup can be merged into +a single resulting stake account. A merge is possible between two stakes in the +following states with no additional conditions: + +- two deactivated stakes +- an inactive stake into an activating stake during its activation epoch + +For the following cases, the voter pubkey and vote credits observed must match: + +- two activated stakes +- two activating accounts that share an activation epoch, during the activation + epoch + +All other combinations of stake states will fail to merge, including all +"transient" states, where a stake is activating or deactivating with a non-zero +effective stake. + +#### Delegation Warmup and Cooldown + +When a stake account is delegated, or a delegation is deactivated, the operation +does not take effect immediately. + +A delegation or deactivation takes several [epochs](/docs/terminology.md#epoch) +to complete, with a fraction of the delegation becoming active or inactive at +each epoch boundary after the transaction containing the instructions has been +submitted to the cluster. + +There is also a limit on how much total stake can become delegated or +deactivated in a single epoch, to prevent large sudden changes in stake across +the network as a whole. Since warmup and cooldown are dependent on the behavior +of other network participants, their exact duration is difficult to predict. +Details on the warmup and cooldown timing can be found +[here](https://docs.anza.xyz/consensus/stake-delegation-and-rewards#stake-warmup-cooldown-withdrawal). + +#### Lockups + +Stake accounts can have a lockup which prevents the tokens they hold from being +withdrawn before a particular date or epoch has been reached. While locked up, +the stake account can still be delegated, un-delegated, or split, and its stake +authority can be changed as normal. Only withdrawal into another wallet or +updating the withdraw authority is not allowed. + +A lockup can only be added when a stake account is first created, but it can be +modified later, by the _lockup authority_ or _custodian_, the address of which +is also set when the account is created. + +#### Destroying a Stake Account + +Like other types of accounts on the Solana network, a stake account that has a +balance of 0 SOL is no longer tracked. If a stake account is not delegated and +all of the tokens it contains are withdrawn to a wallet address, the account at +that address is effectively destroyed, and will need to be manually re-created +for the address to be used again. + +#### Viewing Stake Accounts + +Stake account details can be viewed on the +[Solana Explorer](http://explorer.solana.com/accounts) by copying and pasting an +account address into the search bar. diff --git a/docs/uk/economics/staking/stake-programming.md b/docs/uk/economics/staking/stake-programming.md new file mode 100644 index 000000000..ed9852168 --- /dev/null +++ b/docs/uk/economics/staking/stake-programming.md @@ -0,0 +1,28 @@ +--- +title: Stake Programming +--- + +To maximize stake distribution, decentralization, and censorship resistance on +the Solana network, staking can be performed programmatically. The team and +community have developed several on-chain and offchain programs to make stakes +easier to manage. + +#### Stake-o-matic aka Auto-delegation Bots + +This offchain program manages a large population of validators staked by a +central authority. The Solana Foundation uses an auto-delegation bot to +regularly delegate its stake to "non-delinquent" validators that meet specified +performance requirements. + +#### Stake Pools + +This on-chain program pools together SOL to be staked by a manager, allowing SOL +holders to stake and earn rewards without managing stakes. Users deposit SOL in +exchange for SPL tokens (staking derivatives) that represent their ownership in +the stake pool. The pool manager stakes deposited SOL according to their +strategy, perhaps using a variant of an auto-delegation bot as described above. +As stakes earn rewards, the pool and pool tokens grow proportionally in value. +Finally, pool token holders can send SPL tokens back to the stake pool to redeem +SOL, thereby participating in decentralization with much less work required. +More information can be found at the +[SPL stake pool documentation](https://spl.solana.com/stake-pool). diff --git a/docs/uk/index.md b/docs/uk/index.md new file mode 100644 index 000000000..10ac0c1ec --- /dev/null +++ b/docs/uk/index.md @@ -0,0 +1,73 @@ +--- +sidebarSortOrder: 0 +title: Документація Solana +seoTitle: Дізнайтеся, як працює блокчейн Solana +description: + "Solana — це високопродуктивний блокчейн, створений для масового впровадження. + Дізнайтеся, чому Solana є найкращим вибором для розробників, які прагнуть створювати + масштабовані блокчейн-додатки." +altRoutes: + - /docs/intro/history + - /docs/intro + - /docs/intro/overview +isHiddenInNavSidebar: true +--- + +Solana — це блокчейн, створений для масового використання. Це високопродуктивна мережа, яка використовується для різних сфер, включаючи фінанси, NFT, платежі та ігри. Solana працює як єдина глобальна станова машина, є відкритою, інтероперабельною та децентралізованою. + +## Початок роботи + +Пориньте у світ Solana, щоб почати створювати або налаштовувати своє локальне середовище. + +- [Швидкий старт](/docs/intro/quick-start) — Створіть і розгорніть свою першу програму на Solana прямо у браузері за допомогою Solana Playground +- [Налаштування локального середовища](/docs/intro/installation) — Встановіть CLI Solana для налаштування локального середовища розробки + +## Почніть навчання + +Поглиблено вивчіть основні концепції, які роблять Solana унікальною серед інших блокчейнів. + +- [Акаунти](/docs/core/accounts) — Механізм зберігання даних і стану для Solana +- [Комісії в Solana](/docs/core/fees) — Різні витрати, пов’язані з використанням мережі +- [Транзакції](/docs/core/transactions) — Набір інструкцій для виконання блокчейном +- [Програми](/docs/core/programs) — Виконуваний код для виконання дій у блокчейні +- [Програмно похідні адреси](/docs/core/pda) — Детерміновано створені адреси, які дозволяють програмам Solana програмно "підписувати" транзакції +- [Виклики між програмами](/docs/core/cpi) — Основний механізм "композованості" Solana, який дозволяє програмам "викликати" одна одну + +## Розуміння архітектури + +Дізнайтеся, як працює блокчейн Proof-of-Stake у основі Solana. + +- [Валідатори](https://docs.anza.xyz/validator/anatomy) — окремі вузли, які є основою мережі +- [Кластери](/docs/core/clusters) — група валідаторів, що працюють разом для досягнення консенсусу + +## Запуск валідатора + +Дізнайтеся, що потрібно для роботи валідатора Solana та забезпечення безпеки мережі. + +- [Системні вимоги](https://docs.anza.xyz/operations/requirements) — Рекомендовані апаратні вимоги та очікувана кількість SOL, необхідна для запуску валідатора +- [Швидкий старт](https://docs.anza.xyz/operations/setup-a-validator) — Налаштуйте валідатор і підключіться до кластера вперше + +## Чому Solana? + +Створена для масштабування, Solana призначена для того, щоб блокчейн-додатки могли досягати мільйонів користувачів. Замість оптимізації під блокчейн-рівень розробники можуть зосередитися на створенні додатків, які досягнуть відповідності ринку. Мережа не тільки може масштабуватися для поточних потреб блокчейн-додатків, але й постійно оптимізується з урахуванням досвіду користувачів. + +Створення найкращого користувацького досвіду є головним пріоритетом для розробників. У блокчейнах користувацький досвід часто обмежений базовими технологіями, що спричиняє повільний час відгуку та високі комісії. Низькі комісії Solana та час підтвердження в 400 мс дозволяють розробникам створювати зручні для користувачів додатки, доступні кожному. + +## Особливості Solana + +| Функція | Опис | +| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Розробка програм на блокчейні | Можливість розробляти та розгортати програми на блокчейні. Користувачі можуть взаємодіяти з цими програмами без дозволу, усуваючи потребу у посередниках для створення додатків. | +| 400 мс для блоків | Кожна транзакція користувачів у Solana підтверджується в блоці. З цільовим часом 400 мс для кожного блоку, взаємодія користувачів є швидкою, забезпечуючи найкращий у своєму класі досвід. | +| Низькі комісії | Комісії в Solana відомі своєю низькістю. Середня комісія становить 0.00064 SOL за транзакцію, що дозволяє створювати додатки для користувачів з усього світу, незалежно від їх походження. | +| Висока пропускна здатність | Масштабування до тисяч транзакцій за секунду, Solana створена для масштабування відповідно до потреб користувачів вашого додатку. | + +## Як користуватися цими документами + +Зліва ви знайдете бічну панель документації. Вона містить документацію у порядку від базової до більш просунутої інформації. Якщо ви новачок у Solana, рекомендуємо почати з самого верху і рухатися вниз. Однак ви можете читати їх у будь-якому порядку, який вам подобається. + +Коли будете готові почати створення, ознайомтеся з посібником [Швидкий старт](/docs/intro/quick-start). + +## Потрібна допомога? + +Отримайте допомогу від спільноти Solana на [Solana StackExchange](https://solana.stackexchange.com). diff --git a/docs/uk/intro/dev.md b/docs/uk/intro/dev.md new file mode 100644 index 000000000..37a5f1b85 --- /dev/null +++ b/docs/uk/intro/dev.md @@ -0,0 +1,195 @@ +--- +sidebarLabel: Intro to Development +title: "Getting Started with Solana Development" +description: "Learn how to get started building on Solana" +sidebarSortOrder: 2 +keywords: + - solana basics + - tutorial + - intro to solana development + - blockchain developer + - web3 developer +--- + +Welcome to the Solana developer docs! + +This page has everything you need to know to get started with Solana +development, including basic requirements, how Solana development works, and the +tools you'll need to get started. + +## High Level Developer Overview + +Development on Solana can be broken down into two main parts: + +1. **Onchain Program Development**: This is where you create and deploy custom + programs directly to the blockchain. Once deployed, anyone who knows how to + communicate with them can use them. You can write these programs in Rust, C, + or C++. Rust has the most support for onchain program development today. +2. **Client Development**: This is where you write software (called + decentralized applications, or dApps) that communicates with onchain + programs. Your apps can submit transactions to perform actions onchain. + Client development can be written in any programming language. + +The "glue" between the client side and the onchain side is the +[Solana JSON RPC API](https://solana.com/docs/rpc). The client-side sends RPC +requests to the Solana network to interact with onchain programs. This is very +similar to normal development between a frontend and backend. The major +difference with working on Solana is that the backend is a global permissionless +blockchain. This means that anyone can interact with your onchain program +without the need of issuing API keys or any other form of permission. + +![How clients work with the Solana blockchain](/assets/docs/intro/developer_flow.png) + +Solana development is a bit different from other blockchains because of its +highly composable onchain programs. This means you can build on top of any +program already deployed, and often you can do so without needing to do any +custom onchain program development. For example, if you wanted to work with +tokens, you could use the [Token Program](/docs/core/tokens.md) that is already +deployed on the network. All development on your application would be +client-side in your language of choice. + +Developers looking to build on Solana will find that the development stack is +very similar to any other development stack. The main difference is that you'll +be working with a blockchain and have to think about how users potentially +interact with your application onchain instead of just on the frontend. +Developing on Solana still has CI/CD pipelines, testing, debugging tools, a +frontend and backend, and anything you'd find in a normal development flow. + +## What You'll Need to Get Started + +To get started with Solana development, you'll need different tools based on +whether you are developing for client-side, onchain programs, or both. + +### Client-side Development + +If you're developing onchain apps, you should know Rust. + +If you're developing on the client-side, you can work with any programming +language you're comfortable with. Solana has community-contributed SDKs to help +developers interact with the Solana network in most popular languages : + +| Language | SDK | +| ---------- | -------------------------------------------------------------------------------------------------------- | +| RUST | [solana_sdk](https://docs.rs/solana-sdk/latest/solana_sdk/) | +| Typescript | [@solana/web3.js](https://github.com/solana-labs/solana-web3.js) | +| Python | [solders](https://github.com/kevinheavey/solders) | +| Java | [solanaj](https://github.com/skynetcap/solanaj) or [solana4j](https://github.com/LMAX-Exchange/solana4j) | +| C++ | [solcpp](https://github.com/mschneider/solcpp) | +| Go | [solana-go](https://github.com/gagliardetto/solana-go) | +| Kotlin | [solanaKT](https://github.com/metaplex-foundation/SolanaKT) or [sol4k](https://github.com/sol4k/sol4k) | +| Dart | [solana](https://github.com/espresso-cash/espresso-cash-public/tree/master/packages/solana) | +| C# | [solnet](https://github.com/bmresearch/Solnet) | +| GdScript | [godot](https://github.com/Virus-Axel/godot-solana-sdk/) | + +You'll also need a connection with an RPC to interact with the network. You can +either work with a [RPC infrastructure provider](https://solana.com/rpc) or +[run your own RPC node](https://docs.anza.xyz/operations/setup-an-rpc-node). + +To quickly get started with a front-end for your application, you can generate a +customizable Solana scaffold by typing the following into your CLI: + +```bash +npx create-solana-dapp +``` + +This will create a new project with all the necessary files and basic +configuration to get started building on Solana. The scaffold will include both +an example frontend and an onchain program template (if you selected one). You +can read the +[`create-solana-dapp` docs](https://github.com/solana-developers/create-solana-dapp?tab=readme-ov-file#create-solana-dapp) +to learn more. + +### Onchain Program Development + +Onchain program development consists of either writing programs in Rust, C, or +C++. First you'll need to make sure you have Rust installed on your machine. You +can do this with the following command: + +```bash +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + +You'll then need to have the [Solana CLI installed](/docs/intro/installation.md) +to compile and deploy your programs. You can install the Solana CLI by running +the following command: + +```bash +sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)" +``` + +Using the Solana CLI, it is recommended to run a local validator for testing +your program. To run a local validator after installing the Solana CLI, run the +following command: + +```bash +solana-test-validator +``` + +This will start a local validator on your machine that you can use to test your +programs. You can +[read more about local development in this guide](/docs/intro/installation.md). + +When building onchain programs, you have a choice to either build with native +Rust (ie, without a framework) or use the Anchor framework. Anchor is a +framework that makes it easier to build on Solana by providing a higher-level +API for developers. Think of Anchor like building with React for your websites +instead of raw Javascript and HTML. While Javascript and HTML give you more +control over your website, React accelerates your development and makes +developing easy. You can read more about [Anchor](https://www.anchor-lang.com/) +on their website. + +You'll need a way to test your program. There are a few different ways to test +your program based on your language preference: + +- [solana-program-test](https://docs.rs/solana-program-test/latest/solana_program_test/) - + Testing framework built in Rust +- [solana-bankrun](https://kevinheavey.github.io/solana-bankrun/) - Testing + framework built for writing Typescript tests +- [bankrun](https://kevinheavey.github.io/solders/tutorials/bankrun.html) - + Testing framework built for writing Python tests + +If you do not want to develop your programs locally, there's also the +[online IDE Solana Playground](https://beta.solpg.io). Solana Playground allows +you to write, test, and deploy programs on Solana. You can get started with +Solana Playground by [following our quick start guide](/docs/intro/quick-start). + +### Developer Environments + +Choosing the right environment based on your work is very important. On Solana, +there are a few different network environments (called clusters) to facilitate +mature testing and CI/CD practices: + +- **Mainnet Beta**: The production network where all the action happens. + Transactions cost real money here. +- **Devnet**: The quality assurance network where you deploy your programs to + test before deploying to production. Think "staging environment". +- **Local**: The local network that you run on your machine using + `solana-test-validator` to test your programs. This should be your first + choice when developing programs. + +## Build by Example + +While you get started building on Solana, there's a few more resources available +to help accelerate your journey: + +- [Solana Cookbook](https://solana.com/developers/cookbook): A collection of + references and code snippets to help you build on Solana. +- [Solana Program Examples](https://github.com/solana-developers/program-examples): + A repository of example programs providing building blocks for different + actions on your programs. +- [Guides](https://solana.com/developers/guides): Tutorials and guides to walk + you through building on Solana. + +## Getting Support + +The best support you can find is on +[Solana StackExchange](https://solana.stackexchange.com/). Search for your +question there first - there's a good chance there will already be a question +asked by someone else, with an answer. If it's not there, add a new question! +Remember to include as much detail as you can in your question, and please use +text (not screenshots) to show error messages, so other people with the same +problem can find your question! + +## Next steps + +[You're now ready to get started building on Solana!](/docs/intro/quick-start) diff --git a/docs/uk/intro/index.md b/docs/uk/intro/index.md new file mode 100644 index 000000000..8b9684de4 --- /dev/null +++ b/docs/uk/intro/index.md @@ -0,0 +1,5 @@ +--- +title: Getting Started +sidebarSortOrder: 1 +metaOnly: true +--- diff --git a/docs/uk/intro/installation.md b/docs/uk/intro/installation.md new file mode 100644 index 000000000..9f359e042 --- /dev/null +++ b/docs/uk/intro/installation.md @@ -0,0 +1,664 @@ +--- +title: Installation +seoTitle: Install the Solana CLI and Anchor +sidebarSortOrder: 1 +description: + A comprehensive guide to setting up your local Solana development environment. + Learn how to install Rust, the Solana CLI, and Anchor Framework on Windows + (WSL), Linux, and Mac. Includes step-by-step instructions for creating + wallets, requesting airdrops, and running a local validator. +altRoutes: + - /developers/guides/getstarted/setup-local-development + - /docs/install + - /install + - /setup +--- + +This section covers the steps to set up your local environment for Solana +development. + +## Install Dependencies + +- Windows users must first install WSL (Windows subsystem for Linux) and then + install the dependencies specified in the Linux section below. +- Linux users should first install the dependencies specified in the Linux + section below. +- Mac users should start with the Rust installation instructions below. + + + + +To develop Solana programs on Windows **you must use +[WSL](https://learn.microsoft.com/en-us/windows/wsl/install)** (Windows +subsystem for Linux). All additional dependencies must be installed through the +Linux terminal. + +Once WSL is installed, install the dependencies specified in the Linux section +below before proceeding to install Rust, Solana CLI, and Anchor CLI. + +To install WSL, run the following command in Windows PowerShell: + +```shell +wsl --install +``` + +The install process will prompt you to create a default user account. + +![WSL Install](/assets/docs/intro/installation/wsl-install.png) + +By default, WSL installs Ubuntu. You can open a Linux terminal by searching +"Ubuntu" in the Search bar. + +![WSL Ubuntu](/assets/docs/intro/installation/wsl-ubuntu-search.png) + +If your Ubuntu terminal looks like the image below, you may encounter an issue +where `ctrl + v` (paste keyboard shortcut) doesn't work in the terminal. + +![Ubuntu Terminal](/assets/docs/intro/installation/wsl-ubuntu-terminal-1.png) + +If you encounter this issue, open Windows Terminal by searching for "Terminal" +in the Search bar. + +![Windows Terminal](/assets/docs/intro/installation/wsl-windows-terminal.png) + +Next, close the Windows Terminal and reopen a Linux terminal by searching for +Ubuntu again. The terminal should now look like the image below, where +`ctrl + v` (paste keyboard shortcut) works. + +![Ubuntu Terminal](/assets/docs/intro/installation/wsl-ubuntu-terminal-2.png) + +If you are using VS Code, the +[WSL extension](https://code.visualstudio.com/docs/remote/wsl-tutorial) enables +you to use WSL and VS Code together. + +![WSL Setup in VS Code](/assets/docs/intro/installation/wsl-vscode.png) + +You should then see the following in the VS Code status bar: + +![WSL: Ubuntu](/assets/docs/intro/installation/wsl-vscode-ubuntu.png) + +Once you have WSL set up, all additional dependencies must be installed through +the Linux terminal. Install the dependencies specified in the Linux section +below before proceeding to install Rust, Solana CLI, and Anchor CLI. + + + + +The following dependencies are required for the Anchor CLI installation. + +First, run the following command: + +```shell +sudo apt-get update +``` + +Next, install the following dependencies: + +```shell +sudo apt-get install -y \ + build-essential \ + pkg-config \ + libudev-dev llvm libclang-dev \ + protobuf-compiler libssl-dev +``` + +If you encounter the following error when installing `protobuf-compiler`, make +sure you first run `sudo apt-get update`: + +``` +Package protobuf-compiler is not available, but is referred to by another package. +This may mean that the package is missing, has been obsoleted, or +is only available from another source +``` + + + + + + +### Install Rust + +Solana programs are written in the +[Rust programming language](https://www.rust-lang.org/). + +The recommended installation method for Rust is +[rustup](https://www.rust-lang.org/tools/install). + +Run the following command to install Rust: + +```shell +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y +``` + +You should see the following message after the installation completes: + + + + +``` +Rust is installed now. Great! + +To get started you may need to restart your current shell. +This would reload your PATH environment variable to include +Cargo's bin directory ($HOME/.cargo/bin). + +To configure your current shell, you need to source +the corresponding env file under $HOME/.cargo. + +This is usually done by running one of the following (note the leading DOT): +. "$HOME/.cargo/env" # For sh/bash/zsh/ash/dash/pdksh +source "$HOME/.cargo/env.fish" # For fish +``` + + + + +Run the following command to reload your PATH environment variable to include +Cargo's bin directory: + +```shell +. "$HOME/.cargo/env" +``` + +To verify that the installation was successful, check the Rust version: + +```shell +rustc --version +``` + +You should see output similar to the following: + +``` +rustc 1.80.1 (3f5fd8dd4 2024-08-06) +``` + +### Install the Solana CLI + +The Solana CLI provides all the tools required to build and deploy Solana +programs. + +Install the Solana CLI tool suite using the official install command: + +```shell +sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)" +``` + +You can replace `stable` with the release tag matching the software version of +your desired release (i.e. `v2.0.3`), or use one of the three symbolic channel +names: `stable`, `beta`, or `edge`. + +If it is your first time installing the Solana CLI, you may see the following +message prompting you to add a PATH environment variable: + +``` +Close and reopen your terminal to apply the PATH changes or run the following in your existing shell: + +export PATH="/Users/test/.local/share/solana/install/active_release/bin:$PATH" +``` + + + + +If you are using a Linux or WSL terminal, you can add the PATH environment +variable to your shell configuration file by running the command logged from the +installation or by restarting your terminal. + +```shell +export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" +``` + + + + +If you're on Mac using `zsh`, running the default `export PATH` command logged +from the installation does not persist once you close your terminal. + +Instead, you can add the PATH to your shell configuration file by running the +following command: + +```shell +echo 'export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"' >> ~/.zshrc +``` + +Then run the following command to refresh the terminal session or restart your +terminal. + +```shell +source ~/.zshrc +``` + + + + +To verify that the installation was successful, check the Solana CLI version: + +```shell +solana --version +``` + +You should see output similar to the following: + +``` +solana-cli 1.18.22 (src:9efdd74b; feat:4215500110, client:Agave) +``` + +You can view all available versions on the +[Agave Github repo](https://github.com/anza-xyz/agave/releases). + + + +Agave is the validator client from [Anza](https://www.anza.xyz/), formerly known +as Solana Labs validator client. + + + +To later update the Solana CLI to the latest version, you can use the following +command: + +```shell +agave-install update +``` + +### Install Anchor CLI + +[Anchor](https://www.anchor-lang.com/) is a framework for developing Solana +programs. The Anchor framework leverages Rust macros to simplify the process of +writing Solana programs. + +There are two ways to install the Anchor CLI and tooling: + +1. Using Anchor Version Manager (AVM) - is the **recommended installation** + method since it simplifies updating Anchor versions in the future +2. Without AVM - this requires more a manual process to update Anchor versions + later + + + + +The Anchor version manager (AVM) allows you to install and manage different +Anchor versions on your system, including more easily updating Anchor versions +in the future. + +Install AVM with the following command: + +```shell +cargo install --git https://github.com/coral-xyz/anchor avm --force +``` + +Test to ensure AVM was installed and is accessible: + +```shell +avm --version +``` + +Install the latest version of Anchor CLI using AVM: + +```shell +avm install latest +avm use latest +``` + +Or install a specific version of the Anchor CLI by declaring which version you +want to install: + +```shell +avm install 0.30.1 +avm use 0.30.1 +``` + +> Don't forget to run the `avm use` command to declare which Anchor CLI version +> should be used on your system. +> +> - If you installed the `latest` version, run `avm use latest`. +> - If you installed the version `0.30.1`, run `avm use 0.30.1`. + + + + + +Install a specific version of the Anchor CLI with the following command: + +```shell +cargo install --git https://github.com/coral-xyz/anchor --tag v0.30.1 anchor-cli +``` + + + + +You may see the following warning during installation. However, it does not +affect the installation process. + + + + +``` +warning: unexpected `cfg` condition name: `nightly` + --> cli/src/lib.rs:1:13 + | +1 | #![cfg_attr(nightly, feature(proc_macro_span))] + | ^^^^^^^ + | + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: consider using a Cargo feature instead + = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ['cfg(nightly)'] } + = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(nightly)");` to the top of the `build.rs` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: `anchor-cli` (lib) generated 1 warning +``` + + + + +To verify that the installation was successful, check the Anchor CLI version: + +```shell +anchor --version +``` + +You should see output similar to the following: + +``` +anchor-cli 0.30.1 +``` + +When installing the Anchor CLI on Linux or WSL, you may encounter this error: + +``` +error: could not exec the linker cc = note: Permission denied (os error 13) +``` + +If you see this error message, follow these steps: + +1. Install the dependencies listed in the Linux section at the top of this page. +2. Retry installing the Anchor CLI. + +#### Node.js and Yarn + +Node.js and Yarn are required to run the default Anchor project test file +(TypeScript) created with the `anchor init` command. (Rust test template is also +available using `anchor init --test-template rust`) + + + + +The recommended way to install node is using +[Node Version Manager (nvm)](https://github.com/nvm-sh/nvm). + +Install nvm using the following command: + +```shell +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash +``` + +Restart your terminal and verify that nvm is installed: + +```shell +command -v nvm +``` + +Next, use `nvm` to install node: + +```shell +nvm install node +``` + +To verify that the installation was successful, check the Node version: + +``` +node --version +``` + +You should see output similar to the following: + +``` +v22.7.0 +``` + + + + +Install Yarn: + +```shell +npm install --global yarn +``` + +To verify that the installation was successful, check the Yarn version: + +``` +yarn --version +``` + +You should the following output: + +``` +1.22.1 +``` + + + + +When running `anchor build`, if you encounter similar errors following: + + + + +``` +error: not a directory: '.../solana-release/bin/sdk/sbf/dependencies/platform-tools/rust/lib' +``` + +Try these solutions: + +1. Force install using the following command: + +```shell +cargo build-sbf --force-tools-install +``` + +2. If the above doesn't work, clear the Solana cache: + +```shell +rm -rf ~/.cache/solana/* +``` + + + + +You can fix this by changing the version field of `Cargo.lock` file + +``` +version = 3 +``` + +See [this issue](https://github.com/coral-xyz/anchor/issues/3392) for more +information. + + + + + +After applying either solution, attempt to run `anchor build` again. + +If you are on Linux or WSL and encounter the following errors when running +`anchor test` after creating a new Anchor project, it's may be due to missing +Node.js or Yarn: + +``` +Permission denied (os error 13) +``` + +``` +No such file or directory (os error 2) +``` + + + +## Solana CLI Basics + +This section will walk through some common Solana CLI commands to get you +started. + + + +### Solana Config + +To see your current config: + +```shell +solana config get +``` + +You should see output similar to the following: + +``` +Config File: /Users/test/.config/solana/cli/config.yml +RPC URL: https://api.mainnet-beta.solana.com +WebSocket URL: wss://api.mainnet-beta.solana.com/ (computed) +Keypair Path: /Users/test/.config/solana/id.json +Commitment: confirmed +``` + +The RPC URL and Websocket URL specify the Solana cluster the CLI will make +requests to. By default this will be mainnet-beta. + +You can update the Solana CLI cluster using the following commands: + +``` +solana config set --url mainnet-beta +solana config set --url devnet +solana config set --url localhost +solana config set --url testnet +``` + +You can also use the following short options: + +``` +solana config set -um # For mainnet-beta +solana config set -ud # For devnet +solana config set -ul # For localhost +solana config set -ut # For testnet +``` + +The Keypair Path specifies the location of the default wallet used by the Solana +CLI (to pay transaction fees and deploy programs). The default path is +`~/.config/solana/id.json`. The next step walks through how to generate a +keypair at the default location. + +### Create Wallet + +To interact with the Solana network using the Solana CLI, you need a Solana +wallet funded with SOL. + +To generate a keypair at the default Keypair Path, run the following command: + +```shell +solana-keygen new +``` + +You should see output similar to the following: + +``` +Generating a new keypair + +For added security, enter a BIP39 passphrase + +NOTE! This passphrase improves security of the recovery seed phrase NOT the +keypair file itself, which is stored as insecure plain text + +BIP39 Passphrase (empty for none): + +Wrote new keypair to /Users/test/.config/solana/id.json +=========================================================================== +pubkey: 8dBTPrjnkXyuQK3KDt9wrZBfizEZijmmUQXVHpFbVwGT +=========================================================================== +Save this seed phrase and your BIP39 passphrase to recover your new keypair: +cream bleak tortoise ocean nasty game gift forget fancy salon mimic amazing +=========================================================================== +``` + + + +If you already have a file system wallet saved at the default location, this +command will **NOT** override it unless you explicitly force override using the +`--force` flag. + + + +Once a keypair is generated, you can get the address (public key) of the keypair +with the following command: + +```shell +solana address +``` + +### Airdrop SOL + +Once you've set up your local wallet, request an airdrop of SOL to fund your +wallet. You need SOL to pay for transaction fees and to deploy programs. + +Set your cluster to the devnet: + +```shell +solana config set -ud +``` + +Then request an airdrop of devnet SOL: + +```shell +solana airdrop 2 +``` + +To check your wallet's SOL balance, run the following command: + +```shell +solana balance +``` + + + +The `solana airdrop` command is currently limited to 5 SOL per request on +devnet. Errors are likely due to rate limits. + +Alternatively, you can get devnet SOL using the +[Solana Web Faucet](https://faucet.solana.com). + + + +### Run Local Validator + +The Solana CLI comes with the +[test validator](https://docs.anza.xyz/cli/examples/test-validator) built-in. +Running a local validator will allow you to deploy and test your programs +locally. + +In a separate terminal, run the following command to start a local validator: + +```shell +solana-test-validator +``` + + + +In WSL you may need to first navigate to a folder where you have default write +access: + +```shell +cd ~ +mkdir validator +cd validator +solana-test-validator +``` + + + +Make sure to update the Solana CLI config to localhost before commands. + +```shell +solana config set -ul +``` + + diff --git a/docs/uk/intro/quick-start/cross-program-invocation.md b/docs/uk/intro/quick-start/cross-program-invocation.md new file mode 100644 index 000000000..f3aafb4c9 --- /dev/null +++ b/docs/uk/intro/quick-start/cross-program-invocation.md @@ -0,0 +1,608 @@ +--- +sidebarLabel: Cross Program Invocation +title: Cross Program Invocation +sidebarSortOrder: 5 +description: + Learn how to implement Cross Program Invocations (CPIs) in Solana programs + using the Anchor framework. This tutorial demonstrates how to transfer SOL + between accounts, interact with the System Program, and handle Program Derived + Addresses (PDAs) in CPIs. Perfect for developers looking to build composable + Solana programs. +--- + +In this section, we'll update the CRUD program from the previous PDA section to +include Cross Program Invocations (CPIs). We'll modify the program to transfer +SOL between accounts in the `update` and `delete` instructions, demonstrating +how to interact with other programs (in this case, the System Program) from +within our program. + +The purpose of this section is to walk through the process of implementing CPIs +in a Solana program using the Anchor framework, building upon the PDA concepts +we explored in the previous section. For more details, refer to the +[Cross Program Invocation](/docs/core/cpi) page. + + + +### Modify Update Instruction + +First, we'll implement a simple "pay-to-update" mechanism by modifying the +`Update` struct and `update` function. + +Begin by updating the `lib.rs` file to bring into scope items from the +`system_program` module. + +```rs filename="lib.rs" +use anchor_lang::system_program::{transfer, Transfer}; +``` + + + + +```diff + use anchor_lang::prelude::*; ++ use anchor_lang::system_program::{transfer, Transfer}; +``` + + + + +Next, update the `Update` struct to include an additional account called +`vault_account`. This account, controlled by our program, will receive SOL from +a user when they update their message account. + +```rs filename="lib.rs" +#[account( + mut, + seeds = [b"vault", user.key().as_ref()], + bump, +)] +pub vault_account: SystemAccount<'info>, +``` + + + + +```diff +#[derive(Accounts)] +#[instruction(message: String)] +pub struct Update<'info> { + #[account(mut)] + pub user: Signer<'info>, + ++ #[account( ++ mut, ++ seeds = [b"vault", user.key().as_ref()], ++ bump, ++ )] ++ pub vault_account: SystemAccount<'info>, + #[account( + mut, + seeds = [b"message", user.key().as_ref()], + bump = message_account.bump, + realloc = 8 + 32 + 4 + message.len() + 1, + realloc::payer = user, + realloc::zero = true, + )] + pub message_account: Account<'info, MessageAccount>, + pub system_program: Program<'info, System>, +} +``` + + + + +We're adding a new account called `vault_account` to our `Update` struct. This +account serves as a program-controlled "vault" that will receive SOL from users +when they update their messages. + +By using a PDA for the vault, we create a program-controlled account unique to +each user, enabling us to manage user funds within our program's logic. + +--- + +Key aspects of the `vault_account`: + +- The address of the account is a PDA derived using seeds + `[b"vault", user.key().as_ref()]` +- As a PDA, it has no private key, so only our program can "sign" for the + address when performing CPIs +- As a `SystemAccount` type, it's owned by the System Program like regular + wallet accounts + +This setup allows our program to: + +- Generate unique, deterministic addresses for each user's "vault" +- Control funds without needing a private key to sign for transactions. + +In the `delete` instruction, we'll demonstrate how our program can "sign" for +this PDA in a CPI. + + + + +Next, implement the CPI logic in the `update` instruction to transfer 0.001 SOL +from the user's account to the vault account. + +```rs filename="lib.rs" +let transfer_accounts = Transfer { + from: ctx.accounts.user.to_account_info(), + to: ctx.accounts.vault_account.to_account_info(), +}; +let cpi_context = CpiContext::new( + ctx.accounts.system_program.to_account_info(), + transfer_accounts, +); +transfer(cpi_context, 1_000_000)?; +``` + + + + +```diff + pub fn update(ctx: Context, message: String) -> Result<()> { + msg!("Update Message: {}", message); + let account_data = &mut ctx.accounts.message_account; + account_data.message = message; + ++ let transfer_accounts = Transfer { ++ from: ctx.accounts.user.to_account_info(), ++ to: ctx.accounts.vault_account.to_account_info(), ++ }; ++ let cpi_context = CpiContext::new( ++ ctx.accounts.system_program.to_account_info(), ++ transfer_accounts, ++ ); ++ transfer(cpi_context, 1_000_000)?; + Ok(()) + } +``` + + + + +In the `update` instruction, we implement a Cross Program Invocation (CPI) to +invoke the System Program's `transfer` instruction. This demonstrates how to +perform a CPI from within our program, enabling the composability of Solana +programs. + +The `Transfer` struct specifies the required accounts for the System Program's +transfer instruction: + +- `from` - The user's account (source of funds) +- `to` - The vault account (destination of funds) + + ```rs filename="lib.rs" + let transfer_accounts = Transfer { + from: ctx.accounts.user.to_account_info(), + to: ctx.accounts.vault_account.to_account_info(), + }; + ``` + +The `CpiContext` specifies: + +- The program to be invoked (System Program) +- The accounts required in the CPI (defined in the `Transfer` struct) + + ```rs filename="lib.rs" + let cpi_context = CpiContext::new( + ctx.accounts.system_program.to_account_info(), + transfer_accounts, + ); + ``` + +The `transfer` function then invokes the transfer instruction on the System +Program, passing in the: + +- The `cpi_context` (program and accounts) +- The `amount` to transfer (1,000,000 lamports, equivalent to 0.001 SOL) + + ```rs filename="lib.rs" + transfer(cpi_context, 1_000_000)?; + ``` + +--- + +The setup for a CPI matches how client-side instructions are built, where we +specify the program, accounts, and instruction data for a particular instruction +to invoke. When our program's `update` instruction is invoked, it internally +invokes the System Program's transfer instruction. + + + + +Rebuild the program. + +```shell filename="Terminal" +build +``` + +### Modify Delete Instruction + +We'll now implement a "refund on delete" mechanism by modifying the `Delete` +struct and `delete` function. + +First, update the `Delete` struct to include the `vault_account`. This allows us +to transfer any SOL in the vault back to the user when they close their message +account. + +```rs filename="lib.rs" +#[account( + mut, + seeds = [b"vault", user.key().as_ref()], + bump, +)] +pub vault_account: SystemAccount<'info>, +``` + +Also add the `system_program` as the CPI for the transfer requires invoking the +System Program. + +```rs filename="lib.rs" +pub system_program: Program<'info, System>, +``` + + + + +```diff +#[derive(Accounts)] +pub struct Delete<'info> { + #[account(mut)] + pub user: Signer<'info>, + ++ #[account( ++ mut, ++ seeds = [b"vault", user.key().as_ref()], ++ bump, ++ )] ++ pub vault_account: SystemAccount<'info>, + #[account( + mut, + seeds = [b"message", user.key().as_ref()], + bump = message_account.bump, + close= user, + )] + pub message_account: Account<'info, MessageAccount>, ++ pub system_program: Program<'info, System>, +} +``` + + + + +The `vault_account` uses the same PDA derivation as in the Update struct. + +Add the `vault_account` to the Delete struct enables our program to access the +user's vault account during the delete instruction to transfer any accumulated +SOL back to the user. + + + + +Next, implement the CPI logic in the `delete` instruction to transfer SOL from +the vault account back to the user's account. + +```rs filename="lib.rs" +let user_key = ctx.accounts.user.key(); +let signer_seeds: &[&[&[u8]]] = + &[&[b"vault", user_key.as_ref(), &[ctx.bumps.vault_account]]]; + +let transfer_accounts = Transfer { + from: ctx.accounts.vault_account.to_account_info(), + to: ctx.accounts.user.to_account_info(), +}; +let cpi_context = CpiContext::new( + ctx.accounts.system_program.to_account_info(), + transfer_accounts, +).with_signer(signer_seeds); +transfer(cpi_context, ctx.accounts.vault_account.lamports())?; +``` + +Note that we updated `_ctx: Context` to `ctx: Context` as we'll +be using the context in the body of the function. + + + + +```diff +- pub fn delete(_ctx: Context) -> Result<()> { ++ pub fn delete(ctx: Context) -> Result<()> { + msg!("Delete Message"); + ++ let user_key = ctx.accounts.user.key(); ++ let signer_seeds: &[&[&[u8]]] = ++ &[&[b"vault", user_key.as_ref(), &[ctx.bumps.vault_account]]]; ++ ++ let transfer_accounts = Transfer { ++ from: ctx.accounts.vault_account.to_account_info(), ++ to: ctx.accounts.user.to_account_info(), ++ }; ++ let cpi_context = CpiContext::new( ++ ctx.accounts.system_program.to_account_info(), ++ transfer_accounts, ++ ).with_signer(signer_seeds); ++ transfer(cpi_context, ctx.accounts.vault_account.lamports())?; + Ok(()) + } + +``` + + + + +In the delete instruction, we implement another Cross Program Invocation (CPI) +to invoke the System Program's transfer instruction. This CPI demonstrates how +to make a transfer that requires a Program Derived Address (PDA) signer. + +First, we define the signer seeds for the vault PDA: + +```rs filename="lib.rs" +let user_key = ctx.accounts.user.key(); +let signer_seeds: &[&[&[u8]]] = + &[&[b"vault", user_key.as_ref(), &[ctx.bumps.vault_account]]]; +``` + +The `Transfer` struct specifies the required accounts for the System Program's +transfer instruction: + +- from: The vault account (source of funds) +- to: The user's account (destination of funds) + + ```rs filename="lib.rs" + let transfer_accounts = Transfer { + from: ctx.accounts.vault_account.to_account_info(), + to: ctx.accounts.user.to_account_info(), + }; + ``` + +The `CpiContext` specifies: + +- The program to be invoked (System Program) +- The accounts involved in the transfer (defined in the Transfer struct) +- The signer seeds for the PDA + + ```rs filename="lib.rs" + let cpi_context = CpiContext::new( + ctx.accounts.system_program.to_account_info(), + transfer_accounts, + ).with_signer(signer_seeds); + ``` + +The transfer function then invokes the transfer instruction on the System +Program, passing: + +- The `cpi_context` (program, accounts, and PDA signer) +- The amount to transfer (the entire balance of the vault account) + + ```rs filename="lib.rs" + transfer(cpi_context, ctx.accounts.vault_account.lamports())?; + ``` + +This CPI implementation demonstrates how programs can utilize PDAs to manage +funds. When our program's delete instruction is invoked, it internally calls the +System Program's transfer instruction, signing for the PDA to authorize the +transfer of all funds from the vault back to the user. + + + + +Rebuild the program. + +```shell filename="Terminal" +build +``` + +### Redeploy Program + +After making these changes, we need to redeploy our updated program. This +ensures that our modified program is available for testing. On Solana, updating +a program simply requires deploying the compiled program at the same program ID. + +```shell filename="Terminal" +deploy +``` + + + + +```bash +$ deploy +Deploying... This could take a while depending on the program size and network conditions. +Deployment successful. Completed in 17s. +``` + + + + +Only the upgrade authority of the program can update it. The upgrade authority +is set when the program is deployed, and it's the only account with permission +to modify or close the program. If the upgrade authority is revoked, then the +program becomes immutable and can never be closed or upgraded. + +When deploying programs on Solana Playground, your Playground wallet is the +upgrade authority for all your programs. + + + + +### Update Test File + +Next, we'll update our `anchor.test.ts` file to include the new vault account in +our instructions. This requires deriving the vault PDA and including it in our +update and delete instruction calls. + +#### Derive Vault PDA + +First, add the vault PDA derivation: + +```ts filename="anchor.test.ts" +const [vaultPda, vaultBump] = PublicKey.findProgramAddressSync( + [Buffer.from("vault"), wallet.publicKey.toBuffer()], + program.programId, +); +``` + + + + +```diff +describe("pda", () => { + const program = pg.program; + const wallet = pg.wallet; + + const [messagePda, messageBump] = PublicKey.findProgramAddressSync( + [Buffer.from("message"), wallet.publicKey.toBuffer()], + program.programId + ); + ++ const [vaultPda, vaultBump] = PublicKey.findProgramAddressSync( ++ [Buffer.from("vault"), wallet.publicKey.toBuffer()], ++ program.programId ++ ); + + // ...tests + }); +``` + + + + +#### Modify Update Test + +Then, update the update instruction to include the `vaultAccount`. + +```ts filename="anchor.test.ts" {5} +const transactionSignature = await program.methods + .update(message) + .accounts({ + messageAccount: messagePda, + vaultAccount: vaultPda, + }) + .rpc({ commitment: "confirmed" }); +``` + + + + +```diff + const transactionSignature = await program.methods + .update(message) + .accounts({ + messageAccount: messagePda, ++ vaultAccount: vaultPda, + }) + .rpc({ commitment: "confirmed" }); +``` + + + + +#### Modify Delete Test + +Then, update the delete instruction to include the `vaultAccount`. + +```ts filename="anchor.test.ts" {5} +const transactionSignature = await program.methods + .delete() + .accounts({ + messageAccount: messagePda, + vaultAccount: vaultPda, + }) + .rpc({ commitment: "confirmed" }); +``` + + + + +```diff + const transactionSignature = await program.methods + .delete() + .accounts({ + messageAccount: messagePda, ++ vaultAccount: vaultPda, + }) + .rpc({ commitment: "confirmed" }); +``` + + + + +### Rerun Test + +After making these changes, run the tests to ensure everything is working as +expected: + +```shell filename="Terminal" +test +``` + + + + +```bash +$ test +Running tests... + anchor.test.ts: + pda + { + "user": "3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R", + "message": "Hello, World!", + "bump": 254 +} + Transaction Signature: https://solana.fm/tx/qGsYb87mUUjeyh7Ha7r9VXkACw32HxVBujo2NUxqHiUc8qxRMFB7kdH2D4JyYtPBx171ddS91VyVrFXypgYaKUr?cluster=devnet-solana + ✔ Create Message Account (842ms) + { + "user": "3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R", + "message": "Hello, Solana!", + "bump": 254 +} + Transaction Signature: https://solana.fm/tx/3KCDnNSfDDfmSy8kpiSrJsGGkzgxx2mt18KejuV2vmJjeyenkSoEfs2ghUQ6cMoYYgd9Qax9CbnYRcvF2zzumNt8?cluster=devnet-solana + ✔ Update Message Account (946ms) + Expect Null: null + Transaction Signature: https://solana.fm/tx/3M7Z7Mea3TtQc6m9z386B9QuEgvLKxD999mt2RyVtJ26FgaAzV1QA5mxox3eXie3bpBkNpDQ4mEANr3trVHCWMC2?cluster=devnet-solana + ✔ Delete Message Account (859ms) + 3 passing (3s) +``` + + + + +You can then inspect the SolanFM links to view the transaction details, where +you'll find the CPIs for the transfer instructions within the update and delete +instructions. + +![Update CPI](/assets/docs/intro/quickstart/cpi-update.png) + +![Delete CPI](/assets/docs/intro/quickstart/cpi-delete.png) + +If you encounter any errors, you can reference the +[final code](https://beta.solpg.io/668304cfcffcf4b13384d20a). + + + +## Next Steps + +You've completed the Solana Quickstart guide! You've learned about accounts, +transactions, PDAs, CPIs, and deployed your own programs. + +Visit the [Core Concepts](/docs/core/accounts) pages for more comprehensive +explanations of the topics covered in this guide. + +Additional learning resources can be found on the +[Developer Resources](/developers) page. + +### Explore More Examples + +If you prefer learning by example, check out the +[Program Examples Repository](https://github.com/solana-developers/program-examples) +for a variety of example programs. + +Solana Playground offers a convenient feature allowing you to import or view +projects using their GitHub links. For example, open this +[Solana Playground link](https://beta.solpg.io/https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor) +to view the Anchor project from this +[Github repo](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor). + +Click the `Import` button and enter a project name to add it to your list of +projects in Solana Playground. Once a project is imported, all changes are +automatically saved and persisted within the Playground environment. diff --git a/docs/uk/intro/quick-start/deploying-programs.md b/docs/uk/intro/quick-start/deploying-programs.md new file mode 100644 index 000000000..57c78a01d --- /dev/null +++ b/docs/uk/intro/quick-start/deploying-programs.md @@ -0,0 +1,379 @@ +--- +sidebarLabel: Deploying Programs +title: Deploying Your First Solana Program +sidebarSortOrder: 3 +description: + Learn how to build, deploy, and test your first Solana program using the + Anchor framework and Solana Playground. This beginner-friendly guide walks + through creating a simple program, deploying it to devnet, running tests, and + closing the program. +--- + +In this section, we'll build, deploy, and test a simple Solana program using the +Anchor framework. By the end, you'll have deployed your first program to the +Solana blockchain! + +The purpose of this section is to familiarize you with the Solana Playground. +We'll walk through a more detailed example in the PDA and CPI sections. For more +details, refer to the [Programs on Solana](/docs/core/programs) page. + + + +### Create Anchor Project + +First, open https://beta.solpg.io in a new browser tab. + +- Click the "Create a new project" button on the left-side panel. + +- Enter a project name, select Anchor as the framework, then click the "Create" + button. + +![New Project](/assets/docs/intro/quickstart/pg-new-project.gif) + +You'll see a new project created with the program code in the `src/lib.rs` file. + +```rust filename="lib.rs" +use anchor_lang::prelude::*; + +// This is your program's public key and it will update +// automatically when you build the project. +declare_id!("11111111111111111111111111111111"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); // Message will show up in the tx logs + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + // We must specify the space in order to initialize an account. + // First 8 bytes are default account discriminator, + // next 8 bytes come from NewAccount.data being type u64. + // (u64 = 64 bits unsigned integer = 8 bytes) + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64 +} +``` + + + + +For now, we'll only cover the high-level overview of the program code: + +- The `declare_id!` macro specifies the on-chain address of your program. It + will be automatically updated when we build the program in the next step. + + ```rs + declare_id!("11111111111111111111111111111111"); + ``` + +- The `#[program]` macro annotates a module containing functions that represent + the program's instructions. + + ```rs + #[program] + mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); // Message will show up in the tx logs + Ok(()) + } + } + ``` + + In this example, the `initialize` instruction takes two parameters: + + 1. `ctx: Context` - Provides access to the accounts required for + this instruction, as specified in the `Initialize` struct. + 2. `data: u64` - An instruction parameter that will be passed in when the + instruction is invoked. + + The function body sets the `data` field of `new_account` to the provided + `data` argument and then prints a message to the program logs. + +- The `#[derive(Accounts)]` macro is used to define a struct that specifies the + accounts required for a particular instruction, where each field represents a + separate account. + + The field types (ex. `Signer<'info>`) and constraints (ex. `#[account(mut)]`) + are used by Anchor to automatically handle common security checks related to + account validation. + + ```rs + #[derive(Accounts)] + pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, + } + ``` + +- The `#[account]` macro is used to define a struct that represents the data + structure of an account created and owned by the program. + + ```rs + #[account] + pub struct NewAccount { + data: u64 + } + ``` + + + + +### Build and Deploy Program + +To build the program, simply run `build` in the terminal. + +```shell filename="Terminal" +build +``` + +Notice that the address in `declare_id!()` has been updated. This is your +program's on-chain address. + + + + +```shell filename="Terminal" +$ build +Building... +Build successful. Completed in 1.46s. +``` + + + + +Once the program is built, run `deploy` in the terminal to deploy the program to +the network (devnet by default). To deploy a program, SOL must be allocated to +the on-chain account that stores the program. + +Before deployment, ensure you have enough SOL. You can get devnet SOL by either +running `solana airdrop 5` in the Playground terminal or using the +[Web Faucet](https://faucet.solana.com/). + +```shell filename="Terminal" +deploy +``` + + + + +```shell filename="Terminal" +$ deploy +Deploying... This could take a while depending on the program size and network conditions. +Warning: 1 transaction not confirmed, retrying... +Deployment successful. Completed in 19s. +``` + + + + +Alternatively, you can also use the `Build` and `Deploy` buttons on the +left-side panel. + +![Build and Deploy](/assets/docs/intro/quickstart/pg-build-deploy.png) + +Once the program is deployed, you can now invoke its instructions. + +### Test Program + +Included with the starter code is a test file found in `tests/anchor.test.ts`. +This file demonstrates how to invoke the `initialize` instruction on the starter +program from the client. + +```ts filename="anchor.test.ts" +// No imports needed: web3, anchor, pg and more are globally available + +describe("Test", () => { + it("initialize", async () => { + // Generate keypair for the new account + const newAccountKp = new web3.Keypair(); + + // Send transaction + const data = new BN(42); + const txHash = await pg.program.methods + .initialize(data) + .accounts({ + newAccount: newAccountKp.publicKey, + signer: pg.wallet.publicKey, + systemProgram: web3.SystemProgram.programId, + }) + .signers([newAccountKp]) + .rpc(); + console.log(`Use 'solana confirm -v ${txHash}' to see the logs`); + + // Confirm transaction + await pg.connection.confirmTransaction(txHash); + + // Fetch the created account + const newAccount = await pg.program.account.newAccount.fetch( + newAccountKp.publicKey, + ); + + console.log("On-chain data is:", newAccount.data.toString()); + + // Check whether the data on-chain is equal to local 'data' + assert(data.eq(newAccount.data)); + }); +}); +``` + +To run the test file once the program is deployed, run `test` in the terminal. + +```shell filename="Terminal" +test +``` + +You should see an output indicating that the test passed successfully. + + + + +```shell filename="Terminal" +$ test +Running tests... + hello_anchor.test.ts: + hello_anchor + Use 'solana confirm -v 3TewJtiUz1EgtT88pLJHvKFzqrzDNuHVi8CfD2mWmHEBAaMfC5NAaHdmr19qQYfTiBace6XUmADvR4Qrhe8gH5uc' to see the logs + On-chain data is: 42 + ✔ initialize (961ms) + 1 passing (963ms) +``` + + + + +You can also use the `Test` button on the left-side panel. + +![Run Test](/assets/docs/intro/quickstart/pg-test.png) + +You can then view the transaction logs by running the `solana confirm -v` +command and specifying the transaction hash (signature) from the test output: + +```shell filename="Terminal" +solana confirm -v [TxHash] +``` + +For example: + +```shell filename="Terminal" +solana confirm -v 3TewJtiUz1EgtT88pLJHvKFzqrzDNuHVi8CfD2mWmHEBAaMfC5NAaHdmr19qQYfTiBace6XUmADvR4Qrhe8gH5uc +``` + + + + +```shell filename="Terminal" {29-35} +$ solana confirm -v 3TewJtiUz1EgtT88pLJHvKFzqrzDNuHVi8CfD2mWmHEBAaMfC5NAaHdmr19qQYfTiBace6XUmADvR4Qrhe8gH5uc +RPC URL: https://api.devnet.solana.com +Default Signer: Playground Wallet +Commitment: confirmed + +Transaction executed in slot 308150984: + Block Time: 2024-06-25T12:52:05-05:00 + Version: legacy + Recent Blockhash: 7AnZvY37nMhCybTyVXJ1umcfHSZGbngnm4GZx6jNRTNH + Signature 0: 3TewJtiUz1EgtT88pLJHvKFzqrzDNuHVi8CfD2mWmHEBAaMfC5NAaHdmr19qQYfTiBace6XUmADvR4Qrhe8gH5uc + Signature 1: 3TrRbqeMYFCkjsxdPExxBkLAi9SB2pNUyg87ryBaTHzzYtGjbsAz9udfT9AkrjSo1ZjByJgJHBAdRVVTZv6B87PQ + Account 0: srw- 3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R (fee payer) + Account 1: srw- c7yy8zdP8oeZ2ewbSb8WWY2yWjDpg3B43jk3478Nv7J + Account 2: -r-- 11111111111111111111111111111111 + Account 3: -r-x 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r + Instruction 0 + Program: 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r (3) + Account 0: c7yy8zdP8oeZ2ewbSb8WWY2yWjDpg3B43jk3478Nv7J (1) + Account 1: 3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R (0) + Account 2: 11111111111111111111111111111111 (2) + Data: [175, 175, 109, 31, 13, 152, 155, 237, 42, 0, 0, 0, 0, 0, 0, 0] + Status: Ok + Fee: ◎0.00001 + Account 0 balance: ◎5.47001376 -> ◎5.46900152 + Account 1 balance: ◎0 -> ◎0.00100224 + Account 2 balance: ◎0.000000001 + Account 3 balance: ◎0.00139896 + Log Messages: + Program 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r invoke [1] + Program log: Instruction: Initialize + Program 11111111111111111111111111111111 invoke [2] + Program 11111111111111111111111111111111 success + Program log: Changed data to: 42! + Program 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r consumed 5661 of 200000 compute units + Program 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r success + +Confirmed +``` + + + + +Alternatively, you can view the transaction details on +[SolanaFM](https://solana.fm/) or +[Solana Explorer](https://explorer.solana.com/?cluster=devnet) by searching for +the transaction signature (hash). + + + Reminder to update the cluster (network) connection on the Explorer you are + using to match Solana Playground. Solana Playground's default cluster is devnet. + + +### Close Program + +Lastly, the SOL allocated to the on-chain program can be fully recovered by +closing the program. + +You can close a program by running the following command and specifying the +program address found in `declare_id!()`: + +```shell filename="Terminal" +solana program close [ProgramID] +``` + +For example: + +```shell filename="Terminal" +solana program close 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r +``` + + + + +```shell filename="Terminal" +$ solana program close 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r +Closed Program Id 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r, 2.79511512 SOL reclaimed +``` + + + + +Only the upgrade authority of the program can close it. The upgrade authority is +set when the program is deployed, and it's the only account with permission to +modify or close the program. If the upgrade authority is revoked, then the +program becomes immutable and can never be closed or upgraded. + +When deploying programs on Solana Playground, your Playground wallet is the +upgrade authority for all your programs. + + + + +Congratulations! You've just built and deployed your first Solana program using +the Anchor framework! + + diff --git a/docs/uk/intro/quick-start/index.md b/docs/uk/intro/quick-start/index.md new file mode 100644 index 000000000..b582d3258 --- /dev/null +++ b/docs/uk/intro/quick-start/index.md @@ -0,0 +1,119 @@ +--- +sidebarLabel: Quick Start +title: Solana Quick Start Guide +sidebarSortOrder: 0 +description: + Learn Solana development basics. Create your first program, understand + accounts, send transactions, and explore PDAs and CPIs using Solana Playground + - no installation required. +--- + +Welcome to the Solana Quick Start Guide! This hands-on guide will introduce you +to the core concepts for building on Solana, regardless of your prior +experience. By the end of this tutorial, you'll have a basic foundation in +Solana development and be ready to explore more advanced topics. + +## What You'll Learn + +In this tutorial, you'll learn about: + +- Understanding Accounts: Explore how data is stored on the Solana network. +- Sending Transactions: Learn to interact with the Solana network by sending + transactions. +- Building and Deploying Programs: Create your first Solana program and deploy + it to the network. +- Program Derived Addresses (PDAs): Learn how to use PDAs to create + deterministic addresses for accounts. +- Cross-Program Invocations (CPIs): Learn how to make your programs interact + with other programs on Solana. + +The best part? You don't need to install anything! We'll be using Solana +Playground, a browser-based development environment, for all our examples. This +means you can follow along, copy and paste code, and see results immediately, +all from your web browser. Basic programming knowledge is helpful but not +required. + +Let's dive in and start building on Solana! + +## Solana Playground + +Solana Playground (Solpg) is a browser-based development environment that allows +you to quickly develop, deploy, and test Solana programs! + +Open a new tab in your web browser and navigate to https://beta.solpg.io/. + + + +### Create Playground Wallet + +If you're new to Solana Playground, the first step is to create your Playground +Wallet. This wallet will allow you to interact with the Solana network right +from your browser. + +#### Step 1. Connect to Playground + +Click the "Not connected" button at the bottom left of the screen. + +![Not Connected](/assets/docs/intro/quickstart/pg-not-connected.png) + +#### Step 2. Create Your Wallet + +You'll see an option to save your wallet's keypair. Optionally, save your +wallet's keypair for backup and then click "Continue". + +![Create Playground Wallet](/assets/docs/intro/quickstart/pg-create-wallet.png) + +You should now see your wallet's address, SOL balance, and connected cluster +(devnet by default) at the bottom of the window. + +![Connected](/assets/docs/intro/quickstart/pg-connected.png) + + + Your Playground Wallet will be saved in your browser's local storage. Clearing + your browser cache will remove your saved wallet. + + +Some definitions you may find helpful: + +- _wallet address_: a unique identifier for a digital wallet, used to send or + receive crypto assets on a blockchain. Each wallet address is a string of + alphanumeric characters that represents a specific destination on the network. + Think of it like an email address or bank account number—if someone wants to + send you cryptocurrency, they need your wallet address to direct the funds. +- _connected cluster_: a set of network nodes that work together to maintain a + synchronized copy of the blockchain. These clusters are essential for + providing a decentralized, distributed ledger and powering the Solana network + by validating transactions, securing the chain, and executing programs (smart + contracts). + +### Get Devnet SOL + +Before we start building, we first need some devnet SOL. + +From a developer's perspective, SOL is required for two main use cases: + +- To create accounts where we can store data or deploy programs +- To pay for transaction fees when we interact with the network + +Below are two methods to fund your wallet with devnet SOL: + +#### Option 1: Using the Playground Terminal + +To fund your Playground wallet with devnet SOL. In the Playground terminal, run: + +```shell filename="Terminal" +solana airdrop 5 +``` + +#### Option 2: Using the Devnet Faucet + +If the airdrop command doesn't work (due to rate limits or errors), you can use +the [Web Faucet](https://faucet.solana.com/). + +- Enter your wallet address (found at the bottom of the Playground screen) and + select an amount +- Click "Confirm Airdrop" to receive your devnet SOL + +![Faucet Airdrop](/assets/docs/intro/quickstart/faucet-airdrop.gif) + + diff --git a/docs/uk/intro/quick-start/program-derived-address.md b/docs/uk/intro/quick-start/program-derived-address.md new file mode 100644 index 000000000..18a4886e5 --- /dev/null +++ b/docs/uk/intro/quick-start/program-derived-address.md @@ -0,0 +1,1098 @@ +--- +sidebarLabel: Program Derived Address +title: Program Derived Address +sidebarSortOrder: 4 +description: + Learn how to build a CRUD (Create, Read, Update, Delete) Solana program using + Program Derived Addresses (PDAs) and the Anchor framework. This step-by-step + guide demonstrates how to create, update, and delete on-chain message accounts + using PDAs, implement account validation, and write tests. Perfect for + developers looking to understand how to use PDAs in Solana programs. +--- + +In this section, we'll walk through how to build a basic CRUD (Create, Read, +Update, Delete) program. The program will store a user's message using a Program +Derived Address (PDA) as the account's address. + +The purpose of this section is to guide you through the steps for building and +testing a Solana program using the Anchor framework and demonstrating how to use +PDAs within a program. For more details, refer to the +[Programs Derived Address](/docs/core/pda) page. + +For reference, here is the +[final code](https://beta.solpg.io/668304cfcffcf4b13384d20a) after completing +both the PDA and CPI sections. + + + +### Starter Code + +Begin by opening this +[Solana Playground link](https://beta.solpg.io/66734b7bcffcf4b13384d1ad) with +the starter code. Then click the "Import" button, which will add the program to +your list of projects on Solana Playground. + +![Import](/assets/docs/intro/quickstart/pg-import.png) + +In the `lib.rs` file, you'll find a program scaffolded with the `create`, +`update`, and `delete` instructions we'll implement in the following steps. + +```rs filename="lib.rs" +use anchor_lang::prelude::*; + +declare_id!("8KPzbM2Cwn4Yjak7QYAEH9wyoQh86NcBicaLuzPaejdw"); + +#[program] +pub mod pda { + use super::*; + + pub fn create(_ctx: Context) -> Result<()> { + Ok(()) + } + + pub fn update(_ctx: Context) -> Result<()> { + Ok(()) + } + + pub fn delete(_ctx: Context) -> Result<()> { + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Create {} + +#[derive(Accounts)] +pub struct Update {} + +#[derive(Accounts)] +pub struct Delete {} + +#[account] +pub struct MessageAccount {} +``` + +Before we begin, run `build` in the Playground terminal to check the starter +program builds successfully. + +```shell filename="Terminal" +build +``` + + + + +```shell filename="Terminal" +$ build +Building... +Build successful. Completed in 3.50s. +``` + + + + +### Define Message Account Type + +First, let's define the structure for the message account that our program will +create. This is the data that we'll store in the account created by the program. + +In `lib.rs`, update the `MessageAccount` struct with the following: + +```rs filename="lib.rs" +#[account] +pub struct MessageAccount { + pub user: Pubkey, + pub message: String, + pub bump: u8, +} +``` + + + + +```diff +- #[account] +- pub struct MessageAccount {} + ++ #[account] ++ pub struct MessageAccount { ++ pub user: Pubkey, ++ pub message: String, ++ pub bump: u8, ++ } +``` + + + + +The `#[account]` macro in an Anchor program is used to annotate structs that +represent account data (data type to store in the AccountInfo's data field). + +In this example, we're defining a `MessageAccount` struct to store a message +created by users that contains three fields: + +- `user` - A Pubkey representing the user who created the message account. +- `message` - A String containing the user's message. +- `bump` - A u8 storing the ["bump" seed](/docs/core/pda#canonical-bump) used in + deriving the program derived address (PDA). Storing this value saves compute + by eliminating the need to rederive it for each use in subsequent + instructions. When an account is created, the `MessageAccount` data will be + serialized and stored in the new account's data field. + +Later, when reading from the account, this data can be deserialized back into +the `MessageAccount` data type. The process of creating and reading the account +data will be demonstrated in the testing section. + + + + +Build the program again by running `build` in the terminal. + +```shell filename="Terminal" +build +``` + +We've defined what our message account will look like. Next, we'll implement the +program instructions. + +### Implement Create Instruction + +Now, let's implement the `create` instruction to create and initialize the +`MessageAccount`. + +Start by defining the accounts required for the instruction by updating the +`Create` struct with the following: + +```rs filename="lib.rs" +#[derive(Accounts)] +#[instruction(message: String)] +pub struct Create<'info> { + #[account(mut)] + pub user: Signer<'info>, + + #[account( + init, + seeds = [b"message", user.key().as_ref()], + bump, + payer = user, + space = 8 + 32 + 4 + message.len() + 1 + )] + pub message_account: Account<'info, MessageAccount>, + pub system_program: Program<'info, System>, +} +``` + + + + +```diff +- #[derive(Accounts)] +- pub struct Create {} + ++ #[derive(Accounts)] ++ #[instruction(message: String)] ++ pub struct Create<'info> { ++ #[account(mut)] ++ pub user: Signer<'info>, ++ ++ #[account( ++ init, ++ seeds = [b"message", user.key().as_ref()], ++ bump, ++ payer = user, ++ space = 8 + 32 + 4 + message.len() + 1 ++ )] ++ pub message_account: Account<'info, MessageAccount>, ++ pub system_program: Program<'info, System>, ++ } +``` + + + + +The `#[derive(Accounts)]` macro in an Anchor program is used to annotate structs +that represent a list of accounts required by an instruction where each field in +the struct is an account. + +Each account (field) in the struct is annotated with an account type (ex. +`Signer<'info>`) and can be further annotated with constraints (ex. +`#[account(mut)]`). The account type along with account constraints are used to +perform security checks on the accounts passed to the instruction. + +The naming of each field is only for our understanding and has no effect on +account validation, however, it is recommended to use descriptive account names. + +--- + +The `Create` struct defines the accounts required for the `create` instruction. + +1. `user: Signer<'info>` + + - Represents the user creating the message account + - Marked as mutable (`#[account(mut)]`) as it pays for the new account + - Must be a signer to approve the transaction, as lamports are deducted from + the account + +2. `message_account: Account<'info, MessageAccount>` + + - The new account created to store the user's message + - `init` constraint indicates the account will be created in the instruction + - `seeds` and `bump` constraints indicate the address of the account is a + Program Derived Address (PDA) + - `payer = user` specifies the account paying for the creation of the new + account + - `space` specifies the number of bytes allocated to the new account's data + field + +3. `system_program: Program<'info, System>` + + - Required for creating new accounts + - Under the hood, the `init` constraint invokes the System Program to create + a new account allocated with the specified `space` and reassigns the + program owner to the current program. + +--- + +The `#[instruction(message: String)]` annotation enables the `Create` struct to +access the `message` parameter from the `create` instruction. + +--- + +The `seeds` and `bump` constraints are used together to specify that an +account's address is a Program Derived Address (PDA). + +```rs filename="lib.rs" +seeds = [b"message", user.key().as_ref()], +bump, +``` + +The `seeds` constraint defines the optional inputs used to derive the PDA. + +- `b"message"` - A hardcoded string as the first seed. +- `user.key().as_ref()` - The public key of the `user` account as the second + seed. + +The `bump` constraint tells Anchor to automatically find and use the correct +bump seed. Anchor will use the `seeds` and `bump` to derive the PDA. + +--- + +The `space` calculation (8 + 32 + 4 + message.len() + 1) allocates space for +`MessageAccount` data type: + +- Anchor Account discriminator (identifier): 8 bytes +- User Address (Pubkey): 32 bytes +- User Message (String): 4 bytes for length + variable message length +- PDA Bump seed (u8): 1 byte + +```rs filename="lib.rs" +#[account] +pub struct MessageAccount { + pub user: Pubkey, + pub message: String, + pub bump: u8, +} +``` + +All accounts created through an Anchor program require 8 bytes for an account +discriminator, which is an identifier for the account type that is automatically +generated when the account is created. + +A `String` type requires 4 bytes to store the length of the string, and the +remaining length is the actual data. + + + + +Next, implement the business logic for the `create` instruction by updating the +`create` function with the following: + +```rs filename="lib.rs" +pub fn create(ctx: Context, message: String) -> Result<()> { + msg!("Create Message: {}", message); + let account_data = &mut ctx.accounts.message_account; + account_data.user = ctx.accounts.user.key(); + account_data.message = message; + account_data.bump = ctx.bumps.message_account; + Ok(()) +} +``` + + + + +```diff +- pub fn create(_ctx: Context) -> Result<()> { +- Ok(()) +- } + ++ pub fn create(ctx: Context, message: String) -> Result<()> { ++ msg!("Create Message: {}", message); ++ let account_data = &mut ctx.accounts.message_account; ++ account_data.user = ctx.accounts.user.key(); ++ account_data.message = message; ++ account_data.bump = ctx.bumps.message_account; ++ Ok(()) ++ } +``` + + + + +The `create` function implements the logic for initializing a new message +account's data. It takes two parameters: + +1. `ctx: Context` - Provides access to the accounts specified in the + `Create` struct. +2. `message: String` - The user's message to be stored. + +The body of the function then performs the following logic: + +1. Print a message to program logs using the `msg!()` macro. + + ```rs + msg!("Create Message: {}", message); + ``` + +2. Initializing Account Data: + + - Accesses the `message_account` from the context. + + ```rs + let account_data = &mut ctx.accounts.message_account; + ``` + + - Sets the `user` field to the public key of the `user` account. + + ```rs + account_data.user = ctx.accounts.user.key(); + ``` + + - Sets the `message` field to the `message` from the function argument. + + ```rs + account_data.message = message; + ``` + + - Sets the `bump` value used to derive the PDA, retrieved from + `ctx.bumps.message_account`. + + ```rs + account_data.bump = ctx.bumps.message_account; + ``` + + + + +Rebuild the program. + +```shell filename="Terminal" +build +``` + +### Implement Update Instruction + +Next, implement the `update` instruction to update the `MessageAccount` with a +new message. + +Just as before, the first step is to specify the accounts required by the +`update` instruction. + +Update the `Update` struct with the following: + +```rs filename="lib.rs" +#[derive(Accounts)] +#[instruction(message: String)] +pub struct Update<'info> { + #[account(mut)] + pub user: Signer<'info>, + + #[account( + mut, + seeds = [b"message", user.key().as_ref()], + bump = message_account.bump, + realloc = 8 + 32 + 4 + message.len() + 1, + realloc::payer = user, + realloc::zero = true, + )] + pub message_account: Account<'info, MessageAccount>, + pub system_program: Program<'info, System>, +} +``` + + + + +```diff +- #[derive(Accounts)] +- pub struct Update {} + ++ #[derive(Accounts)] ++ #[instruction(message: String)] ++ pub struct Update<'info> { ++ #[account(mut)] ++ pub user: Signer<'info>, ++ ++ #[account( ++ mut, ++ seeds = [b"message", user.key().as_ref()], ++ bump = message_account.bump, ++ realloc = 8 + 32 + 4 + message.len() + 1, ++ realloc::payer = user, ++ realloc::zero = true, ++ )] ++ pub message_account: Account<'info, MessageAccount>, ++ pub system_program: Program<'info, System>, ++ } +``` + + + + +The `Update` struct defines the accounts required for the `update` instruction. + +1. `user: Signer<'info>` + + - Represents the user updating the message account + - Marked as mutable (`#[account(mut)]`) as it may pay for additional space + for the `message_account` if needed + - Must be a signer to approve the transaction + +2. `message_account: Account<'info, MessageAccount>` + + - The existing account storing the user's message that will be updated + - `mut` constraint indicates this account's data will be modified + - `realloc` constraint allows for resizing the account's data + - `seeds` and `bump` constraints ensure the account is the correct PDA + +3. `system_program: Program<'info, System>` + - Required for potential reallocation of account space + - The `realloc` constraint invokes the System Program to adjust the account's + data size + +--- + +Note that the `bump = message_account.bump` constraint uses the bump seed stored +on the `message_account`, rather than having Anchor recalculate it. + +--- + +`#[instruction(message: String)]` annotation enables the `Update` struct to +access the `message` parameter from the `update` instruction. + + + + +Next, implement the logic for the `update` instruction. + +```rs filename="lib.rs" +pub fn update(ctx: Context, message: String) -> Result<()> { + msg!("Update Message: {}", message); + let account_data = &mut ctx.accounts.message_account; + account_data.message = message; + Ok(()) +} +``` + + + + +```diff +- pub fn update(_ctx: Context) -> Result<()> { +- Ok(()) +- } + ++ pub fn update(ctx: Context, message: String) -> Result<()> { ++ msg!("Update Message: {}", message); ++ let account_data = &mut ctx.accounts.message_account; ++ account_data.message = message; ++ Ok(()) ++ } +``` + + + + +The `update` function implements the logic for modifying an existing message +account. It takes two parameters: + +1. `ctx: Context` - Provides access to the accounts specified in the + `Update` struct. +2. `message: String` - The new message to replace the existing one. + +The body of the function then: + +1. Print a message to program logs using the `msg!()` macro. + +2. Updates Account Data: + - Accesses the `message_account` from the context. + - Sets the `message` field to the new `message` from the function argument. + + + + +Rebuild the program + +```shell filename="Terminal" +build +``` + +### Implement Delete Instruction + +Next, implement the `delete` instruction to close the `MessageAccount`. + +Update the `Delete` struct with the following: + +```rs filename="lib.rs" +#[derive(Accounts)] +pub struct Delete<'info> { + #[account(mut)] + pub user: Signer<'info>, + + #[account( + mut, + seeds = [b"message", user.key().as_ref()], + bump = message_account.bump, + close= user, + )] + pub message_account: Account<'info, MessageAccount>, +} +``` + + + + +```diff +- #[derive(Accounts)] +- pub struct Delete {} + ++ #[derive(Accounts)] ++ pub struct Delete<'info> { ++ #[account(mut)] ++ pub user: Signer<'info>, ++ ++ #[account( ++ mut, ++ seeds = [b"message", user.key().as_ref()], ++ bump = message_account.bump, ++ close = user, ++ )] ++ pub message_account: Account<'info, MessageAccount>, ++ } +``` + + + + +The `Delete` struct defines the accounts required for the `delete` instruction: + +1. `user: Signer<'info>` + + - Represents the user closing the message account + - Marked as mutable (`#[account(mut)]`) as it will receive the lamports from + the closed account + - Must be a signer to ensure only the correct user can close their message + account + +2. `message_account: Account<'info, MessageAccount>` + + - The account being closed + - `mut` constraint indicates this account will be modified + - `seeds` and `bump` constraints ensure the account is the correct PDA + - `close = user` constraint specifies that this account will be closed and + its lamports transferred to the `user` account + + + + +Next, implement the logic for the `delete` instruction. + +```rs filename="lib.rs" +pub fn delete(_ctx: Context) -> Result<()> { + msg!("Delete Message"); + Ok(()) +} +``` + + + + +```diff +- pub fn delete(_ctx: Context) -> Result<()> { +- Ok(()) +- } + ++ pub fn delete(_ctx: Context) -> Result<()> { ++ msg!("Delete Message"); ++ Ok(()) ++ } +``` + + + + +The `delete` function takes one parameter: + +1. `_ctx: Context` - Provides access to the accounts specified in the + `Delete` struct. The `_ctx` syntax indicates we won't be using the Context in + the body of the function. + +The body of the function only prints a message to program logs using the +`msg!()` macro. The function does not require any additional logic because the +actual closing of the account is handled by the `close` constraint in the +`Delete` struct. + + + + +Rebuild the program. + +```shell filename="Terminal" +build +``` + +### Deploy Program + +The basic CRUD program is now complete. Deploy the program by running `deploy` +in the Playground terminal. + +```shell filename="Terminal" +deploy +``` + + + + +```bash +$ deploy +Deploying... This could take a while depending on the program size and network conditions. +Deployment successful. Completed in 17s. +``` + + + + +### Set Up Test File + +Included with the starter code is also a test file in `anchor.test.ts`. + +```ts filename="anchor.test.ts" +import { PublicKey } from "@solana/web3.js"; + +describe("pda", () => { + it("Create Message Account", async () => {}); + + it("Update Message Account", async () => {}); + + it("Delete Message Account", async () => {}); +}); +``` + +Add the code below inside `describe`, but before the `it` sections. + +```ts filename="anchor.test.ts" +const program = pg.program; +const wallet = pg.wallet; + +const [messagePda, messageBump] = PublicKey.findProgramAddressSync( + [Buffer.from("message"), wallet.publicKey.toBuffer()], + program.programId, +); +``` + + + + +```diff + import { PublicKey } from "@solana/web3.js"; + + describe("pda", () => { ++ const program = pg.program; ++ const wallet = pg.wallet; ++ ++ const [messagePda, messageBump] = PublicKey.findProgramAddressSync( ++ [Buffer.from("message"), wallet.publicKey.toBuffer()], ++ program.programId ++ ); + + it("Create Message Account", async () => {}); + + it("Update Message Account", async () => {}); + + it("Delete Message Account", async () => {}); + }); +``` + + + + +In this section, we are simply setting up the test file. + +Solana Playground removes some boilerplate setup where `pg.program` allows us to +access the client library for interacting with the program, while `pg.wallet` is +your playground wallet. + +```ts filename="anchor.test.ts" +const program = pg.program; +const wallet = pg.wallet; +``` + +As part of the setup, we derive the message account PDA. This demonstrates how +to derive the PDA in Javascript using the seeds specified in the program. + +```ts filename="anchor.test.ts" +const [messagePda, messageBump] = PublicKey.findProgramAddressSync( + [Buffer.from("message"), wallet.publicKey.toBuffer()], + program.programId, +); +``` + + + + +Run the test file by running `test` in the Playground terminal to check the file +runs as expected. We will implement the tests in the following steps. + +```shell filename="Terminal" +test +``` + + + + +```bash +$ test +Running tests... + anchor.test.ts: + pda + ✔ Create Message Account + ✔ Update Message Account + ✔ Delete Message Account + 3 passing (4ms) +``` + + + + +### Invoke Create Instruction + +Update the first test with the following: + +```ts filename="anchor.test.ts" +it("Create Message Account", async () => { + const message = "Hello, World!"; + const transactionSignature = await program.methods + .create(message) + .accounts({ + messageAccount: messagePda, + }) + .rpc({ commitment: "confirmed" }); + + const messageAccount = await program.account.messageAccount.fetch( + messagePda, + "confirmed", + ); + + console.log(JSON.stringify(messageAccount, null, 2)); + console.log( + "Transaction Signature:", + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, + ); +}); +``` + + + + +```diff +- it("Create Message Account", async () => {}); + ++ it("Create Message Account", async () => { ++ const message = "Hello, World!"; ++ const transactionSignature = await program.methods ++ .create(message) ++ .accounts({ ++ messageAccount: messagePda, ++ }) ++ .rpc({ commitment: "confirmed" }); ++ ++ const messageAccount = await program.account.messageAccount.fetch( ++ messagePda, ++ "confirmed" ++ ); ++ ++ console.log(JSON.stringify(messageAccount, null, 2)); ++ console.log( ++ "Transaction Signature:", ++ `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana` ++ ); ++ }); +``` + + + + +First, we send a transaction that invokes the `create` instruction, passing in +"Hello, World!" as the message. + +```ts filename="anchor.test.ts" +const message = "Hello, World!"; +const transactionSignature = await program.methods + .create(message) + .accounts({ + messageAccount: messagePda, + }) + .rpc({ commitment: "confirmed" }); +``` + +Once the transaction is sent and the account is created, we then fetch the +account using its address (`messagePda`). + +```ts filename="anchor.test.ts" +const messageAccount = await program.account.messageAccount.fetch( + messagePda, + "confirmed", +); +``` + +Lastly, we log the account data and a link to view the transaction details. + +```ts filename="anchor.test.ts" +console.log(JSON.stringify(messageAccount, null, 2)); +console.log( + "Transaction Signature:", + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, +); +``` + + + + +### Invoke Update Instruction + +Update the second test with the following: + +```ts filename="anchor.test.ts" +it("Update Message Account", async () => { + const message = "Hello, Solana!"; + const transactionSignature = await program.methods + .update(message) + .accounts({ + messageAccount: messagePda, + }) + .rpc({ commitment: "confirmed" }); + + const messageAccount = await program.account.messageAccount.fetch( + messagePda, + "confirmed", + ); + + console.log(JSON.stringify(messageAccount, null, 2)); + console.log( + "Transaction Signature:", + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, + ); +}); +``` + + + + +```diff +- it("Update Message Account", async () => {}); + ++ it("Update Message Account", async () => { ++ const message = "Hello, Solana!"; ++ const transactionSignature = await program.methods ++ .update(message) ++ .accounts({ ++ messageAccount: messagePda, ++ }) ++ .rpc({ commitment: "confirmed" }); ++ ++ const messageAccount = await program.account.messageAccount.fetch( ++ messagePda, ++ "confirmed" ++ ); ++ ++ console.log(JSON.stringify(messageAccount, null, 2)); ++ console.log( ++ "Transaction Signature:", ++ `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana` ++ ); ++ }); +``` + + + + +First, we send a transaction that invokes the `update` instruction, passing in +"Hello, Solana!" as the new message. + +```ts filename="anchor.test.ts" +const message = "Hello, Solana!"; +const transactionSignature = await program.methods + .update(message) + .accounts({ + messageAccount: messagePda, + }) + .rpc({ commitment: "confirmed" }); +``` + +Once the transaction is sent and the account is updated, we then fetch the +account using its address (`messagePda`). + +```ts filename="anchor.test.ts" +const messageAccount = await program.account.messageAccount.fetch( + messagePda, + "confirmed", +); +``` + +Lastly, we log the account data and a link to view the transaction details. + +```ts filename="anchor.test.ts" +console.log(JSON.stringify(messageAccount, null, 2)); +console.log( + "Transaction Signature:", + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, +); +``` + + + + +### Invoke Delete Instruction + +Update the third test with the following: + +```ts filename="anchor.test.ts" +it("Delete Message Account", async () => { + const transactionSignature = await program.methods + .delete() + .accounts({ + messageAccount: messagePda, + }) + .rpc({ commitment: "confirmed" }); + + const messageAccount = await program.account.messageAccount.fetchNullable( + messagePda, + "confirmed", + ); + + console.log("Expect Null:", JSON.stringify(messageAccount, null, 2)); + console.log( + "Transaction Signature:", + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, + ); +}); +``` + + + + +```diff +- it("Delete Message Account", async () => {}); + ++ it("Delete Message Account", async () => { ++ const transactionSignature = await program.methods ++ .delete() ++ .accounts({ ++ messageAccount: messagePda, ++ }) ++ .rpc({ commitment: "confirmed" }); ++ ++ const messageAccount = await program.account.messageAccount.fetchNullable( ++ messagePda, ++ "confirmed" ++ ); ++ ++ console.log("Expect Null:", JSON.stringify(messageAccount, null, 2)); ++ console.log( ++ "Transaction Signature:", ++ `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana` ++ ); ++ }); +``` + + + + +First, we send a transaction that invokes the `delete` instruction to close the +message account. + +```ts filename="anchor.test.ts" +const transactionSignature = await program.methods + .delete() + .accounts({ + messageAccount: messagePda, + }) + .rpc({ commitment: "confirmed" }); +``` + +Once the transaction is sent and the account is closed, we attempt to fetch the +account using its address (`messagePda`) using `fetchNullable` since we expect +the return value to be null because the account is closed. + +```ts filename="anchor.test.ts" +const messageAccount = await program.account.messageAccount.fetchNullable( + messagePda, + "confirmed", +); +``` + +Lastly, we log the account data and a link to view the transaction details where +the account data should be logged as null. + +```ts filename="anchor.test.ts" +console.log(JSON.stringify(messageAccount, null, 2)); +console.log( + "Transaction Signature:", + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, +); +``` + + + + +### Run Test + +Once the tests are set up, run the test file by running `test` in the Playground +terminal. + +```shell filename="Terminal" +test +``` + + + + +```bash +$ test +Running tests... + anchor.test.ts: + pda + { + "user": "3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R", + "message": "Hello, World!", + "bump": 254 +} + Transaction Signature: https://solana.fm/tx/5oBT4jEdUR6CRYsFNGoqvyMBTRDvFqRWTAAmCGM9rEvYRBWy3B2bkb6GVFpVPKBnkr714UCFUurBSDKSa7nLHo8e?cluster=devnet-solana + ✔ Create Message Account (1025ms) + { + "user": "3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R", + "message": "Hello, Solana!", + "bump": 254 +} + Transaction Signature: https://solana.fm/tx/42veGAsQjHbJP1SxWBGcfYF7EdRN9X7bACNv23NSZNe4U7w2dmaYgSv8UUWXYzwgJPoNHejhtWdKZModHiMaTWYK?cluster=devnet-solana + ✔ Update Message Account (713ms) + Expect Null: null + Transaction Signature: https://solana.fm/tx/Sseog2i2X7uDEn2DyDMMJKVHeZEzmuhnqUwicwGhnGhstZo8URNwUZgED8o6HANiojJkfQbhXVbGNLdhsFtWrd6?cluster=devnet-solana + ✔ Delete Message Account (812ms) + 3 passing (3s) +``` + + + + + diff --git a/docs/uk/intro/quick-start/reading-from-network.md b/docs/uk/intro/quick-start/reading-from-network.md new file mode 100644 index 000000000..e65d0abdb --- /dev/null +++ b/docs/uk/intro/quick-start/reading-from-network.md @@ -0,0 +1,401 @@ +--- +sidebarLabel: Reading from Network +title: Reading from Network +sidebarSortOrder: 1 +description: + Learn how to read data from the Solana blockchain network. This guide covers + fetching wallet accounts, program accounts, and token mint accounts using + JavaScript/TypeScript, with practical examples using the Solana web3.js + library. +--- + +Now, let's explore how to read data from the Solana network. We'll fetch a few +different accounts to understand the structure of a Solana account. + +On Solana, all data is contained in what we call "accounts". You can think of +data on Solana as a public database with a single "Accounts" table, where each +entry in this table is an individual account. + +Accounts on Solana can store "state" or "executable" programs, all of which can +be thought of as entries in the same "Accounts" table. Each account has an +"address" (public key) that serves as its unique ID used to locate its +corresponding on-chain data. + +Solana accounts contain either: + +- State: This is data that's meant to be read from and persisted. It could be + information about tokens, user data, or any other type of data defined within + a program. +- Executable Programs: These are accounts that contain the actual code of Solana + programs. They contain the instructions that can be executed on the network. + +This separation of program code and program state is a key feature of Solana's +Account Model. For more details, refer to the +[Solana Account Model](/docs/core/accounts) page. + +## Fetch Playground Wallet + +Let's start by looking at a familiar account - your own Playground Wallet! We'll +fetch this account and examine its structure to understand what a basic Solana +account looks like. + + + +### Open Example 1 + +Click this [link](https://beta.solpg.io/6671c5e5cffcf4b13384d198) to open the +example in Solana Playground. You'll see this code: + +```ts filename="client.ts" +const address = pg.wallet.publicKey; +const accountInfo = await pg.connection.getAccountInfo(address); + +console.log(JSON.stringify(accountInfo, null, 2)); +``` + + + + +This code does three simple things: + +- Gets your Playground wallet's address + + ```ts + const address = pg.wallet.publicKey; + ``` + +- Fetches the `AccountInfo` for the account at that address + + ```ts + const accountInfo = await pg.connection.getAccountInfo(address); + ``` + +- Prints out the `AccountInfo` to the Playground terminal + + ```ts + console.log(JSON.stringify(accountInfo, null, 2)); + ``` + + + + +### Run Example 1 + +In the Playground terminal, type the `run` command and hit enter: + +```shell filename="Terminal" +run +``` + +You should see details about your wallet account, including its balance in +lamports, with output similar to the following: + + + + +```shell filename="Terminal" +$ run +Running client... + client.ts: + { + "data": { + "type": "Buffer", + "data": [] + }, + "executable": false, + "lamports": 5000000000, + "owner": "11111111111111111111111111111111", + "rentEpoch": 18446744073709552000, + "space": 0 +} +``` + + + + +Your wallet is actually just an account owned by the System Program, where the +main purpose of the wallet account is to store your SOL balance (amount in the +`lamports` field). + +--- + +At its core, all Solana accounts are represented in a standard format called the +`AccountInfo`. The +[AccountInfo](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/account_info.rs#L19-L36) +data type is the base data structure for all Solana Accounts. + +Let's break down the fields in the output: + +- `data` - This field contains what we generally refer to as the account "data". + For a wallet, it's empty (0 bytes), but other accounts use this field to store + any arbitrary data as a serialized buffer of bytes. + +> When data is "buffered" in this way, it maintains its integrity and can be +> later deserialized back into its original form for use in applications. This +> process is widely used in blockchain for efficient data handling. + +- `executable` - A flag that indicates whether the account is an executable + program. For wallets and any accounts that store state, this is `false`. +- `owner` - This field shows which program controls the account. For wallets, + it's always the System Program, with the address + `11111111111111111111111111111111`. +- `lamports` - The account's balance in lamports (1 SOL = 1,000,000,000 + lamports). +- `rentEpoch` - A legacy field related to Solana's deprecated rent collection + mechanism (currently not in use). +- `space` - Indicates byte capacity (length) of the `data` field, but is not a + field in the `AccountInfo` type + + + + + + +## Fetch Token Program + +Next, we'll examine the Token Extensions program, an executable program for +interacting with tokens on Solana. + + + +### Open Example 2 + +Click this [link](https://beta.solpg.io/6671c6e7cffcf4b13384d199) to open the +example in Solana Playground. You'll see this code: + +```ts filename="client.ts" {3} +import { PublicKey } from "@solana/web3.js"; + +const address = new PublicKey("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"); +const accountInfo = await pg.connection.getAccountInfo(address); + +console.log(JSON.stringify(accountInfo, null, 2)); +``` + +Instead of fetching your Playground wallet, here we fetch the address of the +Token Extensions Program account. + +### Run Example 2 + +Run the code using the `run` command in the terminal. + +```shell filename="Terminal" +run +``` + +Examine the output and how this program account differs from your wallet +account. + + + + +```shell filename="Terminal" {15, 17} +$ run +Running client... + client.ts: + { + "data": { + "type": "Buffer", + "data": [ + 2, + 0, + //... additional bytes + 86, + 51 + ] + }, + "executable": true, + "lamports": 1141440, + "owner": "BPFLoaderUpgradeab1e11111111111111111111111", + "rentEpoch": 18446744073709552000, + "space": 36 +} +``` + + + + +The Token Extensions program is an executable program account, but note that it +has the same `AccountInfo` structure. + +Key differences in the `AccountInfo`: + +- `executable` - Set to `true`, indicating this account represents an executable + program. +- `data` - Contains serialized data (unlike the empty data in a wallet account). + The data for a program account stores the address of another account (Program + Executable Data Account) that contains the program's bytecode. +- `owner` - The account is owned by the Upgradable BPF Loader + (`BPFLoaderUpgradeab1e11111111111111111111111`), a special program that + manages executable accounts. + +--- + +You can inspect the Solana Explorer for the +[Token Extensions Program Account](https://explorer.solana.com/address/TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb) +and its corresponding +[Program Executable Data Account](https://explorer.solana.com/address/DoU57AYuPFu2QU514RktNPG22QhApEjnKxnBcu4BHDTY). + +The Program Executable Data Account contains the compiled bytecode for the Token +Extensions Program +[source code](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program-2022/src). + + + + + + +## Fetch Mint Account + +In this step, we'll examine a Mint account, which represents a unique token on +the Solana network. + + + +### Open Example 3 + +Click this [link](https://beta.solpg.io/6671c9aecffcf4b13384d19a) to open the +example in Solana Playground. You'll see this code: + +```ts filename="client.ts" {3} +import { PublicKey } from "@solana/web3.js"; + +const address = new PublicKey("C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR"); +const accountInfo = await pg.connection.getAccountInfo(address); + +console.log(JSON.stringify(accountInfo, null, 2)); +``` + +In this example, we'll fetch the address of an existing Mint account on devnet. + +### Run Example 3 + +Run the code using the `run` command. + +```shell filename="Terminal" +run +``` + + + + +```shell filename="Terminal" {17} +$ run +Running client... + client.ts: + { + "data": { + "type": "Buffer", + "data": [ + 1, + 0, + //... additional bytes + 0, + 0 + ] + }, + "executable": false, + "lamports": 4176000, + "owner": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", + "rentEpoch": 18446744073709552000, + "space": 430 +} +``` + + + + +Key differences in the `AccountInfo`: + +- `owner` - The mint account is owned by the Token Extensions program + (`TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`). +- `executable` - Set to `false`, as this account stores state rather than + executable code. +- `data`: Contains serialized data about the token (mint authority, supply, + decimals, etc.). + + + + +### Deserialize Mint Account Data + +To read the `data` field from any account, you need to deserialize the data +buffer into the expected data type. This is often done using helper functions +from client libraries for a particular program. + +**Deserialization** is the process of converting data from a stored format (like +raw bytes or JSON) back into a usable, structured format in a program. In +blockchain, it involves taking raw, encoded data from the network and +transforming it back into objects, classes, or readable structures so developers +can access and manipulate specific information within a program. Deserialization +is essential for interpreting account or transaction data received from a +network in a form that a program can process and display meaningfully. + +Open this next [example](https://beta.solpg.io/6671cd8acffcf4b13384d19b) in +Solana Playground. You'll see this code: + +```ts filename="client.ts" +import { PublicKey } from "@solana/web3.js"; +import { getMint, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token"; + +const address = new PublicKey("C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR"); +const mintData = await getMint( + pg.connection, + address, + "confirmed", + TOKEN_2022_PROGRAM_ID, +); + +console.log(mintData); +``` + +This example uses the `getMint` helper function to automatically deserialize the +data field of the Mint account. + +Run the code using the `run` command. + +```shell filename="Terminal" +run +``` + +You should see the following deserialized Mint account data. + + + + +```shell filename="Terminal" +Running client... + client.ts: + { address: { _bn: { negative: 0, words: [Object], length: 10, red: null } }, + mintAuthority: { _bn: { negative: 0, words: [Object], length: 10, red: null } }, + supply: {}, + decimals: 2, + isInitialized: true, + freezeAuthority: null, + tlvData: } +``` + + + + +The `getMint` function deserializes the account data into the +[Mint](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32) +data type defined in the Token Extensions program source code. + +- `address` - The Mint account's address +- `mintAuthority` - The authority allowed to mint new tokens +- `supply` - The total supply of tokens +- `decimals` - The number of decimal places for the token +- `isInitialized` - Whether the Mint data has been initialized +- `freezeAuthority` - The authority allowed to freeze token accounts +- `tlvData` - Additional data for Token Extensions (requires further + deserialization) + +You can view the fully deserialized +[Mint Account](https://explorer.solana.com/address/C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR?cluster=devnet) +data, including enabled Token Extensions, on the Solana Explorer. + + + + + diff --git a/docs/uk/intro/quick-start/writing-to-network.md b/docs/uk/intro/quick-start/writing-to-network.md new file mode 100644 index 000000000..8d3e55154 --- /dev/null +++ b/docs/uk/intro/quick-start/writing-to-network.md @@ -0,0 +1,365 @@ +--- +sidebarLabel: Writing to Network +title: Writing to Network +sidebarSortOrder: 2 +description: + Learn how to interact with the Solana network by sending transactions and + instructions. Follow step-by-step examples to transfer SOL tokens and create + new tokens using the System Program and Token Extensions Program. +--- + +Now that we've explored reading from the Solana network, let's learn how to +write data to it. On Solana, we interact with the network by sending +transactions made up of instructions. These instructions are defined by +programs, which contain the business logic for how accounts should be updated. + +Let's walk through two common operations, transferring SOL and creating a token, +to demonstrate how to build and send transactions. For more details, refer to +the [Transactions and Instructions](/docs/core/transactions) and +[Fees on Solana](/docs/core/fees) pages. + +## Transfer SOL + +We'll start with a simple SOL transfer from your wallet to another account. This +requires invoking the transfer instruction on the System Program. + + + +### Open Example 1 + +Click this [link](https://beta.solpg.io/6671d85ecffcf4b13384d19e) to open the +example in Solana Playground. You'll see this code: + +```ts filename="client.ts" +import { + LAMPORTS_PER_SOL, + SystemProgram, + Transaction, + sendAndConfirmTransaction, + Keypair, +} from "@solana/web3.js"; + +const sender = pg.wallet.keypair; +const receiver = new Keypair(); + +const transferInstruction = SystemProgram.transfer({ + fromPubkey: sender.publicKey, + toPubkey: receiver.publicKey, + lamports: 0.01 * LAMPORTS_PER_SOL, +}); + +const transaction = new Transaction().add(transferInstruction); + +const transactionSignature = await sendAndConfirmTransaction( + pg.connection, + transaction, + [sender], +); + +console.log( + "Transaction Signature:", + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, +); +``` + + + + +This script does the following: + +- Set your Playground wallet as the sender + + ```ts + const sender = pg.wallet.keypair; + ``` + +- Creates a new keypair as the receiver + + ```ts + const receiver = new Keypair(); + ``` + +- Constructs a transfer instruction to transfer 0.01 SOL + + ```ts + const transferInstruction = SystemProgram.transfer({ + fromPubkey: sender.publicKey, + toPubkey: receiver.publicKey, + lamports: 0.01 * LAMPORTS_PER_SOL, + }); + ``` + +- Builds a transaction including the transfer instruction + + ```ts + const transaction = new Transaction().add(transferInstruction); + ``` + +- Sends and confirms the transaction + + ```ts + const transactionSignature = await sendAndConfirmTransaction( + pg.connection, + transaction, + [sender], + ); + ``` + +- Prints out a link to the SolanaFM explorer in the Playground terminal to view + the transaction details + + ```ts + console.log( + "Transaction Signature:", + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, + ); + ``` + + + + +### Run Example 1 + +Run the code using the `run` command. + +```shell filename="Terminal" +run +``` + +Click on the output link to view the transaction details on the SolanaFM +explorer. + + + + +```shell filename="Terminal" +Running client... + client.ts: + Transaction Signature: https://solana.fm/tx/he9dBwrEPhrfrx2BaX4cUmUbY22DEyqZ837zrGrFRnYEBmKhCb5SvoaUeRKSeLFXiGxC8hFY5eDbHqSJ7NYYo42?cluster=devnet-solana +``` + + + + +![Transfer SOL](/assets/docs/intro/quickstart/transfer-sol.png) + +You've just sent your first transaction on Solana! Notice how we created an +instruction, added it to a transaction, and then sent that transaction to the +network. This is the basic process for building any transaction. + + + +## Create a Token + +Now, let's create a new token by creating and initializing a Mint account. This +requires two instructions: + +- Invoke the System Program to create a new account +- Invoke the Token Extensions Program to initialize the account data + + + +### Open Example 2 + +Click this [link](https://beta.solpg.io/6671da4dcffcf4b13384d19f) to open the +example in Solana Playground. You'll see the following code: + +```ts filename="client.ts" +import { + Connection, + Keypair, + SystemProgram, + Transaction, + clusterApiUrl, + sendAndConfirmTransaction, +} from "@solana/web3.js"; +import { + MINT_SIZE, + TOKEN_2022_PROGRAM_ID, + createInitializeMint2Instruction, + getMinimumBalanceForRentExemptMint, +} from "@solana/spl-token"; + +const wallet = pg.wallet; +const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); + +// Generate keypair to use as address of mint account +const mint = new Keypair(); + +// Calculate minimum lamports for space required by mint account +const rentLamports = await getMinimumBalanceForRentExemptMint(connection); + +// Instruction to create new account with space for new mint account +const createAccountInstruction = SystemProgram.createAccount({ + fromPubkey: wallet.publicKey, + newAccountPubkey: mint.publicKey, + space: MINT_SIZE, + lamports: rentLamports, + programId: TOKEN_2022_PROGRAM_ID, +}); + +// Instruction to initialize mint account +const initializeMintInstruction = createInitializeMint2Instruction( + mint.publicKey, + 2, // decimals + wallet.publicKey, // mint authority + wallet.publicKey, // freeze authority + TOKEN_2022_PROGRAM_ID, +); + +// Build transaction with instructions to create new account and initialize mint account +const transaction = new Transaction().add( + createAccountInstruction, + initializeMintInstruction, +); + +const transactionSignature = await sendAndConfirmTransaction( + connection, + transaction, + [ + wallet.keypair, // payer + mint, // mint address keypair + ], +); + +console.log( + "\nTransaction Signature:", + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, +); + +console.log( + "\nMint Account:", + `https://solana.fm/address/${mint.publicKey}?cluster=devnet-solana`, +); +``` + + + + +This script performs the following steps: + +- Sets up your Playground wallet and a connection to the Solana devnet + + ```ts + const wallet = pg.wallet; + const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); + ``` + +- Generates a new keypair for the mint account + + ```ts + const mint = new Keypair(); + ``` + +- Calculates the minimum lamports needed for a Mint account + + ```ts + const rentLamports = await getMinimumBalanceForRentExemptMint(connection); + ``` + +- Creates an instruction to create a new account for the mint, specifying the + Token Extensions program (`TOKEN_2022_PROGRAM_ID`) as the owner of the new + account + + ```ts + const createAccountInstruction = SystemProgram.createAccount({ + fromPubkey: wallet.publicKey, + newAccountPubkey: mint.publicKey, + space: MINT_SIZE, + lamports: rentLamports, + programId: TOKEN_2022_PROGRAM_ID, + }); + ``` + +- Creates an instruction to initialize the mint account data + + ```ts + const initializeMintInstruction = createInitializeMint2Instruction( + mint.publicKey, + 2, + wallet.publicKey, + wallet.publicKey, + TOKEN_2022_PROGRAM_ID, + ); + ``` + +- Adds both instructions to a single transaction + + ```ts + const transaction = new Transaction().add( + createAccountInstruction, + initializeMintInstruction, + ); + ``` + +- Sends and confirms the transaction. Both the wallet and mint keypair are + passed in as signers on the transaction. The wallet is required to pay for the + creation of the new account. The mint keypair is required because we are using + its publickey as the address of the new account. + + ```ts + const transactionSignature = await sendAndConfirmTransaction( + connection, + transaction, + [wallet.keypair, mint], + ); + ``` + +- Prints out links to view the transaction and mint account details on SolanaFM + + ```ts + console.log( + "\nTransaction Signature:", + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, + ); + + console.log( + "\nMint Account:", + `https://solana.fm/address/${mint.publicKey}?cluster=devnet-solana`, + ); + ``` + + + + +### Run Example 2 + +Run the code using the `run` command. + +```shell filename="Terminal" +run +``` + +You'll see two links printed to the Playground terminal: + +- One for the transaction details +- One for the newly created mint account + +Click the links to inspect the transaction details and the newly created mint +account on SolanaFM. + + + + +```shell filename="Terminal" +Running client... + client.ts: + +Transaction Signature: https://solana.fm/tx/3BEjFxqyGwHXWSrEBnc7vTSaXUGDJFY1Zr6L9iwLrjH8KBZdJSucoMrFUEJgWrWVRYzrFvbjX8TmxKUV88oKr86g?cluster=devnet-solana + +Mint Account: https://solana.fm/address/CoZ3Nz488rmATDhy1hPk5fvwSZaipCngvf8rYBYVc4jN?cluster=devnet-solana +``` + + + + +![Create Token](/assets/docs/intro/quickstart/create-token.png) + +![Mint Account](/assets/docs/intro/quickstart/mint-account.png) + +Notice how we built a transaction with multiple instructions this time. We first +created a new account and then initialized its data as a mint. This is how you +build more complex transactions that involve instructions from multiple +programs. + + diff --git a/docs/uk/intro/wallets.md b/docs/uk/intro/wallets.md new file mode 100644 index 000000000..5c690a950 --- /dev/null +++ b/docs/uk/intro/wallets.md @@ -0,0 +1,69 @@ +--- +sidebarLabel: Wallets +title: Solana Wallet Guide +sidebarSortOrder: 3 +--- + +This document describes the different wallet options that are available to users +of Solana who want to be able to send, receive and interact with SOL tokens on +the Solana blockchain. + +## What is a Wallet? + +A crypto wallet is a device or application that stores a collection of keys and +can be used to send, receive, and track ownership of cryptocurrencies. Wallets +can take many forms. A wallet might be a directory or file in your computer's +file system, a piece of paper, or a specialized device called a _hardware +wallet_. There are also various smartphone apps and computer programs that +provide a user-friendly way to create and manage wallets. + +### Keypair + +A [_keypair_](/docs/terminology.md#keypair) is a securely generated +[_secret key_](#secret-key) and its cryptographically-derived +[_public key_](#public-key). A secret key and its corresponding public key are +together known as a _keypair_. A wallet contains a collection of one or more +keypairs and provides some means to interact with them. + +### Public key + +The [_public key_](/docs/terminology.md#public-key-pubkey) (commonly shortened +to _pubkey_) is known as the wallet's _receiving address_ or simply its +_address_. The wallet address **may be shared and displayed freely**. When +another party is going to send some amount of cryptocurrency to a wallet, they +need to know the wallet's receiving address. Depending on a blockchain's +implementation, the address can also be used to view certain information about a +wallet, such as viewing the balance, but has no ability to change anything about +the wallet or withdraw any tokens. + +### Secret key + +The [_secret key_](/docs/terminology.md#private-key) (also referred to as +_private key_) is required to digitally sign any transactions to send +cryptocurrencies to another address or to make any changes to the wallet. The +secret key **must never be shared**. If someone gains access to the secret key +to a wallet, they can withdraw all the tokens it contains. If the secret key for +a wallet is lost, any tokens that have been sent to that wallet's address are +**permanently lost**. + +## Security + +Different wallet solutions offer different approaches to keypair security, +interacting with the keypair, and signing transactions to use/spend the tokens. +Some are easier to use than others. Some store and back up secret keys more +securely. Solana supports multiple types of wallets so you can choose the right +balance of security and convenience. + +**If you want to be able to receive SOL tokens on the Solana blockchain, you +first will need to create a wallet.** + +## Supported Wallets + +Several browser and mobile app based wallets support Solana. Find some options +that might be right for you on the [Solana Wallets](https://solana.com/wallets) +page. + +For advanced users or developers, the +[command-line wallets](https://docs.anza.xyz/cli/wallets) may be more +appropriate, as new features on the Solana blockchain will always be supported +on the command line first before being integrated into third-party solutions. diff --git a/docs/uk/more/exchange.md b/docs/uk/more/exchange.md new file mode 100644 index 000000000..e59d2b065 --- /dev/null +++ b/docs/uk/more/exchange.md @@ -0,0 +1,1294 @@ +--- +title: Add Solana to Your Exchange +--- + +This guide describes how to add Solana's native token SOL to your cryptocurrency +exchange. + +## Node Setup + +We highly recommend setting up at least two nodes on high-grade computers/cloud +instances, upgrading to newer versions promptly, and keeping an eye on service +operations with a bundled monitoring tool. + +This setup enables you: + +- to have a self-administered gateway to the Solana mainnet-beta cluster to get + data and submit withdrawal transactions +- to have full control over how much historical block data is retained +- to maintain your service availability even if one node fails + +Solana nodes demand relatively high computing power to handle our fast blocks +and high TPS. For specific requirements, please see +[hardware recommendations](https://docs.anza.xyz/operations/requirements). + +To run an api node: + +1. [Install the Solana command-line tool suite](/docs/intro/installation.md) +2. Start the validator with at least the following parameters: + +```shell +solana-validator \ + --ledger \ + --identity \ + --entrypoint \ + --expected-genesis-hash \ + --rpc-port 8899 \ + --no-voting \ + --enable-rpc-transaction-history \ + --limit-ledger-size \ + --known-validator \ + --only-known-rpc +``` + +Customize `--ledger` to your desired ledger storage location, and `--rpc-port` +to the port you want to expose. + +The `--entrypoint` and `--expected-genesis-hash` parameters are all specific to +the cluster you are joining. +[Current parameters for Mainnet Beta](https://docs.anza.xyz/clusters/available#example-solana-validator-command-line-2) + +The `--limit-ledger-size` parameter allows you to specify how many ledger +[shreds](/docs/terminology.md#shred) your node retains on disk. If you do not +include this parameter, the validator will keep the entire ledger until it runs +out of disk space. The default value attempts to keep the ledger disk usage +under 500GB. More or less disk usage may be requested by adding an argument to +`--limit-ledger-size` if desired. Check `solana-validator --help` for the +default limit value used by `--limit-ledger-size`. More information about +selecting a custom limit value is +[available here](https://github.com/solana-labs/solana/blob/583cec922b6107e0f85c7e14cb5e642bc7dfb340/core/src/ledger_cleanup_service.rs#L15-L26). + +Specifying one or more `--known-validator` parameters can protect you from +booting from a malicious snapshot. +[More on the value of booting with known validators](https://docs.anza.xyz/operations/guides/validator-start#known-validators) + +Optional parameters to consider: + +- `--private-rpc` prevents your RPC port from being published for use by other + nodes +- `--rpc-bind-address` allows you to specify a different IP address to bind the + RPC port + +### Automatic Restarts and Monitoring + +We recommend configuring each of your nodes to restart automatically on exit, to +ensure you miss as little data as possible. Running the solana software as a +systemd service is one great option. + +For monitoring, we provide +[`solana-watchtower`](https://github.com/solana-labs/solana/blob/master/watchtower/README.md), +which can monitor your validator and detect with the `solana-validator` process +is unhealthy. It can directly be configured to alert you via Slack, Telegram, +Discord, or Twillio. For details, run `solana-watchtower --help`. + +```shell +solana-watchtower --validator-identity +``` + +> You can find more information about the +> [best practices for Solana Watchtower](https://docs.anza.xyz/operations/best-practices/monitoring#solana-watchtower) +> here in the docs. + +#### New Software Release Announcements + +We release new software frequently (around 1 release / week). Sometimes newer +versions include incompatible protocol changes, which necessitate timely +software update to avoid errors in processing blocks. + +Our official release announcements for all kinds of releases (normal and +security) are communicated via a [discord](https://solana.com/discord) channel +called `#mb-announcement` (`mb` stands for `mainnet-beta`). + +Like staked validators, we expect any exchange-operated validators to be updated +at your earliest convenience within a business day or two after a normal release +announcement. For security-related releases, more urgent action may be needed. + +### Ledger Continuity + +By default, each of your nodes will boot from a snapshot provided by one of your +known validators. This snapshot reflects the current state of the chain, but +does not contain the complete historical ledger. If one of your node exits and +boots from a new snapshot, there may be a gap in the ledger on that node. In +order to prevent this issue, add the `--no-snapshot-fetch` parameter to your +`solana-validator` command to receive historical ledger data instead of a +snapshot. + +Do not pass the `--no-snapshot-fetch` parameter on your initial boot as it's not +possible to boot the node all the way from the genesis block. Instead boot from +a snapshot first and then add the `--no-snapshot-fetch` parameter for reboots. + +It is important to note that the amount of historical ledger available to your +nodes from the rest of the network is limited at any point in time. Once +operational if your validators experience significant downtime they may not be +able to catch up to the network and will need to download a new snapshot from a +known validator. In doing so your validators will now have a gap in its +historical ledger data that cannot be filled. + +### Minimizing Validator Port Exposure + +The validator requires that various UDP and TCP ports be open for inbound +traffic from all other Solana validators. While this is the most efficient mode +of operation, and is strongly recommended, it is possible to restrict the +validator to only require inbound traffic from one other Solana validator. + +First add the `--restricted-repair-only-mode` argument. This will cause the +validator to operate in a restricted mode where it will not receive pushes from +the rest of the validators, and instead will need to continually poll other +validators for blocks. The validator will only transmit UDP packets to other +validators using the _Gossip_ and _ServeR_ ("serve repair") ports, and only +receive UDP packets on its _Gossip_ and _Repair_ ports. + +The _Gossip_ port is bi-directional and allows your validator to remain in +contact with the rest of the cluster. Your validator transmits on the _ServeR_ +to make repair requests to obtaining new blocks from the rest of the network, +since Turbine is now disabled. Your validator will then receive repair responses +on the _Repair_ port from other validators. + +To further restrict the validator to only requesting blocks from one or more +validators, first determine the identity pubkey for that validator and add the +`--gossip-pull-validator PUBKEY --repair-validator PUBKEY` arguments for each +PUBKEY. This will cause your validator to be a resource drain on each validator +that you add, so please do this sparingly and only after consulting with the +target validator. + +Your validator should now only be communicating with the explicitly listed +validators and only on the _Gossip_, _Repair_ and _ServeR_ ports. + +## Setting up Deposit Accounts + +Solana accounts do not require any on-chain initialization; once they contain +some SOL, they exist. To set up a deposit account for your exchange, simply +generate a Solana keypair using any of our +[wallet tools](https://docs.anza.xyz/cli/wallets). + +We recommend using a unique deposit account for each of your users. + +Solana accounts must be made rent-exempt by containing 2-years worth of +[rent](/docs/core/fees.md#rent) in SOL. In order to find the minimum rent-exempt +balance for your deposit accounts, query the +[`getMinimumBalanceForRentExemption` endpoint](/docs/rpc/http/getMinimumBalanceForRentExemption.mdx): + +```shell +curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ + "jsonrpc": "2.0", + "id": 1, + "method": "getMinimumBalanceForRentExemption", + "params": [0] +}' +``` + +##### Result + +```json +{ "jsonrpc": "2.0", "result": 890880, "id": 1 } +``` + +### Offline Accounts + +You may wish to keep the keys for one or more collection accounts offline for +greater security. If so, you will need to move SOL to hot accounts using our +[offline methods](https://docs.anza.xyz/cli/examples/offline-signing). + +## Listening for Deposits + +When a user wants to deposit SOL into your exchange, instruct them to send a +transfer to the appropriate deposit address. + +### Versioned Transaction Migration + +When the Mainnet Beta network starts processing versioned transactions, +exchanges **MUST** make changes. If no changes are made, deposit detection will +no longer work properly because fetching a versioned transaction or a block +containing versioned transactions will return an error. + +- `{"maxSupportedTransactionVersion": 0}` + + The `maxSupportedTransactionVersion` parameter must be added to `getBlock` and + `getTransaction` requests to avoid disruption to deposit detection. The latest + transaction version is `0` and should be specified as the max supported + transaction version value. + +It's important to understand that versioned transactions allow users to create +transactions that use another set of account keys loaded from on-chain address +lookup tables. + +- `{"encoding": "jsonParsed"}` + + When fetching blocks and transactions, it's now recommended to use the + `"jsonParsed"` encoding because it includes all transaction account keys + (including those from lookup tables) in the message `"accountKeys"` list. This + makes it straightforward to resolve balance changes detailed in `preBalances` + / `postBalances` and `preTokenBalances` / `postTokenBalances`. + + If the `"json"` encoding is used instead, entries in `preBalances` / + `postBalances` and `preTokenBalances` / `postTokenBalances` may refer to + account keys that are **NOT** in the `"accountKeys"` list and need to be + resolved using `"loadedAddresses"` entries in the transaction metadata. + +### Poll for Blocks + +To track all the deposit accounts for your exchange, poll for each confirmed +block and inspect for addresses of interest, using the JSON-RPC service of your +Solana API node. + +- To identify which blocks are available, send a + [`getBlocks`](/docs/rpc/http/getBlocks.mdx) request, passing the last block + you have already processed as the start-slot parameter: + +```shell +curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ + "jsonrpc": "2.0", + "id": 1, + "method": "getBlocks", + "params": [160017005, 160017015] +}' +``` + +##### Result + +```json +{ + "jsonrpc": "2.0", + "result": [ + 160017005, 160017006, 160017007, 160017012, 160017013, 160017014, 160017015 + ], + "id": 1 +} +``` + +Not every slot produces a block, so there may be gaps in the sequence of +integers. + +- For each block, request its contents with a + [`getBlock`](/docs/rpc/http/getBlock.mdx) request: + +### Block Fetching Tips + +- `{"rewards": false}` + +By default, fetched blocks will return information about validator fees on each +block and staking rewards on epoch boundaries. If you don't need this +information, disable it with the "rewards" parameter. + +- `{"transactionDetails": "accounts"}` + +By default, fetched blocks will return a lot of transaction info and metadata +that isn't necessary for tracking account balances. Set the "transactionDetails" +parameter to speed up block fetching. + +```shell +curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' -d '{ + "jsonrpc": "2.0", + "id": 1, + "method": "getBlock", + "params": [ + 166974442, + { + "encoding": "jsonParsed", + "maxSupportedTransactionVersion": 0, + "transactionDetails": "accounts", + "rewards": false + } + ] +}' +``` + +##### Result + +```json +{ + "jsonrpc": "2.0", + "result": { + "blockHeight": 157201607, + "blockTime": 1665070281, + "blockhash": "HKhao674uvFc4wMK1Cm3UyuuGbKExdgPFjXQ5xtvsG3o", + "parentSlot": 166974441, + "previousBlockhash": "98CNLU4rsYa2HDUyp7PubU4DhwYJJhSX9v6pvE7SWsAo", + "transactions": [ + ... (omit) + { + "meta": { + "err": null, + "fee": 5000, + "postBalances": [ + 1110663066, + 1, + 1040000000 + ], + "postTokenBalances": [], + "preBalances": [ + 1120668066, + 1, + 1030000000 + ], + "preTokenBalances": [], + "status": { + "Ok": null + } + }, + "transaction": { + "accountKeys": [ + { + "pubkey": "9aE476sH92Vz7DMPyq5WLPkrKWivxeuTKEFKd2sZZcde", + "signer": true, + "source": "transaction", + "writable": true + }, + { + "pubkey": "11111111111111111111111111111111", + "signer": false, + "source": "transaction", + "writable": false + }, + { + "pubkey": "G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o", + "signer": false, + "source": "lookupTable", + "writable": true + } + ], + "signatures": [ + "2CxNRsyRT7y88GBwvAB3hRg8wijMSZh3VNYXAdUesGSyvbRJbRR2q9G1KSEpQENmXHmmMLHiXumw4dp8CvzQMjrM" + ] + }, + "version": 0 + }, + ... (omit) + ] + }, + "id": 1 +} +``` + +The `preBalances` and `postBalances` fields allow you to track the balance +changes in every account without having to parse the entire transaction. They +list the starting and ending balances of each account in +[lamports](/docs/terminology.md#lamport), indexed to the `accountKeys` list. For +example, if the deposit address of interest is +`G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o`, this transaction represents a +transfer of 1040000000 - 1030000000 = 10,000,000 lamports = 0.01 SOL + +If you need more information about the transaction type or other specifics, you +can request the block from RPC in binary format, and parse it using either our +[Rust SDK](https://github.com/solana-labs/solana) or +[Javascript SDK](https://github.com/solana-labs/solana-web3.js). + +### Address History + +You can also query the transaction history of a specific address. This is +generally _not_ a viable method for tracking all your deposit addresses over all +slots, but may be useful for examining a few accounts for a specific period of +time. + +- Send a [`getSignaturesForAddress`](/docs/rpc/http/getSignaturesForAddress.mdx) + request to the api node: + +```shell +curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ + "jsonrpc": "2.0", + "id": 1, + "method": "getSignaturesForAddress", + "params": [ + "3M2b3tLji7rvscqrLAHMukYxDK2nB96Q9hwfV6QkdzBN", + { + "limit": 3 + } + ] +}' +``` + +##### Result + +```json +{ + "jsonrpc": "2.0", + "result": [ + { + "blockTime": 1662064640, + "confirmationStatus": "finalized", + "err": null, + "memo": null, + "signature": "3EDRvnD5TbbMS2mCusop6oyHLD8CgnjncaYQd5RXpgnjYUXRCYwiNPmXb6ZG5KdTK4zAaygEhfdLoP7TDzwKBVQp", + "slot": 148697216 + }, + { + "blockTime": 1662064434, + "confirmationStatus": "finalized", + "err": null, + "memo": null, + "signature": "4rPQ5wthgSP1kLdLqcRgQnkYkPAZqjv5vm59LijrQDSKuL2HLmZHoHjdSLDXXWFwWdaKXUuryRBGwEvSxn3TQckY", + "slot": 148696843 + }, + { + "blockTime": 1662064341, + "confirmationStatus": "finalized", + "err": null, + "memo": null, + "signature": "36Q383JMiqiobuPV9qBqy41xjMsVnQBm9rdZSdpbrLTGhSQDTGZJnocM4TQTVfUGfV2vEX9ZB3sex6wUBUWzjEvs", + "slot": 148696677 + } + ], + "id": 1 +} +``` + +- For each signature returned, get the transaction details by sending a + [`getTransaction`](/docs/rpc/http/getTransaction.mdx) request: + +```shell +curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' -d '{ + "jsonrpc":"2.0", + "id":1, + "method":"getTransaction", + "params":[ + "2CxNRsyRT7y88GBwvAB3hRg8wijMSZh3VNYXAdUesGSyvbRJbRR2q9G1KSEpQENmXHmmMLHiXumw4dp8CvzQMjrM", + { + "encoding":"jsonParsed", + "maxSupportedTransactionVersion":0 + } + ] +}' +``` + +##### Result + +```json +{ + "jsonrpc": "2.0", + "result": { + "blockTime": 1665070281, + "meta": { + "err": null, + "fee": 5000, + "innerInstructions": [], + "logMessages": [ + "Program 11111111111111111111111111111111 invoke [1]", + "Program 11111111111111111111111111111111 success" + ], + "postBalances": [1110663066, 1, 1040000000], + "postTokenBalances": [], + "preBalances": [1120668066, 1, 1030000000], + "preTokenBalances": [], + "rewards": [], + "status": { + "Ok": null + } + }, + "slot": 166974442, + "transaction": { + "message": { + "accountKeys": [ + { + "pubkey": "9aE476sH92Vz7DMPyq5WLPkrKWivxeuTKEFKd2sZZcde", + "signer": true, + "source": "transaction", + "writable": true + }, + { + "pubkey": "11111111111111111111111111111111", + "signer": false, + "source": "transaction", + "writable": false + }, + { + "pubkey": "G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o", + "signer": false, + "source": "lookupTable", + "writable": true + } + ], + "addressTableLookups": [ + { + "accountKey": "4syr5pBaboZy4cZyF6sys82uGD7jEvoAP2ZMaoich4fZ", + "readonlyIndexes": [], + "writableIndexes": [3] + } + ], + "instructions": [ + { + "parsed": { + "info": { + "destination": "G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o", + "lamports": 10000000, + "source": "9aE476sH92Vz7DMPyq5WLPkrKWivxeuTKEFKd2sZZcde" + }, + "type": "transfer" + }, + "program": "system", + "programId": "11111111111111111111111111111111" + } + ], + "recentBlockhash": "BhhivDNgoy4L5tLtHb1s3TP19uUXqKiy4FfUR34d93eT" + }, + "signatures": [ + "2CxNRsyRT7y88GBwvAB3hRg8wijMSZh3VNYXAdUesGSyvbRJbRR2q9G1KSEpQENmXHmmMLHiXumw4dp8CvzQMjrM" + ] + }, + "version": 0 + }, + "id": 1 +} +``` + +## Sending Withdrawals + +To accommodate a user's request to withdraw SOL, you must generate a Solana +transfer transaction, and send it to the api node to be forwarded to your +cluster. + +### Synchronous + +Sending a synchronous transfer to the Solana cluster allows you to easily ensure +that a transfer is successful and finalized by the cluster. + +Solana's command-line tool offers a simple command, `solana transfer`, to +generate, submit, and confirm transfer transactions. By default, this method +will wait and track progress on stderr until the transaction has been finalized +by the cluster. If the transaction fails, it will report any transaction errors. + +```shell +solana transfer --allow-unfunded-recipient --keypair --url http://localhost:8899 +``` + +The [Solana Javascript SDK](https://github.com/solana-labs/solana-web3.js) +offers a similar approach for the JS ecosystem. Use the `SystemProgram` to build +a transfer transaction, and submit it using the `sendAndConfirmTransaction` +method. + +### Asynchronous + +For greater flexibility, you can submit withdrawal transfers asynchronously. In +these cases, it is your responsibility to verify that the transaction succeeded +and was finalized by the cluster. + +**Note:** Each transaction contains a +[recent blockhash](/docs/core/transactions.md#recent-blockhash) to indicate its +liveness. It is **critical** to wait until this blockhash expires before +retrying a withdrawal transfer that does not appear to have been confirmed or +finalized by the cluster. Otherwise, you risk a double spend. See more on +[blockhash expiration](#blockhash-expiration) below. + +First, get a recent blockhash using the +[`getFees`](/docs/rpc/deprecated/getFees.mdx) endpoint or the CLI command: + +```shell +solana fees --url http://localhost:8899 +``` + +In the command-line tool, pass the `--no-wait` argument to send a transfer +asynchronously, and include your recent blockhash with the `--blockhash` +argument: + +```shell +solana transfer --no-wait --allow-unfunded-recipient --blockhash --keypair --url http://localhost:8899 +``` + +You can also build, sign, and serialize the transaction manually, and fire it +off to the cluster using the JSON-RPC +[`sendTransaction`](/docs/rpc/http/sendTransaction.mdx) endpoint. + +#### Transaction Confirmations & Finality + +Get the status of a batch of transactions using the +[`getSignatureStatuses`](/docs/rpc/http/getSignatureStatuses.mdx) JSON-RPC +endpoint. The `confirmations` field reports how many +[confirmed blocks](/docs/terminology.md#confirmed-block) have elapsed since the +transaction was processed. If `confirmations: null`, it is +[finalized](/docs/terminology.md#finality). + +```shell +curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ + "jsonrpc":"2.0", + "id":1, + "method":"getSignatureStatuses", + "params":[ + [ + "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW", + "5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7" + ] + ] +}' +``` + +##### Result + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 82 + }, + "value": [ + { + "slot": 72, + "confirmations": 10, + "err": null, + "status": { + "Ok": null + } + }, + { + "slot": 48, + "confirmations": null, + "err": null, + "status": { + "Ok": null + } + } + ] + }, + "id": 1 +} +``` + +#### Blockhash Expiration + +You can check whether a particular blockhash is still valid by sending a +[`getFeeCalculatorForBlockhash`](/docs/rpc/deprecated/getFeeCalculatorForBlockhash.mdx) +request with the blockhash as a parameter. If the response value is `null`, the +blockhash is expired, and the withdrawal transaction using that blockhash should +never succeed. + +### Validating User-supplied Account Addresses for Withdrawals + +As withdrawals are irreversible, it may be a good practice to validate a +user-supplied account address before authorizing a withdrawal in order to +prevent accidental loss of user funds. + +#### Basic verification + +Solana addresses a 32-byte array, encoded with the bitcoin base58 alphabet. This +results in an ASCII text string matching the following regular expression: + +```text +[1-9A-HJ-NP-Za-km-z]{32,44} +``` + +This check is insufficient on its own as Solana addresses are not checksummed, +so typos cannot be detected. To further validate the user's input, the string +can be decoded and the resulting byte array's length confirmed to be 32. +However, there are some addresses that can decode to 32 bytes despite a typo +such as a single missing character, reversed characters and ignored case + +#### Advanced verification + +Due to the vulnerability to typos described above, it is recommended that the +balance be queried for candidate withdraw addresses and the user prompted to +confirm their intentions if a non-zero balance is discovered. + +#### Valid ed25519 pubkey check + +The address of a normal account in Solana is a Base58-encoded string of a +256-bit ed25519 public key. Not all bit patterns are valid public keys for the +ed25519 curve, so it is possible to ensure user-supplied account addresses are +at least correct ed25519 public keys. + +#### Java + +Here is a Java example of validating a user-supplied address as a valid ed25519 +public key: + +The following code sample assumes you're using the Maven. + +`pom.xml`: + +```xml + + ... + + spring + https://repo.spring.io/libs-release/ + + + +... + + + ... + + io.github.novacrypto + Base58 + 0.1.3 + + + cafe.cryptography + curve25519-elisabeth + 0.1.0 + + +``` + +```java +import io.github.novacrypto.base58.Base58; +import cafe.cryptography.curve25519.CompressedEdwardsY; + +public class PubkeyValidator +{ + public static boolean verifyPubkey(String userProvidedPubkey) + { + try { + return _verifyPubkeyInternal(userProvidedPubkey); + } catch (Exception e) { + return false; + } + } + + public static boolean _verifyPubkeyInternal(String maybePubkey) throws Exception + { + byte[] bytes = Base58.base58Decode(maybePubkey); + return !(new CompressedEdwardsY(bytes)).decompress().isSmallOrder(); + } +} +``` + +## Minimum Deposit & Withdrawal Amounts + +Every deposit and withdrawal of SOL must be greater or equal to the minimum +rent-exempt balance for the account at the wallet address (a basic SOL account +holding no data), currently: 0.000890880 SOL + +Similarly, every deposit account must contain at least this balance. + +```shell +curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ + "jsonrpc": "2.0", + "id": 1, + "method": "getMinimumBalanceForRentExemption", + "params": [0] +}' +``` + +##### Result + +```json +{ "jsonrpc": "2.0", "result": 890880, "id": 1 } +``` + +## Prioritization Fees and Compute Units + +In periods of high demand, it's possible for a transaction to expire before a +validator has included such transactions in their block because they chose other +transactions with higher economic value. Valid Transactions on Solana may be +delayed or dropped if Prioritization Fees are not implemented properly. + +[Prioritization Fees](/docs/terminology.md#prioritization-fee) are additional +fees that can be added on top of the +[base Transaction Fee](/docs/core/fees.md#transaction-fees) to ensure +transaction inclusion within blocks and in these situations and help ensure +deliverability. + +These priority fees are added to transaction by adding a special Compute Budget +instruction that sets the desired priority fee to be paid. + + + +Failure to implement these instructions may result in network disruptions and +dropped transactions. It is strongly recommended that every exchange supporting +Solana make use of priority fees to avoid disruption. + + + +### What is a Prioritization Fee? + +Prioritization Fees are priced in micro-lamports per Compute Unit (e.g. small +amounts of SOL) prepended to transactions to make them economically compelling +for validator nodes to include within blocks on the network. + +### How much should the Prioritization Fee be? + +The method for setting your prioritization fee should involve querying recent +prioritization fees to set a fee which is likely to be compelling for the +network. Using the +[`getRecentPrioritizationFees`](/docs/rpc/http/getrecentprioritizationfees) RPC +method, you can query for the prioritization fees required to land a transaction +in a recent block. + +Pricing strategy for these priority fees will vary based on your use case. There +is no canonical way to do so. One strategy for setting your Prioritization Fees +might be to calculate your transaction success rate and then increase your +Prioritization Fee against a query to the recent transaction fees API and adjust +accordingly. Pricing for Prioritization Fees will be dynamic based on the +activity on the network and bids placed by other participants, only knowable +after the fact. + +One challenge with using the `getRecentPrioritizationFees` API call is that it +may only return the lowest fee for each block. This will often be zero, which is +not a fully useful approximation of what Prioritization Fee to use in order to +avoid being rejected by validator nodes. + +The `getRecentPrioritizationFees` API takes accounts' pubkeys as parameters, and +then returns the highest of the minimum prioritization fees for these accounts. +When no account is specified, the API will return the lowest fee to land to +block, which is usually zero (unless the block is full). + +Exchanges and applications should query the RPC endpoint with the accounts that +a transaction is going to write-lock. The RPC endpoint will return the +`max(account_1_min_fee, account_2_min_fee, ... account_n_min_fee)`, which should +be the base point for the user to set the prioritization fee for that +transaction. + +There are different approaches to setting Prioritization Fees and some +[third-party APIs](https://docs.helius.dev/solana-rpc-nodes/alpha-priority-fee-api) +are available to determine the best fee to apply. Given the dynamic nature of +the network, there will not be a “perfect” way to go about pricing your +Prioritization fees and careful analysis should be applied before choosing a +path forward. + +### How to Implement Prioritization Fees + +Adding priority fees on a transaction consists of prepending two Compute Budget +instructions on a given transaction: + +- one to set the compute unit price, and +- another to set the compute unit limit + +> Here, you can also find a more detailed developer +> [guide on how to use priority fees](/content/guides/advanced/how-to-use-priority-fees.md) +> which includes more information about implementing priority fees. + +Create a `setComputeUnitPrice` instruction to add a Prioritization Fee above the +Base Transaction Fee (5,000 Lamports). + +```typescript +// import { ComputeBudgetProgram } from "@solana/web3.js" +ComputeBudgetProgram.setComputeUnitPrice({ microLamports: number }); +``` + +The value provided in micro-lamports will be multiplied by the Compute Unit (CU) +budget to determine the Prioritization Fee in Lamports. For example, if your CU +budget is 1M CU, and you add `1 microLamport/CU`, the Prioritization Fee will be +1 lamport (1M \* 0. 000001). The total fee will then be 5001 lamports. + +To set a new compute unit budget for the transaction, create a +`setComputeUnitLimit` instruction + +```typescript +// import { ComputeBudgetProgram } from "@solana/web3.js" +ComputeBudgetProgram.setComputeUnitLimit({ units: number }); +``` + +The `units` value provided will replace the Solana runtime's default compute +budget value. + + + +Transactions should request the minimum amount of compute units (CU) required +for execution to maximize throughput and minimize overall fees. + +You can get the CU consumed by a transaction by sending the transaction on a +different Solana cluster, like devnet. For example, a +[simple token transfer](https://explorer.solana.com/tx/5scDyuiiEbLxjLUww3APE9X7i8LE3H63unzonUwMG7s2htpoAGG17sgRsNAhR1zVs6NQAnZeRVemVbkAct5myi17) +takes 300 CU. + + + +```typescript +// import { ... } from "@solana/web3.js" + +const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({ + // note: set this to be the lowest actual CU consumed by the transaction + units: 300, +}); + +const addPriorityFee = ComputeBudgetProgram.setComputeUnitPrice({ + microLamports: 1, +}); + +const transaction = new Transaction() + .add(modifyComputeUnits) + .add(addPriorityFee) + .add( + SystemProgram.transfer({ + fromPubkey: payer.publicKey, + toPubkey: toAccount, + lamports: 10000000, + }), + ); +``` + +### Prioritization Fees And Durable Nonces + +If your setup uses Durable Nonce Transactions, it is important to properly +implement Prioritization Fees in combination with Durable Transaction Nonces to +ensure successful transactions. Failure to do so will cause intended Durable +Nonce transactions not to be detected as such. + +If you ARE using Durable Transaction Nonces, the `AdvanceNonceAccount` +instruction MUST be specified FIRST in the instructions list, even when the +compute budget instructions are used to specify priority fees. + +You can find a specific code example +[using durable nonces and priority fees together](/content/guides/advanced/how-to-use-priority-fees.md#special-considerations) +in this developer guide. + +## Supporting the SPL Token Standard + +[SPL Token](https://spl.solana.com/token) is the standard for wrapped/synthetic +token creation and exchange on the Solana blockchain. + +The SPL Token workflow is similar to that of native SOL tokens, but there are a +few differences which will be discussed in this section. + +### Token Mints + +Each _type_ of SPL Token is declared by creating a _mint_ account. This account +stores metadata describing token features like the supply, number of decimals, +and various authorities with control over the mint. Each SPL Token account +references its associated mint and may only interact with SPL Tokens of that +type. + +### Installing the `spl-token` CLI Tool + +SPL Token accounts are queried and modified using the `spl-token` command line +utility. The examples provided in this section depend upon having it installed +on the local system. + +`spl-token` is distributed from Rust +[crates.io](https://crates.io/crates/spl-token) via the Rust `cargo` command +line utility. The latest version of `cargo` can be installed using a handy +one-liner for your platform at [rustup.rs](https://rustup.rs). Once `cargo` is +installed, `spl-token` can be obtained with the following command: + +```shell +cargo install spl-token-cli +``` + +You can then check the installed version to verify + +```shell +spl-token --version +``` + +Which should result in something like + +```text +spl-token-cli 2.0.1 +``` + +### Account Creation + +SPL Token accounts carry additional requirements that native System Program +accounts do not: + +1. SPL Token accounts must be created before an amount of tokens can be + deposited. Token accounts can be created explicitly with the + `spl-token create-account` command, or implicitly by the + `spl-token transfer --fund-recipient ...` command. +1. SPL Token accounts must remain [rent-exempt](/docs/core/fees.md#rent-exempt) + for the duration of their existence and therefore require a small amount of + native SOL tokens be deposited at account creation. For SPL Token accounts, + this amount is 0.00203928 SOL (2,039,280 lamports). + +#### Command Line + +To create an SPL Token account with the following properties: + +1. Associated with the given mint +1. Owned by the funding account's keypair + +```shell +spl-token create-account +``` + +#### Example + +```shell +spl-token create-account AkUFCWTXb3w9nY2n6SFJvBV6VwvFUCe4KBMCcgLsa2ir +``` + +Giving an output similar to: + +``` +Creating account 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV +Signature: 4JsqZEPra2eDTHtHpB4FMWSfk3UgcCVmkKkP7zESZeMrKmFFkDkNd91pKP3vPVVZZPiu5XxyJwS73Vi5WsZL88D7 +``` + +Or to create an SPL Token account with a specific keypair: + +```shell +solana-keygen new -o token-account.json + +spl-token create-account AkUFCWTXb3w9nY2n6SFJvBV6VwvFUCe4KBMCcgLsa2ir token-account.json +``` + +Giving an output similar to: + +```shell +Creating account 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV +Signature: 4JsqZEPra2eDTHtHpB4FMWSfk3UgcCVmkKkP7zESZeMrKmFFkDkNd91pKP3vPVVZZPiu5XxyJwS73Vi5WsZL88D7 +``` + +### Checking an Account's Balance + +#### Command Line + +```shell +spl-token balance +``` + +#### Example + +```shell +solana balance 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV +``` + +Giving an output similar to: + +``` +0 +``` + +### Token Transfers + +The source account for a transfer is the actual token account that contains the +amount. + +The recipient address however can be a normal wallet account. If an associated +token account for the given mint does not yet exist for that wallet, the +transfer will create it provided that the `--fund-recipient` argument as +provided. + +#### Command Line + +```shell +spl-token transfer --fund-recipient +``` + +#### Example + +```shell +spl-token transfer 6B199xxzw3PkAm25hGJpjj3Wj3WNYNHzDAnt1tEqg5BN 1 +``` + +Giving an output similar to: + +```shell +6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV +Transfer 1 tokens + Sender: 6B199xxzw3PkAm25hGJpjj3Wj3WNYNHzDAnt1tEqg5BN + Recipient: 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV +Signature: 3R6tsog17QM8KfzbcbdP4aoMfwgo6hBggJDVy7dZPVmH2xbCWjEj31JKD53NzMrf25ChFjY7Uv2dfCDq4mGFFyAj +``` + +### Depositing + +Since each `(wallet, mint)` pair requires a separate account onchain. It is +recommended that the addresses for these accounts be derived from SOL deposit +wallets using the +[Associated Token Account](https://spl.solana.com/associated-token-account) +(ATA) scheme and that _only_ deposits from ATA addresses be accepted. + +Monitoring for deposit transactions should follow the +[block polling](#poll-for-blocks) method described above. Each new block should +be scanned for successful transactions referencing user token-account derived +addresses. The `preTokenBalance` and `postTokenBalance` fields from the +transaction's metadata must then be used to determine the effective balance +change. These fields will identify the token mint and account owner (main wallet +address) of the affected account. + +Note that if a receiving account is created during the transaction, it will have +no `preTokenBalance` entry as there is no existing account state. In this case, +the initial balance can be assumed to be zero. + +### Withdrawing + +The withdrawal address a user provides must be that of their SOL wallet. + +Before executing a withdrawal [transfer](#token-transfers), the exchange should +check the address as +[described above](#validating-user-supplied-account-addresses-for-withdrawals). +Additionally this address must be owned by the System Program and have no +account data. If the address has no SOL balance, user confirmation should be +obtained before proceeding with the withdrawal. All other withdrawal addresses +must be rejected. + +From the withdrawal address, the +[Associated Token Account](https://spl.solana.com/associated-token-account) +(ATA) for the correct mint is derived and the transfer issued to that account +via a +[TransferChecked](https://github.com/solana-labs/solana-program-library/blob/fc0d6a2db79bd6499f04b9be7ead0c400283845e/token/program/src/instruction.rs#L268) +instruction. Note that it is possible that the ATA address does not yet exist, +at which point the exchange should fund the account on behalf of the user. For +SPL Token accounts, funding the withdrawal account will require 0.00203928 SOL +(2,039,280 lamports). + +Template `spl-token transfer` command for a withdrawal: + +```shell +spl-token transfer --fund-recipient +``` + +### Other Considerations + +#### Freeze Authority + +For regulatory compliance reasons, an SPL Token issuing entity may optionally +choose to hold "Freeze Authority" over all accounts created in association with +its mint. This allows them to +[freeze](https://spl.solana.com/token#freezing-accounts) the assets in a given +account at will, rendering the account unusable until thawed. If this feature is +in use, the freeze authority's pubkey will be registered in the SPL Token's mint +account. + +### Basic Support for the SPL Token-2022 (Token-Extensions) Standard + +[SPL Token-2022](https://spl.solana.com/token-2022) is the newest standard for +wrapped/synthetic token creation and exchange on the Solana blockchain. + +Also known as "Token Extensions", the standard contains many new features that +token creators and account holders may optionally enable. These features include +confidential transfers, fees on transfer, closing mints, metadata, permanent +delegates, immutable ownership, and much more. Please see the +[extension guide](https://spl.solana.com/token-2022/extensions) for more +information. + +If your exchange supports SPL Token, there isn't a lot more work required to +support SPL Token-2022: + +- the CLI tool works seamlessly with both programs starting with version 3.0.0. +- `preTokenBalances` and `postTokenBalances` include SPL Token-2022 balances +- RPC indexes SPL Token-2022 accounts, but they must be queried separately with + program id `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` + +The Associated Token Account works the same way, and properly calculates the +required deposit amount of SOL for the new account. + +Because of extensions, however, accounts may be larger than 165 bytes, so they +may require more than 0.00203928 SOL to fund. + +For example, the Associated Token Account program always includes the "immutable +owner" extension, so accounts take a minimum of 170 bytes, which requires +0.00207408 SOL. + +### Extension-Specific Considerations + +The previous section outlines the most basic support for SPL Token-2022. Since +the extensions modify the behavior of tokens, exchanges may need to change how +they handle tokens. + +It is possible to see all extensions on a mint or token account: + +```shell +spl-token display +``` + +#### Transfer Fee + +A token may be configured with a transfer fee, where a portion of transferred +tokens are withheld at the destination for future collection. + +If your exchange transfers these tokens, beware that they may not all arrive at +the destination due to the withheld amount. + +It is possible to specify the expected fee during a transfer to avoid any +surprises: + +```shell +spl-token transfer --expected-fee --fund-recipient +``` + +#### Mint Close Authority + +With this extension, a token creator may close a mint, provided the supply of +tokens is zero. + +When a mint is closed, there may still be empty token accounts in existence, and +they will no longer be associated to a valid mint. + +It is safe to simply close these token accounts: + +```shell +spl-token close --address +``` + +#### Confidential Transfer + +Mints may be configured for confidential transfers, so that token amounts are +encrypted, but the account owners are still public. + +Exchanges may configure token accounts to send and receive confidential +transfers, to hide user amounts. It is not required to enable confidential +transfers on token accounts, so exchanges can force users to send tokens +non-confidentially. + +To enable confidential transfers, the account must be configured for it: + +```shell +spl-token configure-confidential-transfer-account --address +``` + +And to transfer: + +```shell +spl-token transfer --confidential +``` + +During a confidential transfer, the `preTokenBalance` and `postTokenBalance` +fields will show no change. In order to sweep deposit accounts, you must decrypt +the new balance to withdraw the tokens: + +```shell +spl-token apply-pending-balance --address +spl-token withdraw-confidential-tokens --address +``` + +#### Default Account State + +Mints may be configured with a default account state, such that all new token +accounts are frozen by default. These token creators may require users to go +through a separate process to thaw the account. + +#### Non-Transferable + +Some tokens are non-transferable, but they may still be burned and the account +can be closed. + +#### Permanent Delegate + +Token creators may designate a permanent delegate for all of their tokens. The +permanent delegate may transfer or burn tokens from any account, potentially +stealing funds. + +This is a legal requirement for stablecoins in certain jurisdictions, or could +be used for token repossession schemes. + +Beware that these tokens may be transferred without your exchange's knowledge. + +#### Transfer Hook + +Tokens may be configured with an additional program that must be called during +transfers, in order to validate the transfer or perform any other logic. + +Since the Solana runtime requires all accounts to be explicitly passed to a +program, and transfer hooks require additional accounts, the exchange needs to +create transfer instructions differently for these tokens. + +The CLI and instruction creators such as +`createTransferCheckedWithTransferHookInstruction` add the extra accounts +automatically, but the additional accounts may also be specified explicitly: + +```shell +spl-token transfer --transfer-hook-account --transfer-hook-account ... +``` + +#### Required Memo on Transfer + +Users may configure their token accounts to require a memo on transfer. + +Exchanges may need to prepend a memo instruction before transferring tokens back +to users, or they may require users to prepend a memo instruction before sending +to the exchange: + +```shell +spl-token transfer --with-memo +``` + +## Testing the Integration + +Be sure to test your complete workflow on Solana devnet and testnet +[clusters](/docs/core/clusters.md) before moving to production on mainnet-beta. +Devnet is the most open and flexible, and ideal for initial development, while +testnet offers more realistic cluster configuration. Both devnet and testnet +support a faucet, run `solana airdrop 1` to obtain some devnet or testnet SOL +for development and testing. diff --git a/docs/uk/more/index.md b/docs/uk/more/index.md new file mode 100644 index 000000000..0c7f22484 --- /dev/null +++ b/docs/uk/more/index.md @@ -0,0 +1,6 @@ +--- +metaOnly: true +title: More Information +# note: sort order is set to a really high number so this section is at the bottom of the sidebar +sidebarSortOrder: 9999 +--- diff --git a/docs/uk/programs/anchor/client-typescript.md b/docs/uk/programs/anchor/client-typescript.md new file mode 100644 index 000000000..f3d72118d --- /dev/null +++ b/docs/uk/programs/anchor/client-typescript.md @@ -0,0 +1,354 @@ +--- +title: JS/TS Client +description: + Learn how to use Anchor's TypeScript client library to interact with Solana + program +sidebarLabel: JS/TS Client +sidebarSortOrder: 3 +--- + +Anchor provides a Typescript client library +([@coral-xyz/anchor](https://github.com/coral-xyz/anchor/tree/v0.30.1/ts/packages/anchor)) +that simplifies the process of interacting with Solana programs from the client +in JavaScript or TypeScript. + +## Client Program + +To use the client library, first create an instance of a +[`Program`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/index.ts#L58) +using the [IDL file](/docs/programs/anchor/idl) generated by Anchor. + +Creating an instance of the `Program` requires the program's IDL and an +[`AnchorProvider`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/provider.ts#L55). +An `AnchorProvider` is an abstraction that combines two things: + +- `Connection` - the connection to a [Solana cluster](/docs/core/clusters.md) + (i.e. localhost, devnet, mainnet) +- `Wallet` - (optional) a default wallet used to pay and sign transactions + + + + + +When integrating with a frontend using the +[wallet adapter](https://solana.com/developers/guides/wallets/add-solana-wallet-adapter-to-nextjs), +you'll need to set up the `AnchorProvider` and `Program`. + +```ts {9-10, 12-14} +import { Program, AnchorProvider, setProvider } from "@coral-xyz/anchor"; +import { useAnchorWallet, useConnection } from "@solana/wallet-adapter-react"; +import type { HelloAnchor } from "./idlType"; +import idl from "./idl.json"; + +const { connection } = useConnection(); +const wallet = useAnchorWallet(); + +const provider = new AnchorProvider(connection, wallet, {}); +setProvider(provider); + +export const program = new Program(idl as HelloAnchor, { + connection, +}); +``` + +In the code snippet above: + +- `idl.json` is the IDL file generated by Anchor, found at + `/target/idl/.json` in an Anchor project. +- `idlType.ts` is the IDL type (for use with TS), found at + `/target/types/.ts` in an Anchor project. + +Alternatively, you can create an instance of the `Program` using only the IDL +and the `Connection` to a Solana cluster. This means there is no default +`Wallet`, but allows you to use the `Program` to fetch accounts or build +instructions without a connected wallet. + +```ts {8-10} +import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js"; +import { Program } from "@coral-xyz/anchor"; +import type { HelloAnchor } from "./idlType"; +import idl from "./idl.json"; + +const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); + +export const program = new Program(idl as HelloAnchor, { + connection, +}); +``` + + + + +Anchor automatically sets up a `Program` instance in the default test file of +new projects. However, this setup differs from how you'd initialize a `Program` +outside the Anchor workspace, such as in React or Node.js applications. + +```typescript +import * as anchor from "@coral-xyz/anchor"; +import { Program } from "@coral-xyz/anchor"; +import { HelloAnchor } from "../target/types/hello_anchor"; + +describe("hello_anchor", () => { + // Configure the client to use the local cluster. + anchor.setProvider(anchor.AnchorProvider.env()); + + const program = anchor.workspace.HelloAnchor as Program; + + it("Is initialized!", async () => { + // Add your test here. + const tx = await program.methods.initialize().rpc(); + console.log("Your transaction signature", tx); + }); +}); +``` + + + + +## Invoke Instructions + +Once the `Program` is set up using a program IDL, you can use the Anchor +[`MethodsBuilder`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L155) +to: + +- Build individual instructions +- Build transactions +- Build and send transactions + +The basic format looks like the following: + + + + + +`program.methods` - This is the builder API for creating instruction calls from +the program's IDL + +```ts /methods/ {1} +await program.methods + .instructionName(instructionData) + .accounts({}) + .signers([]) + .rpc(); +``` + + + + +Following `.methods`, specify the name of an instruction from the program IDL, +passing in any required arguments as comma-separated values. + +```ts /instructionName/ /instructionData1/ /instructionData2/ {2} +await program.methods + .instructionName(instructionData1, instructionData2) + .accounts({}) + .signers([]) + .rpc(); +``` + + + + +`.accounts` - Pass in the address of the accounts required by the instruction as +specified in the IDL + +```ts /accounts/ {3} +await program.methods + .instructionName(instructionData) + .accounts({}) + .signers([]) + .rpc(); +``` + +Note that certain account addresses don't need to be explicitly provided, as the +Anchor client can automatically resolve them. These typically include: + +- Common accounts (ex. the System Program) +- Accounts where the address is a PDA (Program Derived Address) + + + + +`.signers` - Optionally pass in an array of keypairs required as additional +signers by the instruction. This is commonly used when creating new accounts +where the account address is the public key of a newly generated keypair. + +```ts /signers/ {4} +await program.methods + .instructionName(instructionData) + .accounts({}) + .signers([]) + .rpc(); +``` + +Note that `.signers` should only be used when also using `.rpc()`. When using +`.transaction()` or `.instruction()`, signers should be added to the transaction +before sending. + + + + +Anchor provides multiple methods for building program instructions: + + + + + +The +[`rpc()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L283) +method +[sends a signed transaction](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/rpc.ts#L29) +with the specified instruction and returns a `TransactionSignature`. + +When using `.rpc`, the `Wallet` from the `Provider` is automatically included as +a signer. + +```ts {13} +// Generate keypair for the new account +const newAccountKp = new Keypair(); + +const data = new BN(42); +const transactionSignature = await program.methods + .initialize(data) + .accounts({ + newAccount: newAccountKp.publicKey, + signer: wallet.publicKey, + systemProgram: SystemProgram.programId, + }) + .signers([newAccountKp]) + .rpc(); +``` + + + + +The +[`transaction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L382) +method +[builds a `Transaction`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/transaction.ts#L18-L26) +with the specified instruction without sending the transaction. + +```ts {12} /transaction()/1,2,4 +// Generate keypair for the new account +const newAccountKp = new Keypair(); + +const data = new BN(42); +const transaction = await program.methods + .initialize(data) + .accounts({ + newAccount: newAccountKp.publicKey, + signer: wallet.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + +const transactionSignature = await connection.sendTransaction(transaction, [ + wallet.payer, + newAccountKp, +]); +``` + + + + +The +[`instruction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L348) +method +[builds a `TransactionInstruction`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/instruction.ts#L57-L61) +using the specified instruction. This is useful if you want to manually add the +instruction to a transaction and combine it with other instructions. + +```ts {12} /instruction()/ +// Generate keypair for the new account +const newAccountKp = new Keypair(); + +const data = new BN(42); +const instruction = await program.methods + .initialize(data) + .accounts({ + newAccount: newAccountKp.publicKey, + signer: wallet.publicKey, + systemProgram: SystemProgram.programId, + }) + .instruction(); + +const transaction = new Transaction().add(instruction); + +const transactionSignature = await connection.sendTransaction(transaction, [ + wallet.payer, + newAccountKp, +]); +``` + + + + +## Fetch Accounts + +The `Program` client simplifies the process of fetching and deserializing +accounts created by your Anchor program. + +Use `program.account` followed by the name of the account type defined in the +IDL. Anchor provides multiple methods for fetching accounts. + + + + + +Use +[`all()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L251) +to fetch all existing accounts for a specific account type. + +```ts /all/ +const accounts = await program.account.newAccount.all(); +``` + + + + +Use `memcmp` (memory compare) to filter for account data that matches a specific +value at a specific offset. Using `memcmp` requires you to understand the byte +layout of the data field for the account type you are fetching. + +When calculating the offset, remember that the first 8 bytes in accounts created +by an Anchor program are reserved for the account discriminator. + +```ts /memcmp/ +const accounts = await program.account.newAccount.all([ + { + memcmp: { + offset: 8, + bytes: "", + }, + }, +]); +``` + + + + +Use +[`fetch()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L165) +to fetch the account data for a single account + +```ts /fetch/ +const account = await program.account.newAccount.fetch(ACCOUNT_ADDRESS); +``` + + + + +Use +[`fetchMultiple()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L200) +to fetch the account data for multiple accounts by passing in an array of +account addresses + +```ts /fetchMultiple/ +const accounts = await program.account.newAccount.fetchMultiple([ + ACCOUNT_ADDRESS_ONE, + ACCOUNT_ADDRESS_TWO, +]); +``` + + + diff --git a/docs/uk/programs/anchor/cpi.md b/docs/uk/programs/anchor/cpi.md new file mode 100644 index 000000000..bb1d0d583 --- /dev/null +++ b/docs/uk/programs/anchor/cpi.md @@ -0,0 +1,551 @@ +--- +title: CPIs with Anchor +description: + Learn how to implement Cross Program Invocations (CPIs) in Anchor programs, + enabling interaction between different programs on Solana +sidebarLabel: CPIs with Anchor +sidebarSortOrder: 5 +--- + +[Cross Program Invocations (CPI)](/docs/core/cpi.md) refer to the process of one +program invoking instructions of another program, which enables the +composability of programs on Solana. + +This section will cover the basics of implementing CPIs in an Anchor program, +using a simple SOL transfer instruction as a practical example. Once you +understand the basics of how to implement a CPI, you can apply the same concepts +for any instruction. + +## Cross Program Invocations + +Let's examine a program that implements a CPI to the System Program's transfer +instruction. Here is the example program on +[Solana Playground](https://beta.solpg.io/66df2751cffcf4b13384d35a). + +The `lib.rs` file includes a single `sol_transfer` instruction. When the +`sol_transfer` instruction on the Anchor program is invoked, the program +internally invokes the transfer instruction of the System Program. + +```rs filename="lib.rs" /sol_transfer/ /transfer/ {23} +use anchor_lang::prelude::*; +use anchor_lang::system_program::{transfer, Transfer}; + +declare_id!("9AvUNHjxscdkiKQ8tUn12QCMXtcnbR9BVGq3ULNzFMRi"); + +#[program] +pub mod cpi { + use super::*; + + pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.sender.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + let cpi_context = CpiContext::new( + program_id, + Transfer { + from: from_pubkey, + to: to_pubkey, + }, + ); + + transfer(cpi_context, amount)?; + Ok(()) + } +} + +#[derive(Accounts)] +pub struct SolTransfer<'info> { + #[account(mut)] + sender: Signer<'info>, + #[account(mut)] + recipient: SystemAccount<'info>, + system_program: Program<'info, System>, +} +``` + +The `cpi.test.ts` file shows how to invoke the Anchor program's `sol_transfer` +instruction and logs a link to the transaction details on SolanaFM. + +```ts filename="cpi.test.ts" +it("SOL Transfer Anchor", async () => { + const transactionSignature = await program.methods + .solTransfer(new BN(transferAmount)) + .accounts({ + sender: sender.publicKey, + recipient: recipient.publicKey, + }) + .rpc(); + + console.log( + `\nTransaction Signature:` + + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, + ); +}); +``` + +You can build, deploy, and run the test for this example on Playground to view +the transaction details on the [SolanaFM explorer](https://solana.fm/). + +The transaction details will show that the Anchor program was first invoked +(instruction 1), which then invokes the System Program (instruction 1.1), +resulting in a successful SOL transfer. + +![Transaction Details](/assets/docs/core/cpi/transaction-details.png) + +### Example 1 Explanation + +Implementing a CPI follows the same pattern as building an instruction to add to +a transaction. When implementing a CPI, we must specify the program ID, +accounts, and instruction data for the instruction being called. + +The System Program's transfer instruction requires two accounts: + +- `from`: The account sending SOL. +- `to`: The account receiving SOL. + +In the example program, the `SolTransfer` struct specifies the accounts required +by the transfer instruction. The System Program is also included because the CPI +invokes the System Program. + +```rust /sender/ /recipient/ /system_program/ +#[derive(Accounts)] +pub struct SolTransfer<'info> { + #[account(mut)] + sender: Signer<'info>, // from account + #[account(mut)] + recipient: SystemAccount<'info>, // to account + system_program: Program<'info, System>, // program ID +} +``` + +The following tabs present three approaches to implementing Cross Program +Invocations (CPIs), each at a different level of abstraction. All examples are +functionally equivalent. The main purpose is to illustrate the implementation +details of the CPI. + + + + + +The `sol_transfer` instruction included in the example code shows a typical +approach for constructing CPIs using the Anchor framework. + +This approach involves creating a +[`CpiContext`](https://docs.rs/anchor-lang/latest/anchor_lang/context/struct.CpiContext.html), +which includes the `program_id` and accounts required for the instruction being +called, followed by a helper function (`transfer`) to invoke a specific +instruction. + +```rust +use anchor_lang::system_program::{transfer, Transfer}; +``` + +```rust /cpi_context/ {14} +pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.sender.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + let cpi_context = CpiContext::new( + program_id, + Transfer { + from: from_pubkey, + to: to_pubkey, + }, + ); + + transfer(cpi_context, amount)?; + Ok(()) +} +``` + +The `cpi_context` variable specifies the program ID (System Program) and +accounts (sender and recipient) required by the transfer instruction. + +```rust /program_id/ /from_pubkey/ /to_pubkey/ +let cpi_context = CpiContext::new( + program_id, + Transfer { + from: from_pubkey, + to: to_pubkey, + }, +); +``` + +The `cpi_context` and `amount` are then passed into the `transfer` function to +execute the CPI invoking the transfer instruction of the System Program. + +```rust +transfer(cpi_context, amount)?; +``` + + + + +This example shows a different approach to implementing a CPI using the `invoke` +function and +[`system_instruction::transfer`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L881), +which is generally seen in native Rust programs. + +Under the hood, the previous example is an abstraction of this implementation. +The example below is functionally equivalent to the previous example. + +```rust +use anchor_lang::solana_program::{program::invoke, system_instruction}; +``` + +```rust /instruction/1,3 {9} +pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.sender.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + let instruction = + &system_instruction::transfer(&from_pubkey.key(), &to_pubkey.key(), amount); + + invoke(instruction, &[from_pubkey, to_pubkey, program_id])?; + Ok(()) +} +``` + + + + +You can also manually build the instruction to pass into the `invoke()` +function. This is useful when there is no crate available to help build the +instruction you want to invoke. This approach requires you to specify the +`AccountMeta`s for the instruction and correctly create the instruction data +buffer. + +The `sol_transfer` instruction below is a manual implementation of a CPI to the +System Program's transfer instruction. + +```rust /instruction/10,13 {28} +pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.sender.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + // Prepare instruction AccountMetas + let account_metas = vec![ + AccountMeta::new(from_pubkey.key(), true), + AccountMeta::new(to_pubkey.key(), false), + ]; + + // SOL transfer instruction discriminator + let instruction_discriminator: u32 = 2; + + // Prepare instruction data + let mut instruction_data = Vec::with_capacity(4 + 8); + instruction_data.extend_from_slice(&instruction_discriminator.to_le_bytes()); + instruction_data.extend_from_slice(&amount.to_le_bytes()); + + // Create instruction + let instruction = Instruction { + program_id: program_id.key(), + accounts: account_metas, + data: instruction_data, + }; + + // Invoke instruction + invoke(&instruction, &[from_pubkey, to_pubkey, program_id])?; + Ok(()) +} +``` + +The `sol_transfer` instruction above replicates this +[example](/docs/core/transactions.md#manual-sol-transfer) of manually building a +SOL transfer instruction. It follows the same pattern as building an +[instruction](/docs/core/transactions.md#instruction) to add to a transaction. + +When building an instruction in Rust, use the following syntax to specify the +`AccountMeta` for each account: + +```rust +AccountMeta::new(account1_pubkey, true), // writable, signer +AccountMeta::new(account2_pubkey, false), // writable, not signer +AccountMeta::new_readonly(account3_pubkey, false), // not writable, not signer +AccountMeta::new_readonly(account4_pubkey, true), // writable, signer +``` + + + + +Here is a reference program on +[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi) +which includes all 3 examples. + +## Cross Program Invocations with PDA Signers + +Next, let's examine a program that implements a CPI to the System Program's +transfer instruction where the sender is a Program Derived Address (PDA) that +must be "signed" for by the program. Here is the example program on +[Solana Playground](https://beta.solpg.io/66df2bd2cffcf4b13384d35b). + +The `lib.rs` file includes the following program with a single `sol_transfer` +instruction. + +```rust filename="lib.rs" +use anchor_lang::prelude::*; +use anchor_lang::system_program::{transfer, Transfer}; + +declare_id!("3455LkCS85a4aYmSeNbRrJsduNQfYRY82A7eCD3yQfyR"); + +#[program] +pub mod cpi { + use super::*; + + pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.pda_account.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + let seed = to_pubkey.key(); + let bump_seed = ctx.bumps.pda_account; + let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]]; + + let cpi_context = CpiContext::new( + program_id, + Transfer { + from: from_pubkey, + to: to_pubkey, + }, + ) + .with_signer(signer_seeds); + + transfer(cpi_context, amount)?; + Ok(()) + } +} + +#[derive(Accounts)] +pub struct SolTransfer<'info> { + #[account( + mut, + seeds = [b"pda", recipient.key().as_ref()], + bump, + )] + pda_account: SystemAccount<'info>, + #[account(mut)] + recipient: SystemAccount<'info>, + system_program: Program<'info, System>, +} +``` + +The `cpi.test.ts` file shows how to invoke the Anchor program's `sol_transfer` +instruction and logs a link to the transaction details on SolanaFM. + +It shows how to derive the PDA using the seeds specified in the program: + +```ts /pda/ /wallet.publicKey/ +const [PDA] = PublicKey.findProgramAddressSync( + [Buffer.from("pda"), wallet.publicKey.toBuffer()], + program.programId, +); +``` + +The first step in this example is to fund the PDA account with a basic SOL +transfer from the Playground wallet. + +```ts filename="cpi.test.ts" +it("Fund PDA with SOL", async () => { + const transferInstruction = SystemProgram.transfer({ + fromPubkey: wallet.publicKey, + toPubkey: PDA, + lamports: transferAmount, + }); + + const transaction = new Transaction().add(transferInstruction); + + const transactionSignature = await sendAndConfirmTransaction( + connection, + transaction, + [wallet.payer], // signer + ); + + console.log( + `\nTransaction Signature:` + + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, + ); +}); +``` + +Once the PDA is funded with SOL, invoke the `sol_transfer` instruction. This +instruction transfers SOL from the PDA account back to the `wallet` account via +a CPI to the System Program, which is "signed" for by the program. + +```ts +it("SOL Transfer with PDA signer", async () => { + const transactionSignature = await program.methods + .solTransfer(new BN(transferAmount)) + .accounts({ + pdaAccount: PDA, + recipient: wallet.publicKey, + }) + .rpc(); + + console.log( + `\nTransaction Signature: https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, + ); +}); +``` + +You can build, deploy, and run the test to view the transaction details on the +[SolanaFM explorer](https://solana.fm/). + +The transaction details will show that the custom program was first invoked +(instruction 1), which then invokes the System Program (instruction 1.1), +resulting in a successful SOL transfer. + +![Transaction Details](/assets/docs/core/cpi/transaction-details-pda.png) + +### Example 2 Explanation + +In the example code, the `SolTransfer` struct specifies the accounts required by +the transfer instruction. + +The sender is a PDA that the program must sign for. The `seeds` to derive the +address for the `pda_account` include the hardcoded string "pda" and the address +of the `recipient` account. This means the address for the `pda_account` is +unique for each `recipient`. + +```rust /pda_account/ /recipient/2 /system_program/ +#[derive(Accounts)] +pub struct SolTransfer<'info> { + #[account( + mut, + seeds = [b"pda", recipient.key().as_ref()], + bump, + )] + pda_account: SystemAccount<'info>, + #[account(mut)] + recipient: SystemAccount<'info>, + system_program: Program<'info, System>, +} +``` + +The Javascript equivalent to derive the PDA is included in the test file. + +```ts /pda/ /wallet.publicKey/ +const [PDA] = PublicKey.findProgramAddressSync( + [Buffer.from("pda"), wallet.publicKey.toBuffer()], + program.programId, +); +``` + +The following tabs present two approaches to implementing Cross Program +Invocations (CPIs), each at a different level of abstraction. Both examples are +functionally equivalent. The main purpose is to illustrate the implementation +details of the CPI. + + + + + +The `sol_transfer` instruction included in the example code shows a typical +approach for constructing CPIs using the Anchor framework. + +This approach involves creating a +[`CpiContext`](https://docs.rs/anchor-lang/latest/anchor_lang/context/struct.CpiContext.html), +which includes the `program_id` and accounts required for the instruction being +called, followed by a helper function (`transfer`) to invoke a specific +instruction. + +```rust /cpi_context/ {19} +pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.pda_account.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + let seed = to_pubkey.key(); + let bump_seed = ctx.bumps.pda_account; + let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]]; + + let cpi_context = CpiContext::new( + program_id, + Transfer { + from: from_pubkey, + to: to_pubkey, + }, + ) + .with_signer(signer_seeds); + + transfer(cpi_context, amount)?; + Ok(()) +} +``` + +When signing with PDAs, the seeds and bump seed are included in the +`cpi_context` as `signer_seeds` using `with_signer()`. The bump seed for a PDA +can be accessed using `ctx.bumps` followed by the name of the PDA account. + +```rust /signer_seeds/ /bump_seed/ {3} +let seed = to_pubkey.key(); +let bump_seed = ctx.bumps.pda_account; +let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]]; + +let cpi_context = CpiContext::new( + program_id, + Transfer { + from: from_pubkey, + to: to_pubkey, + }, +) +.with_signer(signer_seeds); +``` + +The `cpi_context` and `amount` are then passed into the `transfer` function to +execute the CPI. + +```rust +transfer(cpi_context, amount)?; +``` + +When the CPI is processed, the Solana runtime will validate that the provided +seeds and caller program ID derive a valid PDA. The PDA is then added as a +signer on the invocation. This mechanism allows for programs to sign for PDAs +that are derived from their program ID. + + + + +Under the hood, the previous example is a wrapper around the `invoke_signed()` +function which uses +[`system_instruction::transfer`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L881) +to build the instruction. + +This example shows how to use the `invoke_signed()` function to make a CPI +signed for by a PDA. + +```rust +use anchor_lang::solana_program::{program::invoke_signed, system_instruction}; +``` + +```rust /instruction/1,3 {13} +pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.pda_account.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + let seed = to_pubkey.key(); + let bump_seed = ctx.bumps.pda_account; + let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]]; + + let instruction = + &system_instruction::transfer(&from_pubkey.key(), &to_pubkey.key(), amount); + + invoke_signed(instruction, &[from_pubkey, to_pubkey, program_id], signer_seeds)?; + Ok(()) +} +``` + +This implementation is functionally equivalent to the previous example. The +`signer_seeds` are passed into the `invoke_signed` function. + + + + +Here is a reference program on +[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi-pda) +which includes both examples. diff --git a/docs/uk/programs/anchor/idl.md b/docs/uk/programs/anchor/idl.md new file mode 100644 index 000000000..79e42c8f7 --- /dev/null +++ b/docs/uk/programs/anchor/idl.md @@ -0,0 +1,516 @@ +--- +title: IDL File +description: + Learn about the Interface Definition Language (IDL) file in Anchor, its + purpose, benefits, and how it simplifies program-client interactions +sidebarLabel: IDL File +sidebarSortOrder: 2 +--- + +An Interface Definition Language (IDL) file provides a standardized JSON file +describing the program's instructions and accounts. This file simplifies the +process of integrating your on-chain program with client applications. + +Key Benefits of the IDL: + +- Standardization: Provides a consistent format for describing the program's + instructions and accounts +- Client Generation: Used to generate client code to interact with the program + +The `anchor build` command generates an IDL file located at +`/target/idl/.json`. + +The code snippets below highlights how the program, IDL, and client relate to +each other. + +## Program Instructions + +The `instructions` array in the IDL corresponds directly to the instructions +defined in your program. It specifies the required accounts and parameters for +each instruction. + + + + + +The program below includes an `initialize` instruction, specifying the accounts +and parameters it requires. + +```rust {8-12, 15-22} +use anchor_lang::prelude::*; + +declare_id!("BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64, +} +``` + + + + +The generated IDL file includes the instruction in a standardized JSON format, +including its name, accounts, arguments, and discriminator. + +```json filename="JSON" {11-12, 14-27, 30-33} +{ + "address": "BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd", + "metadata": { + "name": "hello_anchor", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "initialize", + "discriminator": [175, 175, 109, 31, 13, 152, 155, 237], + "accounts": [ + { + "name": "new_account", + "writable": true, + "signer": true + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "data", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "NewAccount", + "discriminator": [176, 95, 4, 118, 91, 177, 125, 232] + } + ], + "types": [ + { + "name": "NewAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "data", + "type": "u64" + } + ] + } + } + ] +} +``` + + + + +The IDL file is then used to generate a client for interacting with the program, +simplifying the process of invoking the program instruction. + +```ts {19-26} +import * as anchor from "@coral-xyz/anchor"; +import { Program, BN } from "@coral-xyz/anchor"; +import { HelloAnchor } from "../target/types/hello_anchor"; +import { Keypair } from "@solana/web3.js"; +import assert from "assert"; + +describe("hello_anchor", () => { + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const wallet = provider.wallet as anchor.Wallet; + const program = anchor.workspace.HelloAnchor as Program; + + it("initialize", async () => { + // Generate keypair for the new account + const newAccountKp = new Keypair(); + + // Send transaction + const data = new BN(42); + const transactionSignature = await program.methods + .initialize(data) + .accounts({ + newAccount: newAccountKp.publicKey, + signer: wallet.publicKey, + }) + .signers([newAccountKp]) + .rpc(); + + // Fetch the created account + const newAccount = await program.account.newAccount.fetch( + newAccountKp.publicKey, + ); + + console.log("Transaction signature: ", transactionSignature); + console.log("On-chain data is:", newAccount.data.toString()); + assert(data.eq(newAccount.data)); + }); +}); +``` + + + + +## Program Accounts + +The `accounts` array in the IDL corresponds to the structs in a program +annotated with the `#[account]` macro. These structs define the data stored in +accounts created by the program. + + + + + +The program below defines a `NewAccount` struct with a single `data` field of +type `u64`. + +```rust {24-27} +use anchor_lang::prelude::*; + +declare_id!("BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64, +} +``` + + + + +The generated IDL file includes the account in a standardized JSON format, +including its name, discriminator, and fields. + +```json filename="JSON" {39-40, 45-54} +{ + "address": "BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd", + "metadata": { + "name": "hello_anchor", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "initialize", + "discriminator": [175, 175, 109, 31, 13, 152, 155, 237], + "accounts": [ + { + "name": "new_account", + "writable": true, + "signer": true + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "data", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "NewAccount", + "discriminator": [176, 95, 4, 118, 91, 177, 125, 232] + } + ], + "types": [ + { + "name": "NewAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "data", + "type": "u64" + } + ] + } + } + ] +} +``` + + + + +The IDL file is then used to generate a client for interacting with the program, +simplifying the process of fetching and deserializing account data. + +```ts {29-31} +import * as anchor from "@coral-xyz/anchor"; +import { Program, BN } from "@coral-xyz/anchor"; +import { HelloAnchor } from "../target/types/hello_anchor"; +import { Keypair } from "@solana/web3.js"; +import assert from "assert"; + +describe("hello_anchor", () => { + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const wallet = provider.wallet as anchor.Wallet; + const program = anchor.workspace.HelloAnchor as Program; + + it("initialize", async () => { + // Generate keypair for the new account + const newAccountKp = new Keypair(); + + // Send transaction + const data = new BN(42); + const transactionSignature = await program.methods + .initialize(data) + .accounts({ + newAccount: newAccountKp.publicKey, + signer: wallet.publicKey, + }) + .signers([newAccountKp]) + .rpc(); + + // Fetch the created account + const newAccount = await program.account.newAccount.fetch( + newAccountKp.publicKey, + ); + + console.log("Transaction signature: ", transactionSignature); + console.log("On-chain data is:", newAccount.data.toString()); + assert(data.eq(newAccount.data)); + }); +}); +``` + + + + +## Discriminators + +Anchor assigns a unique 8 byte discriminator to each instruction and account +type in a program. These discriminators serve as identifiers to distinguish +between different instructions or account types. + +The discriminator is generated using the first 8 bytes of the Sha256 hash of a +prefix combined with the instruction or account name. As of Anchor v0.30, these +discriminators are included in the IDL file. + +Note that when working with Anchor, you typically won't need to interact +directly with these discriminators. This section is primarily to provide context +on how the discriminator is generated and used. + + + + + +The instruction discriminator is used by the program to determine which specific +instruction to execute when called. + +When an Anchor program instruction is invoked, the discriminator is included as +the first 8 bytes of the instruction data. This is done automatically by the +Anchor client. + +```json filename="IDL" {4} + "instructions": [ + { + "name": "initialize", + "discriminator": [175, 175, 109, 31, 13, 152, 155, 237], + ... + } + ] +``` + +The discriminator for an instruction is the first 8 bytes of the Sha256 hash of +the prefix `global` plus the instruction name. + +For example: + +``` +sha256("global:initialize") +``` + +Hexadecimal output: + +``` +af af 6d 1f 0d 98 9b ed d4 6a 95 07 32 81 ad c2 1b b5 e0 e1 d7 73 b2 fb bd 7a b5 04 cd d4 aa 30 +``` + +The first 8 bytes are used as the discriminator for the instruction. + +``` +af = 175 +af = 175 +6d = 109 +1f = 31 +0d = 13 +98 = 152 +9b = 155 +ed = 237 +``` + +You can find the implementation of the discriminator generation in the Anchor +codebase +[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/codegen/program/common.rs#L5-L19), +which is used +[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/codegen/program/instruction.rs#L27). + + + + +The account discriminator is used to identify the specific account type when +deserializing on-chain data and is set when the account is created. + +```json filename="IDL" {4} + "accounts": [ + { + "name": "NewAccount", + "discriminator": [176, 95, 4, 118, 91, 177, 125, 232] + } + ] +``` + +The discriminator for an account is the first 8 bytes of the Sha256 hash of the +prefix `account` plus the account name. + +For example: + +``` +sha256("account:NewAccount") +``` + +Hexadecimal output: + +``` +b0 5f 04 76 5b b1 7d e8 a1 93 57 2a d3 5e b1 ae e5 f0 69 e2 09 7e 5c d2 64 56 55 2a cb 4a e9 57 +``` + +The first 8 bytes are used as the discriminator for the account. + +``` +b0 = 176 +5f = 95 +04 = 4 +76 = 118 +5b = 91 +b1 = 177 +7d = 125 +e8 = 232 +``` + +You can find the implementation of the discriminator generation in the Anchor +codebase +[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L101-L117). + +Note that different programs using identical account names will generate the +same discriminator. When deserializing account data, Anchor programs will also +check an account is owned by the expected program for a specified account type. + + + + +The event discriminator is used to identify the specific event type when +deserializing on-chain data on event emission. + +```json filename="IDL" {4} + "events": [ + { + "name": "NewEvent", + "discriminator": [113, 21, 185, 70, 164, 99, 232, 201] + } + ] +``` + +The discriminator for an event is the first 8 bytes of the Sha256 hash of the +prefix `event` plus the event name. + +For example: + +``` +sha256("event:NewEvent") +``` + +Hexadecimal output: + +``` +71 15 b9 46 a4 63 e8 c9 2a 3c 4d 83 87 16 cd 9b 66 28 cb e2 cb 7c 5d 70 59 f3 42 2b dc 35 03 53 +``` + +The first 8 bytes are used as the discriminator for the account. + +Hex to decimal gives us: + +``` +71 = 113 +15 = 21 +b9 = 185 +46 = 70 +a4 = 164 +63 = 99 +e8 = 232 +c9 = 201 +``` + +You can find the implementation of the discriminator generation in the Anchor +codebase +[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/event/src/lib.rs#L23-L27). + +Note that different programs using identical event names will generate the same +discriminator. When deserializing event data, Anchor programs will also check an +event is owned by the expected program for a specified event type. + + + diff --git a/docs/uk/programs/anchor/index.md b/docs/uk/programs/anchor/index.md new file mode 100644 index 000000000..8b998aed3 --- /dev/null +++ b/docs/uk/programs/anchor/index.md @@ -0,0 +1,384 @@ +--- +title: Getting Started with Anchor +description: + Learn how to build Solana programs using the Anchor framework. This + comprehensive guide covers creating, building, testing, and deploying Solana + smart contracts with Anchor. +sidebarLabel: Anchor Framework +sidebarSortOrder: 0 +altRoutes: + - /docs/programs/debugging + - /docs/programs/lang-c + - /docs/programs/overview +--- + +The Anchor framework is a tool that simplifies the process of building Solana +programs. Whether you're new to blockchain development or an experienced +programmer, Anchor simplifies the process of writing, testing, and deploying +Solana programs. + +In this section, we'll walk through: + +- Creating a new Anchor project +- Building and testing your program +- Deploying to Solana clusters +- Understanding the project file structure + +## Prerequisites + +For detailed installation instructions, visit the +[installation](/docs/intro/installation) page. + +Before you begin, ensure you have the following installed: + +- Rust: The programming language for building Solana programs. +- Solana CLI: Command-line tool for Solana development. +- Anchor CLI: Command-line tool for the Anchor framework. + +To verify Anchor CLI installation, open your terminal and run: + +```shell filename="Terminal" +anchor --version +``` + +Expected output: + +```shell filename="Terminal" +anchor-cli 0.30.1 +``` + +## Getting Started + +This section covers the basic steps to create, build, and test your first local +Anchor program. + + + +### Create a new Project + +To start a new project, use the `anchor init` command followed by your project's +name. This command creates a new directory with the specified name and sets up a +default program and test file. + +```shell filename="Terminal" +anchor init my-project +``` + +Navigate to the new project directory and open it in your code editor. + +```shell filename="Terminal" copy +cd my-project +``` + +The default Anchor program is located at `programs/my-project/src/lib.rs`. + + + + +The value in the `declare_id!` macro is the program ID, a unique identifier for +your program. + +By default, it is the public key of the keypair generated in +`/target/deploy/my_project-keypair.json`. + +```rs filename="lib.rs" +use anchor_lang::prelude::*; + +declare_id!("3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg"); + +#[program] +pub mod my_project { + use super::*; + + pub fn initialize(ctx: Context) -> Result<()> { + msg!("Greetings from: {:?}", ctx.program_id); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize {} +``` + + + + +The default Typescript test file is located at `/tests/my-project.ts`. + + + + +This file demonstrates how to invoke the default program's `initialize` +instruction in Typescript. + +```ts filename="my-project.ts" +import * as anchor from "@coral-xyz/anchor"; +import { Program } from "@coral-xyz/anchor"; +import { MyProject } from "../target/types/my_project"; + +describe("my-project", () => { + // Configure the client to use the local cluster. + anchor.setProvider(anchor.AnchorProvider.env()); + + const program = anchor.workspace.MyProject as Program; + + it("Is initialized!", async () => { + // Add your test here. + const tx = await program.methods.initialize().rpc(); + console.log("Your transaction signature", tx); + }); +}); +``` + + + + +If you prefer Rust for testing, initialize your project with the +`--test-template rust` flag. + +```shell +anchor init --test-template rust my-project +``` + +The Rust test file will be at `/tests/src/test_initialize.rs`. + + + + +```rust filename="test_initialize.rs" +use std::str::FromStr; + +use anchor_client::{ + solana_sdk::{ + commitment_config::CommitmentConfig, pubkey::Pubkey, signature::read_keypair_file, + }, + Client, Cluster, +}; + +#[test] +fn test_initialize() { + let program_id = "3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg"; + let anchor_wallet = std::env::var("ANCHOR_WALLET").unwrap(); + let payer = read_keypair_file(&anchor_wallet).unwrap(); + + let client = Client::new_with_options(Cluster::Localnet, &payer, CommitmentConfig::confirmed()); + let program_id = Pubkey::from_str(program_id).unwrap(); + let program = client.program(program_id).unwrap(); + + let tx = program + .request() + .accounts(my_program::accounts::Initialize {}) + .args(my_program::instruction::Initialize {}) + .send() + .expect(""); + + println!("Your transaction signature {}", tx); +} +``` + + + + +### Build the Program + +Build the program by running `anchor build`. + +```shell filename="Terminal" copy +anchor build +``` + +The compiled program will be at `/target/deploy/my_project.so`. The content of +this file is what gets stored on the Solana network (as an executable account) +when you deploy your program. + +### Test the Program + +To test the program, run `anchor test`. + +```shell filename="Terminal" copy +anchor test +``` + +By default, the `Anchor.toml` config file specifies the `localnet` cluster. When +developing on `localnet`, `anchor test` will automatically: + +1. Start a local Solana validator +2. Build and deploy your program to the local cluster +3. Run the tests in the `tests` folder +4. Stop the local Solana validator + +Alternatively, you can manually start a local Solana validator and run tests +against it. This is useful if you want to keep the validator running while you +iterate on your program. It allows you to inspect accounts and transaction logs +on the [Solana Explorer](https://explorer.solana.com/?cluster=custom) while +developing locally. + +Open a new terminal and start a local Solana validator by running the +`solana-test-validator` command. + +```shell filename="Terminal" copy +solana-test-validator +``` + +In a separate terminal, run the tests against the local cluster. Use the +`--skip-local-validator` flag to skip starting the local validator since it's +already running. + +```shell filename="Terminal" copy +anchor test --skip-local-validator +``` + +### Deploy to Devnet + +By default, the `Anchor.toml` config file in an Anchor project specifies the +localnet cluster. + +```toml filename="Anchor.toml" {14} +[toolchain] + +[features] +resolution = true +skip-lint = false + +[programs.localnet] +my_program = "3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg" + +[registry] +url = "https://api.apr.dev" + +[provider] +cluster = "Localnet" +wallet = "~/.config/solana/id.json" + +[scripts] +test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +``` + +To deploy your program to devnet, change the `cluster` value to `Devnet`. Note +that this requires your wallet to have enough SOL on Devnet to cover deployment +cost. + +```diff +-cluster = "Localnet" ++cluster = "Devnet" +``` + +```toml filename="Anchor.toml" +[provider] +cluster = "Devnet" +wallet = "~/.config/solana/id.json" +``` + +Now when you run `anchor deploy`, your program will be deployed to the devnet +cluster. The `anchor test` command will also use the cluster specified in the +`Anchor.toml` file. + +```shell +anchor deploy +``` + +To deploy to mainnet, simply update the `Anchor.toml` file to specify the +mainnet cluster. + +```toml filename="Anchor.toml" +[provider] +cluster = "Mainnet" +wallet = "~/.config/solana/id.json" +``` + +### Update the Program + +Solana programs can be updated by redeploying the program to the same program +ID. + +To update a program, simply make changes to your program's code and run the +`anchor build` command to generated an updated `.so` file. + +```shell +anchor build +``` + +Then run the `anchor deploy` command to redeploy the updated program. + +```shell +anchor deploy +``` + +### Close the Program + +To reclaim the SOL allocated to a program account, you can close your Solana +program. + +To close a program, use the `solana program close ` command. For +example: + +```shell +solana program close 3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg --bypass-warning +``` + +Note that once a program is closed, the program ID cannot be reused to deploy a +new program. + + + +## Project File Structure + +Below is an overview of default file structure in an Anchor workspace: + +``` +. +├── .anchor +│ └── program-logs +├── app +├── migrations +├── programs +│ └── [project-name] +│ └── src +│ ├── lib.rs +│ ├── Cargo.toml +│ └── Xargo.toml +├── target +│ ├── deploy +│ │ └── [project-name]-keypair.json +│ ├── idl +│ │ └── [project-name].json +│ └── types +│ └── [project-name].ts +├── tests +│ └── [project-name].ts +├── Anchor.toml +├── Cargo.toml +└── package.json +``` + +### Programs Folder + +The `/programs` folder contains your project's Anchor programs. A single +workspace can contain multiple programs. + +### Tests Folder + +The `/tests` folder contains test files for your project. A default test file is +created for you when you create your project. + +### Target Folder + +The `/target` folder contains build outputs. The main subfolders include: + +- `/deploy`: Contains the keypair and program binary for your programs. +- `/idl`: Contains the JSON IDL for your programs. +- `/types`: Contains the TypeScript type for the IDL. + +### Anchor.toml File + +The `Anchor.toml` file configures workspace settings for your project. + +### .anchor Folder + +Includes a `program-logs` file that contains transaction logs from the last run +of test files. + +### App Folder + +The `/app` folder is an empty folder that can be optionally used for your +frontend code. diff --git a/docs/uk/programs/anchor/pda.md b/docs/uk/programs/anchor/pda.md new file mode 100644 index 000000000..bec281733 --- /dev/null +++ b/docs/uk/programs/anchor/pda.md @@ -0,0 +1,325 @@ +--- +title: PDAs with Anchor +description: + Learn how to use Program Derived Addresses (PDAs) in Anchor programs, using + constraints, and implementing common PDA patterns +sidebarLabel: PDAs with Anchor +sidebarSortOrder: 4 +--- + +[Program Derived Addresses (PDA)](/docs/core/pda) refer to a feature of Solana +development that allows you to create a unique address derived deterministically +from pre-defined inputs (seeds) and a program ID. + +This section will cover basic examples of how to use PDAs in an Anchor program. + +## Anchor PDA Constraints + +When using PDAs in an Anchor program, you generally use Anchor's account +constraints to define the seeds used to derive the PDA. These constraints serve +as security checks to ensure that the correct address is derived. + +The constraints used to define the PDA seeds include: + +- `seeds`: An array of optional seeds used to derive the PDA. Seeds can be + static values or dynamic references to account data. +- `bump`: The bump seed used to derive the PDA. Used to ensure the address falls + off the Ed25519 curve and is a valid PDA. +- `seeds::program` - (Optional) The program ID used to derive the PDA address. + This constraint is only used to derive a PDA where the program ID is not the + current program. + +The `seeds` and `bump` constraints are required to be used together. + +### Usage Examples + +Below are examples demonstrating how to use PDA constraints in an Anchor +program. + + + + + +The `seeds` constraint specifies the optional values used to derive the PDA. + +#### No Optional Seeds + +- Use an empty array `[]` to define a PDA without optional seeds. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + #[account( + seeds = [], + bump, + )] + pub pda_account: SystemAccount<'info>, +} +``` + +#### Single Static Seed + +- Specify optional seeds in the `seeds` constraint. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + #[account( + seeds = [b"hello_world"], + bump, + )] + pub pda_account: SystemAccount<'info>, +} +``` + +#### Multiple Seeds and Account References + +- Multiple seeds can be specified in the `seeds` constraint. The `seeds` + constraint can also reference other account addresses or account data. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + pub signer: Signer<'info>, + #[account( + seeds = [b"hello_world", signer.key().as_ref()], + bump, + )] + pub pda_account: SystemAccount<'info>, +} +``` + +The example above uses both a static seed (`b"hello_world"`) and a dynamic seed +(the signer's public key). + + + + +The `bump` constraint specifies the bump seed used to derive the PDA. + +#### Automatic Bump Calculation + +When using the `bump` constraint without a value, the bump is automatically +calculated each time the instruction is invoked. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + #[account( + seeds = [b"hello_world"], + bump, + )] + pub pda_account: SystemAccount<'info>, +} +``` + +#### Specify Bump Value + +You can explicitly provide the bump value, which is useful for optimizing +compute unit usage. This assumes that the PDA account has been created and the +bump seed is stored as a field on an existing account. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + #[account( + seeds = [b"hello_world"], + bump = pda_account.bump_seed, + )] + pub pda_account: Account<'info, CustomAccount>, +} + +#[account] +pub struct CustomAccount { + pub bump_seed: u8, +} +``` + +By storing the bump value in the account's data, the program doesn't need to +recalculate it, saving compute units. The saved bump value can be stored on the +account itself or another account. + + + + +The `seeds::program` constraint specifies the program ID used to derive the PDA. +This constraint is only used when deriving a PDA from a different program. + +Use this constraint when your instruction needs to interact with PDA accounts +created by another program. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + #[account( + seeds = [b"hello_world"], + bump, + seeds::program = other_program.key(), + )] + pub pda_account: SystemAccount<'info>, + pub other_program: Program<'info, OtherProgram>, +} +``` + + + + +The `init` constraint is commonly used with `seeds` and `bump` to create a new +account with an address that is a PDA. Under the hood, the `init` constraint +invokes the System Program to create the account. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + #[account(mut)] + pub signer: Signer<'info>, + #[account( + init, + seeds = [b"hello_world", signer.key().as_ref()], + bump, + payer = signer, + space = 8 + 1, + )] + pub pda_account: Account<'info, CustomAccount>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct CustomAccount { + pub bump_seed: u8, +} +``` + + + + +## PDA seeds in the IDL + +Program Derived Address (PDA) seeds defined in the `seeds` constraint are +included in the program's IDL file. This allows the Anchor client to +automatically resolve accounts using these seeds when constructing instructions. + +This example below shows the relationship between the program, IDL, and client. + + + + + +The program below defines a `pda_account` using a static seed (`b"hello_world"`) +and the signer's public key as a dynamic seed. + +```rs {18} /signer/ +use anchor_lang::prelude::*; + +declare_id!("BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5"); + +#[program] +mod hello_anchor { + use super::*; + pub fn test_instruction(ctx: Context) -> Result<()> { + msg!("PDA: {}", ctx.accounts.pda_account.key()); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + pub signer: Signer<'info>, + #[account( + seeds = [b"hello_world", signer.key().as_ref()], + bump, + )] + pub pda_account: SystemAccount<'info>, +} +``` + + + + +The program's IDL file includes the PDA seeds defined in the `seeds` constraint. + +- The static seed `b"hello_world"` is converted to byte values. +- The dynamic seed is included as reference to the signer account. + +```json {22-29} +{ + "address": "BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5", + "metadata": { + "name": "hello_anchor", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "test_instruction", + "discriminator": [33, 223, 61, 208, 32, 193, 201, 79], + "accounts": [ + { + "name": "signer", + "signer": true + }, + { + "name": "pda_account", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [104, 101, 108, 108, 111, 95, 119, 111, 114, 108, 100] + }, + { + "kind": "account", + "path": "signer" + } + ] + } + } + ], + "args": [] + } + ] +} +``` + + + + +The Anchor client can automatically resolve the PDA address using the IDL file. + +In the example below, Anchor automatically resolves the PDA address using the +provider wallet as the signer, and its public key as the dynamic seed for PDA +derivation. This removes the need to explicitly derive the PDA when building the +instruction. + +```ts {13} +import * as anchor from "@coral-xyz/anchor"; +import { Program } from "@coral-xyz/anchor"; +import { HelloAnchor } from "../target/types/hello_anchor"; + +describe("hello_anchor", () => { + // Configure the client to use the local cluster. + anchor.setProvider(anchor.AnchorProvider.env()); + + const program = anchor.workspace.HelloAnchor as Program; + + it("Is initialized!", async () => { + // Add your test here. + const tx = await program.methods.testInstruction().rpc(); + console.log("Your transaction signature", tx); + }); +}); +``` + +When the instruction is invoked, the PDA is printed to program logs as defined +in the program instruction. + +```{3} +Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 invoke [1] +Program log: Instruction: TestInstruction +Program log: PDA: 3Hikt5mpKaSS4UNA5Du1TZJ8tp4o8VC8YWW6X9vtfVnJ +Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 consumed 18505 of 200000 compute units +Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 success +``` + + + diff --git a/docs/uk/programs/anchor/program-structure.md b/docs/uk/programs/anchor/program-structure.md new file mode 100644 index 000000000..a7d5fc07c --- /dev/null +++ b/docs/uk/programs/anchor/program-structure.md @@ -0,0 +1,399 @@ +--- +title: Anchor Program Structure +description: + Learn about the structure of Anchor programs, including key macros and their + roles in simplifying Solana program development +sidebarLabel: Program Structure +sidebarSortOrder: 1 +--- + +The [Anchor framework](https://www.anchor-lang.com/) uses +[Rust macros](https://doc.rust-lang.org/book/ch19-06-macros.html) to reduce +boilerplate code and simplify the implementation of common security checks +required for writing Solana programs. + +The main macros found in an Anchor program include: + +- [`declare_id`](#declare-id-macro): Specifies the program's on-chain address +- [`#[program]`](#program-macro): Specifies the module containing the program’s + instruction logic +- [`#[derive(Accounts)]`](#derive-accounts-macro): Applied to structs to + indicate a list of accounts required by an instruction +- [`#[account]`](#account-macro): Applied to structs to create custom account + types for the program + +## Example Program + +Let's examine a simple program that demonstrates the usage of the macros +mentioned above to understand the basic structure of an Anchor program. + +The example program below creates a new account (`NewAccount`) that stores a +`u64` value passed to the `initialize` instruction. + +```rust filename="lib.rs" +use anchor_lang::prelude::*; + +declare_id!("11111111111111111111111111111111"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64, +} +``` + +## declare_id! macro + +The +[`declare_id`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L430) +macro specifies the on-chain address of the program, known as the program ID. + +```rust filename="lib.rs" {3} +use anchor_lang::prelude::*; + +declare_id!("11111111111111111111111111111111"); +``` + +By default, the program ID is the public key of the keypair generated at +`/target/deploy/your_program_name.json`. + +To update the value of the program ID in the `declare_id` macro with the public +key of the keypair in the `/target/deploy/your_program_name.json` file, run the +following command: + +```shell filename="Terminal" +anchor keys sync +``` + +The `anchor keys sync` command is useful to run when cloning a repository where +the value of the program ID in a cloned repo's `declare_id` macro won't match +the one generated when you run `anchor build` locally. + +## #[program] macro + +The +[`#[program]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/lib.rs#L12) +macro defines the module that contains all the instruction handlers for your +program. Each public function within this module corresponds to an instruction +that can be invoked. + +```rust filename="lib.rs" {5, 8-12} +use anchor_lang::prelude::*; + +declare_id!("11111111111111111111111111111111"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64, +} +``` + +### Instruction Context + +Instruction handlers are functions that define the logic executed when an +instruction is invoked. The first parameter of each handler is a `Context` +type, where `T` is a struct implementing the `Accounts` trait and specifies the +accounts the instruction requires. + +The +[`Context`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/context.rs#L24) +type provides the instruction with access to the following non-argument inputs: + +```rust +pub struct Context<'a, 'b, 'c, 'info, T> { + /// Currently executing program id. + pub program_id: &'a Pubkey, + /// Deserialized accounts. + pub accounts: &'b mut T, + /// Remaining accounts given but not deserialized or validated. + /// Be very careful when using this directly. + pub remaining_accounts: &'c [AccountInfo<'info>], + /// Bump seeds found during constraint validation. This is provided as a + /// convenience so that handlers don't have to recalculate bump seeds or + /// pass them in as arguments. + pub bumps: BTreeMap, +} +``` + +The `Context` fields can be accessed in an instruction using dot notation: + +- `ctx.accounts`: The accounts required for the instruction +- `ctx.program_id`: The program's public key (address) +- `ctx.remaining_accounts`: Additional accounts not specified in the `Accounts` + struct. +- `ctx.bumps`: Bump seeds for any + [Program Derived Address (PDA)](/docs/core/pda.md) accounts specified in the + `Accounts` struct + +Additional parameters are optional and can be included to specify arguments that +must be provided when the instruction is invoked. + +```rust filename="lib.rs" /Context/ /data/1 +pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) +} +``` + +In this example, the `Initialize` struct implements the `Accounts` trait where +each field in the struct represents an account required by the `initialize` +instruction. + +```rust filename="lib.rs" /Initialize/ /Accounts/ +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} +``` + +## #[derive(Accounts)] macro + +The +[`#[derive(Accounts)]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/derive/accounts/src/lib.rs#L630) +macro is applied to a struct to specify the accounts that must be provided when +an instruction is invoked. This macro implements the +[`Accounts`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/lib.rs#L105) +trait, which simplifies account validation and serialization and deserialization +of account data. + +```rust /Accounts/ {1} +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} +``` + +Each field in the struct represents an account required by an instruction. The +naming of each field is arbitrary, but it is recommended to use a descriptive +name that indicates the purpose of the account. + +```rust /signer/2 /new_account/ /system_program/ +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} +``` + +### Account Validation + +To prevent security vulnerabilities, it's important to verify that accounts +provided to an instruction are the expected accounts. Accounts are validated in +Anchor programs in two ways that are generally used together: + +- [Account Constraints](https://www.anchor-lang.com/docs/account-constraints): + Constraints define additional conditions that an account must satisfy to be + considered valid for the instruction. Constraints are applied using the + `#[account(..)]` attribute, which is placed above a field in a struct that + implements the `Accounts` trait. + + You can find the implementation of the constraints + [here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/parser/accounts/constraints.rs). + + ```rust {3, 5} + #[derive(Accounts)] + pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, + } + ``` + +- [Account Types](https://www.anchor-lang.com/docs/account-types): Anchor + provides various account types to help ensure that the account provided by the + client matches what the program expects. + + You can find the implementation of the account types + [here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/accounts). + + ```rust /Account/2 /Signer/ /Program/ + #[derive(Accounts)] + pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, + } + ``` + +When an instruction in an Anchor program is invoked, the program first validates +the accounts provided before executing the instruction's logic. After +validation, these accounts can be accessed within the instruction using the +`ctx.accounts` syntax. + +```rust filename="lib.rs" /ctx.accounts.new_account/ /new_account/ /Initialize/ +use anchor_lang::prelude::*; + +declare_id!("11111111111111111111111111111111"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64, +} +``` + +## #[account] macro + +The +[`#[account]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L66) +macro is applied to structs that define the data stored in custom accounts +created by your program. + +```rust +#[account] +pub struct NewAccount { + data: u64, +} +``` + +This macro implements various traits +[detailed here](https://docs.rs/anchor-lang/latest/anchor_lang/attr.account.html). +The key functionalities of the `#[account]` macro include: + +- [Assign Program Owner](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L119-L132): + When creating an account, the program owner of the account is automatically + set to the program specified in `declare_id`. +- [Set Discriminator](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L101-L117): + A unique 8 byte discriminator, specific to the account type, is added as the + first 8 bytes of account data during its initialization. This helps in + differentiating account types and is used for account validation. +- [Data Serialization and Deserialization](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L202-L246): + Account data is automatically serialized and deserialized as the account type. + +```rust filename="lib.rs" /data/2,6 /NewAccount/ {24-27} +use anchor_lang::prelude::*; + +declare_id!("11111111111111111111111111111111"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64, +} +``` + +### Account Discriminator + +An account discriminator in an Anchor program refers to an 8 byte identifier +unique to each account type. It's derived from the first 8 bytes of the SHA256 +hash of the string `account:`. This discriminator is stored as the +first 8 bytes of account data when an account is created. + +When creating an account in an Anchor program, 8 bytes must be allocated for the +discriminator. + +```rust /8/1 +#[account(init, payer = signer, space = 8 + 8)] +pub new_account: Account<'info, NewAccount>, +``` + +The discriminator is used during the following two scenarios: + +- Initialization: When an account is created, the discriminator is set as the + first 8 bytes of the account's data. +- Deserialization: When account data is deserialized, the first 8 bytes of + account data is checked against the discriminator of the expected account + type. + +If there's a mismatch, it indicates that the client has provided an unexpected +account. This mechanism serves as an account validation check in Anchor +programs. diff --git a/docs/uk/programs/deploying.md b/docs/uk/programs/deploying.md new file mode 100644 index 000000000..94d79556c --- /dev/null +++ b/docs/uk/programs/deploying.md @@ -0,0 +1,331 @@ +--- +title: "Deploying Programs" +description: + Deploying onchain programs can be done using the Solana CLI using the + Upgradable BPF loader to upload the compiled byte-code to the Solana + blockchain. +sidebarSortOrder: 2 +--- + +Solana programs are stored in "executable" accounts on the network. These +accounts contain the program's compiled bytecode that define the instructions +users invoke to interact with the program. + +## CLI Commands + +The section is intended as a reference for the basic CLI commands for building +and deploying Solana programs. For a step-by-step guide on creating your first +program, start with [Developing Programs in Rust](/docs/programs/rust). + +### Build Program + +To build your program, use the `cargo build-sbf` command. + +```shell +cargo build-sbf +``` + +This command will: + +1. Compile your program +2. Create a `target/deploy` directory +3. Generate a `.so` file, where `` matches your + program's name in `Cargo.toml` + +The output `.so` file contains your program's compiled bytecode that will be +stored in a Solana account when you deploy your program. + +### Deploy Program + +To deploy your program, use the `solana program deploy` command followed by the +path to the `.so` file created by the `cargo build-sbf` command. + +```shell +solana program deploy ./target/deploy/your_program.so +``` + +During times of congestion, there are a few additional flags you can use to help +with program deployment. + +- `--with-compute-unit-price`: Set compute unit price for transaction, in + increments of 0.000001 lamports (micro-lamports) per compute unit. +- `--max-sign-attempts`: Maximum number of attempts to sign or resign + transactions after blockhash expiration. If any transactions sent during the + program deploy are still unconfirmed after the initially chosen recent + blockhash expires, those transactions will be resigned with a new recent + blockhash and resent. Use this setting to adjust the maximum number of + transaction signing iterations. Each blockhash is valid for about 60 seconds, + which means using the default value of 5 will lead to sending transactions for + at least 5 minutes or until all transactions are confirmed,whichever comes + first. [default: 5] +- `--use-rpc`: Send write transactions to the configured RPC instead of + validator TPUs. This flag requires a stake-weighted RPC connection. + +You can use the flags individually or combine them together. For example: + +```shell +solana program deploy ./target/deploy/your_program.so --with-compute-unit-price 10000 --max-sign-attempts 1000 --use-rpc +``` + +- Use the + [Priority Fee API by Helius](https://docs.helius.dev/guides/priority-fee-api) + to get an estimate of the priority fee to set with the + `--with-compute-unit-price` flag. + +- Get a + [stake-weighted](https://solana.com/developers/guides/advanced/stake-weighted-qos) + RPC connection from [Helius](https://www.helius.dev/) or + [Triton](https://triton.one/) to use with the `--use-rpc` flag. The + `--use-rpc` flag should only be used with a stake-weighted RPC connection. + +To update your default RPC URL with a custom RPC endpoint, use the +`solana config set` command. + +```shell +solana config set --url +``` + +You can view the list of programs you've deployed using the `program show` +subcommand: + +```shell +solana program show --programs +``` + +Example output: + +``` +Program Id | Slot | Authority | Balance +2w3sK6CW7Hy1Ljnz2uqPrQsg4KjNZxD4bDerXDkSX3Q1 | 133132 | 4kh6HxYZiAebF8HWLsUWod2EaQQ6iWHpHYCz8UcmFbM1 | 0.57821592 SOL +``` + +### Update Program + +A program's update authority can modify an existing Solana program by deploying +a new `.so` file to the same program ID. + +To update an existing Solana program: + +- Make changes to your program source code +- Run `cargo build-sbf` to generate an updated `.so` file +- Run `solana program deploy ./target/deploy/your_program.so` to deploy the + updated `.so` file + +The update authority can be changed using the `set-upgrade-authority` subcommand +as follows: + +```shell +solana program set-upgrade-authority --new-upgrade-authority +``` + +### Immutable Program + +A program can be made immutable by removing its update authority. This is an +irreversible action. + +```shell +solana program set-upgrade-authority --final +``` + +You can specify that program should be immutable on deployment by setting the +`--final` flag when deploying the program. + +```shell +solana program deploy ./target/deploy/your_program.so --final +``` + +### Close Program + +You can close your Solana program to reclaim the SOL allocated to the account. +Closing a program is irreversible, so it should be done with caution. To close a +program, use the `program close` subcommand. For example: + +```shell filename="Terminal" +solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz +--bypass-warning +``` + +Example output: + +``` +Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOL +reclaimed +``` + +Note that once a program is closed, its program ID cannot be reused. Attempting +to deploy a program with a previously closed program ID will result in an error. + +``` +Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, use +a new Program Id +``` + +If you need to redeploy a program after closing it, you must generate a new +program ID. To generate a new keypair for the program, run the following +command: + +```shell filename="Terminal" +solana-keygen new -o ./target/deploy/your_program-keypair.json --force +``` + +Alternatively, you can delete the existing keypair file and run +`cargo build-sbf` again, which will generate a new keypair file. + +### Program Buffer Accounts + +Deploying a program requires multiple transactions due to the 1232 byte limit +for transactions on Solana. An intermediate step of the deploy process involves +writing the program's byte-code to temporary "buffer account". + +This buffer account is automatically closed after successful program deployment. +However, if the deployment fails, the buffer account remains and you can either: + +- Continue the deployment using the existing buffer account +- Close the buffer account to reclaim the allocated SOL (rent) + +You can check if you have any open buffer accounts by using the `program show` +subcommand as follows: + +```shell +solana program show --buffers +``` + +Example output: + +``` +Buffer Address | Authority | Balance +5TRm1DxYcXLbSEbbxWcQbEUCce7L4tVgaC6e2V4G82pM | 4kh6HxYZiAebF8HWLsUWod2EaQQ6iWHpHYCz8UcmFbM1 | 0.57821592 SOL +``` + +You can continue to the deployment using the `program deploy` subcommand as +follows: + +```shell +solana program deploy --buffer 5TRm1DxYcXLbSEbbxWcQbEUCce7L4tVgaC6e2V4G82pM +``` + +Expected output on successful deployment: + +``` +Program Id: 2w3sK6CW7Hy1Ljnz2uqPrQsg4KjNZxD4bDerXDkSX3Q1 + +Signature: 3fsttJFskUmvbdL5F9y8g43rgNea5tYZeVXbimfx2Up5viJnYehWe3yx45rQJc8Kjkr6nY8D4DP4V2eiSPqvWRNL +``` + +To close buffer accounts, use the `program close` subcommand as follows: + +```shell +solana program close --buffers +``` + +### ELF Dump + +The SBF shared object internals can be dumped to a text file to gain more +insight into a program's composition and what it may be doing at runtime. The +dump will contain both the ELF information as well as a list of all the symbols +and the instructions that implement them. Some of the BPF loader's error log +messages will reference specific instruction numbers where the error occurred. +These references can be looked up in the ELF dump to identify the offending +instruction and its context. + +```shell +cargo build-bpf --dump +``` + +The file will be output to `/target/deploy/your_program-dump.txt`. + +## Program Deployment Process + +Deploying a program on Solana requires multiple transactions, due to the max +size limit of 1232 bytes for Solana transactions. The Solana CLI sends these +transactions with the `solana program deploy` subcommand. The process can be +broken down into the following 3 phases: + +1. [Buffer initialization](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2113): + First, the CLI sends a transaction which + [creates a buffer account](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1903) + large enough for the byte-code being deployed. It also invokes the + [initialize buffer instruction](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L320) + to set the buffer authority to restrict writes to the deployer's chosen + address. +2. [Buffer writes](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2129): + Once the buffer account is initialized, the CLI + [breaks up the program byte-code](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1940) + into ~1KB chunks and + [sends transactions at a rate of 100 transactions per second](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/client/src/tpu_client.rs#L133) + to write each chunk with + [the write buffer instruction](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L334). + These transactions are sent directly to the current leader's transaction + processing (TPU) port and are processed in parallel with each other. Once all + transactions have been sent, the CLI + [polls the RPC API with batches of transaction signatures](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/client/src/tpu_client.rs#L216) + to ensure that every write was successful and confirmed. +3. [Finalization](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1807): + Once writes are completed, the CLI + [sends a final transaction](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2150) + to either + [deploy a new program](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L362) + or + [upgrade an existing program](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L513). + In either case, the byte-code written to the buffer account will be copied + into a program data account and verified. + +## Upgradeable BPF Loader Program + +The BPF loader program is the program that "owns" all executable accounts on +Solana. When you deploy a program, the owner of the program account is set to +the the BPF loader program. + +### State accounts + +The Upgradeable BPF loader program supports three different types of state +accounts: + +1. [Program account](https://github.com/solana-labs/solana/blob/master/sdk/program/src/bpf_loader_upgradeable.rs#L34): + This is the main account of an on-chain program and its address is commonly + referred to as a "program id." Program id's are what transaction instructions + reference in order to invoke a program. Program accounts are immutable once + deployed, so you can think of them as a proxy account to the byte-code and + state stored in other accounts. +2. [Program data account](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/bpf_loader_upgradeable.rs#L39): + This account is what stores the executable byte-code of an on-chain program. + When a program is upgraded, this account's data is updated with new + byte-code. In addition to byte-code, program data accounts are also + responsible for storing the slot when it was last modified and the address of + the sole account authorized to modify the account (this address can be + cleared to make a program immutable). +3. [Buffer accounts](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/bpf_loader_upgradeable.rs#L27): + These accounts temporarily store byte-code while a program is being actively + deployed through a series of transactions. They also each store the address + of the sole account which is authorized to do writes. + +### Instructions + +The state accounts listed above can only be modified with one of the following +instructions supported by the Upgradeable BPF Loader program: + +1. [Initialize buffer](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L21): + Creates a buffer account and stores an authority address which is allowed to + modify the buffer. +2. [Write](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L28): + Writes byte-code at a specified byte offset inside a buffer account. Writes + are processed in small chunks due to a limitation of Solana transactions + having a maximum serialized size of 1232 bytes. +3. [Deploy](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L77): + Creates both a program account and a program data account. It fills the + program data account by copying the byte-code stored in a buffer account. If + the byte-code is valid, the program account will be set as executable, + allowing it to be invoked. If the byte-code is invalid, the instruction will + fail and all changes are reverted. +4. [Upgrade](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L102): + Fills an existing program data account by copying executable byte-code from a + buffer account. Similar to the deploy instruction, it will only succeed if + the byte-code is valid. +5. [Set authority](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L114): + Updates the authority of a program data or buffer account if the account's + current authority has signed the transaction being processed. If the + authority is deleted without replacement, it can never be set to a new + address and the account can never be closed. +6. [Close](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L127): + Clears the data of a program data account or buffer account and reclaims the + SOL used for the rent exemption deposit. diff --git a/docs/uk/programs/examples.md b/docs/uk/programs/examples.md new file mode 100644 index 000000000..d16eaf27a --- /dev/null +++ b/docs/uk/programs/examples.md @@ -0,0 +1,157 @@ +--- +title: "Program Examples" +description: + "A list of Solana program examples in different languages and frameworks, + which can help you learn and use as reference for your own projects." +tags: + - quickstart + - program + - anchor + - javascript + - native + - rust + - token22 + - token extensions +keywords: + - rust + - cargo + - toml + - program + - tutorial + - intro to solana development + - blockchain developer + - blockchain tutorial + - web3 developer + - anchor +sidebarSortOrder: 3 +--- + +The +[Solana Program Examples](https://github.com/solana-developers/program-examples) +repository on GitHub offers several subfolders, each containing code examples +for different Solana programming paradigms and languages, designed to help +developers learn and experiment with Solana blockchain development. + +You can find the examples in the `solana-developers/program-examples` together +with README files that explain you how to run the different examples. Most +examples are self-contained and are available in native Rust (ie, with no +framework) and [Anchor](https://www.anchor-lang.com/docs/installation). It also +contains a list of examples that we would love to +[see as contributions](https://github.com/solana-developers/program-examples?tab=readme-ov-file#examples-wed-love-to-see). + +Within the repo you will find the following subfolder, each with assorted +example programs within them: + +- [Basics](#basics) +- [Compression](#compression) +- [Oracles](#oracles) +- [Tokens](#tokens) +- [Token 2022 (Token Extensions)](#token-2022-token-extensions) +- [Break](#break) + - [Build and Run](#build-and-run) + +## Basics + +Contains a series of examples that demonstrate the foundational steps for +building Solana programs using native Rust libraries. These examples are +designed to help developers understand the core concepts of Solana programming. + +| Example Name | Description | Language | +| ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------- | +| [Account Data](https://github.com/solana-developers/program-examples/tree/main/basics/account-data) | Saving an address with name, house number, street and city in an account. | Native, Anchor | +| [Checking Accounts](https://github.com/solana-developers/program-examples/tree/main/basics/checking-accounts) | Security lessons that shows how to do account checks | Native, Anchor | +| [Close Account](https://github.com/solana-developers/program-examples/tree/main/basics/close-account) | Show you how to close accounts to get its rent back. | Native, Anchor | +| [Counter](https://github.com/solana-developers/program-examples/tree/main/basics/counter) | A simple counter program in all the different architectures. | Native, Anchor, mpl-stack | +| [Create Account](https://github.com/solana-developers/program-examples/tree/main/basics/create-account) | How to create a system account within a program. | Native, Anchor | +| [Cross Program Invocation](https://github.com/solana-developers/program-examples/tree/main/basics/cross-program-invocation) | Using a hand and lever analogy this shows you how to call another program from within a program. | Native, Anchor | +| [hello solana](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana) | Hello world example which just prints hello world in the transaction logs. | Native, Anchor | +| [Pda Rent payer](https://github.com/solana-developers/program-examples/tree/main/basics/pda-rent-payer) | Shows you how you can use the lamports from a PDA to pay for a new account. | Native, Anchor | +| [Processing Instructions](https://github.com/solana-developers/program-examples/tree/main/basics/processing-instructions) | Shows you how to handle instruction data string and u32. | Native, Anchor | +| [Program Derived Addresses](https://github.com/solana-developers/program-examples/tree/main/basics/program-derived-addresses) | Shows how to use seeds to refer to a PDA and save data in it. | Native, Anchor | +| [Realloc](https://github.com/solana-developers/program-examples/tree/main/basics/realloc) | Shows you how to increase and decrease the size of an existing account. | Native, Anchor | +| [Rent](https://github.com/solana-developers/program-examples/tree/main/basics/rent) | Here you will learn how to calculate rent requirements within a program. | Native, Anchor | +| [Repository Layout](https://github.com/solana-developers/program-examples/tree/main/basics/repository-layout) | Recommendations on how to structure your program layout. | Native, Anchor | +| [Transfer SOL](https://github.com/solana-developers/program-examples/tree/main/basics/transfer-sol) | Different methods of transferring SOL for system accounts and PDAs. | Native, Anchor, Seahorse | + +## Compression + +Contains a series of examples that demonstrate how to use +[state compression](/docs/advanced/state-compression.md) on Solana. Mainly +focused on compressed NFTs (cNFTs). + +| Example Name | Description | Language | +| ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | -------- | +| [cNFT-burn](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-burn) | To destroy a cNFT it can be burnt. This examples shows how to do that in a program. | Anchor | +| [cNFT-Vault](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-vault/anchor) | How to custody a cNFT in a program and send it out again. | Anchor | +| [cutils](https://github.com/solana-developers/program-examples/tree/main/compression/cutils) | A suite utils to for example mint and verify cNFTs in a program. | Anchor | + +## Oracles + +Oracles allow to use off chain data in programs. + +| Example Name | Description | Language | +| ------------------------------------------------------------------------------------ | --------------------------------------------------------------- | -------- | +| [Pyth](https://github.com/solana-developers/program-examples/tree/main/oracles/pyth) | Pyth makes price data of tokens available in on chain programs. | Anchor | + +## Tokens + +Most tokens on Solana use the Solana Program Library (SPL) token standard. Here +you can find many examples on how to mint, transfer, burn tokens and even how to +interact with them in programs. + +| Example Name | Description | Language | +| --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------------- | +| [Create Token](https://github.com/solana-developers/program-examples/tree/main/tokens/create-token) | How to create a token and add metaplex metadata to it. | Anchor, Native | +| [NFT Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/nft-minter) | Minting only one amount of a token and then removing the mint authority. | Anchor, Native | +| [PDA Mint Authority](https://github.com/solana-developers/program-examples/tree/main/tokens/pda-mint-authority) | Shows you how to change the mint authority of a mint, to mint tokens from within a program. | Anchor, Native | +| [SPL Token Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/spl-token-minter) | Explains how to use Associated Token Accounts to be able to keep track of token accounts. | Anchor, Native | +| [Token Swap](https://github.com/solana-developers/program-examples/tree/main/tokens/token-swap) | Extensive example that shows you how to build a AMM (automated market maker) pool for SPL tokens. | Anchor | +| [Transfer Tokens](https://github.com/solana-developers/program-examples/tree/main/tokens/transfer-tokens) | Shows how to transfer SPL token using CPIs into the token program. | Anchor, Native | +| [Token-2022](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022) | See Token 2022 (Token extensions). | Anchor, Native | + +## Token 2022 (Token Extensions) + +Token 2022 is a new standard for tokens on Solana. It is a more flexible and +lets you add 16 different extensions to a token mint to add more functionality +to it. A full list of the extensions can be found in the +[Getting Started Guide](https://solana.com/developers/guides/token-extensions/getting-started) + +| Example Name | Description | Language | +| --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -------- | +| [Basics](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/basics/anchor) | How to create a token, mint and transfer it. | Anchor | +| [Default account state](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/default-account-state/native) | This extension lets you create token accounts with a certain state, for example frozen. | Native | +| [Mint Close Authority](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/mint-close-authority) | With the old token program it was not possible to close a mint. Now it is. | Native | +| [Multiple Extensions](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/multiple-extensions) | Shows you how you can add multiple extensions to a single mint | Native | +| [NFT Metadata pointer](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/nft-meta-data-pointer) | It is possible to use the metadata extension to create NFTs and add dynamic on chain metadata. | Anchor | +| [Not Transferable](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/non-transferable/native) | Useful for example for achievements, referral programs or any soul bound tokens. | Native | +| [Transfer fee](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-fees) | Every transfer of the tokens hold some tokens back in the token account which can then be collected. | Native | +| [Transfer Hook](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-hook) | Four examples to add additional functionality to your token using a CPI from the token program into your program. | Anchor | + +## Break + +[Break](https://break.solana.com/) is a React app that gives users a visceral +feeling for just how fast and high-performance the Solana network really is. Can +you _break_ the Solana blockchain? During a 15 second play-through, each click +of a button or keystroke sends a new transaction to the cluster. Smash the +keyboard as fast as you can and watch your transactions get finalized in +real-time while the network takes it all in stride! + +Break can be played on our Devnet, Testnet and Mainnet Beta networks. Plays are +free on Devnet and Testnet, where the session is funded by a network faucet. On +Mainnet Beta, users pay to play 0.08 SOL per game. The session account can be +funded by a local keystore wallet or by scanning a QR code from Trust Wallet to +transfer the tokens. + +[Click here to play Break](https://break.solana.com/) + +### Build and Run + +First fetch the latest version of the example code: + +```shell +git clone https://github.com/solana-labs/break.git +cd break +``` + +Next, follow the steps in the git repository's +[README](https://github.com/solana-labs/break/blob/main/README.md). diff --git a/docs/uk/programs/faq.md b/docs/uk/programs/faq.md new file mode 100644 index 000000000..c478fa37d --- /dev/null +++ b/docs/uk/programs/faq.md @@ -0,0 +1,194 @@ +--- +title: "FAQ" +sidebarSortOrder: 7 +--- + +Post your questions on +[StackExchange](https://solana.stackexchange.com/questions/ask). + +## Berkeley Packet Filter (BPF) + +Solana onchain programs are compiled via the +[LLVM compiler infrastructure](https://llvm.org/) to an +[Executable and Linkable Format (ELF)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) +containing a variation of the +[Berkeley Packet Filter (BPF)](https://en.wikipedia.org/wiki/Berkeley_Packet_Filter) +bytecode. + +Because Solana uses the LLVM compiler infrastructure, a program may be written +in any programming language that can target the LLVM's BPF backend. + +BPF provides an efficient +[instruction set](https://github.com/iovisor/bpf-docs/blob/master/eBPF.md) that +can be executed in an interpreted virtual machine or as efficient just-in-time +compiled native instructions. + +## Memory map + +The virtual address memory map used by Solana SBF programs is fixed and laid out +as follows + +- Program code starts at 0x100000000 +- Stack data starts at 0x200000000 +- Heap data starts at 0x300000000 +- Program input parameters start at 0x400000000 + +The above virtual addresses are start addresses but programs are given access to +a subset of the memory map. The program will panic if it attempts to read or +write to a virtual address that it was not granted access to, and an +`AccessViolation` error will be returned that contains the address and size of +the attempted violation. + +## InvalidAccountData + +This program error can happen for a lot of reasons. Usually, it's caused by +passing an account to the program that the program is not expecting, either in +the wrong position in the instruction or an account not compatible with the +instruction being executed. + +An implementation of a program might also cause this error when performing a +cross-program instruction and forgetting to provide the account for the program +that you are calling. + +## InvalidInstructionData + +This program error can occur while trying to deserialize the instruction, check +that the structure passed in matches exactly the instruction. There may be some +padding between fields. If the program implements the Rust `Pack` trait then try +packing and unpacking the instruction type `T` to determine the exact encoding +the program expects. + +## MissingRequiredSignature + +Some instructions require the account to be a signer; this error is returned if +an account is expected to be signed but is not. + +An implementation of a program might also cause this error when performing a +[cross-program invocation](/docs/core/cpi.md) that requires a signed program +address, but the passed signer seeds passed to `invoke_signed` don't match the +signer seeds used to create the program address +[`create_program_address`](/docs/core/pda.md#createprogramaddress). + +## Stack + +SBF uses stack frames instead of a variable stack pointer. Each stack frame is +4KB in size. + +If a program violates that stack frame size, the compiler will report the +overrun as a warning. + +For example: + +```text +Error: Function _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E Stack offset of -30728 exceeded max offset of -4096 by 26632 bytes, please minimize large stack variables +``` + +The message identifies which symbol is exceeding its stack frame, but the name +might be mangled. + +> To demangle a Rust symbol use [rustfilt](https://github.com/luser/rustfilt). + +The above warning came from a Rust program, so the demangled symbol name is: + +```shell +rustfilt _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E +curve25519_dalek::edwards::EdwardsBasepointTable::create +``` + +The reason a warning is reported rather than an error is because some dependent +crates may include functionality that violates the stack frame restrictions even +if the program doesn't use that functionality. If the program violates the stack +size at runtime, an `AccessViolation` error will be reported. + +SBF stack frames occupy a virtual address range starting at `0x200000000`. + +## Heap size + +Programs have access to a runtime heap via the Rust `alloc` APIs. To facilitate +fast allocations, a simple 32KB bump heap is utilized. The heap does not support +`free` or `realloc`. + +Internally, programs have access to the 32KB memory region starting at virtual +address 0x300000000 and may implement a custom heap based on the program's +specific needs. + +Rust programs implement the heap directly by defining a custom +[`global_allocator`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/entrypoint.rs#L72) + +## Loaders + +Programs are deployed with and executed by runtime loaders, currently there are +two supported loaders +[BPF Loader](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader.rs#L17) +and +[BPF loader deprecated](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader_deprecated.rs#L14) + +Loaders may support different application binary interfaces so developers must +write their programs for and deploy them to the same loader. If a program +written for one loader is deployed to a different one the result is usually a +`AccessViolation` error due to mismatched deserialization of the program's input +parameters. + +For all practical purposes program should always be written to target the latest +BPF loader and the latest loader is the default for the command-line interface +and the javascript APIs. + +- [Rust program entrypoints](/docs/programs/lang-rust.md#program-entrypoint) + +### Deployment + +SBF program deployment is the process of uploading a BPF shared object into a +program account's data and marking the account executable. A client breaks the +SBF shared object into smaller pieces and sends them as the instruction data of +[`Write`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/loader_instruction.rs#L13) +instructions to the loader where loader writes that data into the program's +account data. Once all the pieces are received the client sends a +[`Finalize`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/loader_instruction.rs#L30) +instruction to the loader, the loader then validates that the SBF data is valid +and marks the program account as _executable_. Once the program account is +marked executable, subsequent transactions may issue instructions for that +program to process. + +When an instruction is directed at an executable SBF program the loader +configures the program's execution environment, serializes the program's input +parameters, calls the program's entrypoint, and reports any errors encountered. + +For further information, see [deploying programs](/docs/programs/deploying.md). + +### Input Parameter Serialization + +SBF loaders serialize the program input parameters into a byte array that is +then passed to the program's entrypoint, where the program is responsible for +deserializing it on-chain. One of the changes between the deprecated loader and +the current loader is that the input parameters are serialized in a way that +results in various parameters falling on aligned offsets within the aligned byte +array. This allows deserialization implementations to directly reference the +byte array and provide aligned pointers to the program. + +- [Rust program parameter deserialization](/docs/programs/lang-rust.md#parameter-deserialization) + +The latest loader serializes the program input parameters as follows (all +encoding is little endian): + +- 8 bytes unsigned number of accounts +- For each account + - 1 byte indicating if this is a duplicate account, if not a duplicate then + the value is 0xff, otherwise the value is the index of the account it is a + duplicate of. + - If duplicate: 7 bytes of padding + - If not duplicate: + - 1 byte boolean, true if account is a signer + - 1 byte boolean, true if account is writable + - 1 byte boolean, true if account is executable + - 4 bytes of padding + - 32 bytes of the account public key + - 32 bytes of the account's owner public key + - 8 bytes unsigned number of lamports owned by the account + - 8 bytes unsigned number of bytes of account data + - x bytes of account data + - 10k bytes of padding, used for realloc + - enough padding to align the offset to 8 bytes. + - 8 bytes rent epoch +- 8 bytes of unsigned number of instruction data +- x bytes of instruction data +- 32 bytes of the program id diff --git a/docs/uk/programs/index.md b/docs/uk/programs/index.md new file mode 100644 index 000000000..4189752bd --- /dev/null +++ b/docs/uk/programs/index.md @@ -0,0 +1,5 @@ +--- +title: Developing Programs +sidebarSortOrder: 2 +metaOnly: true +--- diff --git a/docs/uk/programs/limitations.md b/docs/uk/programs/limitations.md new file mode 100644 index 000000000..1ec59ccc3 --- /dev/null +++ b/docs/uk/programs/limitations.md @@ -0,0 +1,112 @@ +--- +title: "Limitations" +sidebarSortOrder: 6 +--- + +Developing programs on the Solana blockchain have some inherent limitation +associated with them. Below is a list of common limitation that you may run +into. + +## Rust libraries + +Since Rust based onchain programs must run be deterministic while running in a +resource-constrained, single-threaded environment, they have some limitations on +various libraries. + +On-chain Rust programs support most of Rust's libstd, libcore, and liballoc, as +well as many 3rd party crates. + +There are some limitations since these programs run in a resource-constrained, +single-threaded environment, as well as being deterministic: + +- No access to + - `rand` + - `std::fs` + - `std::net` + - `std::future` + - `std::process` + - `std::sync` + - `std::task` + - `std::thread` + - `std::time` +- Limited access to: + - `std::hash` + - `std::os` +- Bincode is extremely computationally expensive in both cycles and call depth + and should be avoided +- String formatting should be avoided since it is also computationally + expensive. +- No support for `println!`, `print!`, use the + [`msg!`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/log.rs#L33) + macro instead. +- The runtime enforces a limit on the number of instructions a program can + execute during the processing of one instruction. See + [computation budget](/docs/core/fees.md#compute-budget) for more information. + +## Compute budget + +To prevent abuse of the blockchain's computational resources, each transaction +is allocated a [compute budget](/docs/terminology.md#compute-budget). Exceeding +this compute budget will result in the transaction failing. + +See the [computational constraints](/docs/core/fees.md#compute-budget) +documentation for more specific details. + +## Call stack depth - `CallDepthExceeded` error + +Solana programs are constrained to run quickly, and to facilitate this, the +program's call stack is limited to a max depth of **64 frames**. + +When a program exceeds the allowed call stack depth limit, it will receive the +`CallDepthExceeded` error. + +## CPI call depth - `CallDepth` error + +Cross-program invocations allow programs to invoke other programs directly, but +the depth is constrained currently to `4`. + +When a program exceeds the allowed +[cross-program invocation call depth](/docs/core/cpi.md), it will receive a +`CallDepth` error + +## Float Rust types support + +Programs support a limited subset of Rust's float operations. If a program +attempts to use a float operation that is not supported, the runtime will report +an unresolved symbol error. + +Float operations are performed via software libraries, specifically LLVM's float +built-ins. Due to the software emulated, they consume more compute units than +integer operations. In general, fixed point operations are recommended where +possible. + +The +[Solana Program Library math](https://github.com/solana-labs/solana-program-library/tree/master/libraries/math) +tests will report the performance of some math operations. To run the test, sync +the repo and run: + +```shell +cargo test-sbf -- --nocapture --test-threads=1 +``` + +Recent results show the float operations take more instructions compared to +integers equivalents. Fixed point implementations may vary but will also be less +than the float equivalents: + +```text + u64 f32 +Multiply 8 176 +Divide 9 219 +``` + +## Static writable data + +Program shared objects do not support writable shared data. Programs are shared +between multiple parallel executions using the same shared read-only code and +data. This means that developers should not include any static writable or +global variables in programs. In the future a copy-on-write mechanism could be +added to support writable data. + +## Signed division + +The SBF instruction set does not support signed division. diff --git a/docs/uk/programs/rust/index.md b/docs/uk/programs/rust/index.md new file mode 100644 index 000000000..7fe456337 --- /dev/null +++ b/docs/uk/programs/rust/index.md @@ -0,0 +1,474 @@ +--- +title: Developing Programs in Rust +description: + Learn how to develop Solana programs using Rust, including step-by-step + instructions for creating, building, testing, and deploying smart contracts on + the Solana blockchain. +sidebarLabel: Rust Programs +sidebarSortOrder: 1 +altRoutes: + - /docs/programs/lang-rust +--- + +Solana programs are primarily developed using the Rust programming language. +This page focuses on writing Solana programs in Rust without using the Anchor +framework, an approach often referred to as writing "native Rust" programs. + +Native Rust development provides developers with direct control over their +Solana programs. However, this approach requires more manual setup and +boilerplate code compared to using the Anchor framework. This method is +recommended for developers who: + +- Seek granular control over program logic and optimizations +- Want to learn the underlying concepts before moving to higher-level frameworks + +For beginners, we recommend starting with the Anchor framework. See the +[Anchor](/docs/programs/anchor) section for more information. + +## Prerequisites + +For detailed installation instructions, visit the +[installation](/docs/intro/installation) page. + +Before you begin, ensure you have the following installed: + +- Rust: The programming language for building Solana programs. +- Solana CLI: Command-line tool for Solana development. + +## Getting Started + +The example below covers the basic steps to create your first Solana program +written in Rust. We'll create a minimal program that prints "Hello, world!" to +the program log. + + + +### Create a new Program + +First, create a new Rust project using the standard `cargo init` command with +the `--lib` flag. + +```shell filename="Terminal" +cargo init hello_world --lib +``` + +Navigate to the project directory. You should see the default `src/lib.rs` and +`Cargo.toml` files + +```shell filename="Terminal" +cd hello_world +``` + +Next, add the `solana-program` dependency. This is the minimum dependency +required to build a Solana program. + +```shell filename="Terminal" +cargo add solana-program@1.18.26 +``` + +Next, add the following snippet to `Cargo.toml`. If you don't include this +config, the `target/deploy` directory will not be generated when you build the +program. + +```toml filename="Cargo.toml" +[lib] +crate-type = ["cdylib", "lib"] +``` + +Your `Cargo.toml` file should look like the following: + +```toml filename="Cargo.toml" +[package] +name = "hello_world" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] + +[dependencies] +solana-program = "1.18.26" +``` + +Next, replace the contents of `src/lib.rs` with the following code. This is a +minimal Solana program that prints "Hello, world!" to the program log when the +program is invoked. + +The `msg!` macro is used in Solana programs to print a message to the program +log. + +```rs filename="lib.rs" +use solana_program::{ + account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey, +}; + +entrypoint!(process_instruction); + +pub fn process_instruction( + _program_id: &Pubkey, + _accounts: &[AccountInfo], + _instruction_data: &[u8], +) -> ProgramResult { + msg!("Hello, world!"); + Ok(()) +} +``` + +### Build the Program + +Next, build the program using the `cargo build-sbf` command. + +```shell filename="Terminal" +cargo build-sbf +``` + +This command generates a `target/deploy` directory containing two important +files: + +1. A `.so` file (e.g., `hello_world.so`): This is the compiled Solana program + that will be deployed to the network as a "smart contract". +2. A keypair file (e.g., `hello_world-keypair.json`): The public key of this + keypair is used as the program ID when deploying the program. + +To view the program ID, run the following command in your terminal. This command +prints the public key of the keypair at the specified file path: + +```shell filename="Terminal" +solana address -k ./target/deploy/hello_world-keypair.json +``` + +Example output: + +``` +4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz +``` + +### Test the Program + +Next, test the program using the `solana-program-test` crate. Add the following +dependencies to `Cargo.toml`. + +```shell filename="Terminal" +cargo add solana-program-test@1.18.26 --dev +cargo add solana-sdk@1.18.26 --dev +cargo add tokio --dev +``` + +Add the following test to `src/lib.rs`, below the program code. This is a test +module that invokes the hello world program. + +```rs filename="lib.rs" +#[cfg(test)] +mod test { + use super::*; + use solana_program_test::*; + use solana_sdk::{signature::Signer, transaction::Transaction}; + + #[tokio::test] + async fn test_hello_world() { + let program_id = Pubkey::new_unique(); + let (mut banks_client, payer, recent_blockhash) = + ProgramTest::new("hello_world", program_id, processor!(process_instruction)) + .start() + .await; + + // Create the instruction to invoke the program + let instruction = + solana_program::instruction::Instruction::new_with_borsh(program_id, &(), vec![]); + + // Add the instruction to a new transaction + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer], recent_blockhash); + + // Process the transaction + let transaction_result = banks_client.process_transaction(transaction).await; + assert!(transaction_result.is_ok()); + } +} +``` + +Run the test using the `cargo test-sbf` command. The program log will display +"Hello, world!". + +```shell filename="Terminal" +cargo test-sbf +``` + +Example output: + +```shell filename="Terminal" {4} /Program log: Hello, world!/ +running 1 test +[2024-10-18T21:24:54.889570000Z INFO solana_program_test] "hello_world" SBF program from /hello_world/target/deploy/hello_world.so, modified 35 seconds, 828 ms, 268 µs and 398 ns ago +[2024-10-18T21:24:54.974294000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM invoke [1] +[2024-10-18T21:24:54.974814000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, world! +[2024-10-18T21:24:54.976848000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM consumed 140 of 200000 compute units +[2024-10-18T21:24:54.976868000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM success +test test::test_hello_world ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.13s +``` + +### Deploy the Program + +Next, deploy the program. When developing locally, we can use the +`solana-test-validator`. + +First, configure the Solana CLI to use the local Solana cluster. + +```shell filename="Terminal" +solana config set -ul +``` + +Example output: + +``` +Config File: /.config/solana/cli/config.yml +RPC URL: http://localhost:8899 +WebSocket URL: ws://localhost:8900/ (computed) +Keypair Path: /.config/solana/id.json +Commitment: confirmed +``` + +Open a new terminal and run the `solana-test-validators` command to start the +local validator. + +```shell filename="Terminal" +solana-test-validator +``` + +While the test validator is running, run the `solana program deploy` command in +a separate terminal to deploy the program to the local validator. + +```shell filename="Terminal" +solana program deploy ./target/deploy/hello_world.so +``` + +Example output: + +``` +Program Id: 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz +Signature: +5osMiNMiDZGM7L1e2tPHxU8wdB8gwG8fDnXLg5G7SbhwFz4dHshYgAijk4wSQL5cXiu8z1MMou5kLadAQuHp7ybH +``` + +You can inspect the program ID and transaction signature on +[Solana Explorer](https://explorer.solana.com/?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899). +Note that the cluster on Solana Explorer must also be localhost. The "Custom RPC +URL" option on Solana Explorer defaults to `http://localhost:8899`. + +### Invoke the Program + +Next, we'll demonstrate how to invoke the program using a Rust client. + +First create an `examples` directory and a `client.rs` file. + +```shell filename="Terminal" +mkdir -p examples +touch examples/client.rs +``` + +Add the following to `Cargo.toml`. + +```toml filename="Cargo.toml" +[[example]] +name = "client" +path = "examples/client.rs" +``` + +Add the `solana-client` dependency. + +```shell filename="Terminal" +cargo add solana-client@1.18.26 --dev +``` + +Add the following code to `examples/client.rs`. This is a Rust client script +that funds a new keypair to pay for transaction fees and then invokes the hello +world program. + +```rs filename="example/client.rs" +use solana_client::rpc_client::RpcClient; +use solana_sdk::{ + commitment_config::CommitmentConfig, + instruction::Instruction, + pubkey::Pubkey, + signature::{Keypair, Signer}, + transaction::Transaction, +}; +use std::str::FromStr; + +#[tokio::main] +async fn main() { + // Program ID (replace with your actual program ID) + let program_id = Pubkey::from_str("4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz").unwrap(); + + // Connect to the Solana devnet + let rpc_url = String::from("http://127.0.0.1:8899"); + let client = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed()); + + // Generate a new keypair for the payer + let payer = Keypair::new(); + + // Request airdrop + let airdrop_amount = 1_000_000_000; // 1 SOL + let signature = client + .request_airdrop(&payer.pubkey(), airdrop_amount) + .expect("Failed to request airdrop"); + + // Wait for airdrop confirmation + loop { + let confirmed = client.confirm_transaction(&signature).unwrap(); + if confirmed { + break; + } + } + + // Create the instruction + let instruction = Instruction::new_with_borsh( + program_id, + &(), // Empty instruction data + vec![], // No accounts needed + ); + + // Add the instruction to new transaction + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer], client.get_latest_blockhash().unwrap()); + + // Send and confirm the transaction + match client.send_and_confirm_transaction(&transaction) { + Ok(signature) => println!("Transaction Signature: {}", signature), + Err(err) => eprintln!("Error sending transaction: {}", err), + } +} +``` + +Before running the script, replace the program ID in the code snippet above with +the one for your program. + +You can get your program ID by running the following command. + +```shell filename="Terminal" +solana address -k ./target/deploy/hello_world-keypair.json +``` + +```diff +#[tokio::main] +async fn main() { +- let program_id = Pubkey::from_str("4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz").unwrap(); ++ let program_id = Pubkey::from_str("YOUR_PROGRAM_ID).unwrap(); + } +} +``` + +Run the client script with the following command. + +```shell filename="Terminal" +cargo run --example client +``` + +Example output: + +``` +Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77bAACjKAS9fGnVeEazrXL4SfKrW7xZFYV +``` + +You can inspect the transaction signature on +[Solana Explorer](https://explorer.solana.com/?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899) +(local cluster) to see "Hello, world!" in the program log. + +### Update the Program + +Solana programs can be updated by redeploying to the same program ID. Update the +program in `src/lib.rs` to print "Hello, Solana!" instead of "Hello, world!". + +```diff filename="lib.rs" +pub fn process_instruction( + _program_id: &Pubkey, + _accounts: &[AccountInfo], + _instruction_data: &[u8], +) -> ProgramResult { +- msg!("Hello, world!"); ++ msg!("Hello, Solana!"); + Ok(()) +} +``` + +Test the updated program by running the `cargo test-sbf` command. + +```shell filename="Terminal" +cargo test-sbf +``` + +You should see "Hello, Solana!" in the program log. + +```shell filename="Terminal" {4} +running 1 test +[2024-10-23T19:28:28.842639000Z INFO solana_program_test] "hello_world" SBF program from /code/misc/delete/hello_world/target/deploy/hello_world.so, modified 4 minutes, 31 seconds, 435 ms, 566 µs and 766 ns ago +[2024-10-23T19:28:28.934854000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM invoke [1] +[2024-10-23T19:28:28.936735000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, Solana! +[2024-10-23T19:28:28.938774000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM consumed 140 of 200000 compute units +[2024-10-23T19:28:28.938793000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM success +test test::test_hello_world ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.14s +``` + +Run the `cargo build-sbf` command to generate an updated `.so` file. + +```shell filename="Terminal" +cargo build-sbf +``` + +Redeploy the program using the `solana program deploy` command. + +```shell filename="Terminal" +solana program deploy ./target/deploy/hello_world.so +``` + +Run the client code again and inspect the transaction signature on Solana +Explorer to see "Hello, Solana!" in the program log. + +```shell filename="Terminal" +cargo run --example client +``` + +### Close the Program + +You can close your Solana program to reclaim the SOL allocated to the account. +Closing a program is irreversible, so it should be done with caution. + +To close a program, use the `solana program close ` command. For +example: + +```shell filename="Terminal" +solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz +--bypass-warning +``` + +Example output: + +``` +Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOL +reclaimed +``` + +Note that once a program is closed, its program ID cannot be reused. Attempting +to deploy a program with a previously closed program ID will result in an error. + +``` +Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, use +a new Program Id +``` + +If you need to redeploy a program with the same source code after closing a +program, you must generate a new program ID. To generate a new keypair for the +program, run the following command: + +```shell filename="Terminal" +solana-keygen new -o ./target/deploy/hello_world-keypair.json --force +``` + +Alternatively, you can delete the existing keypair file (e.g. +`./target/deploy/hello_world-keypair.json`) and run `cargo build-sbf` again, +which will generate a new keypair file. + + diff --git a/docs/uk/programs/rust/program-structure.md b/docs/uk/programs/rust/program-structure.md new file mode 100644 index 000000000..5a46ce82d --- /dev/null +++ b/docs/uk/programs/rust/program-structure.md @@ -0,0 +1,1407 @@ +--- +title: Rust Program Structure +sidebarLabel: Program Structure +description: + Learn how to structure Solana programs in Rust, including entrypoints, state + management, instruction handling, and testing. +sidebarSortOrder: 1 +--- + +Solana programs written in Rust have minimal structural requirements, allowing +for flexibility in how code is organized. The only requirement is that a program +must have an `entrypoint`, which defines where the execution of a program +begins. + +## Program Structure + +While there are no strict rules for file structure, Solana programs typically +follow a common pattern: + +- `entrypoint.rs`: Defines the entrypoint that routes incoming instructions. +- `state.rs`: Define program-specific state (account data). +- `instructions.rs`: Defines the instructions that the program can execute. +- `processor.rs`: Defines the instruction handlers (functions) that implement + the business logic for each instruction. +- `error.rs`: Defines custom errors that the program can return. + +You can find examples in the +[Solana Program Library](https://github.com/solana-labs/solana-program-library/tree/master/token/program/src). + +## Example Program + +To demonstrate how to build a native Rust program with multiple instructions, +we'll walk through a simple counter program that implements two instructions: + +1. `InitializeCounter`: Creates and initializes a new account with an initial + value. +2. `IncrementCounter`: Increments the value stored in an existing account. + +For simplicity, the program will be implemented in a single `lib.rs` file, +though in practice you may want to split larger programs into multiple files. + + + + +```rs filename="lib.rs" +use borsh::{BorshDeserialize, BorshSerialize}; +use solana_program::{ + account_info::{next_account_info, AccountInfo}, + entrypoint, + entrypoint::ProgramResult, + msg, + program::invoke, + program_error::ProgramError, + pubkey::Pubkey, + system_instruction, + sysvar::{rent::Rent, Sysvar}, +}; + +// Program entrypoint +entrypoint!(process_instruction); + +// Function to route instructions to the correct handler +pub fn process_instruction( + program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> ProgramResult { + // Unpack instruction data + let instruction = CounterInstruction::unpack(instruction_data)?; + + // Match instruction type + match instruction { + CounterInstruction::InitializeCounter { initial_value } => { + process_initialize_counter(program_id, accounts, initial_value)? + } + CounterInstruction::IncrementCounter => process_increment_counter(program_id, accounts)?, + }; + Ok(()) +} + +// Instructions that our program can execute +#[derive(BorshSerialize, BorshDeserialize, Debug)] +pub enum CounterInstruction { + InitializeCounter { initial_value: u64 }, // variant 0 + IncrementCounter, // variant 1 +} + +impl CounterInstruction { + pub fn unpack(input: &[u8]) -> Result { + // Get the instruction variant from the first byte + let (&variant, rest) = input + .split_first() + .ok_or(ProgramError::InvalidInstructionData)?; + + // Match instruction type and parse the remaining bytes based on the variant + match variant { + 0 => { + // For InitializeCounter, parse a u64 from the remaining bytes + let initial_value = u64::from_le_bytes( + rest.try_into() + .map_err(|_| ProgramError::InvalidInstructionData)?, + ); + Ok(Self::InitializeCounter { initial_value }) + } + 1 => Ok(Self::IncrementCounter), // No additional data needed + _ => Err(ProgramError::InvalidInstructionData), + } + } +} + +// Initialize a new counter account +fn process_initialize_counter( + program_id: &Pubkey, + accounts: &[AccountInfo], + initial_value: u64, +) -> ProgramResult { + let accounts_iter = &mut accounts.iter(); + + let counter_account = next_account_info(accounts_iter)?; + let payer_account = next_account_info(accounts_iter)?; + let system_program = next_account_info(accounts_iter)?; + + // Size of our counter account + let account_space = 8; // Size in bytes to store a u64 + + // Calculate minimum balance for rent exemption + let rent = Rent::get()?; + let required_lamports = rent.minimum_balance(account_space); + + // Create the counter account + invoke( + &system_instruction::create_account( + payer_account.key, // Account paying for the new account + counter_account.key, // Account to be created + required_lamports, // Amount of lamports to transfer to the new account + account_space as u64, // Size in bytes to allocate for the data field + program_id, // Set program owner to our program + ), + &[ + payer_account.clone(), + counter_account.clone(), + system_program.clone(), + ], + )?; + + // Create a new CounterAccount struct with the initial value + let counter_data = CounterAccount { + count: initial_value, + }; + + // Get a mutable reference to the counter account's data + let mut account_data = &mut counter_account.data.borrow_mut()[..]; + + // Serialize the CounterAccount struct into the account's data + counter_data.serialize(&mut account_data)?; + + msg!("Counter initialized with value: {}", initial_value); + + Ok(()) +} + +// Update an existing counter's value +fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult { + let accounts_iter = &mut accounts.iter(); + let counter_account = next_account_info(accounts_iter)?; + + // Verify account ownership + if counter_account.owner != program_id { + return Err(ProgramError::IncorrectProgramId); + } + + // Mutable borrow the account data + let mut data = counter_account.data.borrow_mut(); + + // Deserialize the account data into our CounterAccount struct + let mut counter_data: CounterAccount = CounterAccount::try_from_slice(&data)?; + + // Increment the counter value + counter_data.count = counter_data + .count + .checked_add(1) + .ok_or(ProgramError::InvalidAccountData)?; + + // Serialize the updated counter data back into the account + counter_data.serialize(&mut &mut data[..])?; + + msg!("Counter incremented to: {}", counter_data.count); + Ok(()) +} + +// Struct representing our counter account's data +#[derive(BorshSerialize, BorshDeserialize, Debug)] +pub struct CounterAccount { + count: u64, +} + +#[cfg(test)] +mod test { + use super::*; + use solana_program_test::*; + use solana_sdk::{ + instruction::{AccountMeta, Instruction}, + signature::{Keypair, Signer}, + system_program, + transaction::Transaction, + }; + + #[tokio::test] + async fn test_counter_program() { + let program_id = Pubkey::new_unique(); + let (mut banks_client, payer, recent_blockhash) = ProgramTest::new( + "counter_program", + program_id, + processor!(process_instruction), + ) + .start() + .await; + + // Create a new keypair to use as the address for our counter account + let counter_keypair = Keypair::new(); + let initial_value: u64 = 42; + + // Step 1: Initialize the counter + println!("Testing counter initialization..."); + + // Create initialization instruction + let mut init_instruction_data = vec![0]; // 0 = initialize instruction + init_instruction_data.extend_from_slice(&initial_value.to_le_bytes()); + + let initialize_instruction = Instruction::new_with_bytes( + program_id, + &init_instruction_data, + vec![ + AccountMeta::new(counter_keypair.pubkey(), true), + AccountMeta::new(payer.pubkey(), true), + AccountMeta::new_readonly(system_program::id(), false), + ], + ); + + // Send transaction with initialize instruction + let mut transaction = + Transaction::new_with_payer(&[initialize_instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer, &counter_keypair], recent_blockhash); + banks_client.process_transaction(transaction).await.unwrap(); + + // Check account data + let account = banks_client + .get_account(counter_keypair.pubkey()) + .await + .expect("Failed to get counter account"); + + if let Some(account_data) = account { + let counter: CounterAccount = CounterAccount::try_from_slice(&account_data.data) + .expect("Failed to deserialize counter data"); + assert_eq!(counter.count, 42); + println!( + "✅ Counter initialized successfully with value: {}", + counter.count + ); + } + + // Step 2: Increment the counter + println!("Testing counter increment..."); + + // Create increment instruction + let increment_instruction = Instruction::new_with_bytes( + program_id, + &[1], // 1 = increment instruction + vec![AccountMeta::new(counter_keypair.pubkey(), true)], + ); + + // Send transaction with increment instruction + let mut transaction = + Transaction::new_with_payer(&[increment_instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer, &counter_keypair], recent_blockhash); + banks_client.process_transaction(transaction).await.unwrap(); + + // Check account data + let account = banks_client + .get_account(counter_keypair.pubkey()) + .await + .expect("Failed to get counter account"); + + if let Some(account_data) = account { + let counter: CounterAccount = CounterAccount::try_from_slice(&account_data.data) + .expect("Failed to deserialize counter data"); + assert_eq!(counter.count, 43); + println!("✅ Counter incremented successfully to: {}", counter.count); + } + } +} +``` + +```toml filename="Cargo.toml" +[package] +name = "counter_program" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] + +[dependencies] +borsh = "1.5.1" +solana-program = "1.18.26" + +[dev-dependencies] +solana-program-test = "1.18.26" +solana-sdk = "1.18.26" +tokio = "1.41.0" +``` + + + + + + +### Create a new Program + +First, create a new Rust project using the standard `cargo init` command with +the `--lib` flag. + +```shell filename="Terminal" +cargo init counter_program --lib +``` + +Navigate to the project directory. You should see the default `src/lib.rs` and +`Cargo.toml` files + +```shell filename="Terminal" +cd counter_program +``` + +Next, add the `solana-program` dependency. This is the minimum dependency +required to build a Solana program. + +```shell filename="Terminal" +cargo add solana-program@1.18.26 +``` + +Next, add the following snippet to `Cargo.toml`. If you don't include this +config, the `target/deploy` directory will not be generated when you build the +program. + +```toml filename="Cargo.toml" +[lib] +crate-type = ["cdylib", "lib"] +``` + +Your `Cargo.toml` file should look like the following: + +```toml filename="Cargo.toml" +[package] +name = "counter_program" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] + +[dependencies] +solana-program = "1.18.26" +``` + +### Program Entrypoint + +A Solana program entrypoint is the function that gets called when a program is +invoked. The entrypoint has the following raw definition and developers are free +to create their own implementation of the entrypoint function. + +For simplicity, use the +[`entrypoint!`](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L124-L140) +macro from the `solana_program` crate to define the entrypoint in your program. + +```rs +#[no_mangle] +pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64; +``` + +Replace the default code in `lib.rs` with the following code. This snippet: + +1. Imports the required dependencies from `solana_program` +2. Defines the program entrypoint using the `entrypoint!` macro +3. Implements the `process_instruction` function that will route instructions to + the appropriate handler functions + +```rs filename="lib.rs" {13} /process_instruction/ +use solana_program::{ + account_info::{next_account_info, AccountInfo}, + entrypoint, + entrypoint::ProgramResult, + msg, + program::invoke, + program_error::ProgramError, + pubkey::Pubkey, + system_instruction, + sysvar::{rent::Rent, Sysvar}, +}; + +entrypoint!(process_instruction); + +pub fn process_instruction( + program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> ProgramResult { + // Your program logic + Ok(()) +} +``` + +The `entrypoint!` macro requires a function with the the following +[type signature](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L28-L29) +as an argument: + +```rs +pub type ProcessInstruction = + fn(program_id: &Pubkey, accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult; +``` + +When a Solana program is invoked, the entrypoint +[deserializes](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L277) +the +[input data](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L129-L131) +(provided as bytes) into three values and passes them to the +[`process_instruction`](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L132) +function: + +- `program_id`: The public key of the program being invoked (current program) +- `accounts`: The `AccountInfo` for accounts required by the instruction being + invoked +- `instruction_data`: Additional data passed to the program which specifies the + instruction to execute and its required arguments + +These three parameters directly correspond to the data that clients must provide +when building an instruction to invoke a program. + +### Define Program State + +When building a Solana program, you'll typically start by defining your +program's state - the data that will be stored in accounts created and owned by +your program. + +Program state is defined using Rust structs that represent the data layout of +your program's accounts. You can define multiple structs to represent different +types of accounts for your program. + +When working with accounts, you need a way to convert your program's data types +to and from the raw bytes stored in an account's data field: + +- Serialization: Converting your data types into bytes to store in an account's + data field +- Deserialization: Converting the bytes stored in an account back into your data + types + +While you can use any serialization format for Solana program development, +[Borsh](https://borsh.io/) is commonly used. To use Borsh in your Solana +program: + +1. Add the `borsh` crate as a dependency to your `Cargo.toml`: + +```shell filename="Terminal" +cargo add borsh +``` + +2. Import the Borsh traits and use the derive macro to implement the traits for + your structs: + +```rust +use borsh::{BorshSerialize, BorshDeserialize}; + +// Define struct representing our counter account's data +#[derive(BorshSerialize, BorshDeserialize, Debug)] +pub struct CounterAccount { + count: u64, +} +``` + +Add the `CounterAccount` struct to `lib.rs` to define the program state. This +struct will be used in both the initialization and increment instructions. + +```rs filename="lib.rs" {12} {25-29} +use solana_program::{ + account_info::{next_account_info, AccountInfo}, + entrypoint, + entrypoint::ProgramResult, + msg, + program::invoke, + program_error::ProgramError, + pubkey::Pubkey, + system_instruction, + sysvar::{rent::Rent, Sysvar}, +}; +use borsh::{BorshSerialize, BorshDeserialize}; + +entrypoint!(process_instruction); + +pub fn process_instruction( + program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> ProgramResult { + // Your program logic + Ok(()) +} + +#[derive(BorshSerialize, BorshDeserialize, Debug)] +pub struct CounterAccount { + count: u64, +} +``` + +### Define Instructions + +Instructions refer to the different operations that your Solana program can +perform. Think of them as public APIs for your program - they define what +actions users can take when interacting with your program. + +Instructions are typically defined using a Rust enum where: + +- Each enum variant represents a different instruction +- The variant's payload represents the instruction's parameters + +Note that Rust enum variants are implicitly numbered starting from 0. + +Below is an example of an enum defining two instructions: + +```rust +#[derive(BorshSerialize, BorshDeserialize, Debug)] +pub enum CounterInstruction { + InitializeCounter { initial_value: u64 }, // variant 0 + IncrementCounter, // variant 1 +} +``` + +When a client invokes your program, they must provide instruction data (as a +buffer of bytes) where: + +- The first byte identifies which instruction variant to execute (0, 1, etc.) +- The remaining bytes contain the serialized instruction parameters (if + required) + +To convert the instruction data (bytes) into a variant of the enum, it is common +to implement a helper method. This method: + +1. Splits the first byte to get the instruction variant +2. Matches on the variant and parses any additional parameters from the + remaining bytes +3. Returns the corresponding enum variant + +For example, the `unpack` method for the `CounterInstruction` enum: + +```rust +impl CounterInstruction { + pub fn unpack(input: &[u8]) -> Result { + // Get the instruction variant from the first byte + let (&variant, rest) = input + .split_first() + .ok_or(ProgramError::InvalidInstructionData)?; + + // Match instruction type and parse the remaining bytes based on the variant + match variant { + 0 => { + // For InitializeCounter, parse a u64 from the remaining bytes + let initial_value = u64::from_le_bytes( + rest.try_into() + .map_err(|_| ProgramError::InvalidInstructionData)? + ); + Ok(Self::InitializeCounter { initial_value }) + } + 1 => Ok(Self::IncrementCounter), // No additional data needed + _ => Err(ProgramError::InvalidInstructionData), + } + } +} +``` + +Add the following code to `lib.rs` to define the instructions for the counter +program. + +```rs filename="lib.rs" {18-46} +use borsh::{BorshDeserialize, BorshSerialize}; +use solana_program::{ + account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, + program_error::ProgramError, pubkey::Pubkey, +}; + +entrypoint!(process_instruction); + +pub fn process_instruction( + program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> ProgramResult { + // Your program logic + Ok(()) +} + +#[derive(BorshSerialize, BorshDeserialize, Debug)] +pub enum CounterInstruction { + InitializeCounter { initial_value: u64 }, // variant 0 + IncrementCounter, // variant 1 +} + +impl CounterInstruction { + pub fn unpack(input: &[u8]) -> Result { + // Get the instruction variant from the first byte + let (&variant, rest) = input + .split_first() + .ok_or(ProgramError::InvalidInstructionData)?; + + // Match instruction type and parse the remaining bytes based on the variant + match variant { + 0 => { + // For InitializeCounter, parse a u64 from the remaining bytes + let initial_value = u64::from_le_bytes( + rest.try_into() + .map_err(|_| ProgramError::InvalidInstructionData)?, + ); + Ok(Self::InitializeCounter { initial_value }) + } + 1 => Ok(Self::IncrementCounter), // No additional data needed + _ => Err(ProgramError::InvalidInstructionData), + } + } +} +``` + +### Instruction Handlers + +Instruction handlers refer to the functions that contain the business logic for +each instruction. It's common to name handler functions as +`process_`, but you're free to choose any naming convention. + +Add the following code to `lib.rs`. This code uses the `CounterInstruction` enum +and `unpack` method defined in the previous step to route incoming instructions +to the appropriate handler functions: + +```rs filename="lib.rs" {8-17} {20-32} /process_initialize_counter/1 /process_increment_counter/1 +entrypoint!(process_instruction); + +pub fn process_instruction( + program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> ProgramResult { + // Unpack instruction data + let instruction = CounterInstruction::unpack(instruction_data)?; + + // Match instruction type + match instruction { + CounterInstruction::InitializeCounter { initial_value } => { + process_initialize_counter(program_id, accounts, initial_value)? + } + CounterInstruction::IncrementCounter => process_increment_counter(program_id, accounts)?, + }; +} + +fn process_initialize_counter( + program_id: &Pubkey, + accounts: &[AccountInfo], + initial_value: u64, +) -> ProgramResult { + // Implementation details... + Ok(()) +} + +fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult { + // Implementation details... + Ok(()) +} +``` + +Next, add the implementation of the `process_initialize_counter` function. This +instruction handler: + +1. Creates and allocates space for a new account to store the counter data +2. Initializing the account data with `initial_value` passed to the instruction + + + + +The `process_initialize_counter` function requires three accounts: + +1. The counter account that will be created and initialized +2. The payer account that will fund the new account creation +3. The System Program that we invoke to create the new account + +To define the accounts required by the instruction, we create an iterator over +the `accounts` slice and use the `next_account_info` function to get each +account. The number of accounts you define are the accounts required by the +instruction. + +The order of accounts is important - when building the instruction on the client +side, accounts must be provided in the same order as it is defined in the +program for the instruction to execute successfully. + +While the variable names for the accounts have no effect on the program's +functionality, using descriptive names is recommended. + +```rs filename="lib.rs" {6-10} +fn process_initialize_counter( + program_id: &Pubkey, + accounts: &[AccountInfo], + initial_value: u64, +) -> ProgramResult { + let accounts_iter = &mut accounts.iter(); + + let counter_account = next_account_info(accounts_iter)?; + let payer_account = next_account_info(accounts_iter)?; + let system_program = next_account_info(accounts_iter)?; + + Ok(()) +} +``` + +Before creating an account, we need to: + +1. Specify the space (in bytes) to allocate to the account's data field. Since + we're storing a u64 value (`count`), we need 8 bytes. + +2. Calculate the minimum "rent" balance required. On Solana, accounts must + maintain a minimum balance of lamports (rent) based on amount of data stored + on the account. + +```rs filename="lib.rs" {12-17} +fn process_initialize_counter( + program_id: &Pubkey, + accounts: &[AccountInfo], + initial_value: u64, +) -> ProgramResult { + let accounts_iter = &mut accounts.iter(); + + let counter_account = next_account_info(accounts_iter)?; + let payer_account = next_account_info(accounts_iter)?; + let system_program = next_account_info(accounts_iter)?; + + // Size of our counter account + let account_space = 8; // Size in bytes to store a u64 + + // Calculate minimum balance for rent exemption + let rent = Rent::get()?; + let required_lamports = rent.minimum_balance(account_space); + + Ok(()) +} +``` + +Once the space is defined and rent is calculated, create the account by invoking +the System Program's `create_account` instruction. + +On Solana, new accounts can only be created by the System Program. When creating +an account, we specify the amount of bytes to allocate and the program owner of +the new account. The System Program: + +1. Creates the new account +2. Allocates the specified space for the account's data field +3. Transfers ownership to the specified program + +This ownership transfer is important because only the program owner of an +account can modify an account's data. In this case, we set our program as the +owner, which will allow us to modify the account's data to store the counter +value. + +To invoke the System Program from our program's instruction, we make a Cross +Program Invocation (CPI) via the `invoke` function. A CPI allows one program to +call instructions on other programs - in this case, the System Program's +`create_account` instruction. + +```rs filename="lib.rs" {19-33} +fn process_initialize_counter( + program_id: &Pubkey, + accounts: &[AccountInfo], + initial_value: u64, +) -> ProgramResult { + let accounts_iter = &mut accounts.iter(); + + let counter_account = next_account_info(accounts_iter)?; + let payer_account = next_account_info(accounts_iter)?; + let system_program = next_account_info(accounts_iter)?; + + // Size of our counter account + let account_space = 8; // Size in bytes to store a u64 + + // Calculate minimum balance for rent exemption + let rent = Rent::get()?; + let required_lamports = rent.minimum_balance(account_space); + + // Create the counter account + invoke( + &system_instruction::create_account( + payer_account.key, // Account paying for the new account + counter_account.key, // Account to be created + required_lamports, // Amount of lamports to transfer to the new account + account_space as u64, // Size in bytes to allocate for the data field + program_id, // Set program owner to our program + ), + &[ + payer_account.clone(), + counter_account.clone(), + system_program.clone(), + ], + )?; + + Ok(()) +} +``` + +Once the account is created, we initialize the account data by: + +1. Creating a new `CounterAccount` struct with the `initial_value` provided to + the instruction. +2. Getting a mutable reference to the new account's data field. +3. Serializing the `CounterAccount` struct into the account's data field, + effectively storing the `initial_value` on the account. + +```rs filename="lib.rs" {35-44} /initial_value/ +fn process_initialize_counter( + program_id: &Pubkey, + accounts: &[AccountInfo], + initial_value: u64, +) -> ProgramResult { + let accounts_iter = &mut accounts.iter(); + + let counter_account = next_account_info(accounts_iter)?; + let payer_account = next_account_info(accounts_iter)?; + let system_program = next_account_info(accounts_iter)?; + + // Size of our counter account + let account_space = 8; // Size in bytes to store a u64 + + // Calculate minimum balance for rent exemption + let rent = Rent::get()?; + let required_lamports = rent.minimum_balance(account_space); + + // Create the counter account + invoke( + &system_instruction::create_account( + payer_account.key, // Account paying for the new account + counter_account.key, // Account to be created + required_lamports, // Amount of lamports to transfer to the new account + account_space as u64, // Size in bytes to allocate for the data field + program_id, // Set program owner to our program + ), + &[ + payer_account.clone(), + counter_account.clone(), + system_program.clone(), + ], + )?; + + // Create a new CounterAccount struct with the initial value + let counter_data = CounterAccount { + count: initial_value, + }; + + // Get a mutable reference to the counter account's data + let mut account_data = &mut counter_account.data.borrow_mut()[..]; + + // Serialize the CounterAccount struct into the account's data + counter_data.serialize(&mut account_data)?; + + msg!("Counter initialized with value: {}", initial_value); + + Ok(()) +} +``` + + + + +```rs filename="lib.rs" +// Initialize a new counter account +fn process_initialize_counter( + program_id: &Pubkey, + accounts: &[AccountInfo], + initial_value: u64, +) -> ProgramResult { + let accounts_iter = &mut accounts.iter(); + + let counter_account = next_account_info(accounts_iter)?; + let payer_account = next_account_info(accounts_iter)?; + let system_program = next_account_info(accounts_iter)?; + + // Size of our counter account + let account_space = 8; // Size in bytes to store a u64 + + // Calculate minimum balance for rent exemption + let rent = Rent::get()?; + let required_lamports = rent.minimum_balance(account_space); + + // Create the counter account + invoke( + &system_instruction::create_account( + payer_account.key, // Account paying for the new account + counter_account.key, // Account to be created + required_lamports, // Amount of lamports to transfer to the new account + account_space as u64, // Size in bytes to allocate for the data field + program_id, // Set program owner to our program + ), + &[ + payer_account.clone(), + counter_account.clone(), + system_program.clone(), + ], + )?; + + // Create a new CounterAccount struct with the initial value + let counter_data = CounterAccount { + count: initial_value, + }; + + // Get a mutable reference to the counter account's data + let mut account_data = &mut counter_account.data.borrow_mut()[..]; + + // Serialize the CounterAccount struct into the account's data + counter_data.serialize(&mut account_data)?; + + msg!("Counter initialized with value: {}", initial_value); + + Ok(()) +} +``` + +Next, add the implementation of the `process_increment_counter` function. This +instruction increments the value of an existing counter account. + + + + +Just like the `process_initialize_counter` function, we start by creating an +iterator over the accounts. In this case, we are only expecting one account, +which is the account to be updated. + +Note that in practice, a developer must implement various security checks to +validate the accounts passed to the program. Since all accounts are provided by +the caller of the instruction, there is no guarantee that the accounts provided +are the ones the program expects. Missing account validation checks are a common +source of program vulnerabilities. + +The example below includes a check to ensure the account we're referring to as +the `counter_account` is owned by the executing program. + +```rs filename="lib.rs" {6-9} +// Update an existing counter's value +fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult { + let accounts_iter = &mut accounts.iter(); + let counter_account = next_account_info(accounts_iter)?; + + // Verify account ownership + if counter_account.owner != program_id { + return Err(ProgramError::IncorrectProgramId); + } + + Ok(()) +} +``` + +To update the account data, we: + +- Mutably borrow the existing account's data field +- Deserialize the raw bytes into our `CounterAccount` struct +- Update the `count` value +- Serialize the modified struct back into the account's data field + +```rs filename="lib.rs" {11-24} +// Update an existing counter's value +fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult { + let accounts_iter = &mut accounts.iter(); + let counter_account = next_account_info(accounts_iter)?; + + // Verify account ownership + if counter_account.owner != program_id { + return Err(ProgramError::IncorrectProgramId); + } + + // Mutable borrow the account data + let mut data = counter_account.data.borrow_mut(); + + // Deserialize the account data into our CounterAccount struct + let mut counter_data: CounterAccount = CounterAccount::try_from_slice(&data)?; + + // Increment the counter value + counter_data.count = counter_data + .count + .checked_add(1) + .ok_or(ProgramError::InvalidAccountData)?; + + // Serialize the updated counter data back into the account + counter_data.serialize(&mut &mut data[..])?; + + msg!("Counter incremented to: {}", counter_data.count); + Ok(()) +} +``` + + + + +```rs filename="lib.rs" +// Update an existing counter's value +fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult { + let accounts_iter = &mut accounts.iter(); + let counter_account = next_account_info(accounts_iter)?; + + // Verify account ownership + if counter_account.owner != program_id { + return Err(ProgramError::IncorrectProgramId); + } + + // Mutable borrow the account data + let mut data = counter_account.data.borrow_mut(); + + // Deserialize the account data into our CounterAccount struct + let mut counter_data: CounterAccount = CounterAccount::try_from_slice(&data)?; + + // Increment the counter value + counter_data.count = counter_data + .count + .checked_add(1) + .ok_or(ProgramError::InvalidAccountData)?; + + // Serialize the updated counter data back into the account + counter_data.serialize(&mut &mut data[..])?; + + msg!("Counter incremented to: {}", counter_data.count); + Ok(()) +} +``` + +### Instruction Testing + +To test the program instructions, add the following dependencies to +`Cargo.toml`. + +```shell filename="Terminal" +cargo add solana-program-test@1.18.26 --dev +cargo add solana-sdk@1.18.26 --dev +cargo add tokio --dev +``` + +Then add the following test module to `lib.rs` and run `cargo test-sbf` to +execute the tests. Optionally, use the `--nocapture` flag to see the print +statements in the output. + +```shell filename="Terminal" +cargo test-sbf -- --nocapture +``` + + + + +First, set up the test module and import required dependencies: + +```rs filename="lib.rs" +#[cfg(test)] +mod test { + use super::*; + use solana_program_test::*; + use solana_sdk::{ + instruction::{AccountMeta, Instruction}, + signature::{Keypair, Signer}, + system_program, + transaction::Transaction, + }; + + #[tokio::test] + async fn test_counter_program() { + // Test code will go here + } +} +``` + +Next, set up the test using `ProgramTest`. Then create a new keypair to use as +the address for the counter account we'll initialize and define an initial value +to set for the counter. + +```rs filename="lib.rs" +#[cfg(test)] +mod test { + use super::*; + use solana_program_test::*; + use solana_sdk::{ + instruction::{AccountMeta, Instruction}, + signature::{Keypair, Signer}, + system_program, + transaction::Transaction, + }; + + #[tokio::test] + async fn test_counter_program() { + let program_id = Pubkey::new_unique(); + let (mut banks_client, payer, recent_blockhash) = ProgramTest::new( + "counter_program", + program_id, + processor!(process_instruction), + ) + .start() + .await; + + // Create a new keypair to use as the address for our counter account + let counter_keypair = Keypair::new(); + let initial_value: u64 = 42; + } +} +``` + +When building an instruction, each account must be provided as an +[`AccountMeta`](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/instruction.rs#L539-L545), +which specifies: + +- The account's public key (`Pubkey`) +- `is_writable`: Whether the account data will be modified +- `is_signer`: Whether the account must sign the transaction + +```rs +AccountMeta::new(account1_pubkey, true), // writable, signer +AccountMeta::new(account2_pubkey, false), // writable, not signer +AccountMeta::new_readonly(account3_pubkey, false), // not writable, not signer +AccountMeta::new_readonly(account4_pubkey, true), // writable, signer +``` + +To test the initialize instruction: + +- Create instruction data with variant 0 (`InitializeCounter`) and initial value +- Build the instruction with the program ID, instruction data, and required + accounts +- Send a transaction with the initialize instruction +- Check the account was created with the correct initial value + +```rs filename="lib.rs" {16-53} + #[tokio::test] + async fn test_counter_program() { + let program_id = Pubkey::new_unique(); + let (mut banks_client, payer, recent_blockhash) = ProgramTest::new( + "counter_program", + program_id, + processor!(process_instruction), + ) + .start() + .await; + + // Create a new keypair to use as the address for our counter account + let counter_keypair = Keypair::new(); + let initial_value: u64 = 42; + + // Step 1: Initialize the counter + println!("Testing counter initialization..."); + + // Create initialization instruction + let mut init_instruction_data = vec![0]; // 0 = initialize instruction + init_instruction_data.extend_from_slice(&initial_value.to_le_bytes()); + + let initialize_instruction = Instruction::new_with_bytes( + program_id, + &init_instruction_data, + vec![ + AccountMeta::new(counter_keypair.pubkey(), true), + AccountMeta::new(payer.pubkey(), true), + AccountMeta::new_readonly(system_program::id(), false), + ], + ); + + // Send transaction with initialize instruction + let mut transaction = + Transaction::new_with_payer(&[initialize_instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer, &counter_keypair], recent_blockhash); + banks_client.process_transaction(transaction).await.unwrap(); + + // Check account data + let account = banks_client + .get_account(counter_keypair.pubkey()) + .await + .expect("Failed to get counter account"); + + if let Some(account_data) = account { + let counter: CounterAccount = CounterAccount::try_from_slice(&account_data.data) + .expect("Failed to deserialize counter data"); + assert_eq!(counter.count, 42); + println!( + "✅ Counter initialized successfully with value: {}", + counter.count + ); + } + } +``` + +To test the increment instruction: + +- Build the instruction with the program ID, instruction data, and required + accounts +- Send a transaction with the increment instruction +- Check the account was incremented to the correct value + +Note that the instruction data for the increment instruction is `[1]`, which +corresponds to variant 1 (`IncrementCounter`). Since there are no additional +parameters to the increment instruction, the data is simply the instruction +variant. + +```rs filename="lib.rs" {55-82} + #[tokio::test] + async fn test_counter_program() { + let program_id = Pubkey::new_unique(); + let (mut banks_client, payer, recent_blockhash) = ProgramTest::new( + "counter_program", + program_id, + processor!(process_instruction), + ) + .start() + .await; + + // Create a new keypair to use as the address for our counter account + let counter_keypair = Keypair::new(); + let initial_value: u64 = 42; + + // Step 1: Initialize the counter + println!("Testing counter initialization..."); + + // Create initialization instruction + let mut init_instruction_data = vec![0]; // 0 = initialize instruction + init_instruction_data.extend_from_slice(&initial_value.to_le_bytes()); + + let initialize_instruction = Instruction::new_with_bytes( + program_id, + &init_instruction_data, + vec![ + AccountMeta::new(counter_keypair.pubkey(), true), + AccountMeta::new(payer.pubkey(), true), + AccountMeta::new_readonly(system_program::id(), false), + ], + ); + + // Send transaction with initialize instruction + let mut transaction = + Transaction::new_with_payer(&[initialize_instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer, &counter_keypair], recent_blockhash); + banks_client.process_transaction(transaction).await.unwrap(); + + // Check account data + let account = banks_client + .get_account(counter_keypair.pubkey()) + .await + .expect("Failed to get counter account"); + + if let Some(account_data) = account { + let counter: CounterAccount = CounterAccount::try_from_slice(&account_data.data) + .expect("Failed to deserialize counter data"); + assert_eq!(counter.count, 42); + println!( + "✅ Counter initialized successfully with value: {}", + counter.count + ); + } + + // Step 2: Increment the counter + println!("Testing counter increment..."); + + // Create increment instruction + let increment_instruction = Instruction::new_with_bytes( + program_id, + &[1], // 1 = increment instruction + vec![AccountMeta::new(counter_keypair.pubkey(), true)], + ); + + // Send transaction with increment instruction + let mut transaction = + Transaction::new_with_payer(&[increment_instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer, &counter_keypair], recent_blockhash); + banks_client.process_transaction(transaction).await.unwrap(); + + // Check account data + let account = banks_client + .get_account(counter_keypair.pubkey()) + .await + .expect("Failed to get counter account"); + + if let Some(account_data) = account { + let counter: CounterAccount = CounterAccount::try_from_slice(&account_data.data) + .expect("Failed to deserialize counter data"); + assert_eq!(counter.count, 43); + println!("✅ Counter incremented successfully to: {}", counter.count); + } + } +``` + + + + +```rs filename="lib.rs" +#[cfg(test)] +mod test { + use super::*; + use solana_program_test::*; + use solana_sdk::{ + instruction::{AccountMeta, Instruction}, + signature::{Keypair, Signer}, + system_program, + transaction::Transaction, + }; + + #[tokio::test] + async fn test_counter_program() { + let program_id = Pubkey::new_unique(); + let (mut banks_client, payer, recent_blockhash) = ProgramTest::new( + "counter_program", + program_id, + processor!(process_instruction), + ) + .start() + .await; + + // Create a new keypair to use as the address for our counter account + let counter_keypair = Keypair::new(); + let initial_value: u64 = 42; + + // Step 1: Initialize the counter + println!("Testing counter initialization..."); + + // Create initialization instruction + let mut init_instruction_data = vec![0]; // 0 = initialize instruction + init_instruction_data.extend_from_slice(&initial_value.to_le_bytes()); + + let initialize_instruction = Instruction::new_with_bytes( + program_id, + &init_instruction_data, + vec![ + AccountMeta::new(counter_keypair.pubkey(), true), + AccountMeta::new(payer.pubkey(), true), + AccountMeta::new_readonly(system_program::id(), false), + ], + ); + + // Send transaction with initialize instruction + let mut transaction = + Transaction::new_with_payer(&[initialize_instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer, &counter_keypair], recent_blockhash); + banks_client.process_transaction(transaction).await.unwrap(); + + // Check account data + let account = banks_client + .get_account(counter_keypair.pubkey()) + .await + .expect("Failed to get counter account"); + + if let Some(account_data) = account { + let counter: CounterAccount = CounterAccount::try_from_slice(&account_data.data) + .expect("Failed to deserialize counter data"); + assert_eq!(counter.count, 42); + println!( + "✅ Counter initialized successfully with value: {}", + counter.count + ); + } + + // Step 2: Increment the counter + println!("Testing counter increment..."); + + // Create increment instruction + let increment_instruction = Instruction::new_with_bytes( + program_id, + &[1], // 1 = increment instruction + vec![AccountMeta::new(counter_keypair.pubkey(), true)], + ); + + // Send transaction with increment instruction + let mut transaction = + Transaction::new_with_payer(&[increment_instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer, &counter_keypair], recent_blockhash); + banks_client.process_transaction(transaction).await.unwrap(); + + // Check account data + let account = banks_client + .get_account(counter_keypair.pubkey()) + .await + .expect("Failed to get counter account"); + + if let Some(account_data) = account { + let counter: CounterAccount = CounterAccount::try_from_slice(&account_data.data) + .expect("Failed to deserialize counter data"); + assert_eq!(counter.count, 43); + println!("✅ Counter incremented successfully to: {}", counter.count); + } + } +} +``` + +Example output: + +```shell filename="Terminal" {6} {10} +running 1 test +[2024-10-29T20:51:13.783708000Z INFO solana_program_test] "counter_program" SBF program from /counter_program/target/deploy/counter_program.so, modified 2 seconds, 169 ms, 153 µs and 461 ns ago +[2024-10-29T20:51:13.855204000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM invoke [1] +[2024-10-29T20:51:13.856052000Z DEBUG solana_runtime::message_processor::stable_log] Program 11111111111111111111111111111111 invoke [2] +[2024-10-29T20:51:13.856135000Z DEBUG solana_runtime::message_processor::stable_log] Program 11111111111111111111111111111111 success +[2024-10-29T20:51:13.856242000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Counter initialized with value: 42 +[2024-10-29T20:51:13.856285000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM consumed 3791 of 200000 compute units +[2024-10-29T20:51:13.856307000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM success +[2024-10-29T20:51:13.860038000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM invoke [1] +[2024-10-29T20:51:13.860333000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Counter incremented to: 43 +[2024-10-29T20:51:13.860355000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM consumed 756 of 200000 compute units +[2024-10-29T20:51:13.860375000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM success +test test::test_counter_program ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s +``` + + diff --git a/docs/uk/programs/testing.md b/docs/uk/programs/testing.md new file mode 100644 index 000000000..622364e92 --- /dev/null +++ b/docs/uk/programs/testing.md @@ -0,0 +1,235 @@ +--- +title: "Testing with NodeJS" +description: "Testing native solana programs written with rust using NodeJS" +sidebarSortOrder: 5 +--- + +When developing programs on Solana, ensuring their correctness and reliability +is crucial. Until now devs have been using `solana-test-validator` for testing. +This document covers testing your Solana program with Node.js +using `solana-bankrun`. + +## Overview + +There are two ways to test programs on Solana: + +1. [solana-test-validator](https://docs.anza.xyz/cli/examples/test-validator): + That spins up a local emulator of the Solana Blockchain on your local machine + which receives the transactions to be processed by the validator. +2. The various + [BanksClient-based](https://docs.rs/solana-banks-client/latest/solana_banks_client/) + test frameworks for SBF (Solana Bytecode Format) programs: Bankrun is a + framework that simulates a Solana bank's operations, enabling developers to + deploy, interact with, and assess the behavior of programs under test + conditions that mimic the mainnet. It helps set up the test environment and + offers tools for detailed transaction insights, enhancing debugging and + verification. With the client, we can load programs, and simulate and process + transactions seamlessly. + [solana-program-test](https://docs.rs/solana-program-test) (Rust), + [solana-bankrun](https://github.com/kevinheavey/solana-bankrun) (Rust, + JavaScript), [anchor-bankrun](https://www.npmjs.com/package/anchor-bankrun) + (Anchor, JavaScript), + [solders.bankrun](https://kevinheavey.github.io/solders/api_reference/bankrun.html) + (Python) are examples of the BanksClient-based testing framework. + +> [`pnpm create solana-program`](https://github.com/solana-program/create-solana-program) +> can help you generate JS and Rust clients including tests. Anchor is not yet +> supported. + +In this guide, we are using Solana Bankrun. `Bankrun` is a superfast, powerful, +and lightweight framework for testing Solana programs in Node.js. + +- The biggest advantage of using Solana Bankrun is that you don't have to set + up + an environment to test programs like you'd have to do while using the + `solana-test-validator`. Instead, you can do that with a piece of code, + inside + the tests. +- It also dynamically sets time and account data, which isn't possible with + `solana-test-validator` + +## Installation + +Add `solana-bankrun` as a dev dependency to your node project. If your Solana +program is not a node project yet, you can initialize it using `npm init`. + +```bash +npm i -D solana-bankrun +``` + +## Usage + +### Program Directory + +Firstly, the program's `.so` file must be present in one of the following +directories: + +- `./tests/fixtures` (just create this directory if it doesn't exist already). +- Your current working directory. +- A directory you define in the `BPF_OUT_DIR` or `SBF_OUT_DIR` environment + variables. `export BPF_OUT_DIR='/path/to/binary'` +- Build your program specifying the correct directory so that library can pick + the file up from directory just from the name. + `cargo build-sbf --manifest-path=./program/Cargo.toml --sbf-out-dir=./tests/fixtures` + +### Testing Framework + +solana-bankrun is used in JavaScript or TypeScript with testing frameworks like +[ts-mocha](https://www.npmjs.com/package/ts-mocha), +[ava](https://github.com/avajs/ava), [Jest](https://jestjs.io/), +etc. Make sure to get started with any of the above. + +Add an [npm script](https://docs.npmjs.com/cli/v9/using-npm/scripts) to test +your program and create your `test.ts` file inside `tests` folder. + +```json +{ + "scripts": { + "test": "pnpm ts-mocha -p ./tsconfig.json -t 1000000 ./tests/test.ts" + } +} +``` + +### Start + +`start` function from `solana-bankrun` spins up a BanksServer and a BanksClient, +deploy programs and add accounts as instructed. + +```typescript +import { start } from "solana-bankrun"; +import { PublicKey } from "@solana/web3.js"; + +test("testing program instruction", async () => { + const programId = PublicKey.unique(); + const context = await start([{ name: "program_name", programId }], []); + + const client = context.banksClient; + const payer = context.payer; + // write tests +}); +``` + +### Bankrun `context` + +- We get access to the Bankrun `context` from the `start` function. Context + contains a BanksClient, a recent blockhash and a funded payer keypair. +- `context` has a `payer`, which is a funded keypair that can be used to sign + transactions. +- `context` also has `context.lastBlockhash` or `context.getLatestBlockhash` to + make fetching [Blockhash](https://solana.com/docs/terminology#blockhash) + convenient during tests. +- `context.banksClient` is used to send transactions and query account data from + the ledger state. For example, sometimes + [Rent](https://solana.com/docs/terminology#rent) (in lamports) is + required to build a transaction to be submitted, for example, when using the + SystemProgram's + createAccount() instruction. You can do that using BanksClient: + + ```typescript + const rent = await client.getRent(); + + const Ix: TransactionInstruction = SystemProgram.createAccount({ + // ... + lamports: Number(rent.minimumBalance(BigInt(ACCOUNT_SIZE))), + //.... + }); + ``` + +- You can read account data from BanksClient using `getAccount` function + ```typescript + AccountInfo = await client.getAccount(counter); + ``` + +### Process Transaction + +The `processTransaction()` function executes the transaction with the loaded +programs +and accounts from the start function and will return a transaction. + +```typescript +let transaction = await client.processTransaction(tx); +``` + +## Example + +Here's an example to write test for +a [hello world program](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/native) : + +```typescript +import { + PublicKey, + Transaction, + TransactionInstruction, +} from "@solana/web3.js"; +import { start } from "solana-bankrun"; +import { describe, test } from "node:test"; +import { assert } from "chai"; + +describe("hello-solana", async () => { + // load program in solana-bankrun + const PROGRAM_ID = PublicKey.unique(); + const context = await start( + [{ name: "hello_solana_program", programId: PROGRAM_ID }], + [], + ); + const client = context.banksClient; + const payer = context.payer; + + test("Say hello!", async () => { + const blockhash = context.lastBlockhash; + // We set up our instruction first. + let ix = new TransactionInstruction({ + // using payer keypair from context to sign the txn + keys: [{ pubkey: payer.publicKey, isSigner: true, isWritable: true }], + programId: PROGRAM_ID, + data: Buffer.alloc(0), // No data + }); + + const tx = new Transaction(); + tx.recentBlockhash = blockhash; + // using payer keypair from context to sign the txn + tx.add(ix).sign(payer); + + // Now we process the transaction + let transaction = await client.processTransaction(tx); + + assert(transaction.logMessages[0].startsWith("Program " + PROGRAM_ID)); + assert(transaction.logMessages[1] === "Program log: Hello, Solana!"); + assert( + transaction.logMessages[2] === + "Program log: Our program's Program ID: " + PROGRAM_ID, + ); + assert( + transaction.logMessages[3].startsWith( + "Program " + PROGRAM_ID + " consumed", + ), + ); + assert(transaction.logMessages[4] === "Program " + PROGRAM_ID + " success"); + assert(transaction.logMessages.length == 5); + }); +}); +``` + +This is how the output looks like after running the tests for +[hello world program](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/native). + +```text +[2024-06-04T12:57:36.188822000Z INFO solana_program_test] "hello_solana_program" SBF program from tests/fixtures/hello_solana_program.so, modified 3 seconds, 20 ms, 687 µs and 246 ns ago +[2024-06-04T12:57:36.246838000Z DEBUG solana_runtime::message_processor::stable_log] Program 11111111111111111111111111111112 invoke [1] +[2024-06-04T12:57:36.246892000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, Solana! +[2024-06-04T12:57:36.246917000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Our program's Program ID: 11111111111111111111111111111112 +[2024-06-04T12:57:36.246932000Z DEBUG solana_runtime::message_processor::stable_log] Program 11111111111111111111111111111112 consumed 2905 of 200000 compute units +[2024-06-04T12:57:36.246937000Z DEBUG solana_runtime::message_processor::stable_log] Program 11111111111111111111111111111112 success +▶ hello-solana + ✔ Say hello! (5.667917ms) +▶ hello-solana (7.047667ms) + +ℹ tests 1 +ℹ suites 1 +ℹ pass 1 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 63.52616 +``` diff --git a/docs/uk/rpc.md b/docs/uk/rpc.md new file mode 100644 index 000000000..e8e6582a6 --- /dev/null +++ b/docs/uk/rpc.md @@ -0,0 +1,10 @@ +--- +title: Методи JSON RPC +sidebarSortOrder: 1 +isSkippedInNav: true +--- + +Цей файл не повинен редагуватися, оскільки він не призначений для відображення. Він існує лише для створення посилання в головній бічній панелі документації. + +Документація JSON RPC для Solana доступна в +[`rpc` каталозі](./rpc/) diff --git a/docs/uk/rpc/deprecated/confirmTransaction.mdx b/docs/uk/rpc/deprecated/confirmTransaction.mdx new file mode 100644 index 000000000..9ca5913b0 --- /dev/null +++ b/docs/uk/rpc/deprecated/confirmTransaction.mdx @@ -0,0 +1,13 @@ +--- +sidebarLabel: confirmTransaction +title: confirmTransaction RPC Method +hideTableOfContents: true +--- + +Fetch the current status of a transaction signature (processed, confirmed, +finalized). + + + This method is expected to be removed in `solana-core` v2.0. Please use + [getSignatureStatuses](/docs/rpc/http/getSignatureStatuses) instead. + diff --git a/docs/uk/rpc/deprecated/getConfirmedBlock.mdx b/docs/uk/rpc/deprecated/getConfirmedBlock.mdx new file mode 100644 index 000000000..d9236f130 --- /dev/null +++ b/docs/uk/rpc/deprecated/getConfirmedBlock.mdx @@ -0,0 +1,202 @@ +--- +sidebarLabel: getConfirmedBlock +title: getConfirmedBlock RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getConfirmedBlock + - /docs/rpc/http/getConfirmedBlock +--- + +Returns identity and transaction information about a confirmed block in the +ledger + + + This method is expected to be removed in `solana-core` v2.0. Please use + [getBlock](/docs/rpc/http/getBlock) instead. + + + + + + +### Parameters + + + slot number, as u64 integer + + + + +Configuration object containing the following fields: + + + + + level of transaction detail to return, either "full", "signatures", or "none" + + + + whether to populate the `rewards` array. + + + + +Encoding format for Account data + + + +
+ +- `jsonParsed` encoding attempts to use program-specific instruction parsers to + return more human-readable and explicit data in the + `transaction.message.instructions` list. +- If `jsonParsed` is requested but a parser cannot be found, the instruction + falls back to regular JSON encoding (`accounts`, `data`, and `programIdIndex` + fields). + +
+ +
+ +
+ +### Result + +The result field will be an object with the following fields: + +- `` - if specified block is not confirmed +- `` - if block is confirmed, an object with the following fields: + - `blockhash: ` - the blockhash of this block, as base-58 encoded + string + - `previousBlockhash: ` - the blockhash of this block's parent, as + base-58 encoded string; if the parent block is not available due to ledger + cleanup, this field will return "11111111111111111111111111111111" + - `parentSlot: ` - the slot index of this block's parent + - `transactions: ` - present if "full" transaction details are + requested; an array of JSON objects containing: + - `transaction: ` - + [Transaction](/docs/rpc/json-structures#transactions) object, either in + JSON format or encoded binary data, depending on encoding parameter + - `meta: ` - transaction status metadata object, containing `null` + or: + - `err: ` - Error if transaction failed, null if transaction + succeeded. + [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) + - `fee: ` - fee this transaction was charged, as u64 integer + - `preBalances: ` - array of u64 account balances from before the + transaction was processed + - `postBalances: ` - array of u64 account balances after the + transaction was processed + - `innerInstructions: ` - List of + [inner instructions](/docs/rpc/json-structures#inner-instructions) or + `null` if inner instruction recording was not enabled during this + transaction + - `preTokenBalances: ` - List of + [token balances](/docs/rpc/json-structures#token-balances) from before + the transaction was processed or omitted if token balance recording was + not yet enabled during this transaction + - `postTokenBalances: ` - List of + [token balances](/docs/rpc/json-structures#token-balances) from after + the transaction was processed or omitted if token balance recording was + not yet enabled during this transaction + - `logMessages: ` - array of string log messages or `null` if + log message recording was not enabled during this transaction + - DEPRECATED: `status: ` - Transaction status + - `"Ok": ` - Transaction was successful + - `"Err": ` - Transaction failed with TransactionError + - `signatures: ` - present if "signatures" are requested for + transaction details; an array of signatures strings, corresponding to the + transaction order in the block + - `rewards: ` - present if rewards are requested; an array of JSON + objects containing: + - `pubkey: ` - The public key, as base-58 encoded string, of the + account that received the reward + - `lamports: `- number of reward lamports credited or debited by the + account, as a i64 + - `postBalance: ` - account balance in lamports after the reward was + applied + - `rewardType: ` - type of reward: "fee", "rent", + "voting", "staking" + - `commission: ` - vote account commission when the reward was + credited, only present for voting and staking rewards + - `blockTime: ` - estimated production time, as Unix timestamp + (seconds since the Unix epoch). null if not available + +#### For more details on returned data: + +- [Transaction Structure](/docs/rpc/json-structures#transactions) +- [Inner Instructions Structure](/docs/rpc/json-structures#inner-instructions) +- [Token Balances Structure](/docs/rpc/json-structures#token-balances) + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", "id": 1, + "method": "getConfirmedBlock", + "params": [430, "base64"] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "blockTime": null, + "blockhash": "3Eq21vXNB5s86c62bVuUfTeaMif1N2kUqRPBmGRJhyTA", + "parentSlot": 429, + "previousBlockhash": "mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B", + "rewards": [], + "transactions": [ + { + "meta": { + "err": null, + "fee": 5000, + "innerInstructions": [], + "logMessages": [], + "postBalances": [499998932500, 26858640, 1, 1, 1], + "postTokenBalances": [], + "preBalances": [499998937500, 26858640, 1, 1, 1], + "preTokenBalances": [], + "status": { + "Ok": null + } + }, + "transaction": [ + "AVj7dxHlQ9IrvdYVIjuiRFs1jLaDMHixgrv+qtHBwz51L4/ImLZhszwiyEJDIp7xeBSpm/TX5B7mYzxa+fPOMw0BAAMFJMJVqLw+hJYheizSoYlLm53KzgT82cDVmazarqQKG2GQsLgiqktA+a+FDR4/7xnDX7rsusMwryYVUdixfz1B1Qan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAAAtxOUhPBp2WSjUNJEgfvy70BbxI00fZyEPvFHNfxrtEAQQEAQIDADUCAAAAAQAAAAAAAACtAQAAAAAAAAdUE18R96XTJCe+YfRfUp6WP+YKCy/72ucOL8AoBFSpAA==", + "base64" + ] + } + ] + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/deprecated/getConfirmedBlocks.mdx b/docs/uk/rpc/deprecated/getConfirmedBlocks.mdx new file mode 100644 index 000000000..2e4cc769b --- /dev/null +++ b/docs/uk/rpc/deprecated/getConfirmedBlocks.mdx @@ -0,0 +1,65 @@ +--- +sidebarLabel: getConfirmedBlocks +title: getConfirmedBlocks RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getConfirmedBlocks + - /docs/rpc/http/getConfirmedBlocks +--- + +Returns a list of confirmed blocks between two slots + + + This method is expected to be removed in `solana-core` v2.0. Please use + [getBlocks](/docs/rpc/http/getblocks) instead. + + + + + + +### Parameters + + + start_slot, as u64 integer + + + + +Configuration object containing the following fields: + + + + + +### Result + +The result field will be an array of u64 integers listing confirmed blocks +between `start_slot` and either `end_slot` - if provided, or latest confirmed +block, inclusive. Max range allowed is 500,000 slots. + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc": "2.0","id":1,"method":"getConfirmedBlocks","params":[5, 10]} +' +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": [5, 6, 7, 8, 9, 10], "id": 1 } +``` + + + diff --git a/docs/uk/rpc/deprecated/getConfirmedBlocksWithLimit.mdx b/docs/uk/rpc/deprecated/getConfirmedBlocksWithLimit.mdx new file mode 100644 index 000000000..21efd752f --- /dev/null +++ b/docs/uk/rpc/deprecated/getConfirmedBlocksWithLimit.mdx @@ -0,0 +1,72 @@ +--- +sidebarLabel: getConfirmedBlocksWithLimit +title: getConfirmedBlocksWithLimit RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getConfirmedBlocksWithLimit + - /docs/rpc/http/getConfirmedBlocksWithLimit +--- + +Returns a list of confirmed blocks starting at the given slot + + + This method is expected to be removed in `solana-core` v2.0. Please use + [getBlocksWithLimit](/docs/rpc/http/getblockswithlimit) instead. + + + + + + +### Parameters + + + start_slot, as u64 integer + + + + limit, as u64 integer + + + + +Configuration object containing the following fields: + + + + + +### Result + +The result field will be an array of u64 integers listing confirmed blocks +starting at `start_slot` for up to `limit` blocks, inclusive. + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", "id": 1, + "method": "getConfirmedBlocksWithLimit", + "params": [5, 3] + } +' +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": [5, 6, 7], "id": 1 } +``` + + + diff --git a/docs/uk/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx b/docs/uk/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx new file mode 100644 index 000000000..5db4d57a0 --- /dev/null +++ b/docs/uk/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx @@ -0,0 +1,120 @@ +--- +sidebarLabel: getConfirmedSignaturesForAddress2 +title: getConfirmedSignaturesForAddress2 RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getConfirmedSignaturesForAddress2 + - /docs/rpc/http/getConfirmedSignaturesForAddress2 + - /docs/rpc/getSignaturesForAddress2 + - /docs/rpc/http/getSignaturesForAddress2 + - /docs/rpc/deprecated/getSignaturesForAddress2 + - /docs/rpc/http/getconfirmedsignaturesforaddress + - /docs/rpc/deprecated/getconfirmedsignaturesforaddress + - /docs/rpc/getconfirmedsignaturesforaddress +--- + +Returns signatures for confirmed transactions that include the given address in +their `accountKeys` list. Returns signatures backwards in time from the provided +signature or most recent confirmed block + + + This method is expected to be removed in `solana-core` v2.0. Please use + [getSignaturesForAddress](/docs/rpc/http/getSignaturesForAddress) instead. + + + + + + +### Parameters + + + account address, as base-58 encoded string + + + +Configuration object containing the following fields: + + + + + maximum transaction signatures to return (between 1 and 1,000, default: + 1,000). + + + + start searching backwards from this transaction signature. (If not provided + the search starts from the top of the highest max confirmed block.) + + + + search until this transaction signature, if found before limit reached. + + + + +### Result + +The result field will be an array of ``, ordered from newest to oldest +transaction, containing transaction signature information with the following +fields: + +- `signature: ` - transaction signature as base-58 encoded string +- `slot: ` - The slot that contains the block with the transaction +- `err: ` - Error if transaction failed, null if transaction + succeeded. + [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) +- `memo: ` - Memo associated with the transaction, null if no memo + is present +- `blockTime: ` - estimated production time, as Unix timestamp + (seconds since the Unix epoch) of when transaction was processed. null if not + available. + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getConfirmedSignaturesForAddress2", + "params": [ + "Vote111111111111111111111111111111111111111", + { + "limit": 1 + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": [ + { + "err": null, + "memo": null, + "signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv", + "slot": 114, + "blockTime": null + } + ], + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/deprecated/getConfirmedTransaction.mdx b/docs/uk/rpc/deprecated/getConfirmedTransaction.mdx new file mode 100644 index 000000000..3a96d97c3 --- /dev/null +++ b/docs/uk/rpc/deprecated/getConfirmedTransaction.mdx @@ -0,0 +1,153 @@ +--- +sidebarLabel: getConfirmedTransaction +title: getConfirmedTransaction RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getConfirmedTransaction + - /docs/rpc/http/getConfirmedTransaction +--- + +Returns transaction details for a confirmed transaction + + + This method is expected to be removed in `solana-core` v2.0. Please use + [getTransaction](/docs/rpc/http/getTransaction) instead. + + + + + + +### Parameters + + + transaction signature, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + +Encoding format for Account data + + + +
+ +- `base58` is slow and limited to less than 129 bytes of Account data. +- `jsonParsed` encoding attempts to use program-specific instruction parsers to + return more human-readable and explicit data in the + `transaction.message.instructions` list. +- If `jsonParsed` is requested but a parser cannot be found, the instruction + falls back to regular `json` encoding (`accounts`, `data`, and + `programIdIndex` fields). + +
+ +
+ +
+ +### Result + +- `` - if transaction is not found or not confirmed +- `` - if transaction is confirmed, an object with the following fields: + - `slot: ` - the slot this transaction was processed in + - `transaction: ` - + [Transaction](/docs/rpc/json-structures#transactions) object, either in JSON + format or encoded binary data, depending on encoding parameter + - `blockTime: ` - estimated production time, as Unix timestamp + (seconds since the Unix epoch) of when the transaction was processed. null + if not available + - `meta: ` - transaction status metadata object: + - `err: ` - Error if transaction failed, null if transaction + succeeded. + [TransactionError definitions](https://docs.rs/solana-sdk/latest/solana_sdk/transaction/enum.TransactionError.html) + - `fee: ` - fee this transaction was charged, as u64 integer + - `preBalances: ` - array of u64 account balances from before the + transaction was processed + - `postBalances: ` - array of u64 account balances after the + transaction was processed + - `innerInstructions: ` - List of + [inner instructions](/docs/rpc/json-structures#inner-instructions) or + `null` if inner instruction recording was not enabled during this + transaction + - `preTokenBalances: ` - List of + [token balances](/docs/rpc/json-structures#token-balances) from before the + transaction was processed or omitted if token balance recording was not + yet enabled during this transaction + - `postTokenBalances: ` - List of + [token balances](/docs/rpc/json-structures#token-balances) from after the + transaction was processed or omitted if token balance recording was not + yet enabled during this transaction + - `logMessages: ` - array of string log messages or `null` if + log message recording was not enabled during this transaction + - DEPRECATED: `status: ` - Transaction status + - `"Ok": ` - Transaction was successful + - `"Err": ` - Transaction failed with TransactionError + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getConfirmedTransaction", + "params": [ + "2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv", + "base64" + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "meta": { + "err": null, + "fee": 5000, + "innerInstructions": [], + "postBalances": [499998932500, 26858640, 1, 1, 1], + "postTokenBalances": [], + "preBalances": [499998937500, 26858640, 1, 1, 1], + "preTokenBalances": [], + "status": { + "Ok": null + } + }, + "slot": 430, + "transaction": [ + "AVj7dxHlQ9IrvdYVIjuiRFs1jLaDMHixgrv+qtHBwz51L4/ImLZhszwiyEJDIp7xeBSpm/TX5B7mYzxa+fPOMw0BAAMFJMJVqLw+hJYheizSoYlLm53KzgT82cDVmazarqQKG2GQsLgiqktA+a+FDR4/7xnDX7rsusMwryYVUdixfz1B1Qan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAAAtxOUhPBp2WSjUNJEgfvy70BbxI00fZyEPvFHNfxrtEAQQEAQIDADUCAAAAAQAAAAAAAACtAQAAAAAAAAdUE18R96XTJCe+YfRfUp6WP+YKCy/72ucOL8AoBFSpAA==", + "base64" + ] + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx b/docs/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx new file mode 100644 index 000000000..75d6093e0 --- /dev/null +++ b/docs/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx @@ -0,0 +1,94 @@ +--- +sidebarLabel: getFeeCalculatorForBlockhash +title: getFeeCalculatorForBlockhash RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getFeeCalculatorForBlockhash + - /docs/rpc/http/getFeeCalculatorForBlockhash +--- + +Returns the fee calculator associated with the query blockhash, or `null` if the +blockhash has expired + + + This method is expected to be removed in `solana-core` v2.0. Please use + [isBlockhashValid](/docs/rpc/http/isBlockhashValid) or + [getFeeForMessage](/docs/rpc/http/getFeeForMessage) instead. + + + + + + +### Parameters + + + query blockhash, as a base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + +### Result + +The result will be an RpcResponse JSON object with `value` equal to: + +- `` - if the query blockhash has expired; or +- `` - otherwise, a JSON object containing: + - `feeCalculator: ` - `FeeCalculator` object describing the cluster + fee rate at the queried blockhash + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getFeeCalculatorForBlockhash", + "params": [ + "GJxqhuxcgfn5Tcj6y3f8X4FeCDd2RQ6SnEMo1AAxrPRZ" + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 221 + }, + "value": { + "feeCalculator": { + "lamportsPerSignature": 5000 + } + } + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/deprecated/getFeeRateGovernor.mdx b/docs/uk/rpc/deprecated/getFeeRateGovernor.mdx new file mode 100644 index 000000000..292be480e --- /dev/null +++ b/docs/uk/rpc/deprecated/getFeeRateGovernor.mdx @@ -0,0 +1,74 @@ +--- +sidebarLabel: getFeeRateGovernor +title: getFeeRateGovernor RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getFeeRateGovernor + - /docs/rpc/http/getFeeRateGovernor +--- + +Returns the fee rate governor information from the root bank + + + This method is expected to be removed in `solana-core` v2.0. Please use + [getFeeForMessage](/docs/rpc/http/getFeeForMessage) instead. + + + + + + +### Parameters + +**None** + +### Result + +The result will be an RpcResponse JSON object with `value` equal to an `object` +with the following fields: + +- `burnPercent: ` - Percentage of fees collected to be destroyed +- `maxLamportsPerSignature: ` - Largest value `lamportsPerSignature` can + attain for the next slot +- `minLamportsPerSignature: ` - Smallest value `lamportsPerSignature` can + attain for the next slot +- `targetLamportsPerSignature: ` - Desired fee rate for the cluster +- `targetSignaturesPerSlot: ` - Desired signature rate for the cluster + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getFeeRateGovernor"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 54 + }, + "value": { + "feeRateGovernor": { + "burnPercent": 50, + "maxLamportsPerSignature": 100000, + "minLamportsPerSignature": 5000, + "targetLamportsPerSignature": 10000, + "targetSignaturesPerSlot": 20000 + } + } + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/deprecated/getFees.mdx b/docs/uk/rpc/deprecated/getFees.mdx new file mode 100644 index 000000000..30f0a2435 --- /dev/null +++ b/docs/uk/rpc/deprecated/getFees.mdx @@ -0,0 +1,91 @@ +--- +sidebarLabel: getFees +title: getFees RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getFees + - /docs/rpc/http/getFees +--- + +Returns a recent block hash from the ledger, a fee schedule that can be used to +compute the cost of submitting a transaction using it, and the last slot in +which the blockhash will be valid. + + + This method is expected to be removed in `solana-core` v2.0. Please use + [getFeeForMessage](/docs/rpc/http/getFeeForMessage) instead. + + + + + + +### Parameters + + + Pubkey of account to query, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + +### Result + +The result will be an RpcResponse JSON object with `value` set to a JSON object +with the following fields: + +- `blockhash: ` - a Hash as base-58 encoded string +- `feeCalculator: ` - FeeCalculator object, the fee schedule for this + block hash +- `lastValidSlot: ` - DEPRECATED - this value is inaccurate and should not + be relied upon +- `lastValidBlockHeight: ` - last + [block height](/docs/terminology.md#block-height) at which the blockhash will + be valid + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { "jsonrpc":"2.0", "id": 1, "method":"getFees"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 1 + }, + "value": { + "blockhash": "CSymwgTNX1j3E4qhKfJAUE41nBWEwXufoYryPbkde5RR", + "feeCalculator": { + "lamportsPerSignature": 5000 + }, + "lastValidSlot": 297, + "lastValidBlockHeight": 296 + } + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/deprecated/getRecentBlockhash.mdx b/docs/uk/rpc/deprecated/getRecentBlockhash.mdx new file mode 100644 index 000000000..5668aa90a --- /dev/null +++ b/docs/uk/rpc/deprecated/getRecentBlockhash.mdx @@ -0,0 +1,85 @@ +--- +sidebarLabel: getRecentBlockhash +title: getRecentBlockhash RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/http/getRecentBlockhash + - /docs/rpc/getRecentBlockhash +--- + +Returns a recent block hash from the ledger, and a fee schedule that can be used +to compute the cost of submitting a transaction using it. + + + This method is expected to be removed in `solana-core` v2.0. Please use + [getLatestBlockhash](/docs/rpc/http/getlatestblockhash) instead. + + + + + + +### Parameters + + + Pubkey of account to query, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + +### Result + +An RpcResponse containing a JSON object consisting of a string blockhash and +FeeCalculator JSON object. + +- `RpcResponse` - RpcResponse JSON object with `value` field set to a + JSON object including: +- `blockhash: ` - a Hash as base-58 encoded string +- `feeCalculator: ` - FeeCalculator object, the fee schedule for this + block hash + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getRecentBlockhash"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 1 + }, + "value": { + "blockhash": "CSymwgTNX1j3E4qhKfJAUE41nBWEwXufoYryPbkde5RR", + "feeCalculator": { + "lamportsPerSignature": 5000 + } + } + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/deprecated/getSignatureConfirmation.mdx b/docs/uk/rpc/deprecated/getSignatureConfirmation.mdx new file mode 100644 index 000000000..6bdda7caf --- /dev/null +++ b/docs/uk/rpc/deprecated/getSignatureConfirmation.mdx @@ -0,0 +1,13 @@ +--- +sidebarLabel: getSignatureConfirmation +title: getSignatureConfirmation RPC Method +hideTableOfContents: true +--- + +Fetch the current status of a transaction signature (processed, confirmed, +finalized). + + + This method is expected to be removed in `solana-core` v2.0. Please use + [getSignatureStatuses](/docs/rpc/http/getSignatureStatuses) instead. + diff --git a/docs/uk/rpc/deprecated/getSignatureStatus.mdx b/docs/uk/rpc/deprecated/getSignatureStatus.mdx new file mode 100644 index 000000000..fa6211755 --- /dev/null +++ b/docs/uk/rpc/deprecated/getSignatureStatus.mdx @@ -0,0 +1,13 @@ +--- +sidebarLabel: getSignatureStatus +title: getSignatureStatus RPC Method +hideTableOfContents: true +--- + +Fetch the current status of a transaction signature (processed, confirmed, +finalized). + + + This method is expected to be removed in `solana-core` v2.0. Please use + [getSignatureStatuses](/docs/rpc/http/getSignatureStatuses) instead. + diff --git a/docs/uk/rpc/deprecated/getSnapshotSlot.mdx b/docs/uk/rpc/deprecated/getSnapshotSlot.mdx new file mode 100644 index 000000000..6b4d83fc7 --- /dev/null +++ b/docs/uk/rpc/deprecated/getSnapshotSlot.mdx @@ -0,0 +1,58 @@ +--- +sidebarLabel: getSnapshotSlot +title: getSnapshotSlot RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/http/getSnapshotSlot + - /docs/rpc/getSnapshotSlot +--- + +Returns the highest slot that the node has a snapshot for + + + This method is expected to be removed in `solana-core` v2.0. Please use + [getHighestSnapshotSlot](/docs/rpc/http/getHighestSnapshotSlot) instead. + + + + + + +### Parameters + +**None** + +### Result + +`` - Snapshot slot + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getSnapshotSlot"} +' +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 100, "id": 1 } +``` + +Result when the node has no snapshot: + +```json +{ + "jsonrpc": "2.0", + "error": { "code": -32008, "message": "No snapshot" }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/deprecated/getStakeActivation.mdx b/docs/uk/rpc/deprecated/getStakeActivation.mdx new file mode 100644 index 000000000..c0a808703 --- /dev/null +++ b/docs/uk/rpc/deprecated/getStakeActivation.mdx @@ -0,0 +1,97 @@ +--- +sidebarLabel: getStakeActivation +title: getStakeActivation RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/http/getStakeActivation +--- + +Returns epoch activation information for a stake account + + + This method is expected to be removed in `solana-core` v2.0. Please use [this + alternative + approach](https://github.com/solana-developers/solana-rpc-get-stake-activation) + instead. + + + + + + +### Parameters + + + Pubkey of stake Account to query, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + epoch for which to calculate activation details. If parameter not provided, + defaults to current epoch. **DEPRECATED**, inputs other than the current epoch + return an error. + + + + +### Result + +The result will be a JSON object with the following fields: + +- `state: ` - the stake account's activation state, either: `active`, + `inactive`, `activating`, or `deactivating` +- `active: ` - stake active during the epoch +- `inactive: ` - stake inactive during the epoch + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getStakeActivation", + "params": [ + "CYRJWqiSjLitBAcRxPvWpgX3s5TvmN2SuRY3eEYypFvT", + { + "epoch": 4 + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "active": 124429280, + "inactive": 73287840, + "state": "activating" + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/deprecated/index.mdx b/docs/uk/rpc/deprecated/index.mdx new file mode 100644 index 000000000..45ee991ad --- /dev/null +++ b/docs/uk/rpc/deprecated/index.mdx @@ -0,0 +1,6 @@ +--- +title: Deprecated Methods +sidebarSortOrder: 9999 +hideTableOfContents: true +metaOnly: true +--- diff --git a/docs/uk/rpc/http/getAccountInfo.mdx b/docs/uk/rpc/http/getAccountInfo.mdx new file mode 100644 index 000000000..a96d9ebb2 --- /dev/null +++ b/docs/uk/rpc/http/getAccountInfo.mdx @@ -0,0 +1,138 @@ +--- +sidebarLabel: getAccountInfo +title: getAccountInfo RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getAccountInfo +--- + +Returns all information associated with the account of provided Pubkey + + + + + +### Parameters + + + Pubkey of account to query, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + +Encoding format for Account data + + + +
+ +- `base58` is slow and limited to less than 129 bytes of Account data. +- `base64` will return base64 encoded data for Account data of any size. +- `base64+zstd` compresses the Account data using + [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result. +- `jsonParsed` encoding attempts to use program-specific state parsers to return + more human-readable and explicit account state data. +- If `jsonParsed` is requested but a parser cannot be found, the field falls + back to `base64` encoding, detectable when the `data` field is type `string`. + +
+ +
+ + + Request a slice of the account's data. + +- `length: ` - number of bytes to return +- `offset: ` - byte offset from which to start reading + + + Data slicing is only available for `base58`, `base64`, or `base64+zstd` + encodings. + + + + + + The minimum slot that the request can be evaluated at + + +
+ +### Result + +The result will be an RpcResponse JSON object with `value` equal to: + +- `` - if the requested account doesn't exist +- `` - otherwise, a JSON object containing: + - `lamports: ` - number of lamports assigned to this account, as a u64 + - `owner: ` - base-58 encoded Pubkey of the program this account has + been assigned to + - `data: <[string, encoding]|object>` - data associated with the account, + either as encoded binary data or JSON format `{: }` - + depending on encoding parameter + - `executable: ` - boolean indicating if the account contains a program + \(and is strictly read-only\) + - `rentEpoch: ` - the epoch at which this account will next owe rent, as + u64 + - `space: ` - the data size of the account + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getAccountInfo", + "params": [ + "vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg", + { + "encoding": "base58" + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { "apiVersion": "2.0.15", "slot": 341197053 }, + "value": { + "data": ["", "base58"], + "executable": false, + "lamports": 88849814690250, + "owner": "11111111111111111111111111111111", + "rentEpoch": 18446744073709551615, + "space": 0 + } + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getBalance.mdx b/docs/uk/rpc/http/getBalance.mdx new file mode 100644 index 000000000..514f653cf --- /dev/null +++ b/docs/uk/rpc/http/getBalance.mdx @@ -0,0 +1,72 @@ +--- +sidebarLabel: getBalance +title: getBalance RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getBalance +--- + +Returns the lamport balance of the account of provided Pubkey + + + + + +### Parameters + + + Pubkey of account to query, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + +### Result + +`RpcResponse` - RpcResponse JSON object with `value` field set to the +balance + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", "id": 1, + "method": "getBalance", + "params": [ + "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri" + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { "context": { "slot": 1 }, "value": 0 }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getBlock.mdx b/docs/uk/rpc/http/getBlock.mdx new file mode 100644 index 000000000..d75329dc4 --- /dev/null +++ b/docs/uk/rpc/http/getBlock.mdx @@ -0,0 +1,287 @@ +--- +sidebarLabel: getBlock +title: getBlock RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getBlock +--- + +Returns identity and transaction information about a confirmed block in the +ledger + + + + + +### Parameters + + + slot number, as `u64` integer + + + + +Configuration object containing the following fields: + + + +- `processed` is not supported. + + + + + +encoding format for each returned Transaction + + + +
+ +- `jsonParsed` attempts to use program-specific instruction parsers to return + more human-readable and explicit data in the + `transaction.message.instructions` list. +- If `jsonParsed` is requested but a parser cannot be found, the instruction + falls back to regular JSON encoding (`accounts`, `data`, and `programIdIndex` + fields). + +
+ +
+ + + +level of transaction detail to return + + + +
+ +- If `accounts` are requested, transaction details only include signatures and + an annotated list of accounts in each transaction. +- Transaction metadata is limited to only: fee, err, pre_balances, + post_balances, pre_token_balances, and post_token_balances. + +
+ +
+ + + +the max transaction version to return in responses. + +
+ +- If the requested block contains a transaction with a higher version, an error + will be returned. +- If this parameter is omitted, only legacy transactions will be returned, and a + block containing any versioned transaction will prompt the error. + +
+ +
+ + + whether to populate the `rewards` array. If parameter not provided, the + default includes rewards. + + +
+ +### Result + +The result field will be an object with the following fields: + +- `` - if specified block is not confirmed +- `` - if block is confirmed, an object with the following fields: + - `blockhash: ` - the blockhash of this block, as base-58 encoded + string + - `previousBlockhash: ` - the blockhash of this block's parent, as + base-58 encoded string; if the parent block is not available due to ledger + cleanup, this field will return "11111111111111111111111111111111" + - `parentSlot: ` - the slot index of this block's parent + - `transactions: ` - present if "full" transaction details are + requested; an array of JSON objects containing: + - `transaction: ` - + [Transaction](/docs/rpc/json-structures#transactions) object, either in + JSON format or encoded binary data, depending on encoding parameter + - `meta: ` - transaction status metadata object, containing `null` + or: + - `err: ` - Error if transaction failed, null if transaction + succeeded. + [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) + - `fee: ` - fee this transaction was charged, as u64 integer + - `preBalances: ` - array of u64 account balances from before the + transaction was processed + - `postBalances: ` - array of u64 account balances after the + transaction was processed + - `innerInstructions: ` - List of + [inner instructions](/docs/rpc/json-structures#inner-instructions) or + `null` if inner instruction recording was not enabled during this + transaction + - `preTokenBalances: ` - List of + [token balances](/docs/rpc/json-structures#token-balances) from before + the transaction was processed or omitted if token balance recording was + not yet enabled during this transaction + - `postTokenBalances: ` - List of + [token balances](/docs/rpc/json-structures#token-balances) from after + the transaction was processed or omitted if token balance recording was + not yet enabled during this transaction + - `logMessages: ` - array of string log messages or `null` if + log message recording was not enabled during this transaction + - `rewards: ` - transaction-level rewards, populated if + rewards are requested; an array of JSON objects containing: + - `pubkey: ` - The public key, as base-58 encoded string, of the + account that received the reward + - `lamports: `- number of reward lamports credited or debited by + the account, as a i64 + - `postBalance: ` - account balance in lamports after the reward + was applied + - `rewardType: ` - type of reward: "fee", "rent", + "voting", "staking" + - `commission: ` - vote account commission when the reward + was credited, only present for voting and staking rewards + - DEPRECATED: `status: ` - Transaction status + - `"Ok": ` - Transaction was successful + - `"Err": ` - Transaction failed with TransactionError + - `loadedAddresses: ` - Transaction addresses loaded + from address lookup tables. Undefined if + `maxSupportedTransactionVersion` is not set in request params, or if + `jsonParsed` encoding is set in request params. + - `writable: ` - Ordered list of base-58 encoded + addresses for writable loaded accounts + - `readonly: ` - Ordered list of base-58 encoded + addresses for readonly loaded accounts + - `returnData: ` - the most-recent return data generated + by an instruction in the transaction, with the following fields: + - `programId: ` - the program that generated the return data, as + base-58 encoded Pubkey + - `data: <[string, encoding]>` - the return data itself, as base-64 + encoded binary data + - `computeUnitsConsumed: ` - number of + [compute units](/docs/core/fees.md#compute-budget) consumed by the + transaction + - `version: <"legacy"|number|undefined>` - Transaction version. Undefined if + `maxSupportedTransactionVersion` is not set in request params. + - `signatures: ` - present if "signatures" are requested for + transaction details; an array of signatures strings, corresponding to the + transaction order in the block + - `rewards: ` - block-level rewards, present if rewards are + requested; an array of JSON objects containing: + - `pubkey: ` - The public key, as base-58 encoded string, of the + account that received the reward + - `lamports: `- number of reward lamports credited or debited by the + account, as a i64 + - `postBalance: ` - account balance in lamports after the reward was + applied + - `rewardType: ` - type of reward: "fee", "rent", + "voting", "staking" + - `commission: ` - vote account commission when the reward was + credited, only present for voting and staking rewards + - `blockTime: ` - estimated production time, as Unix timestamp + (seconds since the Unix epoch). null if not available + - `blockHeight: ` - the number of blocks beneath this block + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0","id":1, + "method":"getBlock", + "params": [ + 430, + { + "encoding": "json", + "maxSupportedTransactionVersion":0, + "transactionDetails":"full", + "rewards":false + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "blockHeight": 428, + "blockTime": null, + "blockhash": "3Eq21vXNB5s86c62bVuUfTeaMif1N2kUqRPBmGRJhyTA", + "parentSlot": 429, + "previousBlockhash": "mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B", + "transactions": [ + { + "meta": { + "err": null, + "fee": 5000, + "innerInstructions": [], + "logMessages": [], + "postBalances": [499998932500, 26858640, 1, 1, 1], + "postTokenBalances": [], + "preBalances": [499998937500, 26858640, 1, 1, 1], + "preTokenBalances": [], + "rewards": null, + "status": { + "Ok": null + } + }, + "transaction": { + "message": { + "accountKeys": [ + "3UVYmECPPMZSCqWKfENfuoTv51fTDTWicX9xmBD2euKe", + "AjozzgE83A3x1sHNUR64hfH7zaEBWeMaFuAN9kQgujrc", + "SysvarS1otHashes111111111111111111111111111", + "SysvarC1ock11111111111111111111111111111111", + "Vote111111111111111111111111111111111111111" + ], + "header": { + "numReadonlySignedAccounts": 0, + "numReadonlyUnsignedAccounts": 3, + "numRequiredSignatures": 1 + }, + "instructions": [ + { + "accounts": [1, 2, 3, 0], + "data": "37u9WtQpcm6ULa3WRQHmj49EPs4if7o9f1jSRVZpm2dvihR9C8jY4NqEwXUbLwx15HBSNcP1", + "programIdIndex": 4 + } + ], + "recentBlockhash": "mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B" + }, + "signatures": [ + "2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv" + ] + } + } + ] + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getBlockCommitment.mdx b/docs/uk/rpc/http/getBlockCommitment.mdx new file mode 100644 index 000000000..3d4446da0 --- /dev/null +++ b/docs/uk/rpc/http/getBlockCommitment.mdx @@ -0,0 +1,65 @@ +--- +sidebarLabel: getBlockCommitment +title: getBlockCommitment RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getBlockCommitment +--- + +Returns commitment for particular block + + + + + +### Parameters + + + block number, identified by Slot + + +### Result + +The result field will be a JSON object containing: + +- `commitment` - commitment, comprising either: + - `` - Unknown block + - `` - commitment, array of u64 integers logging the amount of cluster + stake in lamports that has voted on the block at each depth from 0 to + `MAX_LOCKOUT_HISTORY` + 1 +- `totalStake` - total active stake, in lamports, of the current epoch + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", "id": 1, + "method": "getBlockCommitment", + "params":[5] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "commitment": [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 32 + ], + "totalStake": 42 + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getBlockHeight.mdx b/docs/uk/rpc/http/getBlockHeight.mdx new file mode 100644 index 000000000..8be00d7b0 --- /dev/null +++ b/docs/uk/rpc/http/getBlockHeight.mdx @@ -0,0 +1,66 @@ +--- +sidebarLabel: getBlockHeight +title: getBlockHeight RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getBlockHeight +--- + +Returns the current block height of the node + + + + + +### Parameters + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + +### Result + +- `` - Current block height + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc":"2.0","id":1, + "method":"getBlockHeight" + } +' +``` + +Result: + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": 1233, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getBlockProduction.mdx b/docs/uk/rpc/http/getBlockProduction.mdx new file mode 100644 index 000000000..90d03b34f --- /dev/null +++ b/docs/uk/rpc/http/getBlockProduction.mdx @@ -0,0 +1,94 @@ +--- +sidebarLabel: getBlockProduction +title: getBlockProduction RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getBlockProduction +--- + +Returns recent block production information from the current or previous epoch. + + + + + +### Parameters + + + +Configuration object containing the following fields: + + + + + Only return results for this validator identity (base-58 encoded) + + + +Slot range to return block production for. If parameter not provided, defaults to current epoch. + +- `firstSlot: ` - first slot to return block production information for + (inclusive) +- (optional) `lastSlot: ` - last slot to return block production + information for (inclusive). If parameter not provided, defaults to the + highest slot + + + + + +### Result + +The result will be an RpcResponse JSON object with `value` equal to: + +- `` + - `byIdentity: ` - a dictionary of validator identities, as base-58 + encoded strings. Value is a two element array containing the number of + leader slots and the number of blocks produced. + - `range: ` - Block production slot range + - `firstSlot: ` - first slot of the block production information + (inclusive) + - `lastSlot: ` - last slot of block production information (inclusive) + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getBlockProduction"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 9887 + }, + "value": { + "byIdentity": { + "85iYT5RuzRTDgjyRa3cP8SYhM2j21fj7NhfJ3peu1DPr": [9888, 9886] + }, + "range": { + "firstSlot": 0, + "lastSlot": 9887 + } + } + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getBlockTime.mdx b/docs/uk/rpc/http/getBlockTime.mdx new file mode 100644 index 000000000..c0435fab4 --- /dev/null +++ b/docs/uk/rpc/http/getBlockTime.mdx @@ -0,0 +1,75 @@ +--- +sidebarLabel: getBlockTime +title: getBlockTime RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getBlockTime +--- + +Returns the estimated production time of a block. + + + Each validator reports their UTC time to the ledger on a regular interval by + intermittently adding a timestamp to a Vote for a particular block. A + requested block's time is calculated from the stake-weighted mean of the Vote + timestamps in a set of recent blocks recorded on the ledger. + + + + + + +### Parameters + + + block number, identified by Slot + + +### Result + +- `` - estimated production time, as Unix timestamp (seconds since the Unix + epoch) + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc":"2.0", "id":1, + "method": "getBlockTime", + "params":[5] + } +' +``` + +### Response + +When a block time is available: + +```json +{ + "jsonrpc": "2.0", + "result": 1574721591, + "id": 1 +} +``` + +When a block time is not available: + +```json +{ + "jsonrpc": "2.0", + "error": { + "code": -32004, + "message": "Block not available for slot 150" + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getBlocks.mdx b/docs/uk/rpc/http/getBlocks.mdx new file mode 100644 index 000000000..3967e2a85 --- /dev/null +++ b/docs/uk/rpc/http/getBlocks.mdx @@ -0,0 +1,79 @@ +--- +sidebarLabel: getBlocks +title: getBlocks RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getBlocks +--- + +Returns a list of confirmed blocks between two slots + + + + + +### Parameters + + + start_slot, as `u64` integer + + + + end_slot, as `u64` integer (must be no more than 500,000 blocks higher than + the `start_slot`) + + + + +Configuration object containing the following fields: + + + +- "processed" is not supported + + + + + +### Result + +The result field will be an array of u64 integers listing confirmed blocks +between `start_slot` and either `end_slot` - if provided, or latest confirmed +block, inclusive. Max range allowed is 500,000 slots. + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", "id": 1, + "method": "getBlocks", + "params": [ + 5, 10 + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": [5, 6, 7, 8, 9, 10], + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getBlocksWithLimit.mdx b/docs/uk/rpc/http/getBlocksWithLimit.mdx new file mode 100644 index 000000000..f86b888bc --- /dev/null +++ b/docs/uk/rpc/http/getBlocksWithLimit.mdx @@ -0,0 +1,77 @@ +--- +sidebarLabel: getBlocksWithLimit +title: getBlocksWithLimit RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getBlocksWithLimit +--- + +Returns a list of confirmed blocks starting at the given slot + + + + + +### Parameters + + + start_slot, as `u64` integer + + + + limit, as `u64` integer (must be no more than 500,000 blocks higher than the + `start_slot`) + + + + +Configuration object containing the following field: + + + +- "processed" is not supported + + + + + +### Result + +The result field will be an array of u64 integers listing confirmed blocks +starting at `start_slot` for up to `limit` blocks, inclusive. + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id":1, + "method":"getBlocksWithLimit", + "params":[5, 3] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": [5, 6, 7], + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getClusterNodes.mdx b/docs/uk/rpc/http/getClusterNodes.mdx new file mode 100644 index 000000000..18e685a75 --- /dev/null +++ b/docs/uk/rpc/http/getClusterNodes.mdx @@ -0,0 +1,69 @@ +--- +sidebarLabel: getClusterNodes +title: getClusterNodes RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getClusterNodes +--- + +Returns information about all the nodes participating in the cluster + + + + + +### Parameters + +**None** + +### Result + +The result field will be an array of JSON objects, each with the following sub +fields: + +- `pubkey: ` - Node public key, as base-58 encoded string +- `gossip: ` - Gossip network address for the node +- `tpu: ` - TPU network address for the node +- `rpc: ` - JSON RPC network address for the node, or `null` if the + JSON RPC service is not enabled +- `version: ` - The software version of the node, or `null` if the + version information is not available +- `featureSet: ` - The unique identifier of the node's feature set +- `shredVersion: ` - The shred version the node has been configured to + use + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", "id": 1, + "method": "getClusterNodes" + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": [ + { + "gossip": "10.239.6.48:8001", + "pubkey": "9QzsJf7LPLj8GkXbYT3LFDKqsj2hHG7TA3xinJHu8epQ", + "rpc": "10.239.6.48:8899", + "tpu": "10.239.6.48:8856", + "version": "1.0.0 c375ce1f" + } + ], + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getEpochInfo.mdx b/docs/uk/rpc/http/getEpochInfo.mdx new file mode 100644 index 000000000..ce4f696e6 --- /dev/null +++ b/docs/uk/rpc/http/getEpochInfo.mdx @@ -0,0 +1,76 @@ +--- +sidebarLabel: getEpochInfo +title: getEpochInfo RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getEpochInfo +--- + +Returns information about the current epoch + + + + + +### Parameters + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + +### Result + +The result field will be an object with the following fields: + +- `absoluteSlot: ` - the current slot +- `blockHeight: ` - the current block height +- `epoch: ` - the current epoch +- `slotIndex: ` - the current slot relative to the start of the current + epoch +- `slotsInEpoch: ` - the number of slots in this epoch +- `transactionCount: ` - total number of transactions processed + without error since genesis + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getEpochInfo"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "absoluteSlot": 166598, + "blockHeight": 166500, + "epoch": 27, + "slotIndex": 2790, + "slotsInEpoch": 8192, + "transactionCount": 22661093 + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getEpochSchedule.mdx b/docs/uk/rpc/http/getEpochSchedule.mdx new file mode 100644 index 000000000..46f61341f --- /dev/null +++ b/docs/uk/rpc/http/getEpochSchedule.mdx @@ -0,0 +1,64 @@ +--- +sidebarLabel: getEpochSchedule +title: getEpochSchedule RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getEpochSchedule +--- + +Returns the epoch schedule information from this cluster's genesis config + + + + + +### Parameters + +**None** + +### Result + +The result field will be an object with the following fields: + +- `slotsPerEpoch: ` - the maximum number of slots in each epoch +- `leaderScheduleSlotOffset: ` - the number of slots before beginning of an + epoch to calculate a leader schedule for that epoch +- `warmup: ` - whether epochs start short and grow +- `firstNormalEpoch: ` - first normal-length epoch, log2(slotsPerEpoch) - + log2(MINIMUM_SLOTS_PER_EPOCH) +- `firstNormalSlot: ` - MINIMUM_SLOTS_PER_EPOCH \* + (2.pow(firstNormalEpoch) - 1) + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc":"2.0","id":1, + "method":"getEpochSchedule" + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "firstNormalEpoch": 8, + "firstNormalSlot": 8160, + "leaderScheduleSlotOffset": 8192, + "slotsPerEpoch": 8192, + "warmup": true + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getFeeForMessage.mdx b/docs/uk/rpc/http/getFeeForMessage.mdx new file mode 100644 index 000000000..3c2ee74be --- /dev/null +++ b/docs/uk/rpc/http/getFeeForMessage.mdx @@ -0,0 +1,80 @@ +--- +sidebarLabel: getFeeForMessage +title: getFeeForMessage RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getFeeForMessage +--- + +Get the fee the network will charge for a particular Message + + + This method is only available in `solana-core` v1.9 or newer. Please use + [getFees](/docs/rpc/deprecated/getFees.mdx) for `solana-core` v1.8 and below. + + + + + + +### Parameters + + + Base-64 encoded Message + + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + +### Result + +- `` - Fee corresponding to the message at the specified blockhash + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' +{ + "id":1, + "jsonrpc":"2.0", + "method":"getFeeForMessage", + "params":[ + "AQABAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAA", + { + "commitment":"processed" + } + ] +} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { "context": { "slot": 5068 }, "value": 5000 }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getFirstAvailableBlock.mdx b/docs/uk/rpc/http/getFirstAvailableBlock.mdx new file mode 100644 index 000000000..c21af52eb --- /dev/null +++ b/docs/uk/rpc/http/getFirstAvailableBlock.mdx @@ -0,0 +1,45 @@ +--- +sidebarLabel: getFirstAvailableBlock +title: getFirstAvailableBlock RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getFirstAvailableBlock +--- + +Returns the slot of the lowest confirmed block that has not been purged from the +ledger + + + + + +### Parameters + +**None** + +### Result + +- `` - Slot + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc":"2.0","id":1, + "method":"getFirstAvailableBlock" + } +' +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 250000, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/http/getGenesisHash.mdx b/docs/uk/rpc/http/getGenesisHash.mdx new file mode 100644 index 000000000..e7f537644 --- /dev/null +++ b/docs/uk/rpc/http/getGenesisHash.mdx @@ -0,0 +1,45 @@ +--- +sidebarLabel: getGenesisHash +title: getGenesisHash RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getGenesisHash +--- + +Returns the genesis hash + + + + + +### Parameters + +**None** + +### Result + +- `` - a Hash as base-58 encoded string + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getGenesisHash"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": "GH7ome3EiwEr7tu9JuTh2dpYWBJK3z69Xm1ZE3MEE6JC", + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getHealth.mdx b/docs/uk/rpc/http/getHealth.mdx new file mode 100644 index 000000000..48952db2c --- /dev/null +++ b/docs/uk/rpc/http/getHealth.mdx @@ -0,0 +1,78 @@ +--- +sidebarLabel: getHealth +title: getHealth RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getHealth +--- + +Returns the current health of the node. A healthy node is one that is within +`HEALTH_CHECK_SLOT_DISTANCE` slots of the latest cluster confirmed slot. + + + + + +### Parameters + +**None** + +### Result + +If the node is healthy: "ok" + +If the node is unhealthy, a JSON RPC error response is returned. The specifics +of the error response are **UNSTABLE** and may change in the future + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getHealth"} +' +``` + +### Response + +Healthy Result: + +```json +{ "jsonrpc": "2.0", "result": "ok", "id": 1 } +``` + +Unhealthy Result (generic): + +```json +{ + "jsonrpc": "2.0", + "error": { + "code": -32005, + "message": "Node is unhealthy", + "data": {} + }, + "id": 1 +} +``` + +Unhealthy Result (if additional information is available) + +```json +{ + "jsonrpc": "2.0", + "error": { + "code": -32005, + "message": "Node is behind by 42 slots", + "data": { + "numSlotsBehind": 42 + } + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getHighestSnapshotSlot.mdx b/docs/uk/rpc/http/getHighestSnapshotSlot.mdx new file mode 100644 index 000000000..e851c05a0 --- /dev/null +++ b/docs/uk/rpc/http/getHighestSnapshotSlot.mdx @@ -0,0 +1,75 @@ +--- +sidebarLabel: getHighestSnapshotSlot +title: getHighestSnapshotSlot RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getHighestSnapshotSlot +--- + +Returns the highest slot information that the node has snapshots for. + +This will find the highest full snapshot slot, and the highest incremental +snapshot slot _based on_ the full snapshot slot, if there is one. + + + This method is only available in `solana-core` v1.9 or newer. Please use + [getSnapshotSlot](/docs/rpc/http/getSnapshotSlot) for `solana-core` v1.8 and + below. + + + + + + +### Parameters + +**None** + +### Result + +When the node has a snapshot, this returns a JSON object with the following +fields: + +- `full: ` - Highest full snapshot slot +- `incremental: ` - Highest incremental snapshot slot _based on_ + `full` + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1,"method":"getHighestSnapshotSlot"} +' +``` + +### Response + +Result when the node has a snapshot: + +```json +{ + "jsonrpc": "2.0", + "result": { + "full": 100, + "incremental": 110 + }, + "id": 1 +} +``` + +Result when the node has no snapshot: + +```json +{ + "jsonrpc": "2.0", + "error": { "code": -32008, "message": "No snapshot" }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getIdentity.mdx b/docs/uk/rpc/http/getIdentity.mdx new file mode 100644 index 000000000..a027615ad --- /dev/null +++ b/docs/uk/rpc/http/getIdentity.mdx @@ -0,0 +1,50 @@ +--- +sidebarLabel: getIdentity +title: getIdentity RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getIdentity +--- + +Returns the identity pubkey for the current node + + + + + +### Parameters + +**None** + +### Result + +The result field will be a JSON object with the following fields: + +- `identity` - the identity pubkey of the current node \(as a base-58 encoded + string\) + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getIdentity"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "identity": "2r1F4iWqVcb8M1DbAjQuFpebkQHY9hcVU4WuW2DJBppN" + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getInflationGovernor.mdx b/docs/uk/rpc/http/getInflationGovernor.mdx new file mode 100644 index 000000000..e93e7bd5e --- /dev/null +++ b/docs/uk/rpc/http/getInflationGovernor.mdx @@ -0,0 +1,71 @@ +--- +sidebarLabel: getInflationGovernor +title: getInflationGovernor RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getInflationGovernor +--- + +Returns the current inflation governor + + + + + +### Parameters + + + +Configuration object containing the following fields: + + + + + +### Result + +The result field will be a JSON object with the following fields: + +- `initial: ` - the initial inflation percentage from time 0 +- `terminal: ` - terminal inflation percentage +- `taper: ` - rate per year at which inflation is lowered. (Rate reduction + is derived using the target slot time in genesis config) +- `foundation: ` - percentage of total inflation allocated to the + foundation +- `foundationTerm: ` - duration of foundation pool inflation in years + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getInflationGovernor"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "foundation": 0.05, + "foundationTerm": 7, + "initial": 0.15, + "taper": 0.15, + "terminal": 0.015 + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getInflationRate.mdx b/docs/uk/rpc/http/getInflationRate.mdx new file mode 100644 index 000000000..78120b0c0 --- /dev/null +++ b/docs/uk/rpc/http/getInflationRate.mdx @@ -0,0 +1,56 @@ +--- +sidebarLabel: getInflationRate +title: getInflationRate RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getInflationRate +--- + +Returns the specific inflation values for the current epoch + + + + + +### Parameters + +**None** + +### Result + +The result field will be a JSON object with the following fields: + +- `total: ` - total inflation +- `validator: ` -inflation allocated to validators +- `foundation: ` - inflation allocated to the foundation +- `epoch: ` - epoch for which these values are valid + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getInflationRate"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "epoch": 100, + "foundation": 0.001, + "total": 0.149, + "validator": 0.148 + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getInflationReward.mdx b/docs/uk/rpc/http/getInflationReward.mdx new file mode 100644 index 000000000..87d83acf7 --- /dev/null +++ b/docs/uk/rpc/http/getInflationReward.mdx @@ -0,0 +1,96 @@ +--- +sidebarLabel: getInflationReward +title: getInflationReward RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getInflationReward +--- + +Returns the inflation / staking reward for a list of addresses for an epoch + + + + + +### Parameters + + + An array of addresses to query, as base-58 encoded strings + + + + +Configuration object containing the following fields: + + + + + An epoch for which the reward occurs. If omitted, the previous epoch will be + used + + + + The minimum slot that the request can be evaluated at + + + + +### Result + +The result field will be a JSON array with the following fields: + +- `epoch: ` - epoch for which reward occurred +- `effectiveSlot: ` - the slot in which the rewards are effective +- `amount: ` - reward amount in lamports +- `postBalance: ` - post balance of the account in lamports +- `commission: ` - vote account commission when the reward was + credited + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getInflationReward", + "params": [ + [ + "6dmNQ5jwLeLk5REvio1JcMshcbvkYMwy26sJ8pbkvStu", + "BGsqMegLpV6n6Ve146sSX2dTjUMj3M92HnU8BbNRMhF2" + ], + {"epoch": 2} + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": [ + { + "amount": 2500, + "effectiveSlot": 224, + "epoch": 2, + "postBalance": 499999442500 + }, + null + ], + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getLargestAccounts.mdx b/docs/uk/rpc/http/getLargestAccounts.mdx new file mode 100644 index 000000000..6ca86f8a3 --- /dev/null +++ b/docs/uk/rpc/http/getLargestAccounts.mdx @@ -0,0 +1,146 @@ +--- +sidebarLabel: getLargestAccounts +title: getLargestAccounts RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getLargestAccounts +--- + +Returns the 20 largest accounts, by lamport balance (results may be cached up to +two hours) + + + + + +### Parameters + + + +Configuration object containing the following fields: + + + + + filter results by account type + + + + + + +### Result + +The result will be an RpcResponse JSON object with `value` equal to an array of +`` containing: + +- `address: ` - base-58 encoded address of the account +- `lamports: ` - number of lamports in the account, as a u64 + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getLargestAccounts"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 54 + }, + "value": [ + { + "lamports": 999974, + "address": "99P8ZgtJYe1buSK8JXkvpLh8xPsCFuLYhz9hQFNw93WJ" + }, + { + "lamports": 42, + "address": "uPwWLo16MVehpyWqsLkK3Ka8nLowWvAHbBChqv2FZeL" + }, + { + "lamports": 42, + "address": "aYJCgU7REfu3XF8b3QhkqgqQvLizx8zxuLBHA25PzDS" + }, + { + "lamports": 42, + "address": "CTvHVtQ4gd4gUcw3bdVgZJJqApXE9nCbbbP4VTS5wE1D" + }, + { + "lamports": 20, + "address": "4fq3xJ6kfrh9RkJQsmVd5gNMvJbuSHfErywvEjNQDPxu" + }, + { + "lamports": 4, + "address": "AXJADheGVp9cruP8WYu46oNkRbeASngN5fPCMVGQqNHa" + }, + { + "lamports": 2, + "address": "8NT8yS6LiwNprgW4yM1jPPow7CwRUotddBVkrkWgYp24" + }, + { + "lamports": 1, + "address": "SysvarEpochSchedu1e111111111111111111111111" + }, + { + "lamports": 1, + "address": "11111111111111111111111111111111" + }, + { + "lamports": 1, + "address": "Stake11111111111111111111111111111111111111" + }, + { + "lamports": 1, + "address": "SysvarC1ock11111111111111111111111111111111" + }, + { + "lamports": 1, + "address": "StakeConfig11111111111111111111111111111111" + }, + { + "lamports": 1, + "address": "SysvarRent111111111111111111111111111111111" + }, + { + "lamports": 1, + "address": "Config1111111111111111111111111111111111111" + }, + { + "lamports": 1, + "address": "SysvarStakeHistory1111111111111111111111111" + }, + { + "lamports": 1, + "address": "SysvarRecentB1ockHashes11111111111111111111" + }, + { + "lamports": 1, + "address": "SysvarFees111111111111111111111111111111111" + }, + { + "lamports": 1, + "address": "Vote111111111111111111111111111111111111111" + } + ] + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getLatestBlockhash.mdx b/docs/uk/rpc/http/getLatestBlockhash.mdx new file mode 100644 index 000000000..b43940402 --- /dev/null +++ b/docs/uk/rpc/http/getLatestBlockhash.mdx @@ -0,0 +1,90 @@ +--- +sidebarLabel: getLatestBlockhash +title: getLatestBlockhash RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getLatestBlockhash +--- + +Returns the latest blockhash + + + This method is only available in `solana-core` v1.9 or newer. Please use + [getRecentBlockhash](/docs/rpc/http/getRecentBlockhash) for `solana-core` v1.8 + and below. + + + + + + +### Parameters + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + +### Result + +`RpcResponse` - RpcResponse JSON object with `value` field set to a JSON +object including: + +- `blockhash: ` - a Hash as base-58 encoded string +- `lastValidBlockHeight: ` - last + [block height](/docs/terminology.md#block-height) at which the blockhash will + be valid + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "id":1, + "jsonrpc":"2.0", + "method":"getLatestBlockhash", + "params":[ + { + "commitment":"processed" + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 2792 + }, + "value": { + "blockhash": "EkSnNWid2cvwEVnVx9aBqawnmiCNiDgp3gUdkDPTKN1N", + "lastValidBlockHeight": 3090 + } + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getLeaderSchedule.mdx b/docs/uk/rpc/http/getLeaderSchedule.mdx new file mode 100644 index 000000000..4ba0a3bc3 --- /dev/null +++ b/docs/uk/rpc/http/getLeaderSchedule.mdx @@ -0,0 +1,93 @@ +--- +sidebarLabel: getLeaderSchedule +title: getLeaderSchedule RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getLeaderSchedule +--- + +Returns the leader schedule for an epoch + + + + + +### Parameters + + + +Fetch the leader schedule for the epoch that corresponds to the provided slot. + + + If unspecified, the leader schedule for the current epoch is fetched + + + + + + +Configuration object containing the following fields: + + + + + Only return results for this validator identity (base-58 encoded) + + + + +### Result + +Returns a result with one of the two following values: + +- `` - if requested epoch is not found, or +- `` - the result field will be a dictionary of validator identities, as + base-58 encoded strings, and their corresponding leader slot indices as values + (indices are relative to the first slot in the requested epoch) + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getLeaderSchedule", + "params": [ + null, + { + "identity": "4Qkev8aNZcqFNSRhQzwyLMFSsi94jHqE8WNVTJzTP99F" + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "4Qkev8aNZcqFNSRhQzwyLMFSsi94jHqE8WNVTJzTP99F": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63 + ] + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getMaxRetransmitSlot.mdx b/docs/uk/rpc/http/getMaxRetransmitSlot.mdx new file mode 100644 index 000000000..b1f2a1847 --- /dev/null +++ b/docs/uk/rpc/http/getMaxRetransmitSlot.mdx @@ -0,0 +1,42 @@ +--- +sidebarLabel: getMaxRetransmitSlot +title: getMaxRetransmitSlot RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getMaxRetransmitSlot +--- + +Get the max slot seen from retransmit stage. + + + + + +### Parameters + +**None** + +### Result + +`` - Slot number + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getMaxRetransmitSlot"} +' +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 1234, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/http/getMaxShredInsertSlot.mdx b/docs/uk/rpc/http/getMaxShredInsertSlot.mdx new file mode 100644 index 000000000..059c0fd1d --- /dev/null +++ b/docs/uk/rpc/http/getMaxShredInsertSlot.mdx @@ -0,0 +1,42 @@ +--- +sidebarLabel: getMaxShredInsertSlot +title: getMaxShredInsertSlot RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getMaxShredInsertSlot +--- + +Get the max slot seen from after shred insert. + + + + + +### Parameters + +**None** + +### Result + +`` - Slot number + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getMaxShredInsertSlot"} +' +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 1234, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx b/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx new file mode 100644 index 000000000..11ef41b38 --- /dev/null +++ b/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx @@ -0,0 +1,61 @@ +--- +sidebarLabel: getMinimumBalanceForRentExemption +title: getMinimumBalanceForRentExemption RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getMinimumBalanceForRentExemption +--- + +Returns minimum balance required to make account rent exempt. + + + + + +### Parameters + + + the Account's data length + + + + +Configuration object containing the following fields: + + + + + +### Result + +`` - minimum lamports required in the Account to remain rent free + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", "id": 1, + "method": "getMinimumBalanceForRentExemption", + "params": [50] + } +' +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 500, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/http/getMultipleAccounts.mdx b/docs/uk/rpc/http/getMultipleAccounts.mdx new file mode 100644 index 000000000..ce9312bdc --- /dev/null +++ b/docs/uk/rpc/http/getMultipleAccounts.mdx @@ -0,0 +1,154 @@ +--- +sidebarLabel: getMultipleAccounts +title: getMultipleAccounts RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getMultipleAccounts +--- + +Returns the account information for a list of Pubkeys. + + + + + +### Parameters + + + An array of Pubkeys to query, as base-58 encoded strings (up to a maximum of + 100) + + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + Request a slice of the account's data. + +- `length: ` - number of bytes to return +- `offset: ` - byte offset from which to start reading + + + Data slicing is only available for `base58`, `base64`, or `base64+zstd` + encodings. + + + + + + +encoding format for the returned Account data + + + +
+ +- `base58` is slow and limited to less than 129 bytes of Account data. +- `base64` will return base64 encoded data for Account data of any size. +- `base64+zstd` compresses the Account data using + [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result. +- `jsonParsed` encoding attempts to use program-specific state parsers to return + more human-readable and explicit account state data. +- If `jsonParsed` is requested but a parser cannot be found, the field falls + back to `base64` encoding, detectable when the `data` field is type + ``. + +
+ +
+ +
+ +### Result + +The result will be a JSON object with `value` equal to an array of: + +- `` - if the account at that Pubkey doesn't exist, or +- `` - a JSON object containing: + - `lamports: ` - number of lamports assigned to this account, as a u64 + - `owner: ` - base-58 encoded Pubkey of the program this account has + been assigned to + - `data: <[string, encoding]|object>` - data associated with the account, + either as encoded binary data or JSON format `{: }` - + depending on encoding parameter + - `executable: ` - boolean indicating if the account contains a program + \(and is strictly read-only\) + - `rentEpoch: ` - the epoch at which this account will next owe rent, as + u64 + - `space: ` - the data size of the account + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getMultipleAccounts", + "params": [ + [ + "vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg", + "4fYNw3dojWmQ4dXtSGE9epjRGy9pFSx62YypT7avPYvA" + ], + { + "encoding": "base58" + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { "apiVersion": "2.0.15", "slot": 341197247 }, + "value": [ + { + "data": ["", "base58"], + "executable": false, + "lamports": 88849814690250, + "owner": "11111111111111111111111111111111", + "rentEpoch": 18446744073709551615, + "space": 0 + }, + { + "data": ["", "base58"], + "executable": false, + "lamports": 998763433, + "owner": "2WRuhE4GJFoE23DYzp2ij6ZnuQ8p9mJeU6gDgfsjR4or", + "rentEpoch": 18446744073709551615, + "space": 0 + } + ] + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getProgramAccounts.mdx b/docs/uk/rpc/http/getProgramAccounts.mdx new file mode 100644 index 000000000..dd59c122d --- /dev/null +++ b/docs/uk/rpc/http/getProgramAccounts.mdx @@ -0,0 +1,179 @@ +--- +sidebarLabel: getProgramAccounts +title: getProgramAccounts RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getProgramAccounts +--- + +Returns all accounts owned by the provided program Pubkey + + + + + +### Parameters + + + Pubkey of program, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + wrap the result in an RpcResponse JSON object + + + + +encoding format for the returned Account data + + + +
+ +- `base58` is slow and limited to less than 129 bytes of Account data. +- `base64` will return base64 encoded data for Account data of any size. +- `base64+zstd` compresses the Account data using + [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result. +- `jsonParsed` encoding attempts to use program-specific state parsers to return + more human-readable and explicit account state data. +- If `jsonParsed` is requested but a parser cannot be found, the field falls + back to `base64` encoding, detectable when the `data` field is type + ``. + +
+ +
+ + + Request a slice of the account's data. + +- `length: ` - number of bytes to return +- `offset: ` - byte offset from which to start reading + + + Data slicing is only available for `base58`, `base64`, or `base64+zstd` + encodings. + + + + + + +filter results using up to 4 filter objects + + + The resultant account(s) must meet **ALL** filter criteria to be included in + the returned results + + + + +
+ +### Result + +By default, the result field will be an array of JSON objects. + + + If the `withContext` flag is set, the array will be wrapped in an + `RpcResponse` JSON object. + + +The resultant response array will contain: + +- `pubkey: ` - the account Pubkey as base-58 encoded string +- `account: ` - a JSON object, with the following sub fields: + - `lamports: ` - number of lamports assigned to this account, as a u64 + - `owner: ` - base-58 encoded Pubkey of the program this account has + been assigned to + - `data: <[string,encoding]|object>` - data associated with the account, + either as encoded binary data or JSON format `{: }` - + depending on encoding parameter + - `executable: ` - boolean indicating if the account contains a program + \(and is strictly read-only\) + - `rentEpoch: ` - the epoch at which this account will next owe rent, as + u64 + - `space: ` - the data size of the account + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getProgramAccounts", + "params": [ + "4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T", + { + "filters": [ + { + "dataSize": 17 + }, + { + "memcmp": { + "offset": 4, + "bytes": "3Mc6vR" + } + } + ] + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": [ + { + "account": { + "data": "2R9jLfiAQ9bgdcw6h8s44439", + "executable": false, + "lamports": 15298080, + "owner": "4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T", + "rentEpoch": 28, + "space": 42 + }, + "pubkey": "CxELquR1gPP8wHe33gZ4QxqGB3sZ9RSwsJ2KshVewkFY" + } + ], + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getRecentPerformanceSamples.mdx b/docs/uk/rpc/http/getRecentPerformanceSamples.mdx new file mode 100644 index 000000000..2c431533c --- /dev/null +++ b/docs/uk/rpc/http/getRecentPerformanceSamples.mdx @@ -0,0 +1,100 @@ +--- +sidebarLabel: getRecentPerformanceSamples +title: getRecentPerformanceSamples RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getRecentPerformanceSamples +--- + +Returns a list of recent performance samples, in reverse slot order. Performance +samples are taken every 60 seconds and include the number of transactions and +slots that occur in a given time window. + + + + + +### Parameters + + + +number of samples to return (maximum 720) + + + +### Result + +An array of `RpcPerfSample` with the following fields: + +- `slot: ` - Slot in which sample was taken at +- `numTransactions: ` - Number of transactions processed during the sample + period +- `numSlots: ` - Number of slots completed during the sample period +- `samplePeriodSecs: ` - Number of seconds in a sample window +- `numNonVoteTransactions: ` - Number of non-vote transactions processed + during the sample period. + + + `numNonVoteTransactions` is present starting with v1.15. To get a number of + voting transactions compute: +
+ `numTransactions - numNonVoteTransactions` +
+ + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc":"2.0", "id":1, + "method": "getRecentPerformanceSamples", + "params": [4] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": [ + { + "numSlots": 126, + "numTransactions": 126, + "numNonVoteTransactions": 1, + "samplePeriodSecs": 60, + "slot": 348125 + }, + { + "numSlots": 126, + "numTransactions": 126, + "numNonVoteTransactions": 1, + "samplePeriodSecs": 60, + "slot": 347999 + }, + { + "numSlots": 125, + "numTransactions": 125, + "numNonVoteTransactions": 0, + "samplePeriodSecs": 60, + "slot": 347873 + }, + { + "numSlots": 125, + "numTransactions": 125, + "numNonVoteTransactions": 0, + "samplePeriodSecs": 60, + "slot": 347748 + } + ], + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getRecentPrioritizationFees.mdx b/docs/uk/rpc/http/getRecentPrioritizationFees.mdx new file mode 100644 index 000000000..25359e528 --- /dev/null +++ b/docs/uk/rpc/http/getRecentPrioritizationFees.mdx @@ -0,0 +1,93 @@ +--- +sidebarLabel: getRecentPrioritizationFees +title: getRecentPrioritizationFees RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getRecentPrioritizationFees +--- + +Returns a list of prioritization fees from recent blocks. + + + Currently, a node's prioritization-fee cache stores data from up to 150 + blocks. + + + + + + +### Parameters + + + +An array of Account addresses (up to a maximum of 128 addresses), as base-58 +encoded strings + + + If this parameter is provided, the response will reflect a fee to land a + transaction locking all of the provided accounts as writable. + + + + +### Result + +An array of `RpcPrioritizationFee` with the following fields: + +- `slot: ` - slot in which the fee was observed +- `prioritizationFee: ` - the per-compute-unit fee paid by at least one + successfully landed transaction, specified in increments of micro-lamports + (0.000001 lamports) + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc":"2.0", "id":1, + "method": "getRecentPrioritizationFees", + "params": [ + ["CxELquR1gPP8wHe33gZ4QxqGB3sZ9RSwsJ2KshVewkFY"] + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": [ + { + "slot": 348125, + "prioritizationFee": 0 + }, + { + "slot": 348126, + "prioritizationFee": 1000 + }, + { + "slot": 348127, + "prioritizationFee": 500 + }, + { + "slot": 348128, + "prioritizationFee": 0 + }, + { + "slot": 348129, + "prioritizationFee": 1234 + } + ], + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getSignatureStatuses.mdx b/docs/uk/rpc/http/getSignatureStatuses.mdx new file mode 100644 index 000000000..bf101e360 --- /dev/null +++ b/docs/uk/rpc/http/getSignatureStatuses.mdx @@ -0,0 +1,115 @@ +--- +sidebarLabel: getSignatureStatuses +title: getSignatureStatuses RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getSignatureStatuses +--- + +Returns the statuses of a list of signatures. Each signature must be a +[txid](/docs/terminology.md#transaction-id), the first signature of a +transaction. + + + Unless the `searchTransactionHistory` configuration parameter is included, + this method only searches the recent status cache of signatures, which retains + statuses for all active slots plus `MAX_RECENT_BLOCKHASHES` rooted slots. + + + + + + +### Parameters + + + An array of transaction signatures to confirm, as base-58 encoded strings (up + to a maximum of 256) + + + + +Configuration object containing the following fields: + + + +if `true` - a Solana node will search its ledger cache for any signatures not +found in the recent status cache + + + + + +### Result + +An array of `RpcResponse` consisting of either: + +- `` - Unknown transaction, or +- `` + - `slot: ` - The slot the transaction was processed + - `confirmations: ` - Number of blocks since signature + confirmation, null if rooted, as well as finalized by a supermajority of the + cluster + - `err: ` - Error if transaction failed, null if transaction + succeeded. See + [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) + - `confirmationStatus: ` - The transaction's cluster confirmation + status; Either `processed`, `confirmed`, or `finalized`. See + [Commitment](/docs/rpc/index.mdx#configuring-state-commitment) for more on + optimistic confirmation. + - DEPRECATED: `status: ` - Transaction status + - `"Ok": ` - Transaction was successful + - `"Err": ` - Transaction failed with TransactionError + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getSignatureStatuses", + "params": [ + [ + "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW" + ], + { + "searchTransactionHistory": true + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 82 + }, + "value": [ + { + "slot": 48, + "confirmations": null, + "err": null, + "status": { + "Ok": null + }, + "confirmationStatus": "finalized" + }, + null + ] + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getSignaturesForAddress.mdx b/docs/uk/rpc/http/getSignaturesForAddress.mdx new file mode 100644 index 000000000..2587fa931 --- /dev/null +++ b/docs/uk/rpc/http/getSignaturesForAddress.mdx @@ -0,0 +1,115 @@ +--- +sidebarLabel: getSignaturesForAddress +title: getSignaturesForAddress RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getSignaturesForAddress +--- + +Returns signatures for confirmed transactions that include the given address in +their `accountKeys` list. Returns signatures backwards in time from the provided +signature or most recent confirmed block + + + + + +### Parameters + + + Account address as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + maximum transaction signatures to return (between 1 and 1,000). + + + + start searching backwards from this transaction signature. If not provided the + search starts from the top of the highest max confirmed block. + + + + search until this transaction signature, if found before limit reached + + + + +### Result + +An array of ``, ordered from **newest** to **oldest** transaction, +containing transaction signature information with the following fields: + +- `signature: ` - transaction signature as base-58 encoded string +- `slot: ` - The slot that contains the block with the transaction +- `err: ` - Error if transaction failed, null if transaction + succeeded. See + [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) + for more info. +- `memo: ` - Memo associated with the transaction, null if no memo + is present +- `blockTime: ` - estimated production time, as Unix timestamp + (seconds since the Unix epoch) of when transaction was processed. null if not + available. +- `confirmationStatus: ` - The transaction's cluster confirmation + status; Either `processed`, `confirmed`, or `finalized`. See + [Commitment](/docs/rpc/index.mdx#configuring-state-commitment) for more on + optimistic confirmation. + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getSignaturesForAddress", + "params": [ + "Vote111111111111111111111111111111111111111", + { + "limit": 1 + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": [ + { + "err": null, + "memo": null, + "signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv", + "slot": 114, + "blockTime": null + } + ], + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getSlot.mdx b/docs/uk/rpc/http/getSlot.mdx new file mode 100644 index 000000000..504c6c323 --- /dev/null +++ b/docs/uk/rpc/http/getSlot.mdx @@ -0,0 +1,58 @@ +--- +sidebarLabel: getSlot +title: getSlot RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getSlot +--- + +Returns the slot that has reached the +[given or default commitment level](/docs/rpc/index.mdx#configuring-state-commitment) + + + + + +### Parameters + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + +### Result + +`` - Current slot + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getSlot"} +' +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 1234, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/http/getSlotLeader.mdx b/docs/uk/rpc/http/getSlotLeader.mdx new file mode 100644 index 000000000..355c9c024 --- /dev/null +++ b/docs/uk/rpc/http/getSlotLeader.mdx @@ -0,0 +1,61 @@ +--- +sidebarLabel: getSlotLeader +title: getSlotLeader RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getSlotLeader +--- + +Returns the current slot leader + + + + + +### Parameters + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + +### Result + +`` - Node identity Pubkey as base-58 encoded string + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getSlotLeader"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": "ENvAW7JScgYq6o4zKZwewtkzzJgDzuJAFxYasvmEQdpS", + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getSlotLeaders.mdx b/docs/uk/rpc/http/getSlotLeaders.mdx new file mode 100644 index 000000000..2b095babd --- /dev/null +++ b/docs/uk/rpc/http/getSlotLeaders.mdx @@ -0,0 +1,73 @@ +--- +sidebarLabel: getSlotLeaders +title: getSlotLeaders RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getSlotLeaders +--- + +Returns the slot leaders for a given slot range + + + + + +### Parameters + + + Start slot, as u64 integer + + + + Limit, as u64 integer (between 1 and 5,000) + + +### Result + +`` - array of Node identity public keys as base-58 encoded +strings + + + + + +### Code sample + +If the current slot is `#99` - query the next `10` leaders with the following +request: + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc":"2.0", "id": 1, + "method": "getSlotLeaders", + "params": [100, 10] + } +' +``` + +### Response + +The first leader returned is the leader for slot `#100`: + +```json +{ + "jsonrpc": "2.0", + "result": [ + "ChorusmmK7i1AxXeiTtQgQZhQNiXYU84ULeaYF1EH15n", + "ChorusmmK7i1AxXeiTtQgQZhQNiXYU84ULeaYF1EH15n", + "ChorusmmK7i1AxXeiTtQgQZhQNiXYU84ULeaYF1EH15n", + "ChorusmmK7i1AxXeiTtQgQZhQNiXYU84ULeaYF1EH15n", + "Awes4Tr6TX8JDzEhCZY2QVNimT6iD1zWHzf1vNyGvpLM", + "Awes4Tr6TX8JDzEhCZY2QVNimT6iD1zWHzf1vNyGvpLM", + "Awes4Tr6TX8JDzEhCZY2QVNimT6iD1zWHzf1vNyGvpLM", + "Awes4Tr6TX8JDzEhCZY2QVNimT6iD1zWHzf1vNyGvpLM", + "DWvDTSh3qfn88UoQTEKRV2JnLt5jtJAVoiCo3ivtMwXP", + "DWvDTSh3qfn88UoQTEKRV2JnLt5jtJAVoiCo3ivtMwXP" + ], + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getStakeMinimumDelegation.mdx b/docs/uk/rpc/http/getStakeMinimumDelegation.mdx new file mode 100644 index 000000000..b98f1a359 --- /dev/null +++ b/docs/uk/rpc/http/getStakeMinimumDelegation.mdx @@ -0,0 +1,67 @@ +--- +sidebarLabel: getStakeMinimumDelegation +title: getStakeMinimumDelegation RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getStakeMinimumDelegation +--- + +Returns the stake minimum delegation, in lamports. + + + + + +### Parameters + + + +Configuration object containing the following fields: + + + + + +### Result + +The result will be an RpcResponse JSON object with `value` equal to: + +- `` - The stake minimum delegation, in lamports + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc":"2.0", "id":1, + "method": "getStakeMinimumDelegation" + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 501 + }, + "value": 1000000000 + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getSupply.mdx b/docs/uk/rpc/http/getSupply.mdx new file mode 100644 index 000000000..ebd60fa00 --- /dev/null +++ b/docs/uk/rpc/http/getSupply.mdx @@ -0,0 +1,84 @@ +--- +sidebarLabel: getSupply +title: getSupply RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getSupply +--- + +Returns information about the current supply. + + + + + +### Parameters + + + +Configuration object containing the following fields: + + + + + exclude non circulating accounts list from response + + + + +### Result + +The result will be an RpcResponse JSON object with `value` equal to a JSON +object containing: + +- `total: ` - Total supply in lamports +- `circulating: ` - Circulating supply in lamports +- `nonCirculating: ` - Non-circulating supply in lamports +- `nonCirculatingAccounts: ` - an array of account addresses of + non-circulating accounts, as strings. If `excludeNonCirculatingAccountsList` + is enabled, the returned array will be empty. + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0", "id":1, "method":"getSupply"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 1114 + }, + "value": { + "circulating": 16000, + "nonCirculating": 1000000, + "nonCirculatingAccounts": [ + "FEy8pTbP5fEoqMV1GdTz83byuA8EKByqYat1PKDgVAq5", + "9huDUZfxoJ7wGMTffUE7vh1xePqef7gyrLJu9NApncqA", + "3mi1GmwEE3zo2jmfDuzvjSX9ovRXsDUKHvsntpkhuLJ9", + "BYxEJTDerkaRWBem3XgnVcdhppktBXa2HbkHPKj2Ui4Z" + ], + "total": 1016000 + } + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getTokenAccountBalance.mdx b/docs/uk/rpc/http/getTokenAccountBalance.mdx new file mode 100644 index 000000000..dfef4c521 --- /dev/null +++ b/docs/uk/rpc/http/getTokenAccountBalance.mdx @@ -0,0 +1,90 @@ +--- +sidebarLabel: getTokenAccountBalance +title: getTokenAccountBalance RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getTokenAccountBalance +--- + +Returns the token balance of an SPL Token account. + + + + + +### Parameters + + + Pubkey of Token account to query, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + +### Result + +The result will be an RpcResponse JSON object with `value` equal to a JSON +object containing: + +- `amount: ` - the raw balance without decimals, a string representation + of u64 +- `decimals: ` - number of base 10 digits to the right of the decimal place +- `uiAmount: ` - the balance, using mint-prescribed decimals + **DEPRECATED** +- `uiAmountString: ` - the balance as a string, using mint-prescribed + decimals + +For more details on returned data, the +[Token Balances Structure](/docs/rpc/json-structures#token-balances) response +from [getBlock](/docs/rpc/http/getblock) follows a similar structure. + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", "id": 1, + "method": "getTokenAccountBalance", + "params": [ + "7fUAJdStEuGbc3sM84cKRL6yYaaSstyLSU4ve5oovLS7" + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 1114 + }, + "value": { + "amount": "9864", + "decimals": 2, + "uiAmount": 98.64, + "uiAmountString": "98.64" + } + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getTokenAccountsByDelegate.mdx b/docs/uk/rpc/http/getTokenAccountsByDelegate.mdx new file mode 100644 index 000000000..619f743ac --- /dev/null +++ b/docs/uk/rpc/http/getTokenAccountsByDelegate.mdx @@ -0,0 +1,189 @@ +--- +sidebarLabel: getTokenAccountsByDelegate +title: getTokenAccountsByDelegate RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getTokenAccountsByDelegate +--- + +Returns all SPL Token accounts by approved Delegate. + + + + + +### Parameters + + + Pubkey of account delegate to query, as base-58 encoded string + + + + +A JSON object with one of the following fields: + +- `mint: ` - Pubkey of the specific token Mint to limit accounts to, as + base-58 encoded string; or +- `programId: ` - Pubkey of the Token program that owns the accounts, as + base-58 encoded string + + + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + Request a slice of the account's data. + +- `length: ` - number of bytes to return +- `offset: ` - byte offset from which to start reading + + + Data slicing is only available for `base58`, `base64`, or `base64+zstd` + encodings. + + + + + + +Encoding format for Account data + + + +
+ +- `base58` is slow and limited to less than 129 bytes of Account data. +- `base64` will return base64 encoded data for Account data of any size. +- `base64+zstd` compresses the Account data using + [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result. +- `jsonParsed` encoding attempts to use program-specific state parsers to return + more human-readable and explicit account state data. +- If `jsonParsed` is requested but a parser cannot be found, the field falls + back to `base64` encoding, detectable when the `data` field is type `string`. + +
+ +
+ +
+ +### Result + +The result will be an RpcResponse JSON object with `value` equal to an array of +JSON objects, which will contain: + +- `pubkey: ` - the account Pubkey as base-58 encoded string +- `account: ` - a JSON object, with the following sub fields: + - `lamports: ` - number of lamports assigned to this account, as a u64 + - `owner: ` - base-58 encoded Pubkey of the program this account has + been assigned to + - `data: ` - Token state data associated with the account, either as + encoded binary data or in JSON format `{: }` + - `executable: ` - boolean indicating if the account contains a program + (and is strictly read-only\) + - `rentEpoch: ` - the epoch at which this account will next owe rent, as + u64 + - `space: ` - the data size of the account + +When the data is requested with the `jsonParsed` encoding a format similar to +that of the [Token Balances Structure](/docs/rpc/json-structures#token-balances) +can be expected inside the structure, both for the `tokenAmount` and the +`delegatedAmount` - with the latter being an optional object. + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getTokenAccountsByDelegate", + "params": [ + "4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T", + { + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "encoding": "jsonParsed" + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 1114 + }, + "value": [ + { + "account": { + "data": { + "program": "spl-token", + "parsed": { + "info": { + "tokenAmount": { + "amount": "1", + "decimals": 1, + "uiAmount": 0.1, + "uiAmountString": "0.1" + }, + "delegate": "4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T", + "delegatedAmount": { + "amount": "1", + "decimals": 1, + "uiAmount": 0.1, + "uiAmountString": "0.1" + }, + "state": "initialized", + "isNative": false, + "mint": "3wyAj7Rt1TWVPZVteFJPLa26JmLvdb1CAKEFZm3NY75E", + "owner": "CnPoSPKXu7wJqxe59Fs72tkBeALovhsCxYeFwPCQH9TD" + }, + "type": "account" + }, + "space": 165 + }, + "executable": false, + "lamports": 1726080, + "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "rentEpoch": 4, + "space": 165 + }, + "pubkey": "28YTZEwqtMHWrhWcvv34se7pjS7wctgqzCPB3gReCFKp" + } + ] + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getTokenAccountsByOwner.mdx b/docs/uk/rpc/http/getTokenAccountsByOwner.mdx new file mode 100644 index 000000000..a6d1677b2 --- /dev/null +++ b/docs/uk/rpc/http/getTokenAccountsByOwner.mdx @@ -0,0 +1,209 @@ +--- +sidebarLabel: getTokenAccountsByOwner +title: getTokenAccountsByOwner RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getTokenAccountsByOwner +--- + +Returns all SPL Token accounts by token owner. + + + + + +### Parameters + + + Pubkey of account delegate to query, as base-58 encoded string + + + + +A JSON object with either one of the following fields: + +- `mint: ` - Pubkey of the specific token Mint to limit accounts to, as + base-58 encoded string; or +- `programId: ` - Pubkey of the Token program that owns the accounts, as + base-58 encoded string + + + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + Request a slice of the account's data. + +- `length: ` - number of bytes to return +- `offset: ` - byte offset from which to start reading + + + Data slicing is only available for `base58`, `base64`, or `base64+zstd` + encodings. + + + + + + +Encoding format for Account data + + + +
+ +- `base58` is slow and limited to less than 129 bytes of Account data. +- `base64` will return base64 encoded data for Account data of any size. +- `base64+zstd` compresses the Account data using + [Zstandard](https://facebook.github.io/zstd/) and base64-encodes the result. +- `jsonParsed` encoding attempts to use program-specific state parsers to return + more human-readable and explicit account state data. +- If `jsonParsed` is requested but a parser cannot be found, the field falls + back to `base64` encoding, detectable when the `data` field is type `string`. + +
+ +
+ +
+ +### Result + +The result will be an RpcResponse JSON object with `value` equal to an array of +JSON objects, which will contain: + +- `pubkey: ` - the account Pubkey as base-58 encoded string +- `account: ` - a JSON object, with the following sub fields: + - `lamports: ` - number of lamports assigned to this account, as a u64 + - `owner: ` - base-58 encoded Pubkey of the program this account has + been assigned to + - `data: ` - Token state data associated with the account, either as + encoded binary data or in JSON format `{: }` + - `executable: ` - boolean indicating if the account contains a program + \(and is strictly read-only\) + - `rentEpoch: ` - the epoch at which this account will next owe rent, as + u64 + - `space: ` - the data size of the account + +When the data is requested with the `jsonParsed` encoding a format similar to +that of the [Token Balances Structure](/docs/rpc/json-structures#token-balances) +can be expected inside the structure, both for the `tokenAmount` and the +`delegatedAmount` - with the latter being an optional object. + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getTokenAccountsByOwner", + "params": [ + "A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd", + { + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "encoding": "jsonParsed" + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { "apiVersion": "2.0.15", "slot": 341197933 }, + "value": [ + { + "account": { + "data": { + "parsed": { + "info": { + "isNative": false, + "mint": "2cHr7QS3xfuSV8wdxo3ztuF4xbiarF6Nrgx3qpx3HzXR", + "owner": "A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd", + "state": "initialized", + "tokenAmount": { + "amount": "420000000000000", + "decimals": 6, + "uiAmount": 420000000.0, + "uiAmountString": "420000000" + } + }, + "type": "account" + }, + "program": "spl-token", + "space": 165 + }, + "executable": false, + "lamports": 2039280, + "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "rentEpoch": 18446744073709551615, + "space": 165 + }, + "pubkey": "BGocb4GEpbTFm8UFV2VsDSaBXHELPfAXrvd4vtt8QWrA" + }, + { + "account": { + "data": { + "parsed": { + "info": { + "isNative": false, + "mint": "4KVSsAtsG8JByKfB2jYWgGwvVR9WcBSUfsqpTSL9c3Jr", + "owner": "A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd", + "state": "initialized", + "tokenAmount": { + "amount": "10000000000000", + "decimals": 9, + "uiAmount": 10000.0, + "uiAmountString": "10000" + } + }, + "type": "account" + }, + "program": "spl-token", + "space": 165 + }, + "executable": false, + "lamports": 2039280, + "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", + "rentEpoch": 18446744073709551615, + "space": 165 + }, + "pubkey": "9PwCPoWJ75LSgZeGMubXBdufYMVd66HrcF78QzW6ZHkV" + } + ] + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getTokenLargestAccounts.mdx b/docs/uk/rpc/http/getTokenLargestAccounts.mdx new file mode 100644 index 000000000..3702a0ad7 --- /dev/null +++ b/docs/uk/rpc/http/getTokenLargestAccounts.mdx @@ -0,0 +1,97 @@ +--- +sidebarLabel: getTokenLargestAccounts +title: getTokenLargestAccounts RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getTokenLargestAccounts +--- + +Returns the 20 largest accounts of a particular SPL Token type. + + + + + +### Parameters + + + Pubkey of the token Mint to query, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + +### Result + +The result will be an RpcResponse JSON object with `value` equal to an array of +JSON objects containing: + +- `address: ` - the address of the token account +- `amount: ` - the raw token account balance without decimals, a string + representation of u64 +- `decimals: ` - number of base 10 digits to the right of the decimal place +- `uiAmount: ` - the token account balance, using mint-prescribed + decimals **DEPRECATED** +- `uiAmountString: ` - the token account balance as a string, using + mint-prescribed decimals + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", "id": 1, + "method": "getTokenLargestAccounts", + "params": [ + "3wyAj7Rt1TWVPZVteFJPLa26JmLvdb1CAKEFZm3NY75E" + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 1114 + }, + "value": [ + { + "address": "FYjHNoFtSQ5uijKrZFyYAxvEr87hsKXkXcxkcmkBAf4r", + "amount": "771", + "decimals": 2, + "uiAmount": 7.71, + "uiAmountString": "7.71" + }, + { + "address": "BnsywxTcaYeNUtzrPxQUvzAWxfzZe3ZLUJ4wMMuLESnu", + "amount": "229", + "decimals": 2, + "uiAmount": 2.29, + "uiAmountString": "2.29" + } + ] + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getTokenSupply.mdx b/docs/uk/rpc/http/getTokenSupply.mdx new file mode 100644 index 000000000..193f79d48 --- /dev/null +++ b/docs/uk/rpc/http/getTokenSupply.mdx @@ -0,0 +1,86 @@ +--- +sidebarLabel: getTokenSupply +title: getTokenSupply RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getTokenSupply +--- + +Returns the total supply of an SPL Token type. + + + + + +### Parameters + + + Pubkey of the token Mint to query, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + +### Result + +The result will be an RpcResponse JSON object with `value` equal to a JSON +object containing: + +- `amount: ` - the raw total token supply without decimals, a string + representation of u64 +- `decimals: ` - number of base 10 digits to the right of the decimal place +- `uiAmount: ` - the total token supply, using mint-prescribed + decimals **DEPRECATED** +- `uiAmountString: ` - the total token supply as a string, using + mint-prescribed decimals + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", "id": 1, + "method": "getTokenSupply", + "params": [ + "3wyAj7Rt1TWVPZVteFJPLa26JmLvdb1CAKEFZm3NY75E" + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 1114 + }, + "value": { + "amount": "100000", + "decimals": 2, + "uiAmount": 1000, + "uiAmountString": "1000" + } + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getTransaction.mdx b/docs/uk/rpc/http/getTransaction.mdx new file mode 100644 index 000000000..1fa973600 --- /dev/null +++ b/docs/uk/rpc/http/getTransaction.mdx @@ -0,0 +1,213 @@ +--- +sidebarLabel: getTransaction +title: getTransaction RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getTransaction +--- + +Returns transaction details for a confirmed transaction + + + + + +### Parameters + + + Transaction signature, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + +- `processed` is not supported. + + + + + Set the max transaction version to return in responses. If the requested + transaction is a higher version, an error will be returned. If this parameter + is omitted, only legacy transactions will be returned, and any versioned + transaction will prompt the error. + + + + +Encoding for the returned Transaction + + + +
+ +- `jsonParsed` encoding attempts to use program-specific state parsers to return + more human-readable and explicit data in the + `transaction.message.instructions` list. +- If `jsonParsed` is requested but a parser cannot be found, the instruction + falls back to regular JSON encoding (`accounts`, `data`, and `programIdIndex` + fields). + +
+ +
+ +
+ +### Result + +- `` - if transaction is not found or not confirmed +- `` - if transaction is confirmed, an object with the following fields: + - `slot: ` - the slot this transaction was processed in + - `transaction: ` - + [Transaction](/docs/rpc/json-structures#transactions) object, either in JSON + format or encoded binary data, depending on encoding parameter + - `blockTime: ` - estimated production time, as Unix timestamp + (seconds since the Unix epoch) of when the transaction was processed. null + if not available + - `meta: ` - transaction status metadata object: + - `err: ` - Error if transaction failed, null if transaction + succeeded. + [TransactionError definitions](https://docs.rs/solana-sdk/latest/solana_sdk/transaction/enum.TransactionError.html) + - `fee: ` - fee this transaction was charged, as u64 integer + - `preBalances: ` - array of u64 account balances from before the + transaction was processed + - `postBalances: ` - array of u64 account balances after the + transaction was processed + - `innerInstructions: ` - List of + [inner instructions](/docs/rpc/json-structures#inner-instructions) or + `null` if inner instruction recording was not enabled during this + transaction + - `preTokenBalances: ` - List of + [token balances](/docs/rpc/json-structures#token-balances) from before the + transaction was processed or omitted if token balance recording was not + yet enabled during this transaction + - `postTokenBalances: ` - List of + [token balances](/docs/rpc/json-structures#token-balances) from after the + transaction was processed or omitted if token balance recording was not + yet enabled during this transaction + - `logMessages: ` - array of string log messages or `null` if + log message recording was not enabled during this transaction + - DEPRECATED: `status: ` - Transaction status + - `"Ok": ` - Transaction was successful + - `"Err": ` - Transaction failed with TransactionError + - `rewards: ` - transaction-level rewards, populated if rewards + are requested; an array of JSON objects containing: + - `pubkey: ` - The public key, as base-58 encoded string, of the + account that received the reward + - `lamports: `- number of reward lamports credited or debited by the + account, as a i64 + - `postBalance: ` - account balance in lamports after the reward was + applied + - `rewardType: ` - type of reward: currently only "rent", other + types may be added in the future + - `commission: ` - vote account commission when the reward + was credited, only present for voting and staking rewards + - `loadedAddresses: ` - Transaction addresses loaded from + address lookup tables. Undefined if `maxSupportedTransactionVersion` is + not set in request params, or if `jsonParsed` encoding is set in request + params. + - `writable: ` - Ordered list of base-58 encoded addresses + for writable loaded accounts + - `readonly: ` - Ordered list of base-58 encoded addresses + for readonly loaded accounts + - `returnData: ` - the most-recent return data generated + by an instruction in the transaction, with the following fields: + - `programId: ` - the program that generated the return data, as + base-58 encoded Pubkey + - `data: <[string, encoding]>` - the return data itself, as base-64 + encoded binary data + - `computeUnitsConsumed: ` - number of + [compute units](/docs/core/fees.md#compute-budget) consumed by the + transaction + - `version: <"legacy"|number|undefined>` - Transaction version. Undefined if + `maxSupportedTransactionVersion` is not set in request params. + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getTransaction", + "params": [ + "2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv", + "json" + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "meta": { + "err": null, + "fee": 5000, + "innerInstructions": [], + "postBalances": [499998932500, 26858640, 1, 1, 1], + "postTokenBalances": [], + "preBalances": [499998937500, 26858640, 1, 1, 1], + "preTokenBalances": [], + "rewards": [], + "status": { + "Ok": null + } + }, + "slot": 430, + "transaction": { + "message": { + "accountKeys": [ + "3UVYmECPPMZSCqWKfENfuoTv51fTDTWicX9xmBD2euKe", + "AjozzgE83A3x1sHNUR64hfH7zaEBWeMaFuAN9kQgujrc", + "SysvarS1otHashes111111111111111111111111111", + "SysvarC1ock11111111111111111111111111111111", + "Vote111111111111111111111111111111111111111" + ], + "header": { + "numReadonlySignedAccounts": 0, + "numReadonlyUnsignedAccounts": 3, + "numRequiredSignatures": 1 + }, + "instructions": [ + { + "accounts": [1, 2, 3, 0], + "data": "37u9WtQpcm6ULa3WRQHmj49EPs4if7o9f1jSRVZpm2dvihR9C8jY4NqEwXUbLwx15HBSNcP1", + "programIdIndex": 4 + } + ], + "recentBlockhash": "mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B" + }, + "signatures": [ + "2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv" + ] + } + }, + "blockTime": null, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getTransactionCount.mdx b/docs/uk/rpc/http/getTransactionCount.mdx new file mode 100644 index 000000000..d3b07b6c7 --- /dev/null +++ b/docs/uk/rpc/http/getTransactionCount.mdx @@ -0,0 +1,57 @@ +--- +sidebarLabel: getTransactionCount +title: getTransactionCount RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getTransactionCount +--- + +Returns the current Transaction count from the ledger + + + + + +### Parameters + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + +### Result + +`` - the current Transaction count from the ledger + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getTransactionCount"} +' +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 268, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/http/getVersion.mdx b/docs/uk/rpc/http/getVersion.mdx new file mode 100644 index 000000000..5aeb25ea1 --- /dev/null +++ b/docs/uk/rpc/http/getVersion.mdx @@ -0,0 +1,50 @@ +--- +sidebarLabel: getVersion +title: getVersion RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getVersion +--- + +Returns the current Solana version running on the node + + + + + +### Parameters + +**None** + +### Result + +The result field will be a JSON object with the following fields: + +- `solana-core` - software version of solana-core as a `string` +- `feature-set` - unique identifier of the current software's feature set as a + `u32` + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"getVersion"} +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { "feature-set": 2891131721, "solana-core": "1.16.7" }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/getVoteAccounts.mdx b/docs/uk/rpc/http/getVoteAccounts.mdx new file mode 100644 index 000000000..2ba1257d8 --- /dev/null +++ b/docs/uk/rpc/http/getVoteAccounts.mdx @@ -0,0 +1,113 @@ +--- +sidebarLabel: getVoteAccounts +title: getVoteAccounts RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/getVoteAccounts +--- + +Returns the account info and associated stake for all the voting accounts in the +current bank. + + + + + +### Parameters + + + +Configuration object containing the following fields: + + + + + Only return results for this validator vote address (base-58 encoded) + + + + Do not filter out delinquent validators with no stake + + + + Specify the number of slots behind the tip that a validator must fall to be + considered delinquent. **NOTE:** For the sake of consistency between ecosystem + products, _it is **not** recommended that this argument be specified._ + + + + +### Result + +The result field will be a JSON object of `current` and `delinquent` accounts, +each containing an array of JSON objects with the following sub fields: + +- `votePubkey: ` - Vote account address, as base-58 encoded string +- `nodePubkey: ` - Validator identity, as base-58 encoded string +- `activatedStake: ` - the stake, in lamports, delegated to this vote + account and active in this epoch +- `epochVoteAccount: ` - bool, whether the vote account is staked for this + epoch +- `commission: ` - percentage (0-100) of rewards payout owed to the vote + account +- `lastVote: ` - Most recent slot voted on by this vote account +- `epochCredits: ` - Latest history of earned credits for up to five + epochs, as an array of arrays containing: `[epoch, credits, previousCredits]`. +- `rootSlot: ` - Current root slot for this vote account + + + + + +### Code sample + +Restrict results to a single validator vote account: + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getVoteAccounts", + "params": [ + { + "votePubkey": "3ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw" + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "current": [ + { + "commission": 0, + "epochVoteAccount": true, + "epochCredits": [ + [1, 64, 0], + [2, 192, 64] + ], + "nodePubkey": "B97CCUW3AEZFGy6uUg6zUdnNYvnVq5VG8PUtb2HayTDD", + "lastVote": 147, + "activatedStake": 42, + "votePubkey": "3ZT31jkAGhUaw8jsy4bTknwBMP8i4Eueh52By4zXcsVw" + } + ], + "delinquent": [] + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/index.mdx b/docs/uk/rpc/http/index.mdx new file mode 100644 index 000000000..0392e5605 --- /dev/null +++ b/docs/uk/rpc/http/index.mdx @@ -0,0 +1,105 @@ +--- +title: Solana RPC HTTP Methods +seoTitle: Solana RPC HTTP Methods +sidebarLabel: HTTP Methods +sidebarSortOrder: 1 +hideTableOfContents: false +--- + +Solana nodes accept HTTP requests using the +[JSON-RPC 2.0](https://www.jsonrpc.org/specification) specification. + +> For JavaScript applications, use the +> [@solana/web3.js](https://github.com/solana-labs/solana-web3.js) library as a +> convenient interface for the RPC methods to interact with a Solana node. For +> an PubSub connection to a Solana node, use the +> [Websocket API](/docs/rpc/websocket/index.mdx). + +## RPC HTTP Endpoint + +Default port: `8899` + +- http://localhost:8899 +- http://192.168.1.88:8899 + +## Request Formatting + +To make a JSON-RPC request, send an HTTP POST request with a +`Content-Type: application/json` header. The JSON request data should contain 4 +fields: + +- `jsonrpc: ` - set to `"2.0"` +- `id: ` - a unique identifier for the request, + generated by the client. Typically a string or number, though null is + technically allowed but not advised +- `method: ` - a string containing the method to be invoked +- `params: ` - a JSON array of ordered parameter values + +Example using curl: + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getBalance", + "params": [ + "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri" + ] + } +' +``` + +The response output will be a JSON object with the following fields: + +- `jsonrpc: ` - matching the request specification +- `id: ` - matching the request identifier +- `result: ` - requested data or success + confirmation + +Requests can be sent in batches by sending an array of JSON-RPC request objects +as the data for a single POST. + +### Example Request + +The commitment parameter should be included as the last element in the `params` +array: + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "getBalance", + "params": [ + "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri", + { + "commitment": "finalized" + } + ] + } +' +``` + +## Definitions + +- Hash: A SHA-256 hash of a chunk of data. +- Pubkey: The public key of a Ed25519 key-pair. +- Transaction: A list of Solana instructions signed by a client keypair to + authorize those actions. +- Signature: An Ed25519 signature of transaction's payload data including + instructions. This can be used to identify transactions. + +## Health Check + +Although not a JSON RPC API, a `GET /health` at the RPC HTTP Endpoint provides a +health-check mechanism for use by load balancers or other network +infrastructure. This request will always return a HTTP 200 OK response with a +body of "ok", "behind" or "unknown": + +- `ok`: The node is within `HEALTH_CHECK_SLOT_DISTANCE` slots from the latest + cluster confirmed slot +- `behind { distance }`: The node is behind `distance` slots from the latest + cluster confirmed slot where `distance > HEALTH_CHECK_SLOT_DISTANCE` +- `unknown`: The node is unable to determine where it stands in relation to the + cluster diff --git a/docs/uk/rpc/http/isBlockhashValid.mdx b/docs/uk/rpc/http/isBlockhashValid.mdx new file mode 100644 index 000000000..c9e951f67 --- /dev/null +++ b/docs/uk/rpc/http/isBlockhashValid.mdx @@ -0,0 +1,84 @@ +--- +sidebarLabel: isBlockhashValid +title: isBlockhashValid RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/isBlockhashValid +--- + +Returns whether a blockhash is still valid or not + + + This method is only available in `solana-core` v1.9 or newer. Please use + [getFeeCalculatorForBlockhash](/docs/rpc/http/getFeeCalculatorForBlockhash) + for `solana-core` v1.8 and below. + + + + + + +### Parameters + + + the blockhash of the block to evaluate, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + The minimum slot that the request can be evaluated at + + + + +### Result + +`` - `true` if the blockhash is still valid + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "id":45, + "jsonrpc":"2.0", + "method":"isBlockhashValid", + "params":[ + "J7rBdM6AecPDEZp8aPq5iPSNKVkU5Q76F3oAV4eW5wsW", + {"commitment":"processed"} + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 2483 + }, + "value": false + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/minimumLedgerSlot.mdx b/docs/uk/rpc/http/minimumLedgerSlot.mdx new file mode 100644 index 000000000..d4596b0cb --- /dev/null +++ b/docs/uk/rpc/http/minimumLedgerSlot.mdx @@ -0,0 +1,47 @@ +--- +sidebarLabel: minimumLedgerSlot +title: minimumLedgerSlot RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/minimumLedgerSlot +--- + +Returns the lowest slot that the node has information about in its ledger. + + + This value may increase over time if the node is configured to purge older + ledger data + + + + + + +### Parameters + +**None** + +### Result + +`u64` - Minimum ledger slot number + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + {"jsonrpc":"2.0","id":1, "method":"minimumLedgerSlot"} +' +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 1234, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/http/requestAirdrop.mdx b/docs/uk/rpc/http/requestAirdrop.mdx new file mode 100644 index 000000000..b2ff929ad --- /dev/null +++ b/docs/uk/rpc/http/requestAirdrop.mdx @@ -0,0 +1,72 @@ +--- +sidebarLabel: requestAirdrop +title: requestAirdrop RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/requestAirdrop +--- + +Requests an airdrop of lamports to a Pubkey + + + + + +### Parameters + + + Pubkey of account to receive lamports, as a base-58 encoded string + + + + lamports to airdrop, as a "u64" + + + + +Configuration object containing the following fields: + + + + + +### Result + +`` - Transaction Signature of the airdrop, as a base-58 encoded string + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", "id": 1, + "method": "requestAirdrop", + "params": [ + "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri", + 1000000000 + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW", + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/sendTransaction.mdx b/docs/uk/rpc/http/sendTransaction.mdx new file mode 100644 index 000000000..d77f578d0 --- /dev/null +++ b/docs/uk/rpc/http/sendTransaction.mdx @@ -0,0 +1,125 @@ +--- +sidebarLabel: sendTransaction +title: sendTransaction RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/sendTransaction +--- + +Submits a signed transaction to the cluster for processing. + +This method does not alter the transaction in any way; it relays the transaction +created by clients to the node as-is. + +If the node's rpc service receives the transaction, this method immediately +succeeds, without waiting for any confirmations. A successful response from this +method does not guarantee the transaction is processed or confirmed by the +cluster. + +While the rpc service will reasonably retry to submit it, the transaction could +be rejected if transaction's `recent_blockhash` expires before it lands. + +Use [`getSignatureStatuses`](/docs/rpc/http/getSignatureStatuses) to ensure a +transaction is processed and confirmed. + +Before submitting, the following preflight checks are performed: + +1. The transaction signatures are verified +2. The transaction is simulated against the bank slot specified by the preflight + commitment. On failure an error will be returned. Preflight checks may be + disabled if desired. It is recommended to specify the same commitment and + preflight commitment to avoid confusing behavior. + +The returned signature is the first signature in the transaction, which is used +to identify the transaction +([transaction id](/docs/terminology.md#transaction-id)). This identifier can be +easily extracted from the transaction data before submission. + + + + + +### Parameters + + + Fully-signed Transaction, as encoded string. + + + + +Configuration object containing the following optional fields: + + + +Encoding used for the transaction data. + +Values: `base58` (_slow_, **DEPRECATED**), or `base64`. + + + + + when `true`, skip the preflight transaction checks + + + + Commitment level to use for preflight. + + + + Maximum number of times for the RPC node to retry sending the transaction to + the leader. If this parameter not provided, the RPC node will retry the + transaction until it is finalized or until the blockhash expires. + + + + set the minimum slot at which to perform preflight transaction checks + + + + +### Result + +`` - First Transaction Signature embedded in the transaction, as base-58 +encoded string ([transaction id](/docs/terminology.md#transaction-id)) + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "sendTransaction", + "params": [ + "4hXTCkRzt9WyecNzV1XPgCDfGAZzQKNxLXgynz5QDuWWPSAZBZSHptvWRL3BjCvzUXRdKvHL2b7yGrRQcWyaqsaBCncVG7BFggS8w9snUts67BSh3EqKpXLUm5UMHfD7ZBe9GhARjbNQMLJ1QD3Spr6oMTBU6EhdB4RD8CP2xUxr2u3d6fos36PD98XS6oX8TQjLpsMwncs5DAMiD4nNnR8NBfyghGCWvCVifVwvA8B8TJxE1aiyiv2L429BCWfyzAme5sZW8rDb14NeCQHhZbtNqfXhcp2tAnaAT" + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": "2id3YC2jK9G5Wo2phDx4gJVAew8DcY5NAojnVuao8rkxwPYPe8cSwE5GzhEgJA2y8fVjDEo6iR6ykBvDxrTQrtpb", + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/http/simulateTransaction.mdx b/docs/uk/rpc/http/simulateTransaction.mdx new file mode 100644 index 000000000..8256f7d72 --- /dev/null +++ b/docs/uk/rpc/http/simulateTransaction.mdx @@ -0,0 +1,197 @@ +--- +sidebarLabel: simulateTransaction +title: simulateTransaction RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/simulateTransaction +--- + +Simulate sending a transaction + + + + + +### Parameters + + + +Transaction, as an encoded string. + + + The transaction must have a valid blockhash, but is not required to be signed. + + + + + + +Configuration object containing the following fields: + + + Commitment level to simulate the transaction at + + + + if `true` the transaction signatures will be verified (conflicts with + `replaceRecentBlockhash`) + + + + if `true` the transaction recent blockhash will be replaced with the most + recent blockhash. (conflicts with `sigVerify`) + + + + the minimum slot that the request can be evaluated at + + + + +Encoding used for the transaction data. + +Values: `base58` (_slow_, **DEPRECATED**), or `base64`. + + + + + +If `true` the response will include +[inner instructions](/docs/rpc/json-structures#inner-instructions). These inner +instructions will be `jsonParsed` where possible, otherwise `json`. + + + + + +Accounts configuration object containing the following fields: + + + An `array` of accounts to return, as base-58 encoded strings + + + + +encoding for returned Account data + + + +
+ +- `jsonParsed` encoding attempts to use program-specific state parsers to return + more human-readable and explicit account state data. +- If `jsonParsed` is requested but a + [parser cannot be found](https://github.com/solana-labs/solana/blob/cfd0a00ae2ba85a6d76757df8b4fa38ed242d185/account-decoder/src/parse_account_data.rs#L98-L100), + the field falls back to `base64` encoding, detectable when the returned + `accounts.data` field is type `string`. + +
+ +
+ +
+ +
+ +### Result + +The result will be an RpcResponse JSON object with `value` set to a JSON object +with the following fields: + +- `err: ` - Error if transaction failed, null if transaction + succeeded. + [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) +- `logs: ` - Array of log messages the transaction instructions + output during execution, null if simulation failed before the transaction was + able to execute (for example due to an invalid blockhash or signature + verification failure) +- `accounts: ` - array of accounts with the same length as the + `accounts.addresses` array in the request + - `` - if the account doesn't exist or if `err` is not null + - `` - otherwise, a JSON object containing: + - `lamports: ` - number of lamports assigned to this account, as a u64 + - `owner: ` - base-58 encoded Pubkey of the program this account has + been assigned to + - `data: <[string, encoding]|object>` - data associated with the account, + either as encoded binary data or JSON format `{: }` - + depending on encoding parameter + - `executable: ` - boolean indicating if the account contains a + program \(and is strictly read-only\) + - `rentEpoch: ` - the epoch at which this account will next owe rent, + as u64 +- `unitsConsumed: ` - The number of compute budget units consumed + during the processing of this transaction +- `returnData: ` - the most-recent return data generated by an + instruction in the transaction, with the following fields: + - `programId: ` - the program that generated the return data, as + base-58 encoded Pubkey + - `data: <[string, encoding]>` - the return data itself, as base-64 encoded + binary data +- `innerInstructions: ` - Defined only if + `innerInstructions` was set to `true`. The value is a list of + [inner instructions](/docs/rpc/json-structures#inner-instructions). + + + + + +### Code sample + +```shell +curl https://api.devnet.solana.com -s -X POST -H "Content-Type: application/json" -d ' + { + "jsonrpc": "2.0", + "id": 1, + "method": "simulateTransaction", + "params": [ + "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEDArczbMia1tLmq7zz4DinMNN0pJ1JtLdqIJPUw3YrGCzYAMHBsgN27lcgB6H2WQvFgyZuJYHa46puOQo9yQ8CVQbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCp20C7Wj2aiuk5TReAXo+VTVg8QTHjs0UjNMMKCvpzZ+ABAgEBARU=", + { + "encoding":"base64" + } + ] + } +' +``` + +### Response + +```json +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 218 + }, + "value": { + "err": null, + "accounts": null, + "logs": [ + "Program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri invoke [1]", + "Program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri consumed 2366 of 1400000 compute units", + "Program return: 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri KgAAAAAAAAA=", + "Program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri success" + ], + "returnData": { + "data": ["Kg==", "base64"], + "programId": "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri" + }, + "unitsConsumed": 2366 + } + }, + "id": 1 +} +``` + + + diff --git a/docs/uk/rpc/index.mdx b/docs/uk/rpc/index.mdx new file mode 100644 index 000000000..8f9d69045 --- /dev/null +++ b/docs/uk/rpc/index.mdx @@ -0,0 +1,99 @@ +--- +title: Solana RPC Methods & Documentation +seoTitle: "Solana RPC Methods: HTTP & Websockets" +sidebarLabel: Solana RPC Methods +sidebarSortOrder: 1 +hideTableOfContents: false +--- + +Interact with Solana nodes directly with the JSON RPC API via the HTTP and +Websocket methods. + +## Configuring State Commitment + +For preflight checks and transaction processing, Solana nodes choose which bank +state to query based on a commitment requirement set by the client. The +commitment describes how finalized a block is at that point in time. When +querying the ledger state, it's recommended to use lower levels of commitment to +report progress and higher levels to ensure the state will not be rolled back. + +In descending order of commitment (most finalized to least finalized), clients +may specify: + +- `finalized` - the node will query the most recent block confirmed by + supermajority of the cluster as having reached maximum lockout, meaning the + cluster has recognized this block as finalized +- `confirmed` - the node will query the most recent block that has been voted on + by supermajority of the cluster. + - It incorporates votes from gossip and replay. + - It does not count votes on descendants of a block, only direct votes on that + block. + - This confirmation level also upholds "optimistic confirmation" guarantees in + release 1.3 and onwards. +- `processed` - the node will query its most recent block. Note that the block + may still be skipped by the cluster. + +For processing many dependent transactions in series, it's recommended to use +`confirmed` commitment, which balances speed with rollback safety. For total +safety, it's recommended to use `finalized` commitment. + +### Default Commitment + +If commitment configuration is not provided, the node will +[default to `finalized` commitment](https://github.com/anza-xyz/agave/blob/aa0922d6845e119ba466f88497e8209d1c82febc/sdk/src/commitment_config.rs#L199-L203) + +Only methods that query bank state accept the commitment parameter. They are +indicated in the API Reference below. + +## RpcResponse Structure + +Many methods that take a commitment parameter return an RpcResponse JSON object +comprised of two parts: + +- `context` : An RpcResponseContext JSON structure including a `slot` field at + which the operation was evaluated. +- `value` : The value returned by the operation itself. + +## Parsed Responses + +Some methods support an `encoding` parameter, and can return account or +instruction data in parsed JSON format if `"encoding":"jsonParsed"` is requested +and the node has a parser for the owning program. Solana nodes currently support +JSON parsing for the following native and SPL programs: + +| Program | Account State | Instructions | +| ---------------------------- | ------------- | ------------ | +| Address Lookup | v1.15.0 | v1.15.0 | +| BPF Loader | n/a | stable | +| BPF Upgradeable Loader | stable | stable | +| Config | stable | | +| SPL Associated Token Account | n/a | stable | +| SPL Memo | n/a | stable | +| SPL Token | stable | stable | +| SPL Token 2022 | stable | stable | +| Stake | stable | stable | +| Vote | stable | stable | + +The list of account parsers can be found +[here](https://github.com/solana-labs/solana/blob/master/account-decoder/src/parse_account_data.rs), +and instruction parsers +[here](https://github.com/solana-labs/solana/blob/master/transaction-status/src/parse_instruction.rs). + +## Filter criteria + +Some methods support providing a `filters` object to enable pre-filtering the +data returned within the RpcResponse JSON object. The following filters exist: + +- `memcmp: object` - compares a provided series of bytes with program account + data at a particular offset. Fields: + + - `offset: usize` - offset into program account data to start comparison + - `bytes: string` - data to match, as encoded string + - `encoding: string` - encoding for filter `bytes` data, either "base58" or + "base64". Data is limited in size to 128 or fewer decoded bytes.
+ **NEW: This field, and base64 support generally, is only available in + solana-core v1.14.0 or newer. Please omit when querying nodes on earlier + versions** + +- `dataSize: u64` - compares the program account data length with the provided + data size diff --git a/docs/uk/rpc/json-structures.mdx b/docs/uk/rpc/json-structures.mdx new file mode 100644 index 000000000..0855dc189 --- /dev/null +++ b/docs/uk/rpc/json-structures.mdx @@ -0,0 +1,110 @@ +--- +title: Common JSON Data Structures for Solana RPC Methods +sidebarLabel: Data Structures as JSON +sidebarSortOrder: -1 +hideTableOfContents: false +--- + +Various Solana RPC methods will return more complex responses as structured JSON +objects, filled with specific keyed values. + +The most common of these JSON data structures include: + +- [transactions](#transactions) +- [inner instructions](#inner-instructions) +- [token balances](#token-balances) + +## Transactions + +Transactions are quite different from those on other blockchains. Be sure to +review [Anatomy of a Transaction](/docs/core/transactions.md) to learn about +transactions on Solana. + +The JSON structure of a transaction is defined as follows: + +- `signatures: ` - A list of base-58 encoded signatures applied + to the transaction. The list is always of length + `message.header.numRequiredSignatures` and not empty. The signature at index + `i` corresponds to the public key at index `i` in `message.accountKeys`. The + first one is used as the + [transaction id](/docs/terminology.md#transaction-id). +- `message: ` - Defines the content of the transaction. + - `accountKeys: ` - List of base-58 encoded public keys used by + the transaction, including by the instructions and for signatures. The first + `message.header.numRequiredSignatures` public keys must sign the + transaction. + - `header: ` - Details the account types and signatures required by + the transaction. + - `numRequiredSignatures: ` - The total number of signatures + required to make the transaction valid. The signatures must match the + first `numRequiredSignatures` of `message.accountKeys`. + - `numReadonlySignedAccounts: ` - The last + `numReadonlySignedAccounts` of the signed keys are read-only accounts. + Programs may process multiple transactions that load read-only accounts + within a single PoH entry, but are not permitted to credit or debit + lamports or modify account data. Transactions targeting the same + read-write account are evaluated sequentially. + - `numReadonlyUnsignedAccounts: ` - The last + `numReadonlyUnsignedAccounts` of the unsigned keys are read-only accounts. + - `recentBlockhash: ` - A base-58 encoded hash of a recent block in + the ledger used to prevent transaction duplication and to give transactions + lifetimes. + - `instructions: ` - List of program instructions that will be + executed in sequence and committed in one atomic transaction if all succeed. + - `programIdIndex: ` - Index into the `message.accountKeys` array + indicating the program account that executes this instruction. + - `accounts: ` - List of ordered indices into the + `message.accountKeys` array indicating which accounts to pass to the + program. + - `data: ` - The program input data encoded in a base-58 string. + - `addressTableLookups: ` - List of address table + lookups used by a transaction to dynamically load addresses from on-chain + address lookup tables. Undefined if `maxSupportedTransactionVersion` is not + set. + - `accountKey: ` - base-58 encoded public key for an address lookup + table account. + - `writableIndexes: ` - List of indices used to load + addresses of writable accounts from a lookup table. + - `readonlyIndexes: ` - List of indices used to load + addresses of readonly accounts from a lookup table. + +## Inner Instructions + +The Solana runtime records the cross-program instructions that are invoked +during transaction processing and makes these available for greater transparency +of what was executed on-chain per transaction instruction. Invoked instructions +are grouped by the originating transaction instruction and are listed in order +of processing. + +The JSON structure of inner instructions is defined as a list of objects in the +following structure: + +- `index: number` - Index of the transaction instruction from which the inner + instruction(s) originated +- `instructions: ` - Ordered list of inner program instructions + that were invoked during a single transaction instruction. + - `programIdIndex: ` - Index into the `message.accountKeys` array + indicating the program account that executes this instruction. + - `accounts: ` - List of ordered indices into the + `message.accountKeys` array indicating which accounts to pass to the + program. + - `data: ` - The program input data encoded in a base-58 string. + +## Token Balances + +The JSON structure of token balances is defined as a list of objects in the +following structure: + +- `accountIndex: ` - Index of the account in which the token balance is + provided for. +- `mint: ` - Pubkey of the token's mint. +- `owner: ` - Pubkey of token balance's owner. +- `programId: ` - Pubkey of the Token program that owns the + account. +- `uiTokenAmount: ` - + - `amount: ` - Raw amount of tokens as a string, ignoring decimals. + - `decimals: ` - Number of decimals configured for token's mint. + - `uiAmount: ` - Token amount as a float, accounting for + decimals. **DEPRECATED** + - `uiAmountString: ` - Token amount as a string, accounting for + decimals. diff --git a/docs/uk/rpc/websocket/accountSubscribe.mdx b/docs/uk/rpc/websocket/accountSubscribe.mdx new file mode 100644 index 000000000..df731376f --- /dev/null +++ b/docs/uk/rpc/websocket/accountSubscribe.mdx @@ -0,0 +1,160 @@ +--- +sidebarLabel: accountSubscribe +title: accountSubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/accountSubscribe +--- + +Subscribe to an account to receive notifications when the lamports or data for a +given account public key changes + + + + + +### Parameters + + + Account Pubkey, as base-58 encoded string + + + + +Configuration object containing the following fields: + + + + + +Encoding format for Account data + + + +
+ +- `base58` is slow. +- `jsonParsed` encoding attempts to use program-specific state parsers to return + more human-readable and explicit account state data +- If `jsonParsed` is requested but a parser cannot be found, the field falls + back to binary encoding, detectable when the `data`field is type`string`. + +
+ +
+ +
+ +### Result + +`` - Subscription id \(needed to unsubscribe\) + +
+ + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "accountSubscribe", + "params": [ + "CM78CPUeXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNH12", + { + "encoding": "jsonParsed", + "commitment": "finalized" + } + ] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 23784, "id": 1 } +``` + + +
+ +#### Notification Format: + +The notification format is the same as seen in the +[getAccountInfo](/docs/rpc/http/getAccountInfo) RPC HTTP method. + +Base58 encoding: + +```json +{ + "jsonrpc": "2.0", + "method": "accountNotification", + "params": { + "result": { + "context": { + "slot": 5199307 + }, + "value": { + "data": [ + "11116bv5nS2h3y12kD1yUKeMZvGcKLSjQgX6BeV7u1FrjeJcKfsHPXHRDEHrBesJhZyqnnq9qJeUuF7WHxiuLuL5twc38w2TXNLxnDbjmuR", + "base58" + ], + "executable": false, + "lamports": 33594, + "owner": "11111111111111111111111111111111", + "rentEpoch": 635, + "space": 80 + } + }, + "subscription": 23784 + } +} +``` + +Parsed-JSON encoding: + +```json +{ + "jsonrpc": "2.0", + "method": "accountNotification", + "params": { + "result": { + "context": { + "slot": 5199307 + }, + "value": { + "data": { + "program": "nonce", + "parsed": { + "type": "initialized", + "info": { + "authority": "Bbqg1M4YVVfbhEzwA9SpC9FhsaG83YMTYoR4a8oTDLX", + "blockhash": "LUaQTmM7WbMRiATdMMHaRGakPtCkc2GHtH57STKXs6k", + "feeCalculator": { + "lamportsPerSignature": 5000 + } + } + } + }, + "executable": false, + "lamports": 33594, + "owner": "11111111111111111111111111111111", + "rentEpoch": 635, + "space": 80 + } + }, + "subscription": 23784 + } +} +``` diff --git a/docs/uk/rpc/websocket/accountUnsubscribe.mdx b/docs/uk/rpc/websocket/accountUnsubscribe.mdx new file mode 100644 index 000000000..f46399941 --- /dev/null +++ b/docs/uk/rpc/websocket/accountUnsubscribe.mdx @@ -0,0 +1,47 @@ +--- +sidebarLabel: accountUnsubscribe +title: accountUnsubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/accountUnsubscribe +--- + +Unsubscribe from account change notifications + + + + + +### Parameters + + + id of the account Subscription to cancel + + +### Result + +`` - unsubscribe success message + + + + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "accountUnsubscribe", + "params": [0] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": true, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/websocket/blockSubscribe.mdx b/docs/uk/rpc/websocket/blockSubscribe.mdx new file mode 100644 index 000000000..f40659ffa --- /dev/null +++ b/docs/uk/rpc/websocket/blockSubscribe.mdx @@ -0,0 +1,386 @@ +--- +sidebarLabel: blockSubscribe +title: blockSubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/blockSubscribe +--- + +Subscribe to receive notification anytime a new block is `confirmed` or +`finalized`. + + + This subscription is considered **unstable** and is only available if the + validator was started with the `--rpc-pubsub-enable-block-subscription` flag. + The format of this subscription may change in the future. + + + + + + +### Parameters + + + +filter criteria for the logs to receive results by account type; currently +supported: + + + `all` - include all transactions in block + + + + +A JSON object with the following field: + +- `mentionsAccountOrProgram: ` - return only transactions that mention + the provided public key (as base-58 encoded string). If no mentions in a given + block, then no notification will be sent. + + + + + + + +Configuration object containing the following fields: + + + +- `processed` is not supported. + + + + + +encoding format for each returned Transaction + + + +
+ +- `jsonParsed` attempts to use program-specific instruction parsers to return + more human-readable and explicit data in the + `transaction.message.instructions` list. +- If `jsonParsed` is requested but a parser cannot be found, the instruction + falls back to regular JSON encoding (`accounts`, `data`, and `programIdIndex` + fields). + +
+ +
+ + + +level of transaction detail to return + + + +
+ +- If `accounts` are requested, transaction details only include signatures and + an annotated list of accounts in each transaction. +- Transaction metadata is limited to only: fee, err, pre_balances, + post_balances, pre_token_balances, and post_token_balances. + +
+ +
+ + + +the max transaction version to return in responses. + +
+ +- If the requested block contains a transaction with a higher version, an error + will be returned. +- If this parameter is omitted, only legacy transactions will be returned, and a + block containing any versioned transaction will prompt the error. + +
+ +
+ + + whether to populate the `rewards` array. If parameter not provided, the + default includes rewards. + + +
+ +### Result + +`integer` - subscription id \(needed to unsubscribe\) + +
+ + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "method": "blockSubscribe", + "params": ["all"] +} +``` + +```json +{ + "jsonrpc": "2.0", + "id": "1", + "method": "blockSubscribe", + "params": [ + { + "mentionsAccountOrProgram": "LieKvPRE8XeX3Y2xVNHjKlpAScD12lYySBVQ4HqoJ5op" + }, + { + "commitment": "confirmed", + "encoding": "base64", + "showRewards": true, + "transactionDetails": "full" + } + ] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 0, "id": 1 } +``` + + +
+ +#### Notification Format: + +The notification will be an object with the following fields: + +- `slot: ` - The corresponding slot. +- `err: ` - Error if something went wrong publishing the + notification otherwise null. +- `block: ` - A block object as seen in the + [getBlock](/docs/rpc/http/getblock) RPC HTTP method. + +```json +{ + "jsonrpc": "2.0", + "method": "blockNotification", + "params": { + "result": { + "context": { + "slot": 112301554 + }, + "value": { + "slot": 112301554, + "block": { + "previousBlockhash": "GJp125YAN4ufCSUvZJVdCyWQJ7RPWMmwxoyUQySydZA", + "blockhash": "6ojMHjctdqfB55JDpEpqfHnP96fiaHEcvzEQ2NNcxzHP", + "parentSlot": 112301553, + "transactions": [ + { + "transaction": [ + "OpltwoUvWxYi1P2U8vbIdE/aPntjYo5Aa0VQ2JJyeJE2g9Vvxk8dDGgFMruYfDu8/IfUWb0REppTe7IpAuuLRgIBAAkWnj4KHRpEWWW7gvO1c0BHy06wZi2g7/DLqpEtkRsThAXIdBbhXCLvltw50ZnjDx2hzw74NVn49kmpYj2VZHQJoeJoYJqaKcvuxCi/2i4yywedcVNDWkM84Iuw+cEn9/ROCrXY4qBFI9dveEERQ1c4kdU46xjxj9Vi+QXkb2Kx45QFVkG4Y7HHsoS6WNUiw2m4ffnMNnOVdF9tJht7oeuEfDMuUEaO7l9JeUxppCvrGk3CP45saO51gkwVYEgKzhpKjCx3rgsYxNR81fY4hnUQXSbbc2Y55FkwgRBpVvQK7/+clR4Gjhd3L4y+OtPl7QF93Akg1LaU9wRMs5nvfDFlggqI9PqJl+IvVWrNRdBbPS8LIIhcwbRTkSbqlJQWxYg3Bo2CTVbw7rt1ZubuHWWp0mD/UJpLXGm2JprWTePNULzHu67sfqaWF99LwmwjTyYEkqkRt1T0Je5VzHgJs0N5jY4iIU9K3lMqvrKOIn/2zEMZ+ol2gdgjshx+sphIyhw65F3J/Dbzk04LLkK+CULmN571Y+hFlXF2ke0BIuUG6AUF+4214Cu7FXnqo3rkxEHDZAk0lRrAJ8X/Z+iwuwI5cgbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpDLAp8axcEkaQkLDKRoWxqp8XLNZSKial7Rk+ELAVVKWoWLRXRZ+OIggu0OzMExvVLE5VHqy71FNHq4gGitkiKYNFWSLIE4qGfdFLZXy/6hwS+wq9ewjikCpd//C9BcCL7Wl0iQdUslxNVCBZHnCoPYih9JXvGefOb9WWnjGy14sG9j70+RSVx6BlkFELWwFvIlWR/tHn3EhHAuL0inS2pwX7ZQTAU6gDVaoqbR2EiJ47cKoPycBNvHLoKxoY9AZaBjPl6q8SKQJSFyFd9n44opAgI6zMTjYF/8Ok4VpXEESp3QaoUyTI9sOJ6oFP6f4dwnvQelgXS+AEfAsHsKXxGAIUDQENAgMEBQAGBwgIDg8IBJCER3QXl1AVDBADCQoOAAQLERITDAjb7ugh3gOuTy==", + "base64" + ], + "meta": { + "err": null, + "status": { + "Ok": null + }, + "fee": 5000, + "preBalances": [ + 1758510880, 2067120, 1566000, 1461600, 2039280, 2039280, + 1900080, 1865280, 0, 3680844220, 2039280 + ], + "postBalances": [ + 1758505880, 2067120, 1566000, 1461600, 2039280, 2039280, + 1900080, 1865280, 0, 3680844220, 2039280 + ], + "innerInstructions": [ + { + "index": 0, + "instructions": [ + { + "programIdIndex": 13, + "accounts": [1, 15, 3, 4, 2, 14], + "data": "21TeLgZXNbtHXVBzCaiRmH" + }, + { + "programIdIndex": 14, + "accounts": [3, 4, 1], + "data": "6qfC8ic7Aq99" + }, + { + "programIdIndex": 13, + "accounts": [1, 15, 3, 5, 2, 14], + "data": "21TeLgZXNbsn4QEpaSEr3q" + }, + { + "programIdIndex": 14, + "accounts": [3, 5, 1], + "data": "6LC7BYyxhFRh" + } + ] + }, + { + "index": 1, + "instructions": [ + { + "programIdIndex": 14, + "accounts": [4, 3, 0], + "data": "7aUiLHFjSVdZ" + }, + { + "programIdIndex": 19, + "accounts": [17, 18, 16, 9, 11, 12, 14], + "data": "8kvZyjATKQWYxaKR1qD53V" + }, + { + "programIdIndex": 14, + "accounts": [9, 11, 18], + "data": "6qfC8ic7Aq99" + } + ] + } + ], + "logMessages": [ + "Program QMNeHCGYnLVDn1icRAfQZpjPLBNkfGbSKRB83G5d8KB invoke [1]", + "Program QMWoBmAyJLAsA1Lh9ugMTw2gciTihncciphzdNzdZYV invoke [2]" + ], + "preTokenBalances": [ + { + "accountIndex": 4, + "mint": "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u", + "uiTokenAmount": { + "uiAmount": null, + "decimals": 6, + "amount": "0", + "uiAmountString": "0" + }, + "owner": "LieKvPRE8XeX3Y2xVNHjKlpAScD12lYySBVQ4HqoJ5op", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 5, + "mint": "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u", + "uiTokenAmount": { + "uiAmount": 11513.0679, + "decimals": 6, + "amount": "11513067900", + "uiAmountString": "11513.0679" + }, + "owner": "rXhAofQCT7NN9TUqigyEAUzV1uLL4boeD8CRkNBSkYk", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 10, + "mint": "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1", + "uiTokenAmount": { + "uiAmount": null, + "decimals": 6, + "amount": "0", + "uiAmountString": "0" + }, + "owner": "CL9wkGFT3SZRRNa9dgaovuRV7jrVVigBUZ6DjcgySsCU", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + }, + { + "accountIndex": 11, + "mint": "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1", + "uiTokenAmount": { + "uiAmount": 15138.514093, + "decimals": 6, + "amount": "15138514093", + "uiAmountString": "15138.514093" + }, + "owner": "LieKvPRE8XeX3Y2xVNHjKlpAScD12lYySBVQ4HqoJ5op", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + } + ], + "postTokenBalances": [ + { + "accountIndex": 4, + "mint": "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u", + "uiTokenAmount": { + "uiAmount": null, + "decimals": 6, + "amount": "0", + "uiAmountString": "0" + }, + "owner": "LieKvPRE8XeX3Y2xVNHjKlpAScD12lYySBVQ4HqoJ5op", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 5, + "mint": "iouQcQBAiEXe6cKLS85zmZxUqaCqBdeHFpqKoSz615u", + "uiTokenAmount": { + "uiAmount": 11513.103028, + "decimals": 6, + "amount": "11513103028", + "uiAmountString": "11513.103028" + }, + "owner": "rXhAofQCT7NN9TUqigyEAUzV1uLL4boeD8CRkNBSkYk", + "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "accountIndex": 10, + "mint": "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1", + "uiTokenAmount": { + "uiAmount": null, + "decimals": 6, + "amount": "0", + "uiAmountString": "0" + }, + "owner": "CL9wkGFT3SZRRNa9dgaovuRV7jrVVigBUZ6DjcgySsCU", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + }, + { + "accountIndex": 11, + "mint": "Saber2gLauYim4Mvftnrasomsv6NvAuncvMEZwcLpD1", + "uiTokenAmount": { + "uiAmount": 15489.767829, + "decimals": 6, + "amount": "15489767829", + "uiAmountString": "15489.767829" + }, + "owner": "BeiHVPRE8XeX3Y2xVNrSsTpAScH94nYySBVQ4HqgN9at", + "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + } + ], + "rewards": [] + } + } + ], + "blockTime": 1639926816, + "blockHeight": 101210751 + }, + "err": null + } + }, + "subscription": 14 + } +} +``` diff --git a/docs/uk/rpc/websocket/blockUnsubscribe.mdx b/docs/uk/rpc/websocket/blockUnsubscribe.mdx new file mode 100644 index 000000000..a1dd8b893 --- /dev/null +++ b/docs/uk/rpc/websocket/blockUnsubscribe.mdx @@ -0,0 +1,47 @@ +--- +sidebarLabel: blockUnsubscribe +title: blockUnsubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/blockUnsubscribe +--- + +Unsubscribe from block notifications + + + + + +### Parameters + + + subscription id to cancel + + +### Result + +`` - unsubscribe success message + + + + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "blockUnsubscribe", + "params": [0] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": true, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/websocket/index.mdx b/docs/uk/rpc/websocket/index.mdx new file mode 100644 index 000000000..bfee36c14 --- /dev/null +++ b/docs/uk/rpc/websocket/index.mdx @@ -0,0 +1,23 @@ +--- +title: Solana RPC Websocket Methods +seoTitle: Solana RPC Websocket Methods +sidebarLabel: Websocket Methods +sidebarSortOrder: 2 +hideTableOfContents: false +--- + +After connecting to the RPC PubSub websocket at `ws://
/`: + +- Submit subscription requests to the websocket using the methods below +- Multiple subscriptions may be active at once +- Many subscriptions take the optional + [`commitment` parameter](/docs/rpc/index.mdx#configuring-state-commitment), + defining how finalized a change should be to trigger a notification. For + subscriptions, if commitment is unspecified, the default value is `finalized`. + +## RPC PubSub WebSocket Endpoint + +Default port: `8900` + +- ws://localhost:8900 +- http://192.168.1.88:8900 diff --git a/docs/uk/rpc/websocket/logsSubscribe.mdx b/docs/uk/rpc/websocket/logsSubscribe.mdx new file mode 100644 index 000000000..17190b77e --- /dev/null +++ b/docs/uk/rpc/websocket/logsSubscribe.mdx @@ -0,0 +1,138 @@ +--- +sidebarLabel: logsSubscribe +title: logsSubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/logsSubscribe +--- + +Subscribe to transaction logging + + + + + +### Parameters + + + filter criteria for the logs to receive results by account type. The following filters types are currently supported: + + + +A string with one of the following values: + +- `all` - subscribe to all transactions except for simple vote transactions +- `allWithVotes` - subscribe to all transactions, including simple vote + transactions + + + + + +An object with the following field: + +- `mentions: [ ]` - array containing a single Pubkey (as base-58 + encoded string); if present, subscribe to only transactions mentioning this + address + + + The `mentions` field currently [only supports + one](https://github.com/solana-labs/solana/blob/master/rpc/src/rpc_pubsub.rs#L481) + Pubkey string per method call. Listing additional addresses will result in an + error. + + + + + + + + +Configuration object containing the following fields: + + + + + +### Result + +`` - Subscription id \(needed to unsubscribe\) + + + + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "logsSubscribe", + "params": [ + { + "mentions": [ "11111111111111111111111111111111" ] + }, + { + "commitment": "finalized" + } + ] +} +{ + "jsonrpc": "2.0", + "id": 1, + "method": "logsSubscribe", + "params": [ "all" ] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 24040, "id": 1 } +``` + + + + +#### Notification Format: + +The notification will be an RpcResponse JSON object with value equal to: + +- `signature: ` - The transaction signature base58 encoded. +- `err: ` - Error if transaction failed, null if transaction + succeeded. + [TransactionError definitions](https://github.com/solana-labs/solana/blob/c0c60386544ec9a9ec7119229f37386d9f070523/sdk/src/transaction/error.rs#L13) +- `logs: ` - Array of log messages the transaction instructions + output during execution, null if simulation failed before the transaction was + able to execute (for example due to an invalid blockhash or signature + verification failure) + +Example: + +```json +{ + "jsonrpc": "2.0", + "method": "logsNotification", + "params": { + "result": { + "context": { + "slot": 5208469 + }, + "value": { + "signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv", + "err": null, + "logs": [ + "SBF program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri success" + ] + } + }, + "subscription": 24040 + } +} +``` diff --git a/docs/uk/rpc/websocket/logsUnsubscribe.mdx b/docs/uk/rpc/websocket/logsUnsubscribe.mdx new file mode 100644 index 000000000..a98d9da0f --- /dev/null +++ b/docs/uk/rpc/websocket/logsUnsubscribe.mdx @@ -0,0 +1,47 @@ +--- +sidebarLabel: logsUnsubscribe +title: logsUnsubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/logsUnsubscribe +--- + +Unsubscribe from transaction logging + + + + + +### Parameters + + + subscription id to cancel + + +### Result + +`` - unsubscribe success message + + + + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "logsUnsubscribe", + "params": [0] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": true, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/websocket/programSubscribe.mdx b/docs/uk/rpc/websocket/programSubscribe.mdx new file mode 100644 index 000000000..377ef738b --- /dev/null +++ b/docs/uk/rpc/websocket/programSubscribe.mdx @@ -0,0 +1,211 @@ +--- +sidebarLabel: programSubscribe +title: programSubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/programSubscribe +--- + +Subscribe to a program to receive notifications when the lamports or data for an +account owned by the given program changes + + + + + +### Parameters + + + +Pubkey of the `program_id`, as base-58 encoded string + + + + + +Configuration object containing the following fields: + + + + + +filter results using various filter objects + + + The resultant account must meet **ALL** filter criteria to be included in the + returned results + + + + + + +Encoding format for Account data + + + +
+ +- `base58` is slow. +- `jsonParsed` encoding attempts to use program-specific state parsers to return + more human-readable and explicit account state data. +- If `jsonParsed` is requested but a parser cannot be found, the field falls + back to `base64` encoding, detectable when the `data` field is type `string`. + +
+ +
+ +
+ +### Result + +`` - Subscription id \(needed to unsubscribe\) + +
+ + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "programSubscribe", + "params": [ + "11111111111111111111111111111111", + { + "encoding": "base64", + "commitment": "finalized" + } + ] +} +{ + "jsonrpc": "2.0", + "id": 1, + "method": "programSubscribe", + "params": [ + "11111111111111111111111111111111", + { + "encoding": "jsonParsed" + } + ] +} +{ + "jsonrpc": "2.0", + "id": 1, + "method": "programSubscribe", + "params": [ + "11111111111111111111111111111111", + { + "encoding": "base64", + "filters": [ + { + "dataSize": 80 + } + ] + } + ] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 24040, "id": 1 } +``` + + +
+ +#### Notification format + +The notification format is a single program account object as seen in the +[getProgramAccounts](/docs/rpc/http/getprogramaccounts) RPC HTTP method. + +Base58 encoding: + +```json +{ + "jsonrpc": "2.0", + "method": "programNotification", + "params": { + "result": { + "context": { + "slot": 5208469 + }, + "value": { + "pubkey": "H4vnBqifaSACnKa7acsxstsY1iV1bvJNxsCY7enrd1hq", + "account": { + "data": [ + "11116bv5nS2h3y12kD1yUKeMZvGcKLSjQgX6BeV7u1FrjeJcKfsHPXHRDEHrBesJhZyqnnq9qJeUuF7WHxiuLuL5twc38w2TXNLxnDbjmuR", + "base58" + ], + "executable": false, + "lamports": 33594, + "owner": "11111111111111111111111111111111", + "rentEpoch": 636, + "space": 80 + } + } + }, + "subscription": 24040 + } +} +``` + +Parsed-JSON encoding: + +```json +{ + "jsonrpc": "2.0", + "method": "programNotification", + "params": { + "result": { + "context": { + "slot": 5208469 + }, + "value": { + "pubkey": "H4vnBqifaSACnKa7acsxstsY1iV1bvJNxsCY7enrd1hq", + "account": { + "data": { + "program": "nonce", + "parsed": { + "type": "initialized", + "info": { + "authority": "Bbqg1M4YVVfbhEzwA9SpC9FhsaG83YMTYoR4a8oTDLX", + "blockhash": "LUaQTmM7WbMRiATdMMHaRGakPtCkc2GHtH57STKXs6k", + "feeCalculator": { + "lamportsPerSignature": 5000 + } + } + } + }, + "executable": false, + "lamports": 33594, + "owner": "11111111111111111111111111111111", + "rentEpoch": 636, + "space": 80 + } + } + }, + "subscription": 24040 + } +} +``` diff --git a/docs/uk/rpc/websocket/programUnsubscribe.mdx b/docs/uk/rpc/websocket/programUnsubscribe.mdx new file mode 100644 index 000000000..e548ddf88 --- /dev/null +++ b/docs/uk/rpc/websocket/programUnsubscribe.mdx @@ -0,0 +1,47 @@ +--- +sidebarLabel: programUnsubscribe +title: programUnsubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/programUnsubscribe +--- + +Unsubscribe from program-owned account change notifications + + + + + +### Parameters + + + id of account Subscription to cancel + + +### Result + +`` - unsubscribe success message + + + + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "programUnsubscribe", + "params": [0] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": true, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/websocket/rootSubscribe.mdx b/docs/uk/rpc/websocket/rootSubscribe.mdx new file mode 100644 index 000000000..16bf8b689 --- /dev/null +++ b/docs/uk/rpc/websocket/rootSubscribe.mdx @@ -0,0 +1,55 @@ +--- +sidebarLabel: rootSubscribe +title: rootSubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/rootSubscribe +--- + +Subscribe to receive notification anytime a new root is set by the validator. + + + + + +### Parameters + +**None** + +### Result + +`integer` - subscription id \(needed to unsubscribe\) + + + + + +### Code sample + +```json +{ "jsonrpc": "2.0", "id": 1, "method": "rootSubscribe" } +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 0, "id": 1 } +``` + + + + +#### Notification Format: + +The result is the latest root slot number. + +```json +{ + "jsonrpc": "2.0", + "method": "rootNotification", + "params": { + "result": 42, + "subscription": 0 + } +} +``` diff --git a/docs/uk/rpc/websocket/rootUnsubscribe.mdx b/docs/uk/rpc/websocket/rootUnsubscribe.mdx new file mode 100644 index 000000000..4f8068929 --- /dev/null +++ b/docs/uk/rpc/websocket/rootUnsubscribe.mdx @@ -0,0 +1,47 @@ +--- +sidebarLabel: rootUnsubscribe +title: rootUnsubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/rootUnsubscribe +--- + +Unsubscribe from root notifications + + + + + +### Parameters + + + subscription id to cancel + + +### Result + +`` - unsubscribe success message + + + + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "rootUnsubscribe", + "params": [0] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": true, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/websocket/signatureSubscribe.mdx b/docs/uk/rpc/websocket/signatureSubscribe.mdx new file mode 100644 index 000000000..ea33dc026 --- /dev/null +++ b/docs/uk/rpc/websocket/signatureSubscribe.mdx @@ -0,0 +1,149 @@ +--- +sidebarLabel: signatureSubscribe +title: signatureSubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/signatureSubscribe +--- + +Subscribe to receive a notification when the transaction with the given +signature reaches the specified commitment level. + + + This is a subscription to a single notification. It is automatically cancelled + by the server once the notification, `signatureNotification`, is sent by the + RPC. + + + + + + +### Parameters + + + +transaction signature, as base-58 encoded string + + + The transaction signature must be the first signature from the transaction + (see [transaction id](/docs/terminology.md#transaction-id) for more details). + + + + + + +Configuration object containing the following fields: + + + + + +Whether or not to subscribe for notifications when signatures are received by +the RPC, in addition to when they are processed. + + + + + +### Result + +`` - subscription id (needed to unsubscribe) + + + + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "signatureSubscribe", + "params": [ + "2EBVM6cB8vAAD93Ktr6Vd8p67XPbQzCJX47MpReuiCXJAtcjaxpvWpcg9Ege1Nr5Tk3a2GFrByT7WPBjdsTycY9b", + { + "commitment": "finalized", + "enableReceivedNotification": false + } + ] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 0, "id": 1 } +``` + + + + +#### Notification Format: + +The notification will be an RpcResponse JSON object with value containing an +object with: + +- `slot: ` - The corresponding slot. +- `value: ` - a notification value of + [`RpcSignatureResult`](https://github.com/solana-labs/solana/blob/6d28fd455b07e3557fc6c0c3ddf3ba03e3fe8482/rpc-client-api/src/response.rs#L265-L268), + resulting in either: + - when `enableReceivedNotification` is `true` and the signature is received: + the literal string + [`"receivedSignature"`](https://github.com/solana-labs/solana/blob/6d28fd455b07e3557fc6c0c3ddf3ba03e3fe8482/rpc-client-api/src/response.rs#L286-L288), + or + - when the signature is processed: `err: `: + - `null` if the transaction succeeded in being processed at the specified + commitment level, or + - a + [`TransactionError`](https://github.com/solana-labs/solana/blob/6d28fd455b07e3557fc6c0c3ddf3ba03e3fe8482/sdk/src/transaction/error.rs#L15-L164), + if the transaction failed + +#### Example responses: + +The following is an example response of a notification from a successfully +**processed** transactions: + +```json +{ + "jsonrpc": "2.0", + "method": "signatureNotification", + "params": { + "result": { + "context": { + "slot": 5207624 + }, + "value": { + "err": null + } + }, + "subscription": 24006 + } +} +``` + +The following is an example response of a notification from a successfully +**received** transaction signature: + +```json +{ + "jsonrpc": "2.0", + "method": "signatureNotification", + "params": { + "result": { + "context": { + "slot": 5207624 + }, + "value": "receivedSignature" + }, + "subscription": 24006 + } +} +``` diff --git a/docs/uk/rpc/websocket/signatureUnsubscribe.mdx b/docs/uk/rpc/websocket/signatureUnsubscribe.mdx new file mode 100644 index 000000000..f34ced2dd --- /dev/null +++ b/docs/uk/rpc/websocket/signatureUnsubscribe.mdx @@ -0,0 +1,47 @@ +--- +sidebarLabel: signatureUnsubscribe +title: signatureUnsubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/signatureUnsubscribe +--- + +Unsubscribe from signature confirmation notification + + + + + +### Parameters + + + subscription id to cancel + + +### Result + +`` - unsubscribe success message + + + + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "signatureUnsubscribe", + "params": [0] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": true, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/websocket/slotSubscribe.mdx b/docs/uk/rpc/websocket/slotSubscribe.mdx new file mode 100644 index 000000000..e90dff657 --- /dev/null +++ b/docs/uk/rpc/websocket/slotSubscribe.mdx @@ -0,0 +1,65 @@ +--- +sidebarLabel: slotSubscribe +title: slotSubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/slotSubscribe +--- + +Subscribe to receive notification anytime a slot is processed by the validator + + + + + +### Parameters + +**None** + +### Result + +`` - Subscription id \(needed to unsubscribe\) + + + + + +### Code sample + +```json +{ "jsonrpc": "2.0", "id": 1, "method": "slotSubscribe" } +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 0, "id": 1 } +``` + + + + +#### Notification Format: + +The notification will be an object with the following fields: + +- `parent: ` - The parent slot +- `root: ` - The current root slot +- `slot: ` - The newly set slot value + +Example: + +```json +{ + "jsonrpc": "2.0", + "method": "slotNotification", + "params": { + "result": { + "parent": 75, + "root": 44, + "slot": 76 + }, + "subscription": 0 + } +} +``` diff --git a/docs/uk/rpc/websocket/slotUnsubscribe.mdx b/docs/uk/rpc/websocket/slotUnsubscribe.mdx new file mode 100644 index 000000000..450afc276 --- /dev/null +++ b/docs/uk/rpc/websocket/slotUnsubscribe.mdx @@ -0,0 +1,47 @@ +--- +sidebarLabel: slotUnsubscribe +title: slotUnsubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/slotUnsubscribe +--- + +Unsubscribe from slot notifications + + + + + +### Parameters + + + subscription id to cancel + + +### Result + +`` - unsubscribe success message + + + + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "slotUnsubscribe", + "params": [0] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": true, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/websocket/slotsUpdatesSubscribe.mdx b/docs/uk/rpc/websocket/slotsUpdatesSubscribe.mdx new file mode 100644 index 000000000..a683a2755 --- /dev/null +++ b/docs/uk/rpc/websocket/slotsUpdatesSubscribe.mdx @@ -0,0 +1,87 @@ +--- +sidebarLabel: slotsUpdatesSubscribe +title: slotsUpdatesSubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/slotsUpdatesSubscribe +--- + +Subscribe to receive a notification from the validator on a variety of updates +on every slot + + + This subscription is unstable. The format of this subscription may change in + the future, and may not always be supported. + + + + + + +### Parameters + +**None** + +### Result + +`` - Subscription id (needed to unsubscribe) + + + + + +### Code sample + +```json +{ "jsonrpc": "2.0", "id": 1, "method": "slotsUpdatesSubscribe" } +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 0, "id": 1 } +``` + + + + +### Notification Format + +The notification will be an object with the following fields: + +- `err: ` - The error message. Only present if the update is + of type "dead". +- `parent: ` - The parent slot. Only present if the update is of + type "createdBank". +- `slot: ` - The newly updated slot +- `stats: ` - The error message. Only present if the update is + of type "frozen". An object with the following fields: + - `maxTransactionsPerEntry: `, + - `numFailedTransactions: `, + - `numSuccessfulTransactions: `, + - `numTransactionEntries: `, +- `timestamp: ` - The Unix timestamp of the update in milliseconds +- `type: ` - The update type, one of: + - "firstShredReceived" + - "completed" + - "createdBank" + - "frozen" + - "dead" + - "optimisticConfirmation" + - "root" + +```shell +{ + "jsonrpc": "2.0", + "method": "slotsUpdatesNotification", + "params": { + "result": { + "parent": 75, + "slot": 76, + "timestamp": 1625081266243, + "type": "optimisticConfirmation" + }, + "subscription": 0 + } +} +``` diff --git a/docs/uk/rpc/websocket/slotsUpdatesUnsubscribe.mdx b/docs/uk/rpc/websocket/slotsUpdatesUnsubscribe.mdx new file mode 100644 index 000000000..61f25e196 --- /dev/null +++ b/docs/uk/rpc/websocket/slotsUpdatesUnsubscribe.mdx @@ -0,0 +1,47 @@ +--- +sidebarLabel: slotsUpdatesUnsubscribe +title: slotsUpdatesUnsubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/slotsUpdatesUnsubscribe +--- + +Unsubscribe from slot-update notifications + + + + + +### Parameters + + + subscription id to cancel + + +### Result + +`` - unsubscribe success message + + + + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "slotsUpdatesUnsubscribe", + "params": [0] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": true, "id": 1 } +``` + + + diff --git a/docs/uk/rpc/websocket/voteSubscribe.mdx b/docs/uk/rpc/websocket/voteSubscribe.mdx new file mode 100644 index 000000000..77384856a --- /dev/null +++ b/docs/uk/rpc/websocket/voteSubscribe.mdx @@ -0,0 +1,75 @@ +--- +sidebarLabel: voteSubscribe +title: voteSubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/voteSubscribe +--- + +Subscribe to receive notification anytime a new vote is observed in gossip. +These votes are pre-consensus therefore there is no guarantee these votes will +enter the ledger. + + + This subscription is unstable and only available if the validator was started + with the `--rpc-pubsub-enable-vote-subscription` flag. The format of this + subscription may change in the future. + + + + + + +### Parameters + +**None** + +### Result + +`` - subscription id (needed to unsubscribe) + + + + + +### Code sample + +```json +{ "jsonrpc": "2.0", "id": 1, "method": "voteSubscribe" } +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": 0, "id": 1 } +``` + + + + +#### Notification Format: + +The notification will be an object with the following fields: + +- `hash: ` - The vote hash +- `slots: ` - The slots covered by the vote, as an array of u64 integers +- `timestamp: ` - The timestamp of the vote +- `signature: ` - The signature of the transaction that contained this + vote +- `votePubkey: ` - The public key of the vote account, as base-58 + encoded string + +```json +{ + "jsonrpc": "2.0", + "method": "voteNotification", + "params": { + "result": { + "hash": "8Rshv2oMkPu5E4opXTRyuyBeZBqQ4S477VG26wUTFxUM", + "slots": [1, 2], + "timestamp": null + }, + "subscription": 0 + } +} +``` diff --git a/docs/uk/rpc/websocket/voteUnsubscribe.mdx b/docs/uk/rpc/websocket/voteUnsubscribe.mdx new file mode 100644 index 000000000..abcfe1354 --- /dev/null +++ b/docs/uk/rpc/websocket/voteUnsubscribe.mdx @@ -0,0 +1,47 @@ +--- +sidebarLabel: voteUnsubscribe +title: voteUnsubscribe RPC Method +hideTableOfContents: true +altRoutes: + - /docs/rpc/voteUnsubscribe +--- + +Unsubscribe from vote notifications + + + + + +### Parameters + + + subscription id to cancel + + +### Result + +`` - unsubscribe success message + + + + + +### Code sample + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "voteUnsubscribe", + "params": [0] +} +``` + +### Response + +```json +{ "jsonrpc": "2.0", "result": true, "id": 1 } +``` + + + diff --git a/docs/uk/terminology.md b/docs/uk/terminology.md new file mode 100644 index 000000000..f6f8eb13a --- /dev/null +++ b/docs/uk/terminology.md @@ -0,0 +1,438 @@ +--- +title: Терміни +description: + "Дізнайтеся основну термінологію, яка використовується в блокчейні Solana та + моделях розробки." +keywords: + - терміни + - словник + - визначення + - програмні моделі +isSkippedInNav: true +--- + +Наведені нижче терміни використовуються в документації Solana та екосистемі розробки. + +## Обліковий запис (account) + +Запис у реєстрі Solana, який або зберігає дані, або є виконуваною програмою. + +Як і обліковий запис у традиційному банку, обліковий запис Solana може зберігати кошти, які називаються [лампортами](#lamport). Як файл у Linux, він адресується ключем, часто згадуваним як [публічний ключ](#public-key-pubkey) або pubkey. + +Ключ може бути одним із таких: + +- Публічний ключ ed25519 +- Адреса облікового запису, отримана програмно (32-байтне значення поза кривою ed25519) +- Хеш публічного ключа ed25519 із рядком із 32 символів + +## Власник облікового запису (account owner) + +Адреса програми, якій належить обліковий запис. Тільки програма-власник може змінювати обліковий запис. + +Див. також [Повноваження](#authority). + +## Застосунок (app) + +Фронтенд-застосунок, який взаємодіє з кластером Solana. + +## Повноваження (authority) + +Адреса користувача, який має певні дозволи на обліковий запис. + +Наприклад: + +- Можливість карбування нових токенів надається обліковому запису, який є "владою карбування" токена. +- Можливість оновлювати програму надається обліковому запису, який є "владою оновлення" програми. + +## Стан банку (bank state) + +Результат виконання всіх програм у реєстрі на певній [висоті тікання](#tick-height). Він включає щонайменше набір усіх [облікових записів](#account), які зберігають ненульові [нативні токени](#native-token). + +## Блок (block) + +Неперервний набір [записів](#entry) у реєстрі, підтверджений [голосуванням](#ledger-vote). [Лідер](#leader) створює не більше одного блоку за [слот](#slot). + +## Блокхеш (blockhash) + +Унікальне значення ([хеш](#hash)), яке ідентифікує запис (блок). Solana обчислює блокхеш із останнього [ідентифікатора запису](#entry-id) блоку. + +## Висота блоку (block height) + +Кількість [блоків](#block) під поточним блоком. Перший блок після [генезис-блоку](#genesis-block) має висоту один. + +## Завантажувач BPF (BPF loader) + +Програма Solana, яка завантажує [програми на основі BPF](/docs/core/programs#berkeley-packet-filter-bpf) в [блокчейн](#onchain-program), дозволяючи їм взаємодіяти з середовищем виконання. + +## Клієнт (client) + +Програма, яка підключається до серверної мережі Solana [кластеру](#cluster). + +## Зобов'язання (commitment) + +Міра підтвердження мережі для [блоку](#block). + +## Кластер (cluster) + +Набір [валідаторів](#validator), які підтримують єдиний [реєстр](#ledger). + +## Бюджет обчислень (compute budget) + +Максимальна кількість [обчислювальних одиниць](#compute-units), спожитих за транзакцію. + +## Обчислювальні одиниці (compute units) + +Найменша одиниця вимірювання споживання обчислювальних ресурсів блокчейну. + +## Час підтвердження (confirmation time) + +Час, який пройшов між створенням [тікового запису](#tick) [лідером](#leader) та створенням [підтвердженого блоку](#confirmed-block). + +## Підтверджений блок (confirmed block) + +[Блок](#block), який отримав [супербільшість](#supermajority) [голосів реєстру](#ledger-vote). + +## Площина керування (control plane) + +Мережева структура, яка з'єднує всі [вузли](#node) [кластеру](#cluster). + +## Період охолодження (cooldown period) + +Декілька [епох](#epoch) після деактивації [ставки](#stake), протягом яких вона поступово стає доступною для зняття. Під час цього періоду ставка вважається "деактивованою". Докладніше: +[періоди прогріву та охолодження](https://docs.anza.xyz/implemented-proposals/staking-rewards#stake-warmup-cooldown-withdrawal). + +## Кредит (credit) + +Див. [Кредит голосування](#vote-credit). + +## Виклик між програмами (CPI) + +Виклик однієї [програми на блокчейні](#onchain-program) до іншої. Докладніше див. [Виклик між програмами](/docs/core/cpi.md). + +## Площина даних (data plane) + +Мультикаст-мережа, яка використовується для ефективної перевірки [записів](#entry) і досягнення консенсусу. + +## Дрон (drone) + +Зовнішній сервіс, який виступає в ролі хранителя приватного ключа користувача. Зазвичай використовується для перевірки та підпису транзакцій. + +## Запис (entry) + +Запис у [реєстрі](#ledger), який може бути або [тіком](#tick), або [записом транзакції](#transactions-entry). + +## Ідентифікатор запису (entry id) + +Хеш ([hash](#hash)), стійкий до попереднього зображення, який є унікальним ідентифікатором [запису](#entry). Хеш слугує доказом: + +- Генерації запису після певного проміжку часу +- Включення зазначених [транзакцій](#transaction) у запис +- Розташування запису відносно інших записів у [реєстрі](#ledger) + +Див. [Доказ історії (Proof of History)](#proof-of-history-poh). + +## Епоха (epoch) + +Проміжок часу, визначений кількістю [слотів](#slot), протягом яких діє [розклад лідерів](#leader-schedule). + +## Обліковий запис для комісій (fee account) + +Обліковий запис у транзакції, який оплачує вартість включення транзакції до реєстру. Це перший обліковий запис у транзакції. Він має бути оголошений як читально-записуваний (writable), оскільки оплата транзакції зменшує баланс облікового запису. + +## Фінальність (finality) + +Стан, коли вузли, що представляють 2/3 [ставки](#stake), мають спільний [корінь](#root). + +## Форк (fork) + +[Реєстр](#ledger), створений на основі загальних записів, але який розійшовся у своєму розвитку. + +## Генезис-блок (genesis block) + +Перший [блок](#block) у ланцюжку. + +## Генезис-конфігурація (genesis config) + +Файл конфігурації, який підготовлює [реєстр](#ledger) для [генезис-блоку](#genesis-block). + +## Хеш (hash) + +Цифровий відбиток послідовності байтів. + +## Інфляція (inflation) + +Збільшення кількості токенів із часом, яке використовується для фінансування винагород за валідацію та подальшого розвитку Solana. + +## Внутрішня інструкція (inner instruction) + +Див. [Виклик між програмами](#cross-program-invocation-cpi). + +## Інструкція (instruction) + +Виклик для запуску конкретного [обробника інструкцій](#instruction-handler) у [програмі](#program). Інструкція також вказує, які облікові записи потрібно прочитати або змінити, та додаткові дані, які слугують допоміжним вхідним параметром для [обробника інструкцій](#instruction-handler). Кожна [транзакція](#transaction) має містити принаймні одну інструкцію. + +## Обробник інструкцій (instruction handler) + +Функції [програм](#program), які обробляють [інструкції](#instruction) із [транзакцій](#transaction). Обробник інструкцій може містити одну або кілька [викликів між програмами](#cross-program-invocation-cpi). + +## Пара ключів (keypair) + +[Публічний ключ](#public-key-pubkey) і відповідний [приватний ключ](#private-key), які використовуються для доступу до облікового запису. + +## Лампорти (lamport) + +Дробова одиниця [нативного токена](#native-token) із вартістю 0.000000001 [SOL](#sol). + +> У межах бюджету обчислень використовується кількість +> _[мікролампортів](https://github.com/solana-labs/solana/blob/ced8f6a512c61e0dd5308095ae8457add4a39e94/program-runtime/src/prioritization_fee.rs#L1-L2)_ для розрахунку [пріоритетної комісії](#prioritization-fee). + +## Лідер (leader) + +Роль [валідатора](#validator), який додає [записи](#entry) до [реєстру](#ledger). + +## Розклад лідерів (leader schedule) + +Послідовність [публічних ключів](#public-key-pubkey) [валідаторів](#validator), пов’язаних із [слотами](#slot). Кластер використовує цей розклад, щоб визначити, який валідатор є [лідером](#leader) у певний момент часу. + +## Реєстр (ledger) + +Список [записів](#entry), що містять [транзакції](#transaction), підписані [клієнтами](#client). Концептуально це можна простежити до [генезис-блоку](#genesis-block), але реєстр конкретного [валідатора](#validator) може містити лише новіші [блоки](#block), щоб зменшити обсяг зберігання, оскільки старіші блоки не потрібні для перевірки майбутніх блоків за задумом. + +## Голос у реєстрі (ledger vote) + +[Хеш](#hash) стану [валідатора](#validator) на певній [висоті тікання](#tick-height). Він включає підтвердження валідатора, що [блок](#block), який він отримав, був перевірений, а також обіцянку не голосувати за конфліктуючий [блок](#block) (тобто [форк](#fork)) протягом певного часу, відомого як період [блокування](#lockout). + +## Легкий клієнт (light client) + +Тип [клієнта](#client), який може перевірити, що він підключений до валідного [кластеру](#cluster). Він виконує більше перевірок реєстру, ніж [тонкий клієнт](#thin-client), але менше, ніж [валідатор](#validator). + +## Завантажувач (loader) + +[Програма](#program) із можливістю інтерпретувати двійкове кодування інших програм на блокчейні. + +## Блокування (lockout) + +Тривалість часу, протягом якої [валідатор](#validator) не може [голосувати](#ledger-vote) за інший [форк](#fork). + +## Повідомлення (message) + +Структурований вміст [транзакції](#transaction), зазвичай містить заголовок, масив адрес облікових записів, недавній [блокхеш](#blockhash) та масив [інструкцій](#instruction). + +Докладніше про +[форматування повідомлень у транзакціях](/docs/core/transactions.md#message-header). + +## Коефіцієнт Накамото (Nakamoto coefficient) + +Міра децентралізації, яка визначає найменшу кількість незалежних суб’єктів, що можуть колективно зупинити блокчейн. Термін запропонований Балажі С. Срінівасаном і Леландом Лі у статті +[Quantifying Decentralization](https://news.earn.com/quantifying-decentralization-e39db233c28e). + +## Нативний токен (native token) + +[Токен](#token), що використовується для відстеження роботи [вузлів](#node) у кластері. + +## Вузол (node) + +Комп’ютер, що бере участь у [кластері](#cluster). + +## Кількість вузлів (node count) + +Кількість [валідаторів](#validator), що беруть участь у [кластері](#cluster). + +## Програма на блокчейні (onchain program) + +Виконуваний код у блокчейні Solana, який інтерпретує [інструкції](#instruction), надіслані в кожній [транзакції](#transaction), щоб читати та змінювати облікові записи, якими він управляє. Ці програми часто називають "[розумними контрактами](/docs/core/programs.md)" на інших блокчейнах. + +## PoH (Proof of History) + +Див. [Доказ історії (Proof of History)](#proof-of-history-poh). + +## Окуляр (point) + +Зважений [кредит](#credit) у системі винагород. У системі [винагород валідатора](https://docs.anza.xyz/consensus/stake-delegation-and-rewards) кількість очок, що належить [ставці](#stake), є добутком [голосових кредитів](#vote-credit) і кількості лампортів, що були поставлені. + +## Програма (program) + +Див. [Програма на блокчейні (onchain program)](#onchain-program). + +## Програмно отриманий обліковий запис (PDA) + +Обліковий запис, підписуючою владою якого є програма, і тому він не контролюється приватним ключем, як інші облікові записи. + +## Ідентифікатор програми (program id) + +Публічний ключ [облікового запису](#account), який містить [програму](#program). + +## Доказ історії (Proof of History, PoH) + +Стек доказів, кожен із яких підтверджує, що певні дані існували до моменту створення доказу і що пройшов точний проміжок часу до попереднього доказу. Як і [перевірювана функція затримки (VDF)](#verifiable-delay-function-vdf), Proof of History може бути перевірений швидше, ніж його створення. + +## Пріоритетна комісія (prioritization fee) + +Додаткова комісія, яку користувач може вказати в інструкції бюджету обчислень, щоб пріоритизувати свої [транзакції](#transaction). + +Пріоритетна комісія розраховується шляхом множення запитаного максимуму обчислювальних одиниць на ціну обчислювальної одиниці (вказується в інтервалах 0.000001 лампорта за одиницю), округлену до найближчого лампорта. + +Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць, необхідних для виконання, щоб зменшити комісію. + +## Публічний ключ (public key, pubkey) + +Публічний ключ із [пари ключів](#keypair). + +## Оренда (rent) + +Комісія, яку сплачують [облікові записи](#account) і [програми](#program) за зберігання даних у блокчейні. Якщо на рахунку недостатньо балансу для оплати оренди, він може бути видалений. + +Див. також [звільнення від оренди](#rent-exempt). Докладніше про оренду: [Що таке оренда?](/docs/intro/rent.md). + +## Звільнення від оренди (rent exempt) + +Облікові записи, які підтримують мінімальний баланс лампортів, пропорційний кількості даних, що зберігаються в обліковому записі. Усі нові облікові записи зберігаються на блокчейні постійно, доки обліковий запис не буде закрито. Неможливо створити обліковий запис, який не відповідає порогу звільнення від оренди. + +## Корінь (root) + +[Блок](#block) або [слот](#slot), який досяг максимального [блокування](#lockout) у [валідатора](#validator). Корінь є найвищим блоком, який є предком усіх активних форків у валідатора. Усі предкові блоки кореня також транзитивно є коренями. Блоки, які не є предками чи нащадками кореня, виключаються з розгляду для консенсусу і можуть бути відкинуті. + +## Середовище виконання (runtime) + +Компонент [валідатора](#validator), відповідальний за виконання [програм](#program). + +## Sealevel + +Паралельне середовище виконання Solana для [програм на блокчейні](#onchain-program). + +## Шред (shred) + +Фрагмент [блоку](#block); найменша одиниця, яка передається між [валідаторами](#validator). + +## Підпис (signature) + +64-байтний підпис ed25519, що складається з R (32 байти) і S (32 байти). Цей підпис забезпечує відсутність можливості модифікації (мальованості). Кожна транзакція повинна мати щонайменше один підпис для [облікового запису комісій](#fee-account). Таким чином, перший підпис у транзакції може використовуватися як [ідентифікатор транзакції](#transaction-id). + +## Рівень пропуску (skip rate) + +Відсоток [пропущених слотів](#skipped-slot) від загальної кількості слотів лідера в поточній епосі. Ця метрика може бути оманливою через високу варіативність після межі епохи, коли вибірка невелика, а також для валідаторів із малою кількістю слотів лідера. Однак вона може бути корисною для виявлення неправильних конфігурацій вузлів. + +## Пропущений слот (skipped slot) + +Минулий [слот](#slot), у якому не було створено [блоку](#block), тому що лідер був офлайн або [форк](#fork), що містить цей слот, був залишений на користь кращого варіанту за консенсусом кластера. Пропущений слот не з’явиться як предок для блоків у наступних слотах, не збільшить [висоту блоку](#block-height) і не призведе до прострочення найстарішого `recent_blockhash`. + +Чи було пропущено слот, можна визначити лише тоді, коли він стає старішим за останній [корінний](#root) (а отже, не пропущений) слот. + +## Слот (slot) + +Проміжок часу, протягом якого кожен [лідер](#leader) приймає транзакції та створює [блок](#block). + +Колективно слоти створюють логічний годинник. Слоти упорядковані послідовно та не перекриваються, охоплюючи приблизно однакові інтервали реального часу відповідно до [PoH](#proof-of-history-poh). + +## Розумний контракт (smart contract) + +Див. [Програма на блокчейні](#onchain-program). + +## SOL + +[Нативний токен](#native-token) [кластеру](#cluster) Solana. + +## Бібліотека програм Solana (SPL) + +[Бібліотека програм](https://spl.solana.com/) на Solana, таких як spl-token, що сприяють виконанню завдань, як-от створення та використання токенів. + +## Ставка (stake) + +Токени, які можуть бути конфісковані [кластером](#cluster), якщо буде доведено зловмисну поведінку [валідатора](#validator). + +## Якість обслуговування з урахуванням ставки (stake-weighted quality of service, SWQoS) + +SWQoS дозволяє [надавати перевагу транзакціям, які надходять від валідаторів із поставленими токенами](https://solana.com/developers/guides/advanced/stake-weighted-qos). + +## Супербільшість (supermajority) + +2/3 [кластеру](#cluster). + +## Системна змінна (sysvar) + +Системний [обліковий запис](#account). [Системні змінні (Sysvars)](https://docs.anza.xyz/runtime/sysvars) надають інформацію про стан кластера, наприклад поточну висоту тіку, значення винагород [очок](#point) тощо. Програми можуть отримати доступ до системних змінних через обліковий запис Sysvar (публічний ключ) або запитати через системний виклик. + +## Тонкий клієнт (thin client) + +Тип [клієнта](#client), який довіряє, що він підключений до дійсного [кластеру](#cluster). + +## Тік (tick) + +[Запис](#entry) у реєстрі, який оцінює тривалість реального часу. + +## Висота тіку (tick height) + +N-тий [тік](#tick) у [реєстрі](#ledger). + +## Токен (token) + +Цифровий актив, що підлягає передачі. + +## Програма розширення токенів (Token Extensions Program) + +[Програма розширення токенів](https://spl.solana.com/token-2022) має ідентифікатор `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` і включає всі ті самі функції, що й [Програма токенів](#token-program), але додає розширення, як-от конфіденційні перекази, кастомна логіка переказу, розширені метадані тощо. + +## Карбування токенів (token mint) + +Обліковий запис, який може створювати токени. Різні токени відрізняються за унікальними адресами карбування токенів. + +## Програма токенів (Token Program) + +[Програма токенів](https://spl.solana.com/token) має ідентифікатор `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` і надає базові можливості передачі, заморожування та карбування токенів. + +## TPS + +[Транзакції](#transaction) за секунду. + +## TPU + +[Підрозділ обробки транзакцій](https://docs.anza.xyz/validator/tpu). + +## Транзакція (transaction) + +Одна або кілька [інструкцій](#instruction), підписаних [клієнтом](#client) за допомогою однієї або кількох [пар ключів](#keypair), виконуються атомарно з двома можливими результатами: успіх або невдача. + +## Ідентифікатор транзакції (transaction id) + +Перший [підпис](#signature) у [транзакції](#transaction), який можна використовувати для унікальної ідентифікації транзакції у повному [реєстрі](#ledger). + +## Підтвердження транзакції (transaction confirmations) + +Кількість [підтверджених блоків](#confirmed-block) з моменту прийняття транзакції до [реєстру](#ledger). Транзакція завершується, коли її блок стає [коренем](#root). + +## Запис транзакцій (transactions entry) + +Набір [транзакцій](#transaction), які можна виконувати паралельно. + +## TVU + +[Підрозділ перевірки транзакцій](https://docs.anza.xyz/validator/tvu). + +## Валідатор (validator) + +Повноцінний учасник мережі Solana, який створює нові [блоки](#block). Валідатор перевіряє транзакції, додані до [реєстру](#ledger). + +## VDF + +Див. [Перевірювана функція затримки](#verifiable-delay-function-vdf). + +## Перевірювана функція затримки (VDF) + +Функція, яка займає фіксований проміжок часу для виконання та генерує доказ, що вона виконалася. Цей доказ можна перевірити швидше, ніж час, необхідний для його створення. + +## Голос (vote) + +Див. [Голос у реєстрі](#ledger-vote). + +## Кредит голосування (vote credit) + +Нарахування винагороди для [валідаторів](#validator). Кредит голосування присуджується валідатору на його рахунок голосування, коли він досягає [кореня](#root). + +## Гаманець (wallet) + +Набір [пар ключів](#keypair), який дозволяє користувачам керувати своїми коштами. + +## Період прогріву (warmup period) + +Декілька [епох](#epoch) після делегування [ставки](#stake), протягом яких вона поступово стає активною. Під час цього періоду ставка вважається "активованою". Докладніше: +[періоди прогріву та охолодження](https://docs.anza.xyz/consensus/stake-delegation-and-rewards#stake-warmup-cooldown-withdrawal). From 4ff3fd1d135abbd901735b0fdeed1cab01445bfc Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Thu, 9 Jan 2025 22:25:55 +0200 Subject: [PATCH 02/14] Translated confirmation.md --- docs/uk/advanced/confirmation.md | 609 ++++++++++++------------------- 1 file changed, 228 insertions(+), 381 deletions(-) diff --git a/docs/uk/advanced/confirmation.md b/docs/uk/advanced/confirmation.md index a4d1ae3bc..ef49a0f9e 100644 --- a/docs/uk/advanced/confirmation.md +++ b/docs/uk/advanced/confirmation.md @@ -1,155 +1,116 @@ --- sidebarSortOrder: 1 -sidebarLabel: "Confirmation & Expiration" -title: "Transaction Confirmation & Expiration" -seoTitle: "Transaction Confirmation & Expiration" +sidebarLabel: "Підтвердження та закінчення строку дії" +title: "Підтвердження транзакції та закінчення строку дії" +seoTitle: "Підтвердження транзакції та закінчення строку дії" description: - "Understand how Solana transaction confirmation and when a transaction expires - (including recent blockhash checks)." + "Дізнайтеся, як працює підтвердження транзакцій у Solana і коли транзакція завершує дію + (включаючи перевірку останніх blockhash)." altRoutes: - /docs/advanced - /docs/core/transactions/confirmation --- -Problems relating to -[transaction confirmation](/docs/terminology.md#transaction-confirmations) are -common with many newer developers while building applications. This article aims -to boost the overall understanding of the confirmation mechanism used on the -Solana blockchain, including some recommended best practices. - -## Brief background on transactions - -Before diving into how Solana transaction confirmation and expiration works, -let's briefly set the base understanding of a few things: - -- what a transaction is -- the lifecycle of a transaction -- what a blockhash is -- and a brief understanding of Proof of History (PoH) and how it relates to - blockhashes - -### What is a transaction? - -Transactions consist of two components: a -[message](/docs/terminology.md#message) and a -[list of signatures](/docs/terminology.md#signature). The transaction message is -where the magic happens and at a high level it consists of four components: - -- a **header** with metadata about the transaction, -- a **list of instructions** to invoke, -- a **list of accounts** to load, and -- a **“recent blockhash.”** - -In this article, we're going to be focusing a lot on a transaction's -[recent blockhash](/docs/terminology.md#blockhash) because it plays a big role -in transaction confirmation. - -### Transaction lifecycle refresher - -Below is a high level view of the lifecycle of a transaction. This article will -touch on everything except steps 1 and 4. - -1. Create a header and a list of instructions along with the list of accounts - that instructions need to read and write -2. Fetch a recent blockhash and use it to prepare a transaction message -3. Simulate the transaction to ensure it behaves as expected -4. Prompt user to sign the prepared transaction message with their private key -5. Send the transaction to an RPC node which attempts to forward it to the - current block producer -6. Hope that a block producer validates and commits the transaction into their - produced block -7. Confirm the transaction has either been included in a block or detect when it - has expired - -### What is a Blockhash? - -A [“blockhash”](/docs/terminology.md#blockhash) refers to the last Proof of -History (PoH) hash for a [“slot”](/docs/terminology.md#slot) (description -below). Since Solana uses PoH as a trusted clock, a transaction's recent -blockhash can be thought of as a **timestamp**. - -### Proof of History refresher - -Solana's Proof of History mechanism uses a very long chain of recursive SHA-256 -hashes to build a trusted clock. The “history” part of the name comes from the -fact that block producers hash transaction id's into the stream to record which -transactions were processed in their block. - -[PoH hash calculation](https://github.com/anza-xyz/agave/blob/aa0922d6845e119ba466f88497e8209d1c82febc/entry/src/poh.rs#L79): -`next_hash = hash(prev_hash, hash(transaction_ids))` - -PoH can be used as a trusted clock because each hash must be produced -sequentially. Each produced block contains a blockhash and a list of hash -checkpoints called “ticks” so that validators can verify the full chain of -hashes in parallel and prove that some amount of time has actually passed. - -## Transaction Expiration - -By default, all Solana transactions will expire if not committed to a block in a -certain amount of time. The **vast majority** of transaction confirmation issues -are related to how RPC nodes and validators detect and handle **expired** -transactions. A solid understanding of how transaction expiration works should -help you diagnose the bulk of your transaction confirmation issues. - -### How does transaction expiration work? - -Each transaction includes a “recent blockhash” which is used as a PoH clock -timestamp and expires when that blockhash is no longer “recent enough”. - -As each block is finalized (i.e. the maximum tick height -[is reached](https://github.com/anza-xyz/agave/blob/0588ecc6121ba026c65600d117066dbdfaf63444/runtime/src/bank.rs#L3269-L3271), -reaching the "block boundary"), the final hash of the block is added to the -`BlockhashQueue` which stores a maximum of the -[300 most recent blockhashes](https://github.com/anza-xyz/agave/blob/e0b0bcc80380da34bb63364cc393801af1e1057f/sdk/program/src/clock.rs#L123-L126). -During transaction processing, Solana Validators will check if each -transaction's recent blockhash is recorded within the most recent 151 stored -hashes (aka "max processing age"). If the transaction's recent blockhash is -[older than this](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/runtime/src/bank.rs#L3570-L3571) -max processing age, the transaction is not processed. - -> Due to the current -> [max processing age of 150](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L129-L131) -> and the "age" of a blockhash in the queue being -> [0-indexed](https://github.com/anza-xyz/agave/blob/992a398fe8ea29ec4f04d081ceef7664960206f4/accounts-db/src/blockhash_queue.rs#L248-L274), -> there are actually 151 blockhashes that are considered "recent enough" and -> valid for processing. - -Since [slots](/docs/terminology.md#slot) (aka the time period a validator can -produce a block) are configured to last about -[400ms](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L107-L109), -but may fluctuate between 400ms and 600ms, a given blockhash can only be used by -transactions for about 60 to 90 seconds before it will be considered expired by -the runtime. - -### Example of transaction expiration - -Let's walk through a quick example: - -1. A validator is actively producing a new block for the current slot -2. The validator receives a transaction from a user with the recent blockhash - `abcd...` -3. The validator checks this blockhash `abcd...` against the list of recent - blockhashes in the `BlockhashQueue` and discovers that it was created 151 - blocks ago -4. Since it is exactly 151 blockhashes old, the transaction has not expired yet - and can still be processed! -5. But wait: before actually processing the transaction, the validator finished - creating the next block and added it to the `BlockhashQueue`. The validator - then starts producing the block for the next slot (validators get to produce - blocks for 4 consecutive slots) -6. The validator checks that same transaction again and finds it is now 152 - blockhashes old and rejects it because it's too old :( - -## Why do transactions expire? - -There's a very good reason for this actually, it's to help validators avoid -processing the same transaction twice. - -A naive brute force approach to prevent double processing could be to check -every new transaction against the blockchain's entire transaction history. But -by having transactions expire after a short amount of time, validators only need -to check if a new transaction is in a relatively small set of _recently_ -processed transactions. +Проблеми, пов'язані з +[підтвердженням транзакції](/docs/terminology.md#transaction-confirmations), +є поширеними серед нових розробників під час створення застосунків. Ця стаття має на меті підвищити загальне розуміння механізму підтвердження, який використовується в блокчейні Solana, включаючи деякі рекомендовані найкращі практики. + +## Короткий вступ до транзакцій + +Перед тим як розглянути, як працює підтвердження та закінчення строку дії транзакцій у Solana, давайте коротко розглянемо кілька основ: + +- що таке транзакція, +- життєвий цикл транзакції, +- що таке blockhash, +- і коротке ознайомлення з Proof of History (PoH) і тим, як це стосується blockhash. + +### Що таке транзакція? + +Транзакції складаються з двох компонентів: +[повідомлення](/docs/terminology.md#message) +і +[списку підписів](/docs/terminology.md#signature). +Повідомлення транзакції містить основну інформацію та складається з чотирьох компонентів: + +- **заголовок** з метаданими про транзакцію, +- **список інструкцій** для виконання, +- **список акаунтів**, які потрібно завантажити, +- та **“недавній blockhash”**. + +У цій статті ми зосередимося на +[недавньому blockhash](/docs/terminology.md#blockhash), +оскільки він відіграє важливу роль у підтвердженні транзакції. + +### Життєвий цикл транзакції + +Нижче наведено основні етапи життєвого циклу транзакції. У цій статті розглядаються всі етапи, крім 1 і 4. + +1. Створення заголовка та списку інструкцій разом із переліком акаунтів, які потрібно прочитати або записати. +2. Отримання недавнього blockhash та його використання для підготовки повідомлення транзакції. +3. Симуляція транзакції, щоб переконатися, що вона поводиться очікувано. +4. Запит користувача на підписання підготовленого повідомлення транзакції за допомогою його приватного ключа. +5. Відправка транзакції до RPC-вузла, який намагається передати її поточному виробнику блоків. +6. Очікування, що виробник блоку перевірить і додасть транзакцію до свого блоку. +7. Підтвердження того, що транзакція або була включена в блок, або закінчився її термін дії. + +### Що таке Blockhash? + +[“Blockhash”](/docs/terminology.md#blockhash) +означає останній Proof of History (PoH) хеш для +[“слота”](/docs/terminology.md#slot) +(опис нижче). Оскільки Solana використовує PoH як довірений годинник, недавній blockhash транзакції можна розглядати як **мітку часу**. + +### Коротке нагадування про Proof of History + +Механізм Proof of History у Solana використовує довгий ланцюг рекурсивних хешів SHA-256 для створення довіреного годинника. Назва “історія” походить від того, що виробники блоків додають хеш ідентифікаторів транзакцій у потік, щоб зафіксувати, які транзакції були оброблені в їхньому блоці. + +[Обчислення PoH-хешу](https://github.com/anza-xyz/agave/blob/aa0922d6845e119ba466f88497e8209d1c82febc/entry/src/poh.rs#L79): +`next_hash = hash(prev_hash, hash(transaction_ids))`. + +PoH може використовуватися як довірений годинник, оскільки кожен хеш має бути створений послідовно. Кожен згенерований блок містить blockhash і список контрольних точок хешів, званих “ticks,” які дозволяють валідаторам перевіряти весь ланцюг хешів паралельно та доводити, що певний час дійсно минув. + +## Закінчення строку дії транзакції + +За замовчуванням усі транзакції Solana закінчують строк дії, якщо їх не включено в блок протягом певного періоду часу. **Переважна більшість** проблем із підтвердженням транзакцій пов'язана з тим, як RPC-вузли та валідатори виявляють і обробляють **прострочені** транзакції. Чітке розуміння механізму закінчення строку дії транзакції допоможе вам діагностувати більшість проблем із підтвердженням транзакцій. + +### Як працює закінчення строку дії транзакції? + +Кожна транзакція містить “недавній blockhash,” який використовується як часовий штамп PoH і закінчується, коли цей blockhash більше не вважається “достатньо недавнім.” + +Коли кожен блок завершується (тобто досягається максимальна висота тиків, +[визначена](https://github.com/anza-xyz/agave/blob/0588ecc6121ba026c65600d117066dbdfaf63444/runtime/src/bank.rs#L3269-L3271), +до "кордону блоку"), фінальний хеш блоку додається до `BlockhashQueue`, яка зберігає максимум +[300 найновіших blockhash](https://github.com/anza-xyz/agave/blob/e0b0bcc80380da34bb63364cc393801af1e1057f/sdk/program/src/clock.rs#L123-L126). +Під час обробки транзакцій валідатори Solana перевіряють, чи зберігається недавній blockhash транзакції серед останніх 151 записаних хешів (так званий "максимальний вік обробки"). Якщо недавній blockhash транзакції +[старший за цей вік](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/runtime/src/bank.rs#L3570-L3571), +транзакція не обробляється. + +> Завдяки поточному +> [максимальному віку обробки, що становить 150](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L129-L131) +> і тому, що "вік" blockhash у черзі є +> [нульовим індексом](https://github.com/anza-xyz/agave/blob/992a398fe8ea29ec4f04d081ceef7664960206f4/accounts-db/src/blockhash_queue.rs#L248-L274), +> фактично є 151 blockhash, які вважаються "достатньо недавніми" і дійсними для обробки. + +Оскільки [слоти](/docs/terminology.md#slot) (тобто періоди часу, протягом яких валідатор може створити блок) налаштовані на тривалість близько +[400 мс](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L107-L109), +але можуть коливатися між 400 мс і 600 мс, певний blockhash можна використовувати в транзакціях приблизно протягом 60–90 секунд, перш ніж він вважатиметься простроченим у середовищі виконання. + +### Приклад закінчення строку дії транзакції + +Розгляньмо швидкий приклад: + +1. Валідатор активно створює новий блок для поточного слота. +2. Валідатор отримує транзакцію від користувача з недавнім blockhash `abcd...`. +3. Валідатор перевіряє цей blockhash `abcd...` у списку недавніх blockhash у `BlockhashQueue` і виявляє, що він був створений 151 блок тому. +4. Оскільки йому рівно 151 блок, транзакція ще не прострочена та може бути оброблена. +5. Але зачекайте: перед обробкою транзакції валідатор завершує створення наступного блоку та додає його до `BlockhashQueue`. Потім валідатор починає створювати блок для наступного слота (валідатори можуть створювати блоки протягом 4 послідовних слотів). +6. Валідатор перевіряє ту ж транзакцію ще раз і виявляє, що їй тепер 152 блоки. Вона відхиляється, оскільки занадто стара. :( + +## Чому транзакції закінчують строк дії? + +Це робиться для того, щоб валідатори могли уникнути повторної обробки тієї ж транзакції. + +Наївний підхід для запобігання повторній обробці полягав би в перевірці кожної нової транзакції з усією історією транзакцій блокчейна. Але завдяки тому, що транзакції закінчують строк дії за короткий період часу, валідаторам потрібно перевіряти лише відносно невеликий набір **недавніх** транзакцій. ### Other blockchains @@ -163,240 +124,126 @@ Ethereum transactions got stuck in a _pending_ state for a long time and all the later transactions, which used higher nonce values, were blocked from processing. -### Advantages on Solana - -There are a few advantages to Solana's approach: - -1. A single fee payer can submit multiple transactions at the same time that are - allowed to be processed in any order. This might happen if you're using - multiple applications at the same time. -2. If a transaction doesn't get committed to a block and expires, users can try - again knowing that their previous transaction will NOT ever be processed. - -By not using counters, the Solana wallet experience may be easier for users to -understand because they can get to success, failure, or expiration states -quickly and avoid annoying pending states. - -### Disadvantages on Solana - -Of course there are some disadvantages too: - -1. Validators have to actively track a set of all processed transaction id's to - prevent double processing. -2. If the expiration time period is too short, users might not be able to submit - their transaction before it expires. - -These disadvantages highlight a tradeoff in how transaction expiration is -configured. If the expiration time of a transaction is increased, validators -need to use more memory to track more transactions. If expiration time is -decreased, users don't have enough time to submit their transaction. - -Currently, Solana clusters require that transactions use blockhashes that are no -more than 151 blocks old. - -> This [Github issue](https://github.com/solana-labs/solana/issues/23582) -> contains some calculations that estimate that mainnet-beta validators need -> about 150MB of memory to track transactions. This could be slimmed down in the -> future if necessary without decreasing expiration time as are detailed in that -> issue. - -## Transaction confirmation tips - -As mentioned before, blockhashes expire after a time period of only 151 blocks -which can pass as quickly as **one minute** when slots are processed within the -target time of 400ms. - -One minute is not a lot of time considering that a client needs to fetch a -recent blockhash, wait for the user to sign, and finally hope that the -broadcasted transaction reaches a leader that is willing to accept it. Let's go -through some tips to help avoid confirmation failures due to transaction -expiration! - -### Fetch blockhashes with the appropriate commitment level - -Given the short expiration time frame, it's imperative that clients and -applications help users create transactions with a blockhash that is as recent -as possible. - -When fetching blockhashes, the current recommended RPC API is called -[`getLatestBlockhash`](/docs/rpc/http/getLatestBlockhash.mdx). By default, this -API uses the `finalized` commitment level to return the most recently finalized -block's blockhash. However, you can override this behavior by -[setting the `commitment` parameter](/docs/rpc/index.mdx#configuring-state-commitment) -to a different commitment level. - -**Recommendation** - -The `confirmed` commitment level should almost always be used for RPC requests -because it's usually only a few slots behind the `processed` commitment and has -a very low chance of belonging to a dropped -[fork](https://docs.anza.xyz/consensus/fork-generation). - -But feel free to consider the other options: - -- Choosing `processed` will let you fetch the most recent blockhash compared to - other commitment levels and therefore gives you the most time to prepare and - process a transaction. But due to the prevalence of forking in the Solana - blockchain, roughly 5% of blocks don't end up being finalized by the cluster - so there's a real chance that your transaction uses a blockhash that belongs - to a dropped fork. Transactions that use blockhashes for abandoned blocks - won't ever be considered recent by any blocks that are in the finalized - blockchain. -- Using the [default commitment](/docs/rpc#default-commitment) level `finalized` - will eliminate any risk that the blockhash you choose will belong to a dropped - fork. The tradeoff is that there is typically at least a 32 slot difference - between the most recent confirmed block and the most recent finalized block. - This tradeoff is pretty severe and effectively reduces the expiration of your - transactions by about 13 seconds but this could be even more during unstable - cluster conditions. - -### Use an appropriate preflight commitment level - -If your transaction uses a blockhash that was fetched from one RPC node then you -send, or simulate, that transaction with a different RPC node, you could run -into issues due to one node lagging behind the other. - -When RPC nodes receive a `sendTransaction` request, they will attempt to -determine the expiration block of your transaction using the most recent -finalized block or with the block selected by the `preflightCommitment` -parameter. A **VERY** common issue is that a received transaction's blockhash -was produced after the block used to calculate the expiration for that -transaction. If an RPC node can't determine when your transaction expires, it -will only forward your transaction **one time** and afterwards will then -**drop** the transaction. - -Similarly, when RPC nodes receive a `simulateTransaction` request, they will -simulate your transaction using the most recent finalized block or with the -block selected by the `preflightCommitment` parameter. If the block chosen for -simulation is older than the block used for your transaction's blockhash, the -simulation will fail with the dreaded “blockhash not found” error. - -**Recommendation** - -Even if you use `skipPreflight`, **ALWAYS** set the `preflightCommitment` -parameter to the same commitment level used to fetch your transaction's -blockhash for both `sendTransaction` and `simulateTransaction` requests. - -### Be wary of lagging RPC nodes when sending transactions - -When your application uses an RPC pool service or when the RPC endpoint differs -between creating a transaction and sending a transaction, you need to be wary of -situations where one RPC node is lagging behind the other. For example, if you -fetch a transaction blockhash from one RPC node then you send that transaction -to a second RPC node for forwarding or simulation, the second RPC node might be -lagging behind the first. - -**Recommendation** - -For `sendTransaction` requests, clients should keep resending a transaction to a -RPC node on a frequent interval so that if an RPC node is slightly lagging -behind the cluster, it will eventually catch up and detect your transaction's -expiration properly. - -For `simulateTransaction` requests, clients should use the -[`replaceRecentBlockhash`](/docs/rpc/http/simulateTransaction.mdx) parameter to -tell the RPC node to replace the simulated transaction's blockhash with a -blockhash that will always be valid for simulation. - -### Avoid reusing stale blockhashes - -Even if your application has fetched a very recent blockhash, be sure that -you're not reusing that blockhash in transactions for too long. The ideal -scenario is that a recent blockhash is fetched right before a user signs their -transaction. - -**Recommendation for applications** - -Poll for new recent blockhashes on a frequent basis to ensure that whenever a -user triggers an action that creates a transaction, your application already has -a fresh blockhash that's ready to go. - -**Recommendation for wallets** - -Poll for new recent blockhashes on a frequent basis and replace a transaction's -recent blockhash right before they sign the transaction to ensure the blockhash -is as fresh as possible. - -### Use healthy RPC nodes when fetching blockhashes - -By fetching the latest blockhash with the `confirmed` commitment level from an -RPC node, it's going to respond with the blockhash for the latest confirmed -block that it's aware of. Solana's block propagation protocol prioritizes -sending blocks to staked nodes so RPC nodes naturally lag about a block behind -the rest of the cluster. They also have to do more work to handle application -requests and can lag a lot more under heavy user traffic. - -Lagging RPC nodes can therefore respond to -[`getLatestBlockhash`](/docs/rpc/http/getLatestBlockhash.mdx) requests with -blockhashes that were confirmed by the cluster quite awhile ago. By default, a -lagging RPC node detects that it is more than 150 slots behind the cluster will -stop responding to requests, but just before hitting that threshold they can -still return a blockhash that is just about to expire. - -**Recommendation** - -Monitor the health of your RPC nodes to ensure that they have an up-to-date view -of the cluster state with one of the following methods: - -1. Fetch your RPC node's highest processed slot by using the - [`getSlot`](/docs/rpc/http/getSlot.mdx) RPC API with the `processed` - commitment level and then call the - [`getMaxShredInsertSlot`](/docs/rpc/http/getMaxShredInsertSlot.mdx) RPC API - to get the highest slot that your RPC node has received a “shred” of a block - for. If the difference between these responses is very large, the cluster is - producing blocks far ahead of what the RPC node has processed. -2. Call the `getLatestBlockhash` RPC API with the `confirmed` commitment level - on a few different RPC API nodes and use the blockhash from the node that - returns the highest slot for its - [context slot](/docs/rpc/index.mdx#rpcresponse-structure). - -### Wait long enough for expiration - -**Recommendation** - -When calling the [`getLatestBlockhash`](/docs/rpc/http/getLatestBlockhash.mdx) -RPC API to get a recent blockhash for your transaction, take note of the -`lastValidBlockHeight` in the response. - -Then, poll the [`getBlockHeight`](/docs/rpc/http/getBlockHeight.mdx) RPC API -with the `confirmed` commitment level until it returns a block height greater -than the previously returned last valid block height. - -### Consider using “durable” transactions - -Sometimes transaction expiration issues are really hard to avoid (e.g. offline -signing, cluster instability). If the previous tips are still not sufficient for -your use-case, you can switch to using durable transactions (they just require a -bit of setup). - -To start using durable transactions, a user first needs to submit a transaction -that -[invokes instructions that create a special on-chain “nonce” account](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.create_nonce_account.html) -and stores a “durable blockhash” inside of it. At any point in the future (as -long as the nonce account hasn't been used yet), the user can create a durable -transaction by following these 2 rules: - -1. The instruction list must start with an - [“advance nonce” system instruction](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.advance_nonce_account.html) - which loads their on-chain nonce account -2. The transaction's blockhash must be equal to the durable blockhash stored by - the on-chain nonce account - -Here's how these durable transactions are processed by the Solana runtime: - -1. If the transaction's blockhash is no longer “recent”, the runtime checks if - the transaction's instruction list begins with an “advance nonce” system - instruction -2. If so, it then loads the nonce account specified by the “advance nonce” - instruction -3. Then it checks that the stored durable blockhash matches the transaction's - blockhash -4. Lastly it makes sure to advance the nonce account's stored blockhash to the - latest recent blockhash to ensure that the same transaction can never be - processed again - -For more details about how these durable transactions work, you can read the -[original proposal](https://docs.anza.xyz/implemented-proposals/durable-tx-nonces) -and -[check out an example](/content/guides/advanced/introduction-to-durable-nonces.md) -in the Solana docs. +### Інші блокчейни + +Підхід Solana до запобігання повторній обробці транзакцій значно відрізняється від інших блокчейнів. Наприклад, Ethereum використовує лічильник (nonce) для кожного відправника транзакцій і обробляє лише транзакції, які використовують наступний дійсний nonce. + +Підхід Ethereum є простим для реалізації валідаторами, але може викликати проблеми для користувачів. Багато хто стикався із ситуаціями, коли їхні транзакції Ethereum залишалися в стані **очікування** протягом тривалого часу, а всі подальші транзакції з більшими значеннями nonce блокувалися. + +### Переваги на Solana + +Solana має кілька переваг у цьому підході: + +1. Один платник комісії може надсилати кілька транзакцій одночасно, які можуть оброблятися в будь-якому порядку. Це може статися, якщо ви використовуєте кілька додатків одночасно. +2. Якщо транзакція не була додана до блоку та закінчила строк дії, користувачі можуть спробувати знову, знаючи, що їхня попередня транзакція **ніколи** не буде оброблена. + +Відсутність використання лічильників робить досвід роботи з Solana більш зрозумілим для користувачів, оскільки вони швидше отримують результат — успіх, невдачу або закінчення строку дії — та уникають тривалого стану очікування. + +### Недоліки на Solana + +Звісно, є й недоліки: + +1. Валідатори повинні активно відстежувати набір усіх оброблених ідентифікаторів транзакцій, щоб запобігти їх повторній обробці. +2. Якщо час закінчення строку дії надто короткий, користувачі можуть не встигнути надіслати свої транзакції до того, як вони стануть недійсними. + +Ці недоліки показують компроміс у тому, як налаштовано строк дії транзакцій. Якщо збільшити час закінчення строку дії, валідаторам доведеться використовувати більше пам’яті для відстеження транзакцій. Якщо ж скоротити строк дії, користувачам буде важче встигнути надіслати свої транзакції. + +Наразі кластери Solana вимагають, щоб транзакції використовували blockhash, який не старший за 151 блок. + +> У цьому [питанні GitHub](https://github.com/solana-labs/solana/issues/23582) надані розрахунки, які оцінюють, що валідаторам mainnet-beta потрібно близько 150 МБ пам’яті для відстеження транзакцій. У майбутньому це можна оптимізувати, не скорочуючи строк дії транзакцій, як зазначено в цьому обговоренні. + +## Поради щодо підтвердження транзакцій + +Як зазначалося раніше, blockhash закінчують строк дії через період, який може тривати всього **одну хвилину**, коли слоти обробляються з цільовим часом 400 мс. + +Одна хвилина — це не багато, враховуючи, що клієнту потрібно отримати недавній blockhash, дочекатися підписання транзакції користувачем, а потім сподіватися, що надіслана транзакція досягне лідера, який погодиться її обробити. Розглянемо кілька порад, які допоможуть уникнути невдач підтвердження через закінчення строку дії транзакцій. + +### Отримуйте blockhash із відповідним рівнем підтвердження + +З огляду на короткий період закінчення строку дії, клієнти та додатки повинні допомагати користувачам створювати транзакції з blockhash, який є максимально недавнім. + +Коли ви отримуєте blockhash, рекомендованим RPC API є [`getLatestBlockhash`](/docs/rpc/http/getLatestBlockhash.mdx). За замовчуванням цей API використовує рівень підтвердження `finalized`, щоб повернути blockhash останнього фіналізованого блоку. Проте ви можете змінити цю поведінку, встановивши параметр `commitment` на інший рівень підтвердження. + +**Рекомендація** + +Рівень підтвердження `confirmed` майже завжди слід використовувати для запитів RPC, оскільки він зазвичай лише на кілька слотів відстає від рівня `processed` і має дуже низьку ймовірність належати до відхиленого [форку](https://docs.anza.xyz/consensus/fork-generation). + +Але ви також можете розглянути інші варіанти: + +- Вибір `processed` дозволяє отримати найбільш недавній blockhash порівняно з іншими рівнями підтвердження, що дає більше часу на підготовку і обробку транзакції. Однак через поширеність форків у блокчейні Solana близько 5% блоків не потрапляють у фіналізований кластер, що створює ризик того, що ваша транзакція використовує blockhash, що належить до відкинутого форку. Транзакції з такими blockhash ніколи не будуть вважатися недавніми у фіналізованому блокчейні. +- Використання [рівня підтвердження за замовчуванням](/docs/rpc#default-commitment) `finalized` виключає ризик того, що вибраний blockhash належатиме до відкинутого форку. Однак це має компроміс: зазвичай є щонайменше 32 слоти різниці між найбільш недавнім підтвердженим блоком і найбільш недавнім фіналізованим блоком. Це значно зменшує строк дії ваших транзакцій приблизно на 13 секунд, що може бути ще більш суттєвим за нестабільних умов кластеру. + +### Використовуйте відповідний рівень підтвердження для preflight + +Якщо ваша транзакція використовує blockhash, отриманий з одного RPC-вузла, але надсилається або симулюється на іншому, можуть виникнути проблеми через затримку одного з вузлів. + +Коли RPC-вузли отримують запит `sendTransaction`, вони намагаються визначити строк дії транзакції, використовуючи найбільш недавній фіналізований блок або блок, вибраний параметром `preflightCommitment`. **Дуже поширена проблема** виникає, якщо blockhash транзакції створений після блоку, який використовується для обчислення строку дії. У такому випадку RPC-вузол лише один раз пересилає транзакцію, а потім **видаляє** її. + +Аналогічно, при отриманні запиту `simulateTransaction` RPC-вузли симулюють транзакцію, використовуючи найбільш недавній фіналізований блок або блок, вибраний параметром `preflightCommitment`. Якщо вибраний блок для симуляції старіший за blockhash транзакції, симуляція завершиться помилкою “blockhash not found”. + +**Рекомендація** + +Навіть якщо ви використовуєте `skipPreflight`, **завжди** встановлюйте параметр `preflightCommitment` на той самий рівень підтвердження, який використовувався для отримання blockhash транзакції, як для запитів `sendTransaction`, так і `simulateTransaction`. + +### Уникайте відставання RPC-вузлів під час надсилання транзакцій + +Якщо ваш додаток використовує сервіс пулу RPC або якщо кінцева точка RPC відрізняється між створенням транзакції та її надсиланням, будьте обережні зі сценаріями, коли один RPC-вузол відстає від іншого. Наприклад, якщо blockhash транзакції отримано з одного RPC-вузла, а транзакція надсилається на інший для обробки або симуляції, другий RPC-вузол може відставати. + +**Рекомендація** + +Для запитів `sendTransaction` клієнти повинні повторно надсилати транзакцію до RPC-вузла на частих інтервалах, щоб у випадку, якщо RPC-вузол трохи відстає від кластеру, він врешті-решт виявив транзакцію та її строк дії. + +Для запитів `simulateTransaction` клієнти повинні використовувати параметр +[`replaceRecentBlockhash`](/docs/rpc/http/simulateTransaction.mdx), щоб інструктувати RPC-вузол замінювати blockhash симульованої транзакції на blockhash, який завжди буде дійсним для симуляції. + +### Уникайте повторного використання застарілих blockhash + +Навіть якщо ваш додаток отримав дуже недавній blockhash, переконайтеся, що ви не використовуєте його надто довго. Ідеальний сценарій — отримати свіжий blockhash безпосередньо перед підписанням транзакції. + +**Рекомендація для додатків** + +Часто запитуйте нові blockhash, щоб забезпечити готовність вашого додатка до створення транзакції, коли користувач виконує дію. + +**Рекомендація для гаманців** + +Часто запитуйте нові blockhash та оновлюйте blockhash транзакції перед підписанням, щоб забезпечити її актуальність. + +### Використовуйте надійні RPC-вузли для отримання blockhash + +RPC-вузли можуть відставати від кластеру через навантаження або інші причини, повертаючи blockhash, який майже вичерпав строк дії. + +**Рекомендація** + +Моніторте стан RPC-вузлів, використовуючи такі методи: + +1. Викликайте API + [`getSlot`](/docs/rpc/http/getSlot.mdx) з рівнем підтвердження `processed` для отримання останнього обробленого слота вузла та порівняйте його з + [`getMaxShredInsertSlot`](/docs/rpc/http/getMaxShredInsertSlot.mdx), щоб оцінити відставання вузла. +2. Використовуйте RPC API `getLatestBlockhash` з рівнем підтвердження `confirmed` на кількох різних RPC-вузлах та обирайте blockhash від вузла, який повертає найвищий слот для свого [контекстного слоту](/docs/rpc/index.mdx#rpcresponse-structure). + +### Зачекайте достатньо довго перед закінченням терміну дії + +**Рекомендація** + +При виклику RPC API [`getLatestBlockhash`](/docs/rpc/http/getLatestBlockhash.mdx) для отримання останнього blockhash вашої транзакції зверніть увагу на `lastValidBlockHeight` у відповіді. + +Потім викликайте RPC API [`getBlockHeight`](/docs/rpc/http/getBlockHeight.mdx) з рівнем підтвердження `confirmed`, поки він не поверне висоту блоку, більшу за попередньо отриманий `lastValidBlockHeight`. + +### Розгляньте використання "довготривалих" транзакцій + +Іноді уникнути проблем із закінченням терміну дії транзакції дуже важко (наприклад, при офлайн-підписанні або нестабільності кластера). Якщо попередні поради не підходять для вашого випадку використання, ви можете перейти на використання довготривалих транзакцій (вони вимагають трохи налаштувань). + +Щоб почати використовувати довготривалі транзакції, користувач спочатку повинен подати транзакцію, яка +[викликає інструкції для створення спеціального "nonce" облікового запису на блокчейні](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.create_nonce_account.html) і зберігає в ньому "довготривалий blockhash". У будь-який момент у майбутньому (доки nonce-аккаунт ще не використаний) користувач може створити довготривалу транзакцію, дотримуючись двох правил: + +1. Список інструкцій повинен починатися з [системної інструкції "advance nonce"](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.advance_nonce_account.html), яка завантажує їх nonce-аккаунт. +2. Blockhash транзакції повинен дорівнювати довготривалому blockhash, збереженому nonce-аккаунтом на блокчейні. + +Ось як Solana обробляє ці довготривалі транзакції: + +1. Якщо blockhash транзакції більше не є "недавнім", система перевіряє, чи починається список інструкцій транзакції з інструкції "advance nonce". +2. Якщо так, система завантажує nonce-аккаунт, вказаний у цій інструкції. +3. Потім перевіряє, чи збережений довготривалий blockhash відповідає blockhash транзакції. +4. Нарешті, система оновлює blockhash nonce-аккаунту до останнього недавнього blockhash, щоб гарантувати, що ця ж транзакція не може бути оброблена повторно. + +Детальніше про роботу цих довготривалих транзакцій ви можете дізнатися з [оригінальної пропозиції](https://docs.anza.xyz/implemented-proposals/durable-tx-nonces) та [ознайомитися з прикладом](/content/guides/advanced/introduction-to-durable-nonces.md) у документації Solana. From 9cd27c2d6708a4e95e7aecaf3c389de9b8558d3c Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Thu, 9 Jan 2025 22:34:13 +0200 Subject: [PATCH 03/14] Translated lookup-tables.md --- docs/uk/advanced/index.md | 2 +- docs/uk/advanced/lookup-tables.md | 107 +++++++++--------------------- 2 files changed, 33 insertions(+), 76 deletions(-) diff --git a/docs/uk/advanced/index.md b/docs/uk/advanced/index.md index 11ae9d7f4..d7cb47698 100644 --- a/docs/uk/advanced/index.md +++ b/docs/uk/advanced/index.md @@ -1,5 +1,5 @@ --- metaOnly: true -title: Advanced Topics +title: Додаткові теми sidebarSortOrder: 3 --- diff --git a/docs/uk/advanced/lookup-tables.md b/docs/uk/advanced/lookup-tables.md index 3b997c6c8..8709495bd 100644 --- a/docs/uk/advanced/lookup-tables.md +++ b/docs/uk/advanced/lookup-tables.md @@ -1,47 +1,29 @@ --- sidebarSortOrder: 4 -title: Address Lookup Tables +title: Таблиці пошуку адрес description: - Learn how to use Solana Address Lookup Tables (ALTs) to efficiently handle up - to 64 addresses per transaction. Create, extend, and utilize lookup tables - using web3.js. + Дізнайтеся, як використовувати таблиці пошуку адрес Solana (ALTs) для ефективної обробки до 64 адрес у кожній транзакції. Створюйте, розширюйте та використовуйте таблиці пошуку за допомогою web3.js. --- -Address Lookup Tables, commonly referred to as "_lookup tables_" or "_ALTs_" for -short, allow developers to create a collection of related addresses to -efficiently load more addresses in a single transaction. +Таблиці пошуку адрес, зазвичай відомі як "_lookup tables_" або скорочено "_ALTs_", дозволяють розробникам створювати колекції пов’язаних адрес для ефективного завантаження більшої кількості адрес в одній транзакції. -Since each transaction on the Solana blockchain requires a listing of every -address that is interacted with as part of the transaction, this listing would -effectively be capped at 32 addresses per transaction. With the help of -[Address Lookup Tables](/docs/advanced/lookup-tables.md), a transaction would -now be able to raise that limit to 64 addresses per transaction. +Оскільки кожна транзакція в блокчейні Solana вимагає переліку всіх адрес, з якими вона взаємодіє, цей перелік фактично обмежується 32 адресами на транзакцію. Завдяки [Таблицям пошуку адрес](/docs/advanced/lookup-tables.md) це обмеження можна збільшити до 64 адрес у кожній транзакції. -## Compressing onchain addresses +## Стиснення адрес на блокчейні -After all the desired addresses have been stored onchain in an Address Lookup -Table, each address can be referenced inside a transaction by its 1-byte index -within the table (instead of their full 32-byte address). This lookup method -effectively "_compresses_" a 32-byte address into a 1-byte index value. +Після того, як усі необхідні адреси були збережені на блокчейні у Таблиці пошуку адрес, кожну адресу можна посилатися в транзакції за її 1-байтовим індексом у таблиці (замість повної 32-байтової адреси). Цей метод пошуку ефективно "_стискає_" 32-байтову адресу до 1-байтового значення індексу. -This "_compression_" enables storing up to 256 addresses in a single lookup -table for use inside any given transaction. +Таке "_стиснення_" дозволяє зберігати до 256 адрес у одній таблиці пошуку для використання у будь-якій транзакції. -## Versioned Transactions +## Версійні транзакції -To utilize an Address Lookup Table inside a transaction, developers must use v0 -transactions that were introduced with the new -[Versioned Transaction format](/docs/advanced/versions.md). +Щоб використовувати Таблицю пошуку адрес у транзакції, розробники повинні застосовувати транзакції версії v0, які були запроваджені з новим форматом [Версійних транзакцій](/docs/advanced/versions.md). -## How to create an address lookup table +## Як створити таблицю пошуку адрес -Creating a new lookup table with the `@solana/web3.js` library is similar to the -older `legacy` transactions, but with some differences. +Створення нової таблиці пошуку за допомогою бібліотеки `@solana/web3.js` подібне до старішого формату `legacy` транзакцій, але має певні відмінності. -Using the `@solana/web3.js` library, you can use the -[`createLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#createLookupTable) -function to construct the instruction needed to create a new lookup table, as -well as determine its address: +Використовуючи бібліотеку `@solana/web3.js`, ви можете скористатися функцією [`createLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#createLookupTable) для створення інструкції, необхідної для створення нової таблиці пошуку, а також для визначення її адреси. ```js const web3 = require("@solana/web3.js"); @@ -66,17 +48,11 @@ console.log("lookup table address:", lookupTableAddress.toBase58()); // send the `lookupTableInst` instruction in a transaction ``` -> NOTE: Address lookup tables can be **created** with either a `v0` transaction -> or a `legacy` transaction. But the Solana runtime can only retrieve and handle -> the additional addresses within a lookup table while using -> [v0 Versioned Transactions](/docs/advanced/versions.md#current-transaction-versions). +> ПРИМІТКА: Таблиці пошуку адрес можуть бути **створені** за допомогою як транзакцій `v0`, так і `legacy`. Але виконуюче середовище Solana може отримувати та обробляти додаткові адреси в таблиці пошуку лише під час використання [Версійних транзакцій v0](/docs/advanced/versions.md#current-transaction-versions). -## Add addresses to a lookup table +## Додавання адрес до таблиці пошуку -Adding addresses to a lookup table is known as "_extending_". Using the -`@solana/web3.js` library, you can create a new _extend_ instruction using the -[`extendLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#extendLookupTable) -method: +Додавання адрес до таблиці пошуку відоме як "_розширення_" ("_extending_"). Використовуючи бібліотеку `@solana/web3.js`, ви можете створити нову інструкцію для _розширення_ за допомогою методу [`extendLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#extendLookupTable): ```js // add addresses to the `lookupTableAddress` table via an `extend` instruction @@ -95,22 +71,13 @@ const extendInstruction = web3.AddressLookupTableProgram.extendLookupTable({ // to insert the listing of `addresses` into your lookup table with address `lookupTableAddress` ``` -> NOTE: Due to the same memory limits of `legacy` transactions, any transaction -> used to _extend_ an Address Lookup Table is also limited in how many addresses -> can be added at a time. Because of this, you will need to use multiple -> transactions to _extend_ any table with more addresses (~20) that can fit -> within a single transaction's memory limits. +> ПРИМІТКА: Через ті самі обмеження пам'яті транзакцій `legacy`, будь-яка транзакція, яка використовується для _розширення_ таблиці пошуку адрес, також обмежена в кількості адрес, які можна додати одночасно. Через це вам потрібно буде використовувати кілька транзакцій, щоб _розширити_ будь-яку таблицю більшою кількістю адрес (приблизно 20), ніж це дозволяють обмеження пам'яті однієї транзакції. -Once these addresses have been inserted into the table, and stored onchain, you -will be able to utilize the Address Lookup Table in future transactions. -Enabling up to 64 addresses in those future transactions. +Після того як ці адреси були вставлені в таблицю та збережені в блокчейні, ви зможете використовувати таблицю пошуку адрес у майбутніх транзакціях. Це дозволяє включити до 64 адрес у цих транзакціях. -## Fetch an Address Lookup Table +## Отримання таблиці пошуку адрес -Similar to requesting another account (or PDA) from the cluster, you can fetch a -complete Address Lookup Table with the -[`getAddressLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getAddressLookupTable) -method: +Аналогічно запиту іншого облікового запису (або PDA) з кластера, ви можете отримати повну таблицю пошуку адрес за допомогою методу [`getAddressLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getAddressLookupTable): ```js // define the `PublicKey` of the lookup table to fetch @@ -126,9 +93,7 @@ const lookupTableAccount = ( console.log("Table address from cluster:", lookupTableAccount.key.toBase58()); ``` -Our `lookupTableAccount` variable will now be a `AddressLookupTableAccount` -object which we can parse to read the listing of all the addresses stored on -chain in the lookup table: +Змінна `lookupTableAccount` тепер буде об'єктом типу `AddressLookupTableAccount`, який можна проаналізувати для читання списку всіх адрес, збережених у таблиці пошуку в блокчейні: ```js // loop through and parse all the addresses stored in the table @@ -137,22 +102,16 @@ for (let i = 0; i < lookupTableAccount.state.addresses.length; i++) { console.log(i, address.toBase58()); } ``` +## Як використовувати таблицю пошуку адрес у транзакції -## How to use an address lookup table in a transaction +Після того як ви створили таблицю пошуку і зберегли необхідні адреси в блокчейні (через розширення таблиці пошуку), ви можете створити транзакцію `v0`, щоб скористатися можливостями пошуку адрес в блокчейні. -After you have created your lookup table, and stored your needed address on -chain (via extending the lookup table), you can create a `v0` transaction to -utilize the onchain lookup capabilities. +Так само, як і для старих транзакцій `legacy`, ви можете створити всі +[інструкції](/docs/terminology.md#instruction), які ваша транзакція виконуватиме в блокчейні. Потім ви можете передати масив цих інструкцій у +[Message](/docs/terminology.md#message), що використовується в транзакції `v0`. -Just like older `legacy` transactions, you can create all the -[instructions](/docs/terminology.md#instruction) your transaction will execute -onchain. You can then provide an array of these instructions to the -[Message](/docs/terminology.md#message) used in the `v0` transaction. - -> NOTE: The instructions used inside a `v0` transaction can be constructed using -> the same methods and functions used to create the instructions in the past. -> There is no required change to the instructions used involving an Address -> Lookup Table. +> **Примітка:** Інструкції, що використовуються в транзакції `v0`, можна створювати за допомогою тих самих методів і функцій, які використовувалися раніше для створення інструкцій. +> Немає необхідності змінювати інструкції, пов'язані з використанням таблиці пошуку адрес. ```js // Assumptions: @@ -181,12 +140,10 @@ console.log( ); ``` -> NOTE: When sending a `VersionedTransaction` to the cluster, it must be signed -> BEFORE calling the `sendAndConfirmTransaction` method. If you pass an array of -> `Signer` (like with `legacy` transactions) the method will trigger an error! +> **Примітка:** Під час відправлення `VersionedTransaction` до кластеру, вона має бути підписана **ДО** виклику методу `sendAndConfirmTransaction`. Якщо передати масив `Signer` (як у транзакціях `legacy`), метод викличе помилку! + +## Додаткові ресурси -## More Resources +- Ознайомтеся з [пропозицією](https://docs.anza.xyz/proposals/versioned-transactions) щодо таблиць пошуку адрес і версійованих транзакцій +- [Приклад програми на Rust, яка використовує таблиці пошуку адрес](https://github.com/TeamRaccoons/address-lookup-table-multi-swap) -- Read the [proposal](https://docs.anza.xyz/proposals/versioned-transactions) - for Address Lookup Tables and Versioned transactions -- [Example Rust program using Address Lookup Tables](https://github.com/TeamRaccoons/address-lookup-table-multi-swap) From 00f57783235cf58ade7930e04c9bd2985aebe496 Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Thu, 9 Jan 2025 22:56:25 +0200 Subject: [PATCH 04/14] Finished advanced folder --- docs/uk/advanced/retry.md | 336 +++++----------------- docs/uk/advanced/state-compression.md | 383 +++++++++----------------- docs/uk/advanced/versions.md | 155 +++++------ 3 files changed, 264 insertions(+), 610 deletions(-) diff --git a/docs/uk/advanced/retry.md b/docs/uk/advanced/retry.md index be27ecefa..e69f0815a 100644 --- a/docs/uk/advanced/retry.md +++ b/docs/uk/advanced/retry.md @@ -1,228 +1,59 @@ --- sidebarSortOrder: 2 -title: Retrying Transactions +title: Повторна відправка транзакцій altRoutes: - /docs/core/transactions/retry description: - Learn how to handle dropped transactions and implement custom retry logic on - Solana. This guide covers transaction rebroadcasting, preflight checks, and - best practices for managing transaction retries to ensure reliable transaction - processing on the Solana blockchain. + Дізнайтеся, як обробляти втрачені транзакції та впроваджувати користувацьку + логіку повторної відправки у Solana. Цей посібник охоплює повторне + передавання транзакцій, перевірки перед виконанням (preflight) і найкращі + практики для забезпечення надійної обробки транзакцій у блокчейні Solana. --- -# Retrying Transactions - -On some occasions, a seemingly valid transaction may be dropped before it is -included in a block. This most often occurs during periods of network -congestion, when an RPC node fails to rebroadcast the transaction to the -[leader](/docs/terminology.md#leader). To an end-user, it may appear as if their -transaction disappears entirely. While RPC nodes are equipped with a generic -rebroadcasting algorithm, application developers are also capable of developing -their own custom rebroadcasting logic. - -## TLDR; - -- RPC nodes will attempt to rebroadcast transactions using a generic algorithm -- Application developers can implement their own custom rebroadcasting logic -- Developers should take advantage of the `maxRetries` parameter on the - `sendTransaction` JSON-RPC method -- Developers should enable preflight checks to raise errors before transactions - are submitted -- Before re-signing any transaction, it is **very important** to ensure that the - initial transaction's blockhash has expired - -## The Journey of a Transaction - -### How Clients Submit Transactions - -In Solana, there is no concept of a mempool. All transactions, whether they are -initiated programmatically or by an end-user, are efficiently routed to leaders -so that they can be processed into a block. There are two main ways in which a -transaction can be sent to leaders: - -1. By proxy via an RPC server and the - [sendTransaction](/docs/rpc/http/sendTransaction.mdx) JSON-RPC method -2. Directly to leaders via a - [TPU Client](https://docs.rs/solana-client/latest/solana_client/tpu_client/index.html) - -The vast majority of end-users will submit transactions via an RPC server. When -a client submits a transaction, the receiving RPC node will in turn attempt to -broadcast the transaction to both the current and next leaders. Until the -transaction is processed by a leader, there is no record of the transaction -outside of what the client and the relaying RPC nodes are aware of. In the case -of a TPU client, rebroadcast and leader forwarding is handled entirely by the -client software. - -![Overview of a transactions journey, from client to leader](/assets/docs/rt-tx-journey.png) - -### How RPC Nodes Broadcast Transactions - -After an RPC node receives a transaction via `sendTransaction`, it will convert -the transaction into a -[UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol) packet before -forwarding it to the relevant leaders. UDP allows validators to quickly -communicate with one another, but does not provide any guarantees regarding -transaction delivery. - -Because Solana's leader schedule is known in advance of every -[epoch](/docs/terminology.md#epoch) (~2 days), an RPC node will broadcast its -transaction directly to the current and next leaders. This is in contrast to -other gossip protocols such as Ethereum that propagate transactions randomly and -broadly across the entire network. By default, RPC nodes will try to forward -transactions to leaders every two seconds until either the transaction is -finalized or the transaction's blockhash expires (150 blocks or ~1 minute 19 -seconds as of the time of this writing). If the outstanding rebroadcast queue -size is greater than -[10,000 transactions](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/send-transaction-service/src/send_transaction_service.rs#L20), -newly submitted transactions are dropped. There are command-line -[arguments](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/validator/src/main.rs#L1172) -that RPC operators can adjust to change the default behavior of this retry -logic. - -When an RPC node broadcasts a transaction, it will attempt to forward the -transaction to a leader's -[Transaction Processing Unit (TPU)](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/validator.rs#L867). -The TPU processes transactions in five distinct phases: - -- [Fetch Stage](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/fetch_stage.rs#L21) -- [SigVerify Stage](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/tpu.rs#L91) -- [Banking Stage](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/banking_stage.rs#L249) -- [Proof of History Service](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/poh/src/poh_service.rs) -- [Broadcast Stage](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/core/src/tpu.rs#L136) - -![Overview of the Transaction Processing Unit (TPU)](/assets/docs/rt-tpu-jito-labs.png) - -Of these five phases, the Fetch Stage is responsible for receiving transactions. -Within the Fetch Stage, validators will categorize incoming transactions -according to three ports: - -- [tpu](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/gossip/src/contact_info.rs#L27) - handles regular transactions such as token transfers, NFT mints, and program - instructions -- [tpu_vote](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/gossip/src/contact_info.rs#L31) - focuses exclusively on voting transactions -- [tpu_forwards](https://github.com/solana-labs/solana/blob/cd6f931223181d5a1d47cba64e857785a175a760/gossip/src/contact_info.rs#L29) - forwards unprocessed packets to the next leader if the current leader is - unable to process all transactions - -For more information on the TPU, please refer to -[this excellent writeup by Jito Labs](https://jito-labs.medium.com/solana-validator-101-transaction-processing-90bcdc271143). - -## How Transactions Get Dropped - -Throughout a transaction's journey, there are a few scenarios in which the -transaction can be unintentionally dropped from the network. - -### Before a transaction is processed - -If the network drops a transaction, it will most likely do so before the -transaction is processed by a leader. UDP -[packet loss](https://en.wikipedia.org/wiki/Packet_loss) is the simplest reason -why this might occur. During times of intense network load, it's also possible -for validators to become overwhelmed by the sheer number of transactions -required for processing. While validators are equipped to forward surplus -transactions via `tpu_forwards`, there is a limit to the amount of data that can -be -[forwarded](https://github.com/solana-labs/solana/blob/master/core/src/banking_stage.rs#L389). -Furthermore, each forward is limited to a single hop between validators. That -is, transactions received on the `tpu_forwards` port are not forwarded on to -other validators. - -There are also two lesser known reasons why a transaction may be dropped before -it is processed. The first scenario involves transactions that are submitted via -an RPC pool. Occasionally, part of the RPC pool can be sufficiently ahead of the -rest of the pool. This can cause issues when nodes within the pool are required -to work together. In this example, the transaction's -[recentBlockhash](/docs/core/transactions.md#recent-blockhash) is queried from -the advanced part of the pool (Backend A). When the transaction is submitted to -the lagging part of the pool (Backend B), the nodes will not recognize the -advanced blockhash and will drop the transaction. This can be detected upon -transaction submission if developers enable -[preflight checks](/docs/rpc/http/sendTransaction.mdx) on `sendTransaction`. - -![Transaction dropped via an RPC Pool](/assets/docs/rt-dropped-via-rpc-pool.png) - -Temporary network forks can also result in dropped transactions. If a validator -is slow to replay its blocks within the Banking Stage, it may end up creating a -minority fork. When a client builds a transaction, it's possible for the -transaction to reference a `recentBlockhash` that only exists on the minority -fork. After the transaction is submitted, the cluster can then switch away from -its minority fork before the transaction is processed. In this scenario, the -transaction is dropped due to the blockhash not being found. - -![Transaction dropped due to minority fork (before processed)](/assets/docs/rt-dropped-minority-fork-pre-process.png) - -### After a transaction is processed and before it is finalized - -In the event a transaction references a `recentBlockhash` from a minority fork, -it's still possible for the transaction to be processed. In this case, however, -it would be processed by the leader on the minority fork. When this leader -attempts to share its processed transactions with the rest of the network, it -would fail to reach consensus with the majority of validators that do not -recognize the minority fork. At this time, the transaction would be dropped -before it could be finalized. - -![Transaction dropped due to minority fork (after processed)](/assets/docs/rt-dropped-minority-fork-post-process.png) - -## Handling Dropped Transactions - -While RPC nodes will attempt to rebroadcast transactions, the algorithm they -employ is generic and often ill-suited for the needs of specific applications. -To prepare for times of network congestion, application developers should -customize their own rebroadcasting logic. - -### An In-Depth Look at sendTransaction - -When it comes to submitting transactions, the `sendTransaction` RPC method is -the primary tool available to developers. `sendTransaction` is only responsible -for relaying a transaction from a client to an RPC node. If the node receives -the transaction, `sendTransaction` will return the transaction id that can be -used to track the transaction. A successful response does not indicate whether -the transaction will be processed or finalized by the cluster. - -### Request Parameters - -- `transaction`: `string` - fully-signed Transaction, as encoded string -- (optional) `configuration object`: `object` - - `skipPreflight`: `boolean` - if true, skip the preflight transaction checks - (default: false) - - (optional) `preflightCommitment`: `string` - - [Commitment](/docs/rpc/index.mdx#configuring-state-commitment) level to use - for preflight simulations against the bank slot (default: "finalized"). - - (optional) `encoding`: `string` - Encoding used for the transaction data. - Either "base58" (slow), or "base64". (default: "base58"). - - (optional) `maxRetries`: `usize` - Maximum number of times for the RPC node - to retry sending the transaction to the leader. If this parameter is not - provided, the RPC node will retry the transaction until it is finalized or - until the blockhash expires. - -**Response:** - -- `transaction id`: `string` - First transaction signature embedded in the - transaction, as base-58 encoded string. This transaction id can be used with - [`getSignatureStatuses`](/docs/rpc/http/getSignatureStatuses.mdx) to poll for - status updates. - -## Customizing Rebroadcast Logic - -In order to develop their own rebroadcasting logic, developers should take -advantage of `sendTransaction`'s `maxRetries` parameter. If provided, -`maxRetries` will override an RPC node's default retry logic, allowing -developers to manually control the retry process -[within reasonable bounds](https://github.com/solana-labs/solana/blob/98707baec2385a4f7114d2167ef6dfb1406f954f/validator/src/main.rs#L1258-L1274). - -A common pattern for manually retrying transactions involves temporarily storing -the `lastValidBlockHeight` that comes from -[getLatestBlockhash](/docs/rpc/http/getLatestBlockhash.mdx). Once stashed, an -application can then -[poll the cluster's blockheight](/docs/rpc/http/getBlockHeight.mdx) and manually -retry the transaction at an appropriate interval. In times of network -congestion, it's advantageous to set `maxRetries` to 0 and manually rebroadcast -via a custom algorithm. While some applications may employ an -[exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff) -algorithm, others such as [Mango](https://www.mango.markets/) opt to -[continuously resubmit](https://github.com/blockworks-foundation/mango-ui/blob/b6abfc6c13b71fc17ebbe766f50b8215fa1ec54f/src/utils/send.tsx#L713) -transactions at a constant interval until some timeout has occurred. +# Повторна відправка транзакцій + +Іноді здається, що дійсна транзакція може бути втрачена до її включення в блок. Це зазвичай трапляється під час завантаженості мережі, коли RPC-вузол не може повторно передати транзакцію до [лідера](/docs/terminology.md#leader). Для кінцевого користувача це може виглядати так, ніби транзакція повністю зникає. Хоча RPC-вузли мають універсальний алгоритм повторного передавання, розробники додатків також можуть створювати власну логіку повторної передачі. + +## Коротко: + +- RPC-вузли намагатимуться повторно передати транзакції за допомогою універсального алгоритму. +- Розробники додатків можуть впроваджувати власну логіку повторного передавання. +- Розробникам слід використовувати параметр `maxRetries` у методі JSON-RPC `sendTransaction`. +- Розробникам слід вмикати перевірки перед виконанням (preflight), щоб виявляти помилки до відправки транзакцій. +- Перед повторним підписанням будь-якої транзакції важливо переконатися, що термін дії blockhash вихідної транзакції минув. + +## Шлях транзакції + +### Як клієнти відправляють транзакції + +У Solana немає концепції мемпулу. Усі транзакції, незалежно від того, чи ініційовані вони програмно або користувачем, ефективно маршрутизуються до лідерів для обробки в блоках. Є два основні способи надсилання транзакцій до лідерів: + +1. Через RPC-сервер за допомогою методу JSON-RPC [sendTransaction](/docs/rpc/http/sendTransaction.mdx). +2. Безпосередньо до лідерів через [TPU Client](https://docs.rs/solana-client/latest/solana_client/tpu_client/index.html). + +Більшість користувачів відправляють транзакції через RPC-сервер. Коли клієнт надсилає транзакцію, RPC-вузол намагається передати її поточному та наступному лідерам. Поки транзакція не буде оброблена лідером, вона існує лише у вигляді запису в клієнта або проміжних RPC-вузлів. У випадку використання TPU клієнтом, передавання та маршрутизація обробляються програмним забезпеченням клієнта. + +![Огляд шляху транзакції, від клієнта до лідера](/assets/docs/rt-tx-journey.png) + +### Як RPC-вузли передають транзакції + +Після отримання транзакції через `sendTransaction`, RPC-вузол перетворює транзакцію в [UDP](https://uk.wikipedia.org/wiki/UDP) пакет і передає його відповідним лідерам. UDP дозволяє вузлам швидко обмінюватися даними, але не гарантує доставки пакетів. + +Оскільки розклад лідерів Solana відомий заздалегідь для кожного [епоха](/docs/terminology.md#epoch) (~2 дні), RPC-вузол передає транзакції безпосередньо до поточного та наступного лідерів. За замовчуванням RPC-вузли намагаються повторно передавати транзакції кожні дві секунди, доки транзакція не буде завершена або доки термін дії її blockhash не закінчиться (~1 хвилина 19 секунд). Якщо черга для повторної передачі перевищує [10,000 транзакцій](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/send-transaction-service/src/send_transaction_service.rs#L20), нові транзакції скидаються. + +![Процес обробки транзакцій TPU](/assets/docs/rt-tpu-jito-labs.png) + +## Як транзакції скидаються + +Транзакції можуть бути скинуті через кілька причин, таких як перевантаження мережі, втрати пакетів UDP або конфлікти через різні статуси вузлів у пулі RPC. + +## Обробка скинутих транзакцій + +Розробники можуть використовувати параметр `maxRetries` методу `sendTransaction` для створення власної логіки повторного передавання, зокрема перевірки `lastValidBlockHeight` і опитування стану мережі. + +## Налаштування власної логіки + +Впровадження алгоритмів, таких як [експоненціальне збільшення інтервалів](https://uk.wikipedia.org/wiki/Експоненційне_зростання), або постійне повторне передавання, як у [Mango](https://github.com/blockworks-foundation/mango-ui/blob/b6abfc6c13b71fc17ebbe766f50b8215fa1ec54f/src/utils/send.tsx#L713), може допомогти впоратися із завантаженістю мережі. ```ts import { @@ -281,49 +112,26 @@ const sleep = async (ms: number) => { })(); ``` -When polling via `getLatestBlockhash`, applications should specify their -intended [commitment](/docs/rpc/index.mdx#configuring-state-commitment) level. -By setting its commitment to `confirmed` (voted on) or `finalized` (~30 blocks -after `confirmed`), an application can avoid polling a blockhash from a minority -fork. - -If an application has access to RPC nodes behind a load balancer, it can also -choose to divide its workload amongst specific nodes. RPC nodes that serve -data-intensive requests such as -[getProgramAccounts](/content/guides/javascript/get-program-accounts.md) may be -prone to falling behind and can be ill-suited for also forwarding transactions. -For applications that handle time-sensitive transactions, it may be prudent to -have dedicated nodes that only handle `sendTransaction`. - -### The Cost of Skipping Preflight - -By default, `sendTransaction` will perform three preflight checks prior to -submitting a transaction. Specifically, `sendTransaction` will: - -- Verify that all signatures are valid -- Check that the referenced blockhash is within the last 150 blocks -- Simulate the transaction against the bank slot specified by the - `preflightCommitment` - -In the event that any of these three preflight checks fail, `sendTransaction` -will raise an error prior to submitting the transaction. Preflight checks can -often be the difference between losing a transaction and allowing a client to -gracefully handle an error. To ensure that these common errors are accounted -for, it is recommended that developers keep `skipPreflight` set to `false`. - -### When to Re-Sign Transactions - -Despite all attempts to rebroadcast, there may be times in which a client is -required to re-sign a transaction. Before re-signing any transaction, it is -**very important** to ensure that the initial transaction's blockhash has -expired. If the initial blockhash is still valid, it is possible for both -transactions to be accepted by the network. To an end-user, this would appear as -if they unintentionally sent the same transaction twice. - -In Solana, a dropped transaction can be safely discarded once the blockhash it -references is older than the `lastValidBlockHeight` received from -`getLatestBlockhash`. Developers should keep track of this -`lastValidBlockHeight` by querying -[`getEpochInfo`](/docs/rpc/http/getEpochInfo.mdx) and comparing with -`blockHeight` in the response. Once a blockhash is invalidated, clients may -re-sign with a newly-queried blockhash. +При опитуванні через `getLatestBlockhash` додатки повинні вказувати бажаний рівень [зобов'язань (commitment)](/docs/rpc/index.mdx#configuring-state-commitment). Встановлюючи зобов'язання на рівень `confirmed` (підтверджений) або `finalized` (~30 блоків після `confirmed`), додаток може уникнути опитування blockhash із меншості вузлів. + +Якщо додаток має доступ до RPC-вузлів за балансувальником навантаження, він також може розподіляти своє навантаження між конкретними вузлами. RPC-вузли, які обслуговують ресурсоємні запити, такі як +[getProgramAccounts](/content/guides/javascript/get-program-accounts.md), можуть відставати і бути менш ефективними для пересилання транзакцій. Для додатків, що обробляють транзакції в реальному часі, може бути розумним використовувати спеціалізовані вузли, які обслуговують лише `sendTransaction`. + +### Вартість пропуску перевірки перед виконанням + +За замовчуванням `sendTransaction` виконує три перевірки перед відправкою транзакції. Зокрема, `sendTransaction`: + +- Перевіряє, що всі підписи є дійсними. +- Перевіряє, що вказаний blockhash знаходиться в межах останніх 150 блоків. +- Симулює транзакцію на основі слоту банку, зазначеного у `preflightCommitment`. + +У разі, якщо одна з цих перевірок не пройде, `sendTransaction` видасть помилку до відправки транзакції. Перевірки перед виконанням можуть стати вирішальним фактором між втратою транзакції та можливістю клієнта обробити помилку. Щоб гарантувати врахування цих поширених помилок, рекомендується залишати `skipPreflight` встановленим у значення `false`. + +### Коли потрібно повторно підписувати транзакції + +Попри всі спроби повторного передавання, іноді клієнт може бути змушений повторно підписати транзакцію. Перед повторним підписанням будь-якої транзакції **дуже важливо** переконатися, що термін дії blockhash вихідної транзакції закінчився. Якщо початковий blockhash все ще дійсний, обидві транзакції можуть бути прийняті мережею. Для кінцевого користувача це виглядатиме як ненавмисне повторне відправлення однієї і тієї ж транзакції. + +У Solana втрачену транзакцію можна безпечно відхилити, якщо blockhash, на який вона посилається, старший за `lastValidBlockHeight`, отриманий із +`getLatestBlockhash`. Розробникам слід відстежувати цей `lastValidBlockHeight`, опитуючи +[`getEpochInfo`](/docs/rpc/http/getEpochInfo.mdx) і порівнюючи з `blockHeight` у відповіді. Після того, як blockhash стане недійсним, клієнти можуть повторно підписати транзакцію з новозапитаним blockhash. + diff --git a/docs/uk/advanced/state-compression.md b/docs/uk/advanced/state-compression.md index 5e01a602e..ceb6665e2 100644 --- a/docs/uk/advanced/state-compression.md +++ b/docs/uk/advanced/state-compression.md @@ -1,150 +1,81 @@ --- sidebarSortOrder: 4 -title: State Compression +title: Стиснення стану (State Compression) description: - 'State Compression is the method of cheaply and securely storing - "fingerprints" of offchain data in the Solana leger, instead of expensive - accounts.' + 'Стиснення стану - це метод дешевого та безпечного збереження + "відбитків" даних поза мережею в реєстрі Solana замість дорогих облікових записів.' --- -On Solana, [State Compression](/docs/advanced/state-compression.md) is the -method of creating a "fingerprint" (or hash) of offchain data and storing this -fingerprint on-chain for secure verification. Effectively using the security of -the Solana ledger to securely validate offchain data, verifying it has not been -tampered with. - -This method of "compression" allows Solana programs and dApps to use cheap -blockchain [ledger](/docs/terminology.md#ledger) space, instead of the more -expensive [account](/docs/terminology.md#account) space, to securely store data. - -This is accomplished by using a special binary tree structure, known as a -[concurrent merkle tree](#what-is-a-concurrent-merkle-tree), to create a hash of -each piece of data (called a `leaf`), hashing those together, and only storing -this final hash on-chain. - -## What is State Compression? - -In simple terms, state compression uses "**_tree_**" structures to -cryptographically hash offchain data together, in a deterministic way, to -compute a single final hash that gets stored on-chain. - -These _trees_ are created in this "_deterministic_" process by: - -- taking any piece of data -- creating a hash of this data -- storing this hash as a `leaf` at the bottom of the tree -- each `leaf` pair is then hashed together, creating a `branch` -- each `branch` is then hashed together -- continually climbing the tree and hashing adjacent branches together -- once at the top of the tree, a final `root hash` is produced - -This `root hash` is then stored onchain, as a verifiable **_proof_** of all of -the data within every leaf. Allowing anyone to cryptographically verify all the -offchain data within the tree, while only actually storing a **minimal** amount -of data on-chain. Therefore, significantly reducing the cost to store/prove -large amounts of data due to this "state compression". - -## Merkle trees and concurrent merkle trees - -Solana's state compression used a special type of -[merkle tree](#what-is-a-merkle-tree) that allows for multiple changes to any -given tree to happen, while still maintaining the integrity and validity of the -tree. - -This special tree, known as a -"[concurrent merkle tree](#what-is-a-concurrent-merkle-tree)", effectively -retains a "changelog" of the tree on-chain. Allowing for multiple rapid changes -to the same tree (i.e. all in the same block), before a proof is invalidated. - -### What is a merkle tree? - -A [merkle tree](https://en.wikipedia.org/wiki/merkle_tree), sometimes called a -"hash tree", is a hash based binary tree structure where each `leaf` node is -represented as a cryptographic hash of its inner data. And every node that is -**not** a leaf, called a `branch`, is represented as a hash of its child leaf -hashes. - -Each branch is then also hashed together, climbing the tree, until eventually -only a single hash remains. This final hash, called the `root hash` or "root", -can then be used in combination with a "proof path" to verify any piece of data -stored within a leaf node. - -Once a final `root hash` has been computed, any piece of data stored within a -`leaf` node can be verified by rehashing the specific leaf's data and the hash -label of each adjacent branch climbing the tree (known as the `proof` or "proof -path"). Comparing this "rehash" to the `root hash` is the verification of the -underlying leaf data. If they match, the data is verified accurate. If they do -not match, the leaf data was changed. - -Whenever desired, the original leaf data can be changed by simply hashing the -**new leaf** data and recomputing the root hash in the same manner of the -original root. This **new root hash** is then used to verify any of the data, -and effectively invalidates the previous root hash and previous proof. -Therefore, each change to these _traditional merkle trees_ are required to be -performed in series. - -> This process of changing leaf data, and computing a new root hash can be a -> **very common** thing when using merkle trees! While it is one of the design -> points of the tree, it can result in one of the most notable drawbacks: rapid -> changes. - -### What is a Concurrent merkle tree? - -In high throughput applications, like within the -[Solana runtime](/docs/core/fees.md), requests to change an on-chain -_traditional merkle tree_ could be received by validators in relatively rapid -succession (e.g. within the same slot). Each leaf data change would still be -required to be performed in series. Resulting in each subsequent request for -change to fail, due to the root hash and proof being invalidated by the previous -change request in the slot. - -Enter, Concurrent merkle trees. - -A **Concurrent merkle tree** stores a **secure changelog** of the most recent -changes, their root hash, and the proof to derive it. This changelog "buffer" is -stored on-chain in an account specific to each tree, with a maximum number of -changelog "records" (aka `maxBufferSize`). - -When multiple leaf data change requests are received by validators in the same -slot, the on-chain _concurrent merkle tree_ can use this "changelog buffer" as a -source of truth for more acceptable proofs. Effectively allowing for up to -`maxBufferSize` changes to the same tree in the same slot. Significantly -boosting throughput. - -## Sizing a concurrent merkle tree - -When creating one of these on-chain trees, there are 3 values that will -determine the size of your tree, the cost to create your tree, and the number of -concurrent changes to your tree: - -1. max depth -2. max buffer size -3. canopy depth - -### Max depth - -The "max depth" of a tree is the **maximum number** of hops to get from any data -`leaf` to the `root` of the tree. - -Since merkle trees are binary trees, every leaf is connected to **only one** -other leaf; existing as a `leaf pair`. - -Therefore, the `maxDepth` of a tree is used to determine the maximum number of -nodes (aka pieces of data or `leafs`) to store within the tree using a simple -calculation: +У Solana [стиснення стану](/docs/advanced/state-compression.md) є методом створення "відбитку" (або гешу) даних поза мережею та збереження цього відбитку в мережі для безпечної перевірки. Цей процес використовує безпеку реєстру Solana для гарантування цілісності даних поза мережею, забезпечуючи їх незмінність. + +Цей метод "стиснення" дозволяє програмам та децентралізованим додаткам (dApps) використовувати дешевий простір у [реєстрі](/docs/terminology.md#ledger) блокчейну, замість більш дорогого простору [облікових записів](/docs/terminology.md#account), для безпечного зберігання даних. + +Це досягається за допомогою спеціальної структури двійкового дерева, відомого як +[конкурентне мерклеве дерево](#what-is-a-concurrent-merkle-tree), яке створює геш кожного фрагмента даних (названого `листком`), об'єднує ці геші і зберігає тільки фінальний геш у мережі. + +## Що таке стиснення стану? + +Простіше кажучи, стиснення стану використовує структури "**_дерев_**" для криптографічного хешування даних поза мережею детермінованим способом, щоб обчислити один кінцевий геш, який зберігається у мережі. + +Ці _дерева_ створюються таким "_детермінованим_" процесом: + +- Береться будь-який фрагмент даних. +- Створюється геш цих даних. +- Цей геш зберігається як `листок` на нижньому рівні дерева. +- Кожна пара `листків` об'єднується в геш, створюючи `гілку`. +- Кожна `гілка` також хешується разом. +- Процес повторюється, поки не буде обчислено фінальний `кореневий геш`. + +Цей `кореневий геш` зберігається в мережі як верифіковане **_підтвердження_** для всіх даних у кожному листку. Це дозволяє криптографічно перевіряти всі дані поза мережею, використовуючи мінімальну кількість даних у мережі. Таким чином, значно знижуються витрати на зберігання/перевірку великих обсягів даних завдяки "стисненню стану". + +## Мерклеві дерева та конкурентні мерклеві дерева + +Стиснення стану у Solana використовує спеціальний тип +[мерклевого дерева](#what-is-a-merkle-tree), який дозволяє виконувати кілька змін у дереві, зберігаючи його цілісність і валідність. + +Це спеціальне дерево, відоме як +"[конкурентне мерклеве дерево](#what-is-a-concurrent-merkle-tree)", зберігає "журнал змін" дерева в мережі. Це дозволяє виконувати кілька змін до дерева (наприклад, у межах одного блоку), не порушуючи підтвердження. + +### Що таке мерклеве дерево? + +[Мерклеве дерево](https://uk.wikipedia.org/wiki/Мерклеве_дерево), або "дерево гешів", — це двійкова структура, у якій кожен `листок` є криптографічним гешем даних. Всі вузли, які **не** є листками, називаються `гілками` і є гешами їхніх дочірніх листків. + +Кожна гілка також хешується разом, поступово піднімаючись вгору, поки не залишиться один геш. Цей фінальний геш, званий `кореневим гешем`, можна використовувати разом із "шляхом підтвердження" для перевірки будь-яких даних, збережених у листковому вузлі. + +### Що таке Конкурентне Мерклеве дерево? + +У високопродуктивних застосунках, таких як [середовище виконання Solana](/docs/core/fees.md), запити на зміну ончейн _традиційного мерклевого дерева_ можуть надходити до валідаторів досить швидко (наприклад, у межах одного слота). У таких випадках кожна зміна даних у листках повинна виконуватися послідовно. Це призводить до невдачі наступних запитів на зміну, оскільки кореневий геш і підтвердження стають недійсними після попередньої зміни в слоті. + +Рішенням цієї проблеми є Конкурентні Мерклеві дерева. + +**Конкурентне Мерклеве дерево** зберігає **захищений журнал змін**, який містить останні зміни, їх кореневий геш і підтвердження для його обчислення. Цей буфер змін ("changelog buffer") зберігається ончейн у спеціальному акаунті для кожного дерева, з обмеженням на максимальну кількість записів у журналі змін (`maxBufferSize`). + +Коли валідатори отримують кілька запитів на зміну даних у листках у межах одного слота, ончейн _конкурентне мерклеве дерево_ може використовувати цей буфер змін як джерело правдивої інформації для більш прийнятних підтверджень. Це дозволяє виконувати до `maxBufferSize` змін для одного дерева в межах одного слота, що значно підвищує пропускну здатність. + +## Розмір Конкурентного Мерклевого дерева + +При створенні такого ончейн дерева існує 3 параметри, які визначають розмір дерева, вартість його створення і кількість одночасних змін: + +1. Максимальна глибина (max depth) +2. Розмір буфера змін (max buffer size) +3. Глибина крони дерева (canopy depth) + +### Максимальна глибина + +"Максимальна глибина" дерева — це **максимальна кількість** переходів від будь-якого `листка` даних до `кореня` дерева. + +Оскільки мерклеві дерева є двійковими, кожен листок з'єднаний лише з **одним** іншим листком; вони утворюють `пару листків`. + +Таким чином, `maxDepth` дерева використовується для визначення максимальної кількості вузлів (тобто елементів даних або `листків`), які можна зберігати у дереві, за допомогою простої формули: ```text nodes_count = 2 ^ maxDepth ``` +Оскільки глибину дерева потрібно встановити під час його створення, ви повинні визначити, скільки елементів даних ви хочете зберігати у своєму дереві. Потім, використовуючи просту формулу вище, ви можете визначити найменше значення `maxDepth`, яке дозволить зберігати ваші дані. -Since a trees depth must be set at tree creation, you must decide how many -pieces of data you want your tree to store. Then using the simple calculation -above, you can determine the lowest `maxDepth` to store your data. +#### Приклад 1: Мінтинг 100 NFT -#### Example 1: minting 100 nfts - -If you wanted to create a tree to store 100 compressed nfts, we will need a -minimum of "100 leafs" or "100 nodes". +Якщо ви хочете створити дерево для зберігання 100 стиснутих NFT, вам знадобиться щонайменше "100 листків" або "100 вузлів". ```text // maxDepth=6 -> 64 nodes @@ -153,13 +84,11 @@ minimum of "100 leafs" or "100 nodes". // maxDepth=7 -> 128 nodes 2^7 = 128 ``` +Ми повинні використовувати значення `maxDepth` рівне `7`, щоб забезпечити можливість зберігати всі наші дані. -We must use a `maxDepth` of `7` to ensure we can store all of our data. - -#### Example 2: minting 15000 nfts +#### Приклад 2: Мінтинг 15000 NFT -If you wanted to create a tree to store 15000 compressed nfts, we will need a -minimum of "15000 leafs" or "15000 nodes". +Якщо ви хочете створити дерево для зберігання 15000 стиснутих NFT, вам знадобиться щонайменше "15000 листків" або "15000 вузлів". ```text // maxDepth=13 -> 8192 nodes @@ -168,123 +97,71 @@ minimum of "15000 leafs" or "15000 nodes". // maxDepth=14 -> 16384 nodes 2^14 = 16384 ``` +Ми повинні використовувати `maxDepth` рівне `14`, щоб забезпечити можливість зберігати всі наші дані. -We must use a `maxDepth` of `14` to ensure we can store all of our data. +#### Чим більша максимальна глибина, тим вища вартість -#### The higher the max depth, the higher the cost +Значення `maxDepth` є одним із основних чинників вартості під час створення дерева, оскільки ви оплачуєте цю вартість наперед при створенні дерева. Чим більша глибина дерева, тим більше даних (відбитків або хешів) можна зберігати, але тим вища вартість. -The `maxDepth` value will be one of the primary drivers of cost when creating a -tree since you will pay this cost upfront at tree creation. The higher the max -tree depth, the more data fingerprints (aka hashes) you can store, the higher -the cost. - -### Max buffer size +--- -The "max buffer size" is effectively the maximum number of changes that can -occur on a tree, with the `root hash` still being valid. +### Максимальний розмір буфера (maxBufferSize) -Due to the root hash effectively being a single hash of all leaf data, changing -any single leaf would invalidate the proof needed for all subsequent attempts to -change any leaf of a regular tree. +"Максимальний розмір буфера" — це максимальна кількість змін, які можуть бути внесені до дерева, доки кореневий хеш (`root hash`) залишається дійсним. -But with a [concurrent tree](#what-is-a-concurrent-merkle-tree), there is -effectively a changelog of updates for these proofs. This changelog buffer is -sized and set at tree creation via this `maxBufferSize` value. +Оскільки кореневий хеш є єдиним хешем для всіх даних листків, зміна будь-якого окремого листка інвалідовує proof, потрібний для всіх наступних спроб змінити будь-який інший листок у звичайному дереві. -### Canopy depth +У випадку [Concurrent Tree](#що-таке-concurrent-merkle-tree), існує журнал змін для цих proof, який задається під час створення дерева через параметр `maxBufferSize`. -The "canopy depth," also known as the canopy size, refers to the number of proof -node levels that are cached or stored onchain for a given proof path. +--- -When performing an update action on a `leaf`, like transferring ownership (e.g. -selling a compressed NFT), the **complete** proof path must be used to verify -original ownership of the leaf and therefore allow for the update action. This -verification is performed using the **complete** proof path to correctly compute -the current `root hash` (or any cached `root hash` via the onchain "concurrent -buffer"). +### Глибина козирка (canopyDepth) -The larger a tree's max depth is, the more proof nodes are required to perform -this verification. For example, if your max depth is `14`, there are `14` total -proof nodes required to be used to verify. As a tree gets larger, the complete -proof path gets larger. +"Глибина козирка" або "розмір козирка" визначає кількість рівнів proof, які кешуються або зберігаються on-chain для даного proof-шляху. -Normally, each of these proof nodes would be required to be included within each -tree update transaction. Since each proof node value takes up `32 bytes` in a -transaction (similar to providing a Public Key), larger trees would very quickly -exceed the maximum transaction size limit. +Коли виконується дія оновлення для `leaf` (наприклад, передача права власності), **повний** proof-шлях повинен бути використаний для верифікації початкового права власності на листок. Це здійснюється шляхом обчислення поточного `root hash`. -Enter the canopy. The canopy enables storing a set number of proof nodes on -chain (for any given proof path). Allowing for less proof nodes to be included -within each update transactions, therefore keeping the overall transaction size -below the limit. +Для великих дерев потрібно більше proof-вузлів, щоб виконати цю перевірку. Наприклад, якщо `maxDepth` дорівнює `14`, потрібно `14` proof-вузлів. З використанням козирка частина цих вузлів зберігається on-chain, зменшуючи кількість proof-вузлів, які потрібно включити в транзакції. -For example, a tree with a max depth of `14` would require `14` total proof -nodes. With a canopy of `10`, only `4` proof nodes are required to be submitted -per update transaction. +Наприклад, дерево з `maxDepth` рівне `14` із козирком розміром `10` потребуватиме лише `4` proof-вузли на транзакцію. -![Canopy depth of 1 for a Concurrent Merkle Tree of max depth of 3](/assets/docs/compression/canopy-depth-1.png) +![Глибина козирка 1 для Concurrent Merkle Tree з максимальною глибиною 3](/assets/docs/compression/canopy-depth-1.png) -Consider another example, this time with a tree of max depth `3`. If we want to -apply an action to one of the tree’s leaves—such as updating `R4`—we need to -provide proofs for `L4` and `R2`. However, we can omit `R1` since it is already -cached/stored onchain due to our canopy depth of `1`, which ensures that all -nodes at level 1 (`L1` and `R1`) are stored onchain. This results in a total of -2 required proofs. +--- -Therefore, the number of proofs required to update a leaf is equal to the max -depth minus the canopy depth. In this example, `3 - 1 = 2`. +#### Чим більша глибина козирка, тим вища вартість -#### The larger the canopy depth value, the higher the cost +Значення `canopyDepth` також є одним із основних чинників вартості створення дерева. Чим більше proof-вузлів зберігається on-chain, тим вища вартість. -The `canopyDepth` value is also a primary factor of cost when creating a tree -since you will pay this cost upfront at tree creation. The higher the canopy -depth, the more data proof nodes are stored onchain, the higher the cost. +#### Низький козирок обмежує композитність -#### Smaller canopy limits composability +Низьке значення `canopyDepth` вимагає більше proof-вузлів у кожній транзакції оновлення. Це обмежує можливості для інтеграції вашого дерева з іншими Solana-програмами або dApps. -While a tree's creation costs are higher with a higher canopy, having a lower -`canopyDepth` will require more proof nodes to be included within each update -transaction. The more nodes required to be submitted, the larger the transaction -size, and therefore the easier it is to exceed the transaction size limits. +Наприклад, дерево, яке використовується для стиснутих NFT з низьким `canopyDepth`, може дозволяти лише базові дії, як-от передача, але не підтримувати розширені функції, такі як система ставок. -This will also be the case for any other Solana program or dApp that attempts to -interact with your tree/leafs. If your tree requires too many proof nodes -(because of a low canopy depth), then any other additional actions another -on-chain program **could** offer will be **limited** by their specific -instruction size plus your proof node list size. Limiting composability, and -potential additional utility for your specific tree. +--- -For example, if your tree is being used for compressed NFTs and has a very low -canopy depth, an NFT marketplace may only be able to support simple NFTs -transfers. And not be able to support an on-chain bidding system. +## Вартість створення дерева -## Cost of creating a tree +Вартість створення Concurrent Merkle Tree залежить від його параметрів: `maxDepth`, `maxBufferSize`, і `canopyDepth`. Ці параметри визначають необхідний простір (у байтах) для дерева. -The cost of creating a concurrent merkle tree is based on the tree's size -parameters: `maxDepth`, `maxBufferSize`, and `canopyDepth`. These values are all -used to calculate the on-chain storage (in bytes) required for a tree to exist -onchain. +Використовуючи метод +[`getMinimumBalanceForRentExemption`](/docs/rpc/http/getminimumbalanceforrentexemption), +можна дізнатися вартість (у лампортах) для виділення цього простору on-chain. -Once the required space (in bytes) has been calculated, and using the -[`getMinimumBalanceForRentExemption`](/docs/rpc/http/getminimumbalanceforrentexemption) -RPC method, request the cost (in lamports) to allocate this amount of bytes -on-chain. +--- -### Calculate tree cost in JavaScript +### Розрахунок вартості дерева у JavaScript -Within the +У пакеті [`@solana/spl-account-compression`](https://www.npmjs.com/package/@solana/spl-account-compression) -package, developers can use the +можна використовувати функцію [`getConcurrentMerkleTreeAccountSize`](https://solana-labs.github.io/solana-program-library/account-compression/sdk/docs/modules/index.html#getConcurrentMerkleTreeAccountSize) -function to calculate the required space for a given tree size parameters. - -Then using the -[`getMinimumBalanceForRentExemption`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getMinimumBalanceForRentExemption) -function to get the final cost (in lamports) to allocate the required space for -the tree on-chain. +для розрахунку необхідного простору для дерева з заданими параметрами. -Then determine the cost in lamports to make an account of this size rent exempt, -similar to any other account creation. +Далі, за допомогою функції +[`getMinimumBalanceForRentExemption`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getMinimumBalanceForRentExemption), +можна визначити остаточну вартість (у лампортах) для створення дерева, подібно до будь-якого іншого акаунта. ```ts // calculate the space required for the tree @@ -299,41 +176,39 @@ const storageCost = await connection.getMinimumBalanceForRentExemption(requiredSpace); ``` -### Example costs +### Приклади вартості -Listed below are several example costs, for different tree sizes, including how -many leaf nodes are possible for each: +Нижче наведено кілька прикладів вартості для дерев різного розміру, включаючи кількість можливих листків: -**Example #1: 16,384 nodes costing 0.222 SOL** +**Приклад №1: 16,384 вузлів, вартість 0.222 SOL** -- max depth of `14` and max buffer size of `64` -- maximum number of leaf nodes: `16,384` -- canopy depth of `0` costs approximately `0.222 SOL` to create +- максимальна глибина: `14`, максимальний розмір буфера: `64` +- максимальна кількість листків: `16,384` +- глибина козирка: `0`, вартість створення приблизно `0.222 SOL` -**Example #2: 16,384 nodes costing 1.134 SOL** +**Приклад №2: 16,384 вузлів, вартість 1.134 SOL** -- max depth of `14` and max buffer size of `64` -- maximum number of leaf nodes: `16,384` -- canopy depth of `11` costs approximately `1.134 SOL` to create +- максимальна глибина: `14`, максимальний розмір буфера: `64` +- максимальна кількість листків: `16,384` +- глибина козирка: `11`, вартість створення приблизно `1.134 SOL` -**Example #3: 1,048,576 nodes costing 1.673 SOL** +**Приклад №3: 1,048,576 вузлів, вартість 1.673 SOL** -- max depth of `20` and max buffer size of `256` -- maximum number of leaf nodes: `1,048,576` -- canopy depth of `10` costs approximately `1.673 SOL` to create +- максимальна глибина: `20`, максимальний розмір буфера: `256` +- максимальна кількість листків: `1,048,576` +- глибина козирка: `10`, вартість створення приблизно `1.673 SOL` -**Example #4: 1,048,576 nodes costing 15.814 SOL** +**Приклад №4: 1,048,576 вузлів, вартість 15.814 SOL** -- max depth of `20` and max buffer size of `256` -- maximum number of leaf nodes: `1,048,576` -- canopy depth of `15` costs approximately `15.814 SOL` to create +- максимальна глибина: `20`, максимальний розмір буфера: `256` +- максимальна кількість листків: `1,048,576` +- глибина козирка: `15`, вартість створення приблизно `15.814 SOL` + +--- -## Compressed NFTs +## Стиснуті NFT -Compressed NFTs are one of the most popular use cases for State Compression on -Solana. With compression, a one million NFT collection could be minted for -`~50 SOL`, vice `~12,000 SOL` for its uncompressed equivalent collection. +Стиснуті NFT є одним із найпопулярніших варіантів використання стиснення стану на Solana. Завдяки стисненню колекцію з одного мільйона NFT можна створити за `~50 SOL`, у порівнянні з `~12,000 SOL` для її нестиснутої еквівалентної колекції. -If you are interested in creating compressed NFTs yourself, read our developer -guide for -[minting and transferring compressed NFTs](/content/guides/javascript/compressed-nfts.md). +Якщо ви зацікавлені в створенні стиснутих NFT, ознайомтеся з нашим посібником для розробників: +[створення та передача стиснутих NFT](/content/guides/javascript/compressed-nfts.md). diff --git a/docs/uk/advanced/versions.md b/docs/uk/advanced/versions.md index c94013997..7effd6b6b 100644 --- a/docs/uk/advanced/versions.md +++ b/docs/uk/advanced/versions.md @@ -1,70 +1,60 @@ --- sidebarSortOrder: 3 -title: Versioned Transactions +title: "Версійні Транзакції" description: - "Explore the core Solana concepts: transactions, versioned transactions, - enabling additional functionality in the Solana runtime, address lookup - tables, and more." + "Дослідіть основні концепції Solana: транзакції, версійні транзакції, розширення функціональності в Solana Runtime, таблиці пошуку адрес та інше." altRoutes: - /docs/core/transactions/versions --- -Versioned Transactions are the new transaction format that allow for additional -functionality in the Solana runtime, including -[Address Lookup Tables](/docs/advanced/lookup-tables.md). +Версійні Транзакції - це новий формат транзакцій, який дозволяє додаткову функціональність у Solana Runtime, включаючи +[Таблиці пошуку адрес](/docs/advanced/lookup-tables.md). -While changes to onchain programs are **NOT** required to support the new -functionality of versioned transactions (or for backwards compatibility), -developers **WILL** need update their client side code to prevent -[errors due to different transaction versions](#max-supported-transaction-version). +Хоча зміни в ончейн-програмах **НЕ** потрібні для підтримки нової функціональності версійних транзакцій (або для зворотної сумісності), розробники **ПОВИННІ** оновити клієнтський код, щоб уникнути +[помилок через різні версії транзакцій](#max-supported-transaction-version). -## Current Transaction Versions +## Поточні версії транзакцій -The Solana runtime supports two transaction versions: +Solana Runtime підтримує дві версії транзакцій: -- `legacy` - older transaction format with no additional benefit -- `0` - added support for - [Address Lookup Tables](/docs/advanced/lookup-tables.md) +- `legacy` - старий формат транзакцій без додаткових переваг +- `0` - додає підтримку + [Таблиць пошуку адрес](/docs/advanced/lookup-tables.md) -## Max supported transaction version +## Максимально підтримувана версія транзакцій -All RPC requests that return a transaction **_should_** specify the highest -version of transactions they will support in their application using the -`maxSupportedTransactionVersion` option, including -[`getBlock`](/docs/rpc/http/getBlock.mdx) and +Усі RPC-запити, які повертають транзакцію, **_повинні_** вказувати найвищу версію транзакцій, яку вони підтримують у своїй програмі, використовуючи параметр +`maxSupportedTransactionVersion`, включаючи +[`getBlock`](/docs/rpc/http/getBlock.mdx) та [`getTransaction`](/docs/rpc/http/getTransaction.mdx). -An RPC request will fail if a Versioned Transaction is returned that is higher -than the set `maxSupportedTransactionVersion`. (i.e. if a version `0` -transaction is returned when `legacy` is selected) +RPC-запит завершиться невдачею, якщо буде повернута версійна транзакція, яка має версію вище встановленої `maxSupportedTransactionVersion`. (наприклад, якщо повертається транзакція версії `0`, а встановлено `legacy`) -> WARNING: If no `maxSupportedTransactionVersion` value is set, then only -> `legacy` transactions will be allowed in the RPC response. Therefore, your RPC -> requests **WILL** fail if any version `0` transactions are returned. +> УВАГА: Якщо значення `maxSupportedTransactionVersion` не встановлено, тоді лише транзакції `legacy` будуть дозволені у відповіді RPC. Таким чином, ваші RPC-запити **ПРИЗВЕДУТЬ ДО ПОМИЛКИ**, якщо буде повернута будь-яка транзакція версії `0`. -## How to set max supported version +## Як встановити максимально підтримувану версію -You can set the `maxSupportedTransactionVersion` using both the -[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/) library -and JSON formatted requests directly to an RPC endpoint. +Ви можете встановити `maxSupportedTransactionVersion`, використовуючи бібліотеку +[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/) +або шляхом прямого надсилання JSON-запитів до RPC-ендпоінту. -### Using web3.js +### Використання web3.js -Using the -[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/) library, -you can retrieve the most recent block or get a specific transaction: +Використовуючи бібліотеку +[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/), +ви можете отримати останній блок або конкретну транзакцію: ```js -// connect to the `devnet` cluster and get the current `slot` +// підключення до кластера `devnet` та отримання поточного `slot` const connection = new web3.Connection(web3.clusterApiUrl("devnet")); const slot = await connection.getSlot(); -// get the latest block (allowing for v0 transactions) +// отримання останнього блоку (дозволяючи транзакції версії v0) const block = await connection.getBlock(slot, { maxSupportedTransactionVersion: 0, }); -// get a specific transaction (allowing for v0 transactions) +// отримання конкретної транзакції (дозволяючи транзакції версії v0) const getTx = await connection.getTransaction( "3jpoANiFeVGisWRY5UP648xRXs3iQasCHABPWRWnoEjeA93nc79WrnGgpgazjq4K9m8g2NJoyKoWBV1Kx5VmtwHQ", { @@ -73,10 +63,10 @@ const getTx = await connection.getTransaction( ); ``` -### JSON requests to the RPC +### JSON-запити до RPC -Using a standard JSON formatted POST request, you can set the -`maxSupportedTransactionVersion` when retrieving a specific block: +Використовуючи стандартний JSON-запит POST, ви можете встановити +`maxSupportedTransactionVersion` при отриманні конкретного блоку: ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d \ @@ -88,30 +78,26 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - }]}' ``` -## How to create a Versioned Transaction +## Як створити версійну транзакцію -Versioned transactions can be created similar to the older method of creating -transactions. There are differences in using certain libraries that should be -noted. +Версійні транзакції можна створити подібно до старого методу створення транзакцій. Є відмінності у використанні певних бібліотек, які слід враховувати. -Below is an example of how to create a Versioned Transaction, using the -`@solana/web3.js` library, to send perform a SOL transfer between two accounts. +Нижче наведено приклад створення версійної транзакції з використанням бібліотеки +`@solana/web3.js` для передачі SOL між двома рахунками. -#### Notes: +#### Примітки: -- `payer` is a valid `Keypair` wallet, funded with SOL -- `toAccount` a valid `Keypair` +- `payer` - це дійсний гаманець `Keypair`, наповнений SOL +- `toAccount` - дійсний `Keypair` -Firstly, import the web3.js library and create a `connection` to your desired -cluster. +Спочатку імпортуйте бібліотеку web3.js та створіть `connection` до бажаного кластера. -We then define the recent `blockhash` and `minRent` we will need for our -transaction and the account: +Далі визначте останній `blockhash` і `minRent`, які будуть потрібні для вашої транзакції та рахунку: ```js const web3 = require("@solana/web3.js"); -// connect to the cluster and get the minimum rent for rent exempt status +// підключення до кластера та отримання мінімальної орендної плати для статусу rent exempt const connection = new web3.Connection(web3.clusterApiUrl("devnet")); let minRent = await connection.getMinimumBalanceForRentExemption(0); let blockhash = await connection @@ -119,12 +105,10 @@ let blockhash = await connection .then(res => res.blockhash); ``` -Create an `array` of all the `instructions` you desire to send in your -transaction. In this example below, we are creating a simple SOL transfer -instruction: +Створіть `array` усіх `instructions`, які ви хочете відправити у вашій транзакції. У прикладі нижче ми створюємо просту інструкцію передачі SOL: ```js -// create an array with your desired `instructions` +// створення масиву з вашими інструкціями const instructions = [ web3.SystemProgram.transfer({ fromPubkey: payer.publicKey, @@ -134,11 +118,10 @@ const instructions = [ ]; ``` -Next, construct a `MessageV0` formatted transaction message with your desired -`instructions`: +Далі створіть повідомлення у форматі `MessageV0` для вашої транзакції: ```js -// create v0 compatible message +// створення повідомлення, сумісного з v0 const messageV0 = new web3.TransactionMessage({ payerKey: payer.publicKey, recentBlockhash: blockhash, @@ -146,46 +129,34 @@ const messageV0 = new web3.TransactionMessage({ }).compileToV0Message(); ``` -Then, create a new `VersionedTransaction`, passing in our v0 compatible message: +Потім створіть нову `VersionedTransaction`, передаючи ваше повідомлення v0: ```js const transaction = new web3.VersionedTransaction(messageV0); -// sign your transaction with the required `Signers` +// підпишіть вашу транзакцію потрібними підписами transaction.sign([payer]); ``` -You can sign the transaction by either: - -- passing an array of `signatures` into the `VersionedTransaction` method, or -- call the `transaction.sign()` method, passing an array of the required - `Signers` - -> NOTE: After calling the `transaction.sign()` method, all the previous -> transaction `signatures` will be fully replaced by new signatures created from -> the provided in `Signers`. - -After your `VersionedTransaction` has been signed by all required accounts, you -can send it to the cluster and `await` the response: +Після того, як ваша `VersionedTransaction` підписана всіма необхідними рахунками, ви можете відправити її до кластера та отримати відповідь: ```js -// send our v0 transaction to the cluster +// відправка нашої транзакції v0 до кластера const txId = await connection.sendTransaction(transaction); console.log(`https://explorer.solana.com/tx/${txId}?cluster=devnet`); ``` -> NOTE: Unlike `legacy` transactions, sending a `VersionedTransaction` via -> `sendTransaction` does **NOT** support transaction signing via passing in an -> array of `Signers` as the second parameter. You will need to sign the -> transaction before calling `connection.sendTransaction()`. - -## More Resources - -- using - [Versioned Transactions for Address Lookup Tables](/docs/advanced/lookup-tables.md#how-to-create-an-address-lookup-table) -- view an - [example of a v0 transaction](https://explorer.solana.com/tx/h9WQsqSUYhFvrbJWKFPaXximJpLf6Z568NW1j6PBn3f7GPzQXe9PYMYbmWSUFHwgnUmycDNbEX9cr6WjUWkUFKx/?cluster=devnet) - on Solana Explorer -- read the - [accepted proposal](https://docs.anza.xyz/proposals/versioned-transactions) - for Versioned Transaction and Address Lookup Tables +> УВАГА: На відміну від `legacy` транзакцій, відправка `VersionedTransaction` через +> `sendTransaction` **НЕ** підтримує підпис транзакцій через передачу масиву `Signers` як другого параметра. Ви повинні підписати транзакцію перед викликом `connection.sendTransaction()`. + +## Додаткові ресурси + +- Використання + [версійних транзакцій для таблиць пошуку адрес](/docs/advanced/lookup-tables.md#how-to-create-an-address-lookup-table) +- Перегляд + [прикладу транзакції v0](https://explorer.solana.com/tx/h9WQsqSUYhFvrbJWKFPaXximJpLf6Z568NW1j6PBn3f7GPzQXe9PYMYbmWSUFHwgnUmycDNbEX9cr6WjUWkUFKx/?cluster=devnet) + на Solana Explorer +- Читання + [ухваленої пропозиції](https://docs.anza.xyz/proposals/versioned-transactions) + для версійних транзакцій та таблиць пошуку адрес + From e26bcb05410c5f49863f2eefdd205c854d8dcfb3 Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Fri, 10 Jan 2025 15:20:35 +0200 Subject: [PATCH 05/14] Finished clients folder. Started core folder. Translated accounts.md --- docs/uk/clients/index.md | 2 +- docs/uk/clients/javascript-reference.md | 298 +++++++++--------------- docs/uk/clients/javascript.md | 179 +++++--------- docs/uk/clients/rust.md | 51 ++-- docs/uk/core/accounts.md | 263 ++++++++++----------- 5 files changed, 323 insertions(+), 470 deletions(-) diff --git a/docs/uk/clients/index.md b/docs/uk/clients/index.md index bdafa7921..3f0c7aadd 100644 --- a/docs/uk/clients/index.md +++ b/docs/uk/clients/index.md @@ -1,5 +1,5 @@ --- metaOnly: true -title: Solana Clients +title: Solana клієнти sidebarSortOrder: 4 --- diff --git a/docs/uk/clients/javascript-reference.md b/docs/uk/clients/javascript-reference.md index cfa80f396..220d8f00a 100644 --- a/docs/uk/clients/javascript-reference.md +++ b/docs/uk/clients/javascript-reference.md @@ -1,32 +1,29 @@ --- -title: Web3.js API Examples +title: Web3.js API Приклади description: - Learn how to interact with the Solana blockchain using the @solana/web3.js - library through practical code samples and explanations. + Дізнайтеся, як взаємодіяти з блокчейном Solana за допомогою бібліотеки @solana/web3.js + через практичні приклади коду та пояснення. --- -## Web3 API Reference Guide +## Довідник по Web3 API -The `@solana/web3.js` library is a package that has coverage over the +Бібліотека `@solana/web3.js` забезпечує покриття [Solana JSON RPC API](/docs/rpc). -You can find the full documentation for the `@solana/web3.js` library -[here](https://solana-labs.github.io/solana-web3.js/v1.x/). +Повну документацію до бібліотеки `@solana/web3.js` можна знайти +[тут](https://solana-labs.github.io/solana-web3.js/v1.x/). -## General +## Загальні -### Connection +### Підключення -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html) +[Документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html) -Connection is used to interact with the [Solana JSON RPC](/docs/rpc). You can -use Connection to confirm transactions, get account info, and more. +Об'єкт `Connection` використовується для взаємодії з [Solana JSON RPC](/docs/rpc). Ви можете використовувати Connection для підтвердження транзакцій, отримання інформації про облікові записи тощо. -You create a connection by defining the JSON RPC cluster endpoint and the -desired commitment. Once this is complete, you can use this connection object to -interact with any of the Solana JSON RPC API. +Створення підключення здійснюється шляхом вказання URL-адреси RPC-кластера та бажаного рівня зобов'язань. Після цього ви можете використовувати цей об'єкт підключення для взаємодії з будь-яким із API JSON RPC Solana. -#### Example Usage +#### Приклад використання ```javascript const web3 = require("@solana/web3.js"); @@ -61,28 +58,22 @@ console.log(slotLeader); //49AqLYbpJYc2DrzGUAH1fhWJy62yxBxpLEkfJwjKy2jr ``` -The above example shows only a few of the methods on Connection. Please see the -[source generated docs](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html) -for the full list. +Наведений вище приклад показує лише кілька методів класу Connection. Повний список можна знайти у +[генерованій документації](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html). -### Transaction +### Транзакція -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html) +[Документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html) -A transaction is used to interact with programs on the Solana blockchain. These -transactions are constructed with TransactionInstructions, containing all the -accounts possible to interact with, as well as any needed data or program -addresses. Each TransactionInstruction consists of keys, data, and a programId. -You can do multiple instructions in a single transaction, interacting with -multiple programs at once. +Транзакція використовується для взаємодії з програмами на блокчейні Solana. Ці транзакції створюються за допомогою TransactionInstructions, які містять усі можливі облікові записи для взаємодії, а також необхідні дані або адреси програм. Кожна TransactionInstruction складається з ключів, даних і programId. Ви можете виконувати кілька інструкцій в одній транзакції, взаємодіючи з кількома програмами одночасно. -#### Example Usage +#### Приклад використання ```javascript const web3 = require("@solana/web3.js"); const nacl = require("tweetnacl"); -// Airdrop SOL for paying transactions +// Запит airdrop SOL для оплати транзакцій let payer = web3.Keypair.generate(); let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); @@ -95,10 +86,10 @@ await connection.confirmTransaction({ signature: airdropSignature }); let toAccount = web3.Keypair.generate(); -// Create Simple Transaction +// Створення простої транзакції let transaction = new web3.Transaction(); -// Add an instruction to execute +// Додати інструкцію для виконання transaction.add( web3.SystemProgram.transfer({ fromPubkey: payer.publicKey, @@ -107,11 +98,11 @@ transaction.add( }), ); -// Send and confirm transaction -// Note: feePayer is by default the first signer, or payer, if the parameter is not set +// Відправка та підтвердження транзакції +// За замовчуванням feePayer - це перший підписант await web3.sendAndConfirmTransaction(connection, transaction, [payer]); -// Alternatively, manually construct the transaction +// Альтернативно, створення транзакції вручну let recentBlockhash = await connection.getLatestBlockhash(); let manualTransaction = new web3.Transaction({ recentBlockhash: recentBlockhash.blockhash, @@ -142,13 +133,11 @@ await web3.sendAndConfirmRawTransaction(connection, rawTransaction); ### Keypair -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Keypair.html) +[Документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Keypair.html) -The keypair is used to create an account with a public key and secret key within -Solana. You can either generate, generate from a seed, or create from a secret -key. +Keypair використовується для створення облікового запису з публічним і секретним ключами в Solana. Ви можете згенерувати Keypair, створити його з seed або секретного ключа. -#### Example Usage +#### Приклад використання ```javascript const { Keypair } = require("@solana/web3.js"); @@ -159,18 +148,10 @@ console.log(account.publicKey.toBase58()); console.log(account.secretKey); // 2DVaHtcdTf7cm18Zm9VV8rKK4oSnjmTkKE6MiXe18Qsb -// Uint8Array(64) [ -// 152, 43, 116, 211, 207, 41, 220, 33, 193, 168, 118, -// 24, 176, 83, 206, 132, 47, 194, 2, 203, 186, 131, -// 197, 228, 156, 170, 154, 41, 56, 76, 159, 124, 18, -// 14, 247, 32, 210, 51, 102, 41, 43, 21, 12, 170, -// 166, 210, 195, 188, 60, 220, 210, 96, 136, 158, 6, -// 205, 189, 165, 112, 32, 200, 116, 164, 234 -// ] +// Uint8Array(64) [...] let seed = Uint8Array.from([ - 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, - 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, + 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, ]); let accountFromSeed = Keypair.fromSeed(seed); @@ -178,14 +159,7 @@ console.log(accountFromSeed.publicKey.toBase58()); console.log(accountFromSeed.secretKey); // 3LDverZtSC9Duw2wyGC1C38atMG49toPNW9jtGJiw9Ar -// Uint8Array(64) [ -// 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, 102, -// 100, 70, 60, 102, 100, 70, 60, 102, 100, 70, 60, -// 102, 100, 70, 60, 102, 100, 70, 60, 102, 100, 34, -// 164, 6, 12, 9, 193, 196, 30, 148, 122, 175, 11, -// 28, 243, 209, 82, 240, 184, 30, 31, 56, 223, 236, -// 227, 60, 72, 215, 47, 208, 209, 162, 59 -// ] +// Uint8Array(64) [...] let accountFromSecret = Keypair.fromSecretKey(account.secretKey); @@ -193,44 +167,32 @@ console.log(accountFromSecret.publicKey.toBase58()); console.log(accountFromSecret.secretKey); // 2DVaHtcdTf7cm18Zm9VV8rKK4oSnjmTkKE6MiXe18Qsb -// Uint8Array(64) [ -// 152, 43, 116, 211, 207, 41, 220, 33, 193, 168, 118, -// 24, 176, 83, 206, 132, 47, 194, 2, 203, 186, 131, -// 197, 228, 156, 170, 154, 41, 56, 76, 159, 124, 18, -// 14, 247, 32, 210, 51, 102, 41, 43, 21, 12, 170, -// 166, 210, 195, 188, 60, 220, 210, 96, 136, 158, 6, -// 205, 189, 165, 112, 32, 200, 116, 164, 234 -// ] +// Uint8Array(64) [...] ``` -Using `generate` generates a random Keypair for use as an account on Solana. -Using `fromSeed`, you can generate a Keypair using a deterministic constructor. -`fromSecret` creates a Keypair from a secret Uint8array. You can see that the -publicKey for the `generate` Keypair and `fromSecret` Keypair are the same -because the secret from the `generate` Keypair is used in `fromSecret`. +Використання `generate` генерує випадкову Keypair для облікового запису на Solana. Використання `fromSeed` дозволяє створити Keypair з детермінованим конструктором. `fromSecret` створює Keypair із секретного масиву Uint8Array. Ви можете побачити, що publicKey для Keypair, створеної за допомогою `generate`, і `fromSecret` однакові, оскільки секретний ключ однаковий. +### Використання `generate` створює випадкову пару ключів для використання як обліковий запис у Solana. +Використання `fromSeed` дозволяє створити пару ключів за допомогою детермінованого конструктора. +`fromSecret` створює пару ключів із секретного масиву Uint8Array. Ви можете побачити, що publicKey для пари ключів `generate` і `fromSecret` є однаковими, оскільки секрет від пари ключів `generate` використовується в `fromSecret`. -**Warning**: Do not use `fromSeed` unless you are creating a seed with high -entropy. Do not share your seed. Treat the seed like you would a private key. +**Попередження**: Не використовуйте `fromSeed`, якщо ви не створюєте seed із високою ентропією. Не розголошуйте ваш seed. Ставтеся до seed так само, як до приватного ключа. ### PublicKey -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/PublicKey.html) +[Джерело документації](https://solana-labs.github.io/solana-web3.js/v1.x/classes/PublicKey.html) -PublicKey is used throughout `@solana/web3.js` in transactions, keypairs, and -programs. You require publickey when listing each account in a transaction and -as a general identifier on Solana. +`PublicKey` використовується в `@solana/web3.js` для транзакцій, пар ключів і програм. Вам потрібен publicKey при зазначенні кожного облікового запису в транзакції, а також як загальний ідентифікатор у Solana. -A PublicKey can be created with a base58 encoded string, buffer, Uint8Array, -number, and an array of numbers. +`PublicKey` можна створити за допомогою base58-строки, буфера, Uint8Array, числа або масиву чисел. -#### Example Usage +#### Приклад використання ```javascript const { Buffer } = require("buffer"); const web3 = require("@solana/web3.js"); const crypto = require("crypto"); -// Create a PublicKey with a base58 encoded string +// Створення PublicKey з base58-строки let base58publicKey = new web3.PublicKey( "5xot9PVkphiX2adznghwrAuxGs2zeWisNSxMW6hU6Hkj", ); @@ -238,41 +200,38 @@ console.log(base58publicKey.toBase58()); // 5xot9PVkphiX2adznghwrAuxGs2zeWisNSxMW6hU6Hkj -// Create a Program Address +// Створення програмної адреси let highEntropyBuffer = crypto.randomBytes(31); let programAddressFromKey = await web3.PublicKey.createProgramAddress( [highEntropyBuffer.slice(0, 31)], base58publicKey, ); -console.log(`Generated Program Address: ${programAddressFromKey.toBase58()}`); +console.log(`Згенерована програмна адреса: ${programAddressFromKey.toBase58()}`); -// Generated Program Address: 3thxPEEz4EDWHNxo1LpEpsAxZryPAHyvNVXJEJWgBgwJ +// Згенерована програмна адреса: 3thxPEEz4EDWHNxo1LpEpsAxZryPAHyvNVXJEJWgBgwJ -// Find Program address given a PublicKey +// Знаходження програмної адреси за PublicKey let validProgramAddress = await web3.PublicKey.findProgramAddress( [Buffer.from("", "utf8")], programAddressFromKey, ); -console.log(`Valid Program Address: ${validProgramAddress}`); +console.log(`Дійсна програмна адреса: ${validProgramAddress}`); -// Valid Program Address: C14Gs3oyeXbASzwUpqSymCKpEyccfEuSe8VRar9vJQRE,253 +// Дійсна програмна адреса: C14Gs3oyeXbASzwUpqSymCKpEyccfEuSe8VRar9vJQRE,253 ``` ### SystemProgram -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/SystemProgram.html) +[Джерело документації](https://solana-labs.github.io/solana-web3.js/v1.x/classes/SystemProgram.html) -The SystemProgram grants the ability to create accounts, allocate account data, -assign an account to programs, work with nonce accounts, and transfer lamports. -You can use the SystemInstruction class to help with decoding and reading -individual instructions +`SystemProgram` дозволяє створювати облікові записи, виділяти дані облікових записів, призначати облікові записи програмам, працювати з nonce-обліковими записами та переводити лампорти. Ви можете використовувати клас `SystemInstruction` для декодування та читання окремих інструкцій. -#### Example Usage +#### Приклад використання ```javascript const web3 = require("@solana/web3.js"); -// Airdrop SOL for paying transactions +// Запит SOL для оплати транзакцій let payer = web3.Keypair.generate(); let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); @@ -283,7 +242,7 @@ let airdropSignature = await connection.requestAirdrop( await connection.confirmTransaction({ signature: airdropSignature }); -// Allocate Account Data +// Виділення даних облікового запису let allocatedAccount = web3.Keypair.generate(); let allocateInstruction = web3.SystemProgram.allocate({ accountPubkey: allocatedAccount.publicKey, @@ -296,7 +255,7 @@ await web3.sendAndConfirmTransaction(connection, transaction, [ allocatedAccount, ]); -// Create Nonce Account +// Створення nonce-облікового запису let nonceAccount = web3.Keypair.generate(); let minimumAmountForNonceAccount = await connection.getMinimumBalanceForRentExemption(web3.NONCE_ACCOUNT_LENGTH); @@ -315,7 +274,7 @@ await web3.sendAndConfirmTransaction( [payer, nonceAccount], ); -// Advance nonce - Used to create transactions as an account custodian +// Переведення nonce - використовується для створення транзакцій як зберігач облікового запису let advanceNonceTransaction = new web3.Transaction().add( web3.SystemProgram.nonceAdvance({ noncePubkey: nonceAccount.publicKey, @@ -327,7 +286,7 @@ await web3.sendAndConfirmTransaction(connection, advanceNonceTransaction, [ payer, ]); -// Transfer lamports between accounts +// Переведення лампортів між обліковими записами let toAccount = web3.Keypair.generate(); let transferTransaction = new web3.Transaction().add( @@ -339,7 +298,7 @@ let transferTransaction = new web3.Transaction().add( ); await web3.sendAndConfirmTransaction(connection, transferTransaction, [payer]); -// Assign a new account to a program +// Призначення нового облікового запису програмі let programId = web3.Keypair.generate(); let assignedAccount = web3.Keypair.generate(); @@ -354,23 +313,22 @@ await web3.sendAndConfirmTransaction(connection, assignTransaction, [ payer, assignedAccount, ]); -``` +``` ### Secp256k1Program -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Secp256k1Program.html) +[Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Secp256k1Program.html) -The Secp256k1Program is used to verify Secp256k1 signatures, which are used by -both Bitcoin and Ethereum. +`Secp256k1Program` використовується для перевірки підписів `Secp256k1`, які використовуються як у Bitcoin, так і в Ethereum. -#### Example Usage +#### Приклад Використання ```javascript const { keccak_256 } = require("js-sha3"); const web3 = require("@solana/web3.js"); const secp256k1 = require("secp256k1"); -// Create a Ethereum Address from secp256k1 +// Створення Ethereum адреси з secp256k1 let secp256k1PrivateKey; do { secp256k1PrivateKey = web3.Keypair.generate().secretKey.slice(0, 32); @@ -386,7 +344,7 @@ console.log(`Ethereum Address: 0x${ethAddress.toString("hex")}`); // Ethereum Address: 0xadbf43eec40694eacf36e34bb5337fba6a2aa8ee -// Fund a keypair to create instructions +// Фінансування облікового запису для створення інструкцій let fromPublicKey = web3.Keypair.generate(); let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); @@ -397,7 +355,7 @@ let airdropSignature = await connection.requestAirdrop( await connection.confirmTransaction({ signature: airdropSignature }); -// Sign Message with Ethereum Key +// Підписування повідомлення з ключем Ethereum let plaintext = Buffer.from("string address"); let plaintextHash = Buffer.from(keccak_256.update(plaintext).digest()); let { signature, recid: recoveryId } = secp256k1.ecdsaSign( @@ -405,7 +363,7 @@ let { signature, recid: recoveryId } = secp256k1.ecdsaSign( secp256k1PrivateKey, ); -// Create transaction to verify the signature +// Створення транзакції для перевірки підпису let transaction = new Transaction().add( web3.Secp256k1Program.createInstructionWithEthAddress({ ethAddress: ethAddress.toString("hex"), @@ -415,21 +373,17 @@ let transaction = new Transaction().add( }), ); -// Transaction will succeed if the message is verified to be signed by the address +// Транзакція буде успішною, якщо повідомлення підтверджено, що його підписано цією адресою await web3.sendAndConfirmTransaction(connection, transaction, [fromPublicKey]); ``` ### Message -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Message.html) +[Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Message.html) -Message is used as another way to construct transactions. You can construct a -message using the accounts, header, instructions, and recentBlockhash that are a -part of a transaction. A [Transaction](/docs/clients/javascript.md#Transaction) -is a Message plus the list of required signatures required to execute the -transaction. +`Message` використовується як альтернативний спосіб створення транзакцій. Ви можете створити повідомлення за допомогою облікових записів, заголовка, інструкцій та недавнього блочного хеша, які є частиною транзакції. [Transaction](/docs/clients/javascript.md#Transaction) є `Message` плюс список необхідних підписів для виконання транзакції. -#### Example Usage +#### Приклад Використання ```javascript const { Buffer } = require("buffer"); @@ -487,14 +441,13 @@ await web3.sendAndConfirmTransaction(connection, transaction, [fromPublicKey]); ### Struct -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Struct.html) +[Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Struct.html) -The struct class is used to create Rust compatible structs in javascript. This -class is only compatible with Borsh encoded Rust structs. +Клас `Struct` використовується для створення структур, сумісних із Rust, у JavaScript. Цей клас сумісний лише з Rust-структурами, закодованими за допомогою Borsh. -#### Example Usage +#### Приклад Використання -Struct in Rust: +Структура в Rust: ```rust pub struct Fee { @@ -503,7 +456,7 @@ pub struct Fee { } ``` -Using web3: +Використання з web3: ```javascript import BN from "bn.js"; @@ -517,15 +470,11 @@ export class Fee extends Struct { ### Enum -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Enum.html) +[Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Enum.html) -The Enum class is used to represent a Rust compatible Enum in javascript. The -enum will just be a string representation if logged but can be properly -encoded/decoded when used in conjunction with -[Struct](/docs/clients/javascript.md#Struct). This class is only compatible with -Borsh encoded Rust enumerations. +Клас `Enum` використовується для представлення сумісного з Rust енумератора у JavaScript. Енумератор буде представлений як строка при логуванні, але може бути правильно закодований/декодований при використанні разом з [Struct](/docs/clients/javascript.md#Struct). Цей клас сумісний лише з Rust-енумераторами, закодованими за допомогою Borsh. -#### Example Usage +#### Приклад Використання Rust: @@ -547,29 +496,25 @@ export class AccountType extends Enum {} ### NonceAccount -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/NonceAccount.html) +[Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/NonceAccount.html) -Normally a transaction is rejected if a transaction's `recentBlockhash` field is -too old. To provide for certain custodial services, Nonce Accounts are used. -Transactions which use a `recentBlockhash` captured on-chain by a Nonce Account -do not expire as long at the Nonce Account is not advanced. +Зазвичай транзакція відхиляється, якщо поле `recentBlockhash` транзакції є застарілим. Для забезпечення певних кастодіальних послуг використовуються облікові записи `NonceAccount`. Транзакції, які використовують `recentBlockhash`, зафіксовані на блокчейні обліковим записом `NonceAccount`, не старіють доти, доки цей обліковий запис не буде оновлено. -You can create a nonce account by first creating a normal account, then using -`SystemProgram` to make the account a Nonce Account. +Ви можете створити `NonceAccount`, спочатку створивши звичайний обліковий запис, а потім використовуючи `SystemProgram`, щоб зробити цей обліковий запис `NonceAccount`. -#### Example Usage +#### Приклад Використання ```javascript const web3 = require("@solana/web3.js"); -// Create connection +// Створення з'єднання let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); -// Generate accounts +// Генерація облікових записів let account = web3.Keypair.generate(); let nonceAccount = web3.Keypair.generate(); -// Fund account +// Фінансування облікового запису let airdropSignature = await connection.requestAirdrop( account.publicKey, web3.LAMPORTS_PER_SOL, @@ -577,12 +522,12 @@ let airdropSignature = await connection.requestAirdrop( await connection.confirmTransaction({ signature: airdropSignature }); -// Get Minimum amount for rent exemption +// Отримання мінімальної суми для звільнення від оренди let minimumAmount = await connection.getMinimumBalanceForRentExemption( web3.NONCE_ACCOUNT_LENGTH, ); -// Form CreateNonceAccount transaction +// Формування транзакції CreateNonceAccount let transaction = new web3.Transaction().add( web3.SystemProgram.createNonceAccount({ fromPubkey: account.publicKey, @@ -591,7 +536,7 @@ let transaction = new web3.Transaction().add( lamports: minimumAmount, }), ); -// Create Nonce Account +// Створення Nonce Account await web3.sendAndConfirmTransaction(connection, transaction, [ account, nonceAccount, @@ -630,19 +575,15 @@ console.log(nonceAccountFromInfo); // } ``` -The above example shows both how to create a `NonceAccount` using -`SystemProgram.createNonceAccount`, as well as how to retrieve the -`NonceAccount` from accountInfo. Using the nonce, you can create transactions -offline with the nonce in place of the `recentBlockhash`. +Наведений вище приклад показує як створити `NonceAccount` за допомогою `SystemProgram.createNonceAccount`, а також як отримати `NonceAccount` з accountInfo. Використовуючи nonce, ви можете створювати транзакції офлайн з nonce замість `recentBlockhash`. ### VoteAccount -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/VoteAccount.html) +[Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/VoteAccount.html) -Vote account is an object that grants the capability of decoding vote accounts -from the native vote account program on the network. +`VoteAccount` — це об'єкт, який дозволяє декодувати облікові записи для голосування з використанням нативної програми голосування в мережі. -#### Example Usage +#### Приклад Використання ```javascript const web3 = require("@solana/web3.js"); @@ -685,7 +626,6 @@ VoteAccount { [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], - [Object], [Object], [Object], [Object], [Object] ], epochCredits: [ @@ -711,20 +651,16 @@ VoteAccount { ### StakeProgram -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/StakeProgram.html) +[Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/StakeProgram.html) -The StakeProgram facilitates staking SOL and delegating them to any validators -on the network. You can use StakeProgram to create a stake account, stake some -SOL, authorize accounts for withdrawal of your stake, deactivate your stake, and -withdraw your funds. The StakeInstruction class is used to decode and read more -instructions from transactions calling the StakeProgram +`StakeProgram` полегшує процес стейкінгу SOL і делегування їх будь-яким валідаторам у мережі. Ви можете використовувати `StakeProgram`, щоб створити стейк-обліковий запис, застейкати SOL, авторизувати облікові записи для виведення стейка, деактивувати стейк і вивести кошти. Клас `StakeInstruction` використовується для декодування та читання додаткових інструкцій з транзакцій, що викликають `StakeProgram`. -#### Example Usage +#### Приклад Використання ```javascript const web3 = require("@solana/web3.js"); -// Fund a key to create transactions +// Фінансування ключа для створення транзакцій let fromPublicKey = web3.Keypair.generate(); let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed"); @@ -734,11 +670,11 @@ let airdropSignature = await connection.requestAirdrop( ); await connection.confirmTransaction({ signature: airdropSignature }); -// Create Account +// Створення облікового запису let stakeAccount = web3.Keypair.generate(); let authorizedAccount = web3.Keypair.generate(); -/* Note: This is the minimum amount for a stake account -- Add additional Lamports for staking - For example, we add 50 lamports as part of the stake */ +/* Примітка: Це мінімальна сума для стейк-облікового запису — Додайте додаткові лампорти для стейкінгу + Наприклад, ми додаємо 50 лампорт як частину стейка */ let lamportsForStakeAccount = (await connection.getMinimumBalanceForRentExemption( web3.StakeProgram.space, @@ -759,22 +695,22 @@ await web3.sendAndConfirmTransaction(connection, createAccountTransaction, [ stakeAccount, ]); -// Check that stake is available +// Перевірка доступності стейка let stakeBalance = await connection.getBalance(stakeAccount.publicKey); console.log(`Stake balance: ${stakeBalance}`); // Stake balance: 2282930 -// We can verify the state of our stake. This may take some time to become active +// Ми можемо перевірити стан нашого стейка. Це може зайняти деякий час, щоб активуватись let stakeState = await connection.getStakeActivation(stakeAccount.publicKey); console.log(`Stake state: ${stakeState.state}`); // Stake state: inactive -// To delegate our stake, we get the current vote accounts and choose the first +// Щоб делегувати наш стейк, ми отримуємо поточні облікові записи голосування та вибираємо перший let voteAccounts = await connection.getVoteAccounts(); let voteAccount = voteAccounts.current.concat(voteAccounts.delinquent)[0]; let votePubkey = new web3.PublicKey(voteAccount.votePubkey); -// We can then delegate our stake to the voteAccount +// Тепер ми можемо делегувати наш стейк до облікового запису голосування let delegateTransaction = web3.StakeProgram.delegate({ stakePubkey: stakeAccount.publicKey, authorizedPubkey: authorizedAccount.publicKey, @@ -785,7 +721,7 @@ await web3.sendAndConfirmTransaction(connection, delegateTransaction, [ authorizedAccount, ]); -// To withdraw our funds, we first have to deactivate the stake +// Щоб вивести наші кошти, ми спочатку повинні деактивувати стейк let deactivateTransaction = web3.StakeProgram.deactivate({ stakePubkey: stakeAccount.publicKey, authorizedPubkey: authorizedAccount.publicKey, @@ -795,7 +731,7 @@ await web3.sendAndConfirmTransaction(connection, deactivateTransaction, [ authorizedAccount, ]); -// Once deactivated, we can withdraw our funds +// Після деактивації ми можемо вивести наші кошти let withdrawTransaction = web3.StakeProgram.withdraw({ stakePubkey: stakeAccount.publicKey, authorizedPubkey: authorizedAccount.publicKey, @@ -811,26 +747,19 @@ await web3.sendAndConfirmTransaction(connection, withdrawTransaction, [ ### Authorized -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Authorized.html) +[Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Authorized.html) -Authorized is an object used when creating an authorized account for staking -within Solana. You can designate a `staker` and `withdrawer` separately, -allowing for a different account to withdraw other than the staker. +`Authorized` — це об'єкт, який використовується під час створення авторизованого облікового запису для стейкінгу в Solana. Ви можете окремо призначити `staker` і `withdrawer`, що дозволяє іншому обліковому запису виводити кошти, ніж той, що виконує стейкінг. -You can find more usage of the `Authorized` object under -[`StakeProgram`](/docs/clients/javascript.md#StakeProgram) +Більше прикладів використання об'єкта `Authorized` ви можете знайти в розділі [`StakeProgram`](/docs/clients/javascript.md#StakeProgram). ### Lockup -[Source Documentation](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Lockup.html) +[Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Lockup.html) -Lockup is used in conjunction with the -[StakeProgram](/docs/clients/javascript.md#StakeProgram) to create an account. -The Lockup is used to determine how long the stake will be locked, or unable to -be retrieved. If the Lockup is set to 0 for both epoch and the Unix timestamp, -the lockup will be disabled for the stake account. +`Lockup` використовується разом із [StakeProgram](/docs/clients/javascript.md#StakeProgram) для створення облікового запису. `Lockup` визначає, як довго стейк буде заблокований або недоступний для вилучення. Якщо `Lockup` встановлений на 0 як для епохи, так і для мітки часу Unix, блокування для облікового запису буде відключено. -#### Example Usage +#### Приклад Використання ```javascript const { @@ -854,8 +783,7 @@ let createStakeAccountInstruction = StakeProgram.createAccount({ }); ``` -The above code creates a `createStakeAccountInstruction` to be used when -creating an account with the `StakeProgram`. The Lockup is set to 0 for both the -epoch and Unix timestamp, disabling lockup for the account. +Наведений вище код створює `createStakeAccountInstruction`, який використовується для створення облікового запису за допомогою `StakeProgram`. Блокування встановлено на 0 як для епохи, так і для мітки часу Unix, що відключає блокування для облікового запису. + +Детальніше див. у розділі [StakeProgram](/docs/clients/javascript.md#StakeProgram). -See [StakeProgram](/docs/clients/javascript.md#StakeProgram) for more. diff --git a/docs/uk/clients/javascript.md b/docs/uk/clients/javascript.md index 6d4932896..790d6f6ef 100644 --- a/docs/uk/clients/javascript.md +++ b/docs/uk/clients/javascript.md @@ -1,35 +1,34 @@ --- sidebarLabel: JavaScript / TypeScript -title: JavaScript Client for Solana +title: JavaScript Клієнт для Solana sidebarSortOrder: 2 description: - Learn how to interact with Solana using the JavaScript/TypeScript client - library (@solana/web3.js). This guide covers wallet connections, transactions, - and custom program interactions with code examples. + Дізнайтеся, як взаємодіяти з Solana за допомогою клієнтської бібліотеки + JavaScript/TypeScript (@solana/web3.js). У цьому посібнику розглядаються підключення гаманця, транзакції та взаємодія з власними програмами з прикладами коду. --- -## What is Solana-Web3.js? +## Що таке Solana-Web3.js? -The Solana-Web3.js library aims to provide complete coverage of Solana. The -library was built on top of the [Solana JSON RPC API](/docs/rpc). +Бібліотека Solana-Web3.js створена для забезпечення повного охоплення Solana. Ця +бібліотека побудована на основі [Solana JSON RPC API](/docs/rpc). -You can find the full documentation for the `@solana/web3.js` library -[here](https://solana-labs.github.io/solana-web3.js/v1.x/). +Повну документацію для бібліотеки `@solana/web3.js` можна знайти +[тут](https://solana-labs.github.io/solana-web3.js/v1.x/). -## Common Terminology +## Загальна термінологія -| Term | Definition | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Program | Stateless executable code written to interpret instructions. Programs are capable of performing actions based on the instructions provided. | -| Instruction | The smallest unit of a program that a client can include in a transaction. Within its processing code, an instruction may contain one or more cross-program invocations. | -| Transaction | One or more instructions signed by the client using one or more Keypairs and executed atomically with only two possible outcomes: success or failure. | +| Термін | Визначення | +| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Програма | Безстанова виконувана програма, написана для інтерпретації інструкцій. Програми можуть виконувати дії на основі наданих інструкцій. | +| Інструкція | Найменша одиниця програми, яку клієнт може включити в транзакцію. Під час виконання коду інструкція може містити одну або кілька міжпрограмних викликів. | +| Транзакція | Одна або кілька інструкцій, підписаних клієнтом за допомогою одного або кількох Keypair, і виконуються атомарно з двома можливими результатами: успіх або невдача. | -For the full list of terms, see -[Solana terminology](/docs/terminology.md#cross-program-invocation-cpi) +Для повного списку термінів дивіться +[Термінологія Solana](/docs/terminology.md#cross-program-invocation-cpi) -## Getting Started +## Початок роботи -### Installation +### Встановлення #### yarn @@ -43,17 +42,17 @@ yarn add @solana/web3.js@1 npm install --save @solana/web3.js@1 ``` -#### Bundle +#### Пакет ```html - + - + ``` -### Usage +### Використання #### Javascript @@ -69,27 +68,25 @@ import * as solanaWeb3 from "@solana/web3.js"; console.log(solanaWeb3); ``` -#### Browser Bundle +#### Пакет для браузера ```javascript -// solanaWeb3 is provided in the global namespace by the bundle script +// solanaWeb3 надається в глобальному просторі імен за допомогою скрипта пакета console.log(solanaWeb3); ``` -## Quickstart +## Швидкий старт -### Connecting to a Wallet +### Підключення до гаманця -To allow users to use your dApp or application on Solana, they will need to get -access to their Keypair. A Keypair is a private key with a matching public key, -used to sign transactions. +Щоб користувачі могли використовувати ваш dApp або додаток у Solana, їм потрібно отримати доступ до свого Keypair. Keypair - це приватний ключ з відповідним відкритим ключем, який використовується для підпису транзакцій. -There are two ways to obtain a Keypair: +Є два способи отримати Keypair: -1. Generate a new Keypair -2. Obtain a Keypair using the secret key +1. Генерація нового Keypair +2. Отримання Keypair за допомогою секретного ключа -You can obtain a new Keypair with the following: +Ви можете отримати новий Keypair наступним чином: ```javascript const { Keypair } = require("@solana/web3.js"); @@ -97,11 +94,9 @@ const { Keypair } = require("@solana/web3.js"); let keypair = Keypair.generate(); ``` -This will generate a brand new Keypair for a user to fund and use within your -application. +Це згенерує новий Keypair для користувача, який можна використовувати у вашому додатку. -You can allow entry of the secretKey using a textbox, and obtain the Keypair -with `Keypair.fromSecretKey(secretKey)`. +Ви можете дозволити введення secretKey через текстове поле та отримати Keypair за допомогою `Keypair.fromSecretKey(secretKey)`. ```javascript const { Keypair } = require("@solana/web3.js"); @@ -116,25 +111,16 @@ let secretKey = Uint8Array.from([ let keypair = Keypair.fromSecretKey(secretKey); ``` -Many wallets today allow users to bring their Keypair using a variety of -extensions or web wallets. The general recommendation is to use wallets, not -Keypairs, to sign transactions. The wallet creates a layer of separation between -the dApp and the Keypair, ensuring that the dApp never has access to the secret -key. You can find ways to connect to external wallets with the -[wallet-adapter](https://github.com/solana-labs/wallet-adapter) library. +Багато гаманців сьогодні дозволяють користувачам імпортувати свій Keypair за допомогою різних розширень або веб-гаманців. Загальна рекомендація - використовувати гаманці, а не Keypair, для підпису транзакцій. Гаманець створює шар розділення між dApp та Keypair, забезпечуючи, що dApp ніколи не має доступу до секретного ключа. Ви можете знайти способи підключення до зовнішніх гаманців за допомогою бібліотеки [wallet-adapter](https://github.com/solana-labs/wallet-adapter). -### Creating and Sending Transactions +### Створення та відправка транзакцій -To interact with programs on Solana, you create, sign, and send transactions to -the network. Transactions are collections of instructions with signatures. The -order that instructions exist in a transaction determines the order they are -executed. +Щоб взаємодіяти з програмами на Solana, ви створюєте, підписуєте та відправляєте транзакції до мережі. Транзакції - це колекції інструкцій з підписами. Порядок, в якому інструкції існують у транзакції, визначає порядок їх виконання. -A transaction in Solana-Web3.js is created using the -[`Transaction`](/docs/clients/javascript.md#Transaction) object and adding -desired messages, addresses, or instructions. +Транзакція в Solana-Web3.js створюється за допомогою +об'єкта [`Transaction`](/docs/clients/javascript.md#Transaction) і додавання бажаних повідомлень, адрес або інструкцій. -Take the example of a transfer transaction: +Приклад транзакції передачі: ```javascript const { @@ -157,16 +143,9 @@ transaction.add( ); ``` -The above code achieves creating a transaction ready to be signed and -broadcasted to the network. The `SystemProgram.transfer` instruction was added -to the transaction, containing the amount of lamports to send, and the `to` and -`from` public keys. +Вищенаведений код створює транзакцію, готову до підпису та передачі в мережу. Інструкція `SystemProgram.transfer` була додана до транзакції, що містить суму lamports для відправки, а також публічні ключі `to` і `from`. -All that is left is to sign the transaction with keypair and send it over the -network. You can accomplish sending a transaction by using -`sendAndConfirmTransaction` if you wish to alert the user or do something after -a transaction is finished, or use `sendTransaction` if you don't need to wait -for the transaction to be confirmed. +Все, що залишилося зробити - підписати транзакцію за допомогою Keypair і відправити її через мережу. Ви можете виконати відправку транзакції за допомогою `sendAndConfirmTransaction`, якщо хочете сповістити користувача або зробити щось після завершення транзакції, або використовувати `sendTransaction`, якщо не потрібно чекати підтвердження транзакції. ```javascript const { @@ -181,20 +160,13 @@ let connection = new Connection(clusterApiUrl("testnet")); sendAndConfirmTransaction(connection, transaction, [keypair]); ``` -The above code takes in a `TransactionInstruction` using `SystemProgram`, -creates a `Transaction`, and sends it over the network. You use `Connection` in -order to define which Solana network you are connecting to, namely -`mainnet-beta`, `testnet`, or `devnet`. +Вищенаведений код приймає `TransactionInstruction` за допомогою `SystemProgram`, створює `Transaction` і відправляє її через мережу. Ви використовуєте `Connection`, щоб визначити, до якої мережі Solana ви підключаєтесь, а саме `mainnet-beta`, `testnet` або `devnet`. -### Interacting with Custom Programs +### Взаємодія з власними програмами -The previous section visits sending basic transactions. In Solana everything you -do interacts with different programs, including the previous section's transfer -transaction. At the time of writing programs on Solana are either written in -Rust or C. +Попередній розділ розглядає відправлення базових транзакцій. У Solana все, що ви робите, взаємодіє з різними програмами, включаючи транзакцію передачі в попередньому розділі. На момент написання програми на Solana пишуться на Rust або C. -Let's look at the `SystemProgram`. The method signature for allocating space in -your account on Solana in Rust looks like this: +Розглянемо `SystemProgram`. Сигнатура методу для виділення простору в вашому обліковому записі в Solana на Rust виглядає так: ```rust pub fn allocate( @@ -203,21 +175,13 @@ pub fn allocate( ) -> Instruction ``` -In Solana when you want to interact with a program you must first know all the -accounts you will be interacting with. +У Solana, коли ви хочете взаємодіяти з програмою, ви повинні спочатку знати всі облікові записи, з якими програма буде взаємодіяти. -You must always provide every account that the program will be interacting -within the instruction. Not only that, but you must provide whether or not the -account is `isSigner` or `isWritable`. +Ви завжди повинні надавати кожен обліковий запис, з яким програма буде взаємодіяти в інструкції. Крім того, ви повинні вказати, чи є обліковий запис `isSigner` або `isWritable`. -In the `allocate` method above, a single account `pubkey` is required, as well -as an amount of `space` for allocation. We know that the `allocate` method -writes to the account by allocating space within it, making the `pubkey` -required to be `isWritable`. `isSigner` is required when you are designating the -account that is running the instruction. In this case, the signer is the account -calling to allocate space within itself. +У методі `allocate` вище потрібен один обліковий запис `pubkey`, а також кількість `space` для виділення. Ми знаємо, що метод `allocate` записує в обліковий запис, виділяючи в ньому простір, роблячи `pubkey` обов'язковим `isWritable`. `isSigner` потрібен, коли ви вказуєте обліковий запис, який виконує інструкцію. У цьому випадку підписувач - це обліковий запис, який викликає виділення простору в собі. -Let's look at how to call this instruction using solana-web3.js: +Давайте подивимося, як викликати цю інструкцію за допомогою solana-web3.js: ```javascript let keypair = web3.Keypair.generate(); @@ -232,9 +196,7 @@ let airdropSignature = await connection.requestAirdrop( await connection.confirmTransaction({ signature: airdropSignature }); ``` -First, we set up the account Keypair and connection so that we have an account -to make allocate on the testnet. We also create a payer Keypair and airdrop some -SOL so we can pay for the allocate transaction. +Спочатку ми налаштовуємо Keypair і підключення, щоб у нас був обліковий запис для виділення на тестовій мережі. Ми також створюємо Keypair для платника і додаємо трохи SOL, щоб оплатити транзакцію виділення. ```javascript let allocateTransaction = new web3.Transaction({ @@ -244,12 +206,7 @@ let keys = [{ pubkey: keypair.publicKey, isSigner: true, isWritable: true }]; let params = { space: 100 }; ``` -We create the transaction `allocateTransaction`, keys, and params objects. -`feePayer` is an optional field when creating a transaction that specifies who -is paying for the transaction, defaulting to the pubkey of the first signer in -the transaction. `keys` represents all accounts that the program's `allocate` -function will interact with. Since the `allocate` function also required space, -we created `params` to be used later when invoking the `allocate` function. +Ми створюємо транзакцію `allocateTransaction`, об'єкти keys та params. Поле `feePayer` є необов'язковим при створенні транзакції, воно вказує, хто оплачує транзакцію, за замовчуванням використовується pubkey першого підписувача в транзакції. `keys` представляє всі облікові записи, з якими функція програми `allocate` буде взаємодіяти. Оскільки функція `allocate` також вимагає простору, ми створили `params`, щоб його використати пізніше при виклику функції `allocate`. ```javascript let allocateStruct = { @@ -258,13 +215,9 @@ let allocateStruct = { }; ``` -The above is created using `u32` and `ns64` from `@solana/buffer-layout` to -facilitate the payload creation. The `allocate` function takes in the parameter -`space`. To interact with the function we must provide the data as a Buffer -format. The `buffer-layout` library helps with allocating the buffer and -encoding it correctly for Rust programs on Solana to interpret. +Це створено за допомогою `u32` і `ns64` з `@solana/buffer-layout` для створення payload. Функція `allocate` приймає параметр `space`. Щоб взаємодіяти з функцією, ми повинні надати дані у форматі Buffer. Бібліотека `buffer-layout` допомагає з виділенням буфера та його правильним кодуванням для інтерпретації програмами на Rust в Solana. -Let's break down this struct. +Давайте розглянемо цю структуру детальніше. ```javascript { @@ -276,8 +229,7 @@ Let's break down this struct. } ``` -`index` is set to 8 because the function `allocate` is in the 8th position in -the instruction enum for `SystemProgram`. +`index` встановлений у 8, тому що функція `allocate` знаходиться на 8-й позиції у enum інструкцій для `SystemProgram`. ```rust /* https://github.com/solana-labs/solana/blob/21bc43ed58c63c827ba4db30426965ef3e807180/sdk/program/src/system_instruction.rs#L142-L305 */ @@ -298,7 +250,7 @@ pub enum SystemInstruction { } ``` -Next up is `u32('instruction')`. +Далі `u32('instruction')`. ```javascript { @@ -310,8 +262,8 @@ Next up is `u32('instruction')`. } ``` -The `layout` in the allocate struct must always have `u32('instruction')` first -when you are using it to call an instruction. +`layout` у структурі allocate завжди має мати `u32('instruction')` першим +при використанні для виклику інструкції. ```javascript { @@ -323,12 +275,7 @@ when you are using it to call an instruction. } ``` -`ns64('space')` is the argument for the `allocate` function. You can see in the -original `allocate` function in Rust that space was of the type `u64`. `u64` is -an unsigned 64bit integer. Javascript by default only provides up to 53bit -integers. `ns64` comes from `@solana/buffer-layout` to help with type -conversions between Rust and Javascript. You can find more type conversions -between Rust and Javascript at +`ns64('space')` - це аргумент для функції `allocate`. Ви можете бачити, що в оригінальній функції `allocate` на Rust, space мав тип `u64`. `u64` є 64-бітовим unsigned integer. У Javascript за замовчуванням підтримуються тільки 53-бітові числа. `ns64` з `@solana/buffer-layout` допомагає з конвертацією типів між Rust і Javascript. Ви можете знайти більше конвертацій типів між Rust і Javascript на [solana-labs/buffer-layout](https://github.com/solana-labs/buffer-layout). ```javascript @@ -337,10 +284,7 @@ let layoutFields = Object.assign({ instruction: allocateStruct.index }, params); allocateStruct.layout.encode(layoutFields, data); ``` -Using the previously created bufferLayout, we can allocate a data buffer. We -then assign our params `{ space: 100 }` so that it maps correctly to the layout, -and encode it to the data buffer. Now the data is ready to be sent to the -program. +Використовуючи створений раніше bufferLayout, ми можемо виділити буфер даних. Потім ми присвоюємо наші params `{ space: 100 }`, щоб вони правильно відповідали макету, і кодуємо їх у буфер даних. Тепер дані готові для відправлення до програми. ```javascript allocateTransaction.add( @@ -357,10 +301,9 @@ await web3.sendAndConfirmTransaction(connection, allocateTransaction, [ ]); ``` -Finally, we add the transaction instruction with all the account keys, payer, -data, and programId and broadcast the transaction to the network. +Нарешті, ми додаємо інструкцію транзакції з усіма ключами облікових записів, платником, даними та programId і передаємо транзакцію до мережі. -The full code can be found below. +Повний код можна знайти нижче. ```javascript const { struct, u32, ns64 } = require("@solana/buffer-layout"); diff --git a/docs/uk/clients/rust.md b/docs/uk/clients/rust.md index 7dd221995..5a15b1f78 100644 --- a/docs/uk/clients/rust.md +++ b/docs/uk/clients/rust.md @@ -1,49 +1,44 @@ --- sidebarLabel: Rust -title: Rust Client for Solana +title: Rust Клієнт для Solana sidebarSortOrder: 1 -description: Learn how to use Solana's Rust crates for development. +description: Дізнайтеся, як використовувати Rust пакети для розробки в Solana. --- -Solana's Rust crates are -[published to crates.io](https://crates.io/search?q=solana-) and can be found -[on docs.rs](https://docs.rs/releases/search?query=solana-) with the `solana-` -prefix. +Rust пакети для Solana +[опубліковані на crates.io](https://crates.io/search?q=solana-) і доступні на +[docs.rs](https://docs.rs/releases/search?query=solana-) з префіксом `solana-`. - + -To quickly get started with Solana development and build your first Rust -program, take a look at these detailed quick start guides: +Щоб швидко почати розробку в Solana і створити вашу першу програму на Rust, +ознайомтеся з цими детальними посібниками для швидкого старту: -- [Build and deploy your first Solana program using only your browser](/content/guides/getstarted/hello-world-in-your-browser.md). - No installation needed. -- [Setup your local environment](/docs/intro/installation) and use the local - test validator. +- [Створіть і розгорніть вашу першу програму Solana, використовуючи тільки ваш браузер](/content/guides/getstarted/hello-world-in-your-browser.md). + Інсталяція не потрібна. +- [Налаштуйте ваше локальне середовище](/docs/intro/installation) і використовуйте локальний тестовий валідатор. -## Rust Crates +## Rust Пакети -The following are the most important and commonly used Rust crates for Solana -development: +Нижче наведено найважливіші та найчастіше використовувані Rust пакети для розробки в Solana: -- [`solana-program`] — Imported by programs running on Solana, compiled to - SBF. This crate contains many fundamental data types and is re-exported from - [`solana-sdk`], which cannot be imported from a Solana program. +- [`solana-program`] — Імпортується програмами, що працюють у Solana, і компілюється до + SBF. Цей пакет містить багато фундаментальних типів даних і реекспортується з + [`solana-sdk`], який не можна імпортувати у програму Solana. -- [`solana-sdk`] — The basic offchain SDK, it re-exports - [`solana-program`] and adds more APIs on top of that. Most Solana programs - that do not run on-chain will import this. +- [`solana-sdk`] — Базовий SDK для роботи поза мережею, реекспортує + [`solana-program`] і додає більше API на додаток до цього. Більшість програм Solana, + що не працюють у мережі, імпортують цей пакет. -- [`solana-client`] — For interacting with a Solana node via the +- [`solana-client`] — Для взаємодії з вузлом Solana через [JSON RPC API](/docs/rpc). -- [`solana-cli-config`] — Loading and saving the Solana CLI configuration - file. +- [`solana-cli-config`] — Завантаження та збереження конфігураційного файлу Solana CLI. -- [`solana-clap-utils`] — Routines for setting up a CLI, using [`clap`], - as used by the main Solana CLI. Includes functions for loading all types of - signers supported by the CLI. +- [`solana-clap-utils`] — Рутини для налаштування CLI, використовуючи [`clap`], як у + основному CLI Solana. Включає функції для завантаження всіх типів підписантів, підтримуваних CLI. [`solana-program`]: https://docs.rs/solana-program [`solana-sdk`]: https://docs.rs/solana-sdk diff --git a/docs/uk/core/accounts.md b/docs/uk/core/accounts.md index 7cc886308..f45f08df5 100644 --- a/docs/uk/core/accounts.md +++ b/docs/uk/core/accounts.md @@ -1,197 +1,184 @@ --- sidebarSortOrder: 1 -sidebarLabel: Solana Account Model -title: Solana Account Model +sidebarLabel: Модель облікових записів Solana +title: Модель облікових записів Solana description: - Learn about Solana's account model, including how accounts store data and - programs, rent mechanics, account ownership, and the relationship between - programs and data accounts. Understand the core concepts of Solana's key-value - storage system. + Дізнайтеся про модель облікових записів Solana, включаючи те, як облікові записи зберігають дані + і програми, механіку оренди, власність облікових записів і взаємозв'язок між + програмами та обліковими записами даних. Зрозумійте основні концепції системи + зберігання ключ-значення Solana. --- -On Solana, all data is stored in what are referred to as "accounts”. The way -data is organized on Solana resembles a -[key-value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), -where each entry in the database is called an "account". +У Solana всі дані зберігаються в так званих "облікових записах". Спосіб +організації даних у Solana нагадує +[сховище ключ-значення](https://uk.wikipedia.org/wiki/%D0%91%D0%B0%D0%B7%D0%B0_%D0%B4%D0%B0%D0%BD%D0%B8%D1%85_%C2%AB%D0%BA%D0%BB%D1%8E%D1%87%E2%80%94%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%BD%D1%8F%C2%BB), +де кожен запис у базі даних називається "обліковим записом". -![Accounts](/assets/docs/core/accounts/accounts.svg) +![Облікові записи](/assets/docs/core/accounts/accounts.svg) -## Key Points +## Основні моменти -- Accounts can store up to 10MB of data, which can consist of either executable - program code or program state. +- Облікові записи можуть зберігати до 10 МБ даних, які можуть складатися з виконуваного + коду програми або стану програми. -- Accounts require a rent deposit in SOL, proportional to the amount of data - stored, which is fully refundable when the account is closed. +- Облікові записи потребують застави в SOL, пропорційної обсягу збережених даних, + яка повністю повертається при закритті облікового запису. -- Every account has a program "owner". Only the program that owns an account can - modify its data or deduct its lamport balance. However, anyone can increase - the balance. +- Кожен обліковий запис має "власника" програми. Тільки програма, яка володіє обліковим записом, може + змінювати його дані або знімати баланс лампортів. Однак будь-хто може + збільшити баланс. -- Programs (smart contracts) are stateless accounts that store executable code. +- Програми (смартконтракти) є безстанними обліковими записами, які зберігають виконуваний код. -- Data accounts are created by programs to store and manage program state. +- Облікові записи даних створюються програмами для зберігання і керування станом програми. -- Native programs are built-in programs included with the Solana runtime. +- Вбудовані програми - це вбудовані програми, які включені у середовище виконання Solana. -- Sysvar accounts are special accounts that store network cluster state. +- Системні облікові записи - це спеціальні облікові записи, які зберігають стан кластера мережі. -## Account +## Обліковий запис -Each account is identifiable by its unique address, represented as 32 bytes in -the format of an [Ed25519](https://ed25519.cr.yp.to/) `PublicKey`. You can think -of the address as the unique identifier for the account. +Кожен обліковий запис ідентифікується його унікальною адресою, представленою у форматі 32 байт +як [Ed25519](https://ed25519.cr.yp.to/) `PublicKey`. Ви можете вважати +адресу унікальним ідентифікатором облікового запису. -![Account Address](/assets/docs/core/accounts/account-address.svg) +![Адреса облікового запису](/assets/docs/core/accounts/account-address.svg) -This relationship between the account and its address can be thought of as a -key-value pair, where the address serves as the key to locate the corresponding -on-chain data of the account. +Цей зв'язок між обліковим записом та його адресою можна розглядати як +пару ключ-значення, де адреса є ключем для пошуку відповідних +даних облікового запису в ланцюжку. ### AccountInfo -Accounts have a -[max size of 10MB](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L85) -(10 Mega Bytes) and the data stored on every account on Solana has the following -structure known as the +Облікові записи мають +[максимальний розмір у 10 МБ](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L85) +(10 мегабайт), а дані, що зберігаються в кожному обліковому записі Solana, мають наступну +структуру, відому як [AccountInfo](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/account_info.rs#L19). ![AccountInfo](/assets/docs/core/accounts/accountinfo.svg) -The `AccountInfo` for each account includes the following fields: - -- `data`: A byte array that stores the state of an account. If the account is a - program (smart contract), this stores executable program code. This field is - often referred to as the "account data". -- `executable`: A boolean flag that indicates if the account is a program. -- `lamports`: A numeric representation of the account's balance in - [lamports](/docs/terminology.md#lamport), the smallest unit of SOL (1 SOL = 1 - billion lamports). -- `owner`: Specifies the public key (program ID) of the program that owns the - account. +`AccountInfo` для кожного облікового запису включає наступні поля: -As a key part of the Solana Account Model, every account on Solana has a -designated "owner", specifically a program. Only the program designated as the -owner of an account can modify the data stored on the account or deduct the -lamport balance. It's important to note that while only the owner may deduct the -balance, anyone can increase the balance. +- `data`: Масив байтів, який зберігає стан облікового запису. Якщо обліковий запис є + програмою (смартконтрактом), це поле зберігає виконуваний код програми. Це поле часто + називають "даними облікового запису". +- `executable`: Булевий прапорець, який вказує, чи є обліковий запис програмою. +- `lamports`: Числове представлення балансу облікового запису в + [лампортах](/docs/terminology.md#lamport), найменшій одиниці SOL (1 SOL = 1 + мільярд лампортів). +- `owner`: Вказує публічний ключ (Program ID) програми, яка володіє обліковим записом. -> To store data on-chain, a certain amount of SOL must be transferred to an -> account. The amount transferred is proportional to the size of the data stored -> on the account. This concept is commonly referred to as “rent”. However, you -> can think of "rent" more like a "deposit" because the SOL allocated to an -> account can be fully recovered when the account is closed. +Як ключова частина моделі облікових записів Solana, кожен обліковий запис у Solana має +визначеного "власника", а саме програму. Тільки програма, зазначена як власник облікового запису, може +змінювати дані, що зберігаються в обліковому записі, або знімати баланс лампортів. Важливо зазначити, що, хоча тільки власник може знімати баланс, будь-хто може збільшити баланс. -## Native Programs +> Для зберігання даних у ланцюжку потрібно передати певну кількість SOL до +> облікового запису. Кількість, що передається, пропорційна розміру даних, що зберігаються в обліковому записі. Ця концепція зазвичай називається "орендою". Однак, ви можете розглядати "оренду" швидше як "депозит", оскільки SOL, виділені для облікового запису, можуть бути повністю відновлені при закритті облікового запису. -Solana contains a small handful of native programs that are part of the -validator implementation and provide various core functionalities for the -network. You can find the full list of native programs -[here](https://docs.anza.xyz/runtime/programs). +## Вбудовані програми -When developing custom programs on Solana, you will commonly interact with two -native programs, the System Program and the BPF Loader. +Solana містить невелику кількість вбудованих програм, які є частиною +реалізації валідатора і забезпечують різні основні функціональності для +мережі. Ви можете знайти повний список вбудованих програм +[тут](https://docs.anza.xyz/runtime/programs). -### System Program +При розробці користувацьких програм на Solana ви часто будете взаємодіяти з двома +вбудованими програмами: Системною Програмою і Завантажувачем BPF. -By default, all new accounts are owned by the -[System Program](https://github.com/solana-labs/solana/tree/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src). -The System Program performs several key tasks such as: +### Системна Програма -- [New Account Creation](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L145): - Only the System Program can create new accounts. -- [Space Allocation](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L70): - Sets the byte capacity for the data field of each account. -- [Assign Program Ownership](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L112): - Once the System Program creates an account, it can reassign the designated - program owner to a different program account. This is how custom programs take - ownership of new accounts created by the System Program. +За замовчуванням усі нові облікові записи належать +[Системній Програмі](https://github.com/solana-labs/solana/tree/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src). +Системна Програма виконує кілька ключових завдань, таких як: -On Solana, a "wallet" is simply an account owned by the System Program. The -lamport balance of the wallet is the amount of SOL owned by the account. +- [Створення нового облікового запису](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L145): + Тільки Системна Програма може створювати нові облікові записи. +- [Виділення простору](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L70): + Встановлює обсяг пам'яті для поля даних кожного облікового запису. +- [Призначення власника програми](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L112): + Після створення облікового запису Системною Програмою вона може перепризначити власника + програми іншому обліковому запису програми. Це спосіб, за яким користувацькі програми беруть + у власність нові облікові записи, створені Системною Програмою. -![System Account](/assets/docs/core/accounts/system-account.svg) +У Solana "гаманець" просто є обліковим записом, який належить Системній Програмі. Баланс лампортів у гаманці є кількістю SOL, що належать обліковому запису. -> Only accounts owned by the System Program can be used as transaction fee -> payers. +![Системний Обліковий Запис](/assets/docs/core/accounts/system-account.svg) -### BPFLoader Program +> Тільки облікові записи, що належать Системній Програмі, можуть використовуватися як платники комісій за транзакції. -The -[BPF Loader](https://github.com/solana-labs/solana/tree/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src) -is the program designated as the "owner" of all other programs on the network, -excluding Native Programs. It is responsible for deploying, upgrading, and -executing custom programs. +### Завантажувач BPF -## Sysvar Accounts +[Завантажувач BPF](https://github.com/solana-labs/solana/tree/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src) +є програмою, яка призначена як "власник" усіх інших програм у мережі, +крім Вбудованих Програм. Він відповідає за розгортання, оновлення та виконання користувацьких програм. -Sysvar accounts are special accounts located at predefined addresses that -provide access to cluster state data. These accounts are dynamically updated -with data about the network cluster. You can find the full list of Sysvar -Accounts [here](https://docs.anza.xyz/runtime/sysvars). +## Системні Облікові Записи -## Custom Programs +Системні облікові записи - це спеціальні облікові записи, розташовані за попередньо визначеними адресами, які +надають доступ до даних про стан кластера мережі. Ці облікові записи динамічно оновлюються +даними про кластер мережі. Ви можете знайти повний список Системних Облікових Записів +[тут](https://docs.anza.xyz/runtime/sysvars). -On Solana, “smart contracts” are referred to as -[programs](/docs/core/programs.md). A program is an account that contains -executable code and is indicated by an “executable” flag that is set to true. +## Користувацькі Програми -For a more detailed explanation of the program deployment process, refer to the -[Deploying Programs](/docs/programs/deploying.md) page of this documentation. +У Solana "смартконтракти" називаються +[програмами](/docs/core/programs.md). Програма є обліковим записом, який містить +виконуваний код, і позначається прапорцем "виконуваний", який встановлено в значення "true". -### Program Account +Для детального пояснення процесу розгортання програми, зверніться до сторінки +[Розгортання Програм](/docs/programs/deploying.md) цієї документації. -When new programs are -[deployed](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L498) -on Solana, technically three separate accounts are created: +### Обліковий Запис Програми -- **Program Account**: The main account representing an on-chain program. This - account stores the address of an executable data account (which stores the - compiled program code) and the update authority for the program (address - authorized to make changes to the program). -- **Program Executable Data Account**: An account that contains the executable - byte code of the program. -- **Buffer Account**: A temporary account that stores byte code while a program - is being actively deployed or upgraded. Once the process is complete, the data - is transferred to the Program Executable Data Account and the buffer account - is closed. +Коли нові програми +[розгортаються](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L498) +на Solana, технічно створюються три окремі облікові записи: -For example, here are links to the Solana Explorer for the Token Extensions -[Program Account](https://explorer.solana.com/address/TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb) -and its corresponding -[Program Executable Data Account](https://explorer.solana.com/address/DoU57AYuPFu2QU514RktNPG22QhApEjnKxnBcu4BHDTY). +- **Обліковий Запис Програми**: Основний обліковий запис, який представляє програму в ланцюжку. Цей + обліковий запис зберігає адресу виконуваного облікового запису даних (який зберігає + зкомпільований код програми) і право на оновлення програми (адреса, яка + має дозвіл на внесення змін до програми). +- **Виконуваний Обліковий Запис Програми**: Обліковий запис, який містить виконуваний + байт-код програми. +- **Буферний Обліковий Запис**: Тимчасовий обліковий запис, який зберігає байт-код під час + активного розгортання або оновлення програми. Після завершення процесу дані + передаються до Виконуваного Облікового Запису Програми, а буферний обліковий запис + закривається. -![Program and Executable Data Accounts](/assets/docs/core/accounts/program-account-expanded.svg) +Наприклад, ось посилання на Solana Explorer для Програмного Розширення Токенів +[Обліковий Запис Програми](https://explorer.solana.com/address/TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb) +і його відповідний +[Виконуваний Обліковий Запис Програми](https://explorer.solana.com/address/DoU57AYuPFu2QU514RktNPG22QhApEjnKxnBcu4BHDTY). -For simplicity, you can think of the "Program Account" as the program itself. +![Облікові Записи Програми та Виконуваних Даних](/assets/docs/core/accounts/program-account-expanded.svg) -![Program Account](/assets/docs/core/accounts/program-account-simple.svg) +Для простоти ви можете вважати "Обліковий Запис Програми" як саму програму. -> The address of the "Program Account" is commonly referred to as the “Program -> ID”, which is used to invoke the program. +![Обліковий Запис Програми](/assets/docs/core/accounts/program-account-simple.svg) -### Data Account +> Адреса "Облікового Запису Програми" зазвичай називається "ID Програми", який використовується для виклику програми. -Solana programs are "stateless", meaning that program accounts only contain the -program's executable byte code. To store and modify additional data, new -accounts must be created. These accounts are commonly referred to as “data -accounts”. +### Обліковий Запис Даних -Data accounts can store any arbitrary data as defined in the owner program's -code. +Програми Solana є "безстанними", тобто облікові записи програм містять лише +виконуваний байт-код програми. Для зберігання та модифікації додаткових даних необхідно створювати нові +облікові записи. Ці облікові записи зазвичай називаються "обліковими записами даних". -![Data Account](/assets/docs/core/accounts/data-account.svg) +Облікові записи даних можуть зберігати будь-які довільні дані, визначені в коді програми-власника. -Note that only the [System Program](/docs/core/accounts.md#system-program) can -create new accounts. Once the System Program creates an account, it can then -transfer ownership of the new account to another program. +![Обліковий Запис Даних](/assets/docs/core/accounts/data-account.svg) -In other words, creating a data account for a custom program requires two steps: +Зверніть увагу, що тільки [Системна Програма](/docs/core/accounts.md#system-program) може +створювати нові облікові записи. Після створення облікового запису Системною Програмою вона може потім +передати власність нового облікового запису іншій програмі. -1. Invoke the System Program to create an account, which then transfers - ownership to a custom program -2. Invoke the custom program, which now owns the account, to then initialize the - account data as defined in the program code +Іншими словами, створення облікового запису даних для користувацької програми вимагає двох кроків: -This data account creation process is often abstracted as a single step, but -it's helpful to understand the underlying process. +1. Виклик Системної Програми для створення облікового запису, яка потім передає + власність користувацькій програмі +2. Виклик користувацької програми, яка тепер володіє обліковим записом, для + ініціалізації даних облікового запису, як це визначено в коді програми + +Цей процес створення облікового запису даних часто абстрагується як єдиний крок, але +корисно розуміти підлеглий процес. From aad3bf1a9ee5eacd72fb4173d301827cfb0e0c3f Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Sat, 11 Jan 2025 20:13:45 +0200 Subject: [PATCH 06/14] core folder in progress --- docs/uk/core/clusters.md | 204 ++++++------- docs/uk/core/cpi.md | 181 ++++++------ docs/uk/core/fees.md | 610 +++++++++++++-------------------------- docs/uk/core/index.md | 116 +++----- docs/uk/core/pda.md | 308 ++++++++++---------- docs/uk/core/programs.md | 133 +++++---- docs/uk/core/tokens.md | 555 +++++++++++++++++------------------ 7 files changed, 912 insertions(+), 1195 deletions(-) diff --git a/docs/uk/core/clusters.md b/docs/uk/core/clusters.md index 4134ff06c..f2f455da3 100644 --- a/docs/uk/core/clusters.md +++ b/docs/uk/core/clusters.md @@ -1,37 +1,38 @@ --- -sidebarLabel: Clusters & Endpoints -title: Clusters and Public RPC Endpoints +sidebarLabel: Кластери та точки доступу RPC +title: Кластери та публічні точки доступу RPC sidebarSortOrder: 8 description: - Learn about Solana's network clusters (Devnet, Testnet, and Mainnet Beta), - their public RPC endpoints, rate limits, and use cases. Learn how to connect - to different Solana networks for development, testing, and production. + Дізнайтеся про кластери мережі Solana (Devnet, Testnet і Mainnet Beta), їхні + публічні точки доступу RPC, обмеження швидкості та випадки використання. + Дізнайтеся, як підключатися до різних мереж Solana для розробки, тестування + та виробничого середовища. --- -The Solana blockchain has several different groups of validators, known as -[Clusters](/docs/core/clusters.md). Each serving different purposes within the -overall ecosystem and containing dedicated API nodes to fulfill -[JSON-RPC](/docs/rpc/index.mdx) requests for their respective Cluster. +Блокчейн Solana має кілька різних груп валідаторів, відомих як +[Кластери](/docs/core/clusters.md). Кожен з них обслуговує різні цілі в межах +загальної екосистеми та містить виділені вузли API для виконання +[JSON-RPC](/docs/rpc/index.mdx) запитів для своїх відповідних кластерів. -The individual nodes within a Cluster are owned and operated by third parties, -with a public endpoint available for each. +Індивідуальні вузли в межах кластера належать та управляються третіми сторонами, +з публічною точкою доступу, доступною для кожного. -## Solana public RPC endpoints +## Публічні точки доступу RPC Solana -The Solana Labs organization operates a public RPC endpoint for each Cluster. -Each of these public endpoints are subject to rate limits, but are available for -users and developers to interact with the Solana blockchain. +Організація Solana Labs керує публічною точкою доступу RPC для кожного кластера. +Кожна з цих публічних точок доступу має обмеження швидкості, але доступна для +користувачів та розробників для взаємодії з блокчейном Solana. -> Public endpoint rate limits are subject to change. The specific rate limits -> listed on this document are not guaranteed to be the most up-to-date. +> Обмеження швидкості публічних точок доступу можуть змінюватися. Зазначені +> обмеження швидкості в цьому документі можуть бути не найактуальнішими. -### Using explorers with different Clusters +### Використання експлорерів з різними кластерами -Many of the popular Solana blockchain explorers support selecting any of the -Clusters, often allowing advanced users to add a custom/private RPC endpoint as -well. +Багато популярних експлорерів блокчейну Solana підтримують вибір будь-якого +кластера, часто дозволяючи досвідченим користувачам додавати користувацьку/ +приватну точку доступу RPC. -An example of some of these Solana blockchain explorers include: +Прикладами таких експлорерів є: - [http://explorer.solana.com/](https://explorer.solana.com/). - [http://solana.fm/](https://solana.fm/). @@ -39,131 +40,132 @@ An example of some of these Solana blockchain explorers include: - [http://solanabeach.io/](http://solanabeach.io/). - [http://validators.app/](http://validators.app/). -## On a high level +## Основні відомості -- Mainnet: Live production environment for deployed applications. -- Devnet: Testing with public accessibility for developers experimenting with - their applications. -- Testnet: Stress-testing for network upgrades and validator performance. +- Mainnet: Живе виробниче середовище для розгорнутих додатків. +- Devnet: Тестування з публічним доступом для розробників, які експериментують зі + своїми додатками. +- Testnet: Стрес-тестування для оновлень мережі та продуктивності валідаторів. -**Example use cases**: You may want to debug a new program on Devnet or verify -performance metrics on Testnet before Mainnet deployment. +**Приклади використання**: Можливо, ви захочете налагодити нову програму на Devnet +або перевірити метрики продуктивності на Testnet перед розгортанням на Mainnet. -| **Cluster** | **Endpoint** | **Purpose** | **Notes** | -| ----------- | ------------------------------------- | ------------------------------ | ------------------------------ | -| Mainnet | `https://api.mainnet-beta.solana.com` | Live production environment | Requires SOL for transactions | -| Devnet | `https://api.devnet.solana.com` | Public testing and development | Free SOL airdrop for testing | -| Testnet | `https://api.testnet.solana.com` | Validator and stress testing | May have intermittent downtime | +| **Кластер** | **Точка доступу** | **Призначення** | **Примітки** | +| ----------- | ---------------------------------------- | ------------------------------- | ------------------------------ | +| Mainnet | `https://api.mainnet-beta.solana.com` | Живе виробниче середовище | Потребує SOL для транзакцій | +| Devnet | `https://api.devnet.solana.com` | Публічне тестування та розробка | Безкоштовний SOL для тестування| +| Testnet | `https://api.testnet.solana.com` | Тестування валідаторів | Може мати періодичні простої | ## Devnet -Devnet serves as a playground for anyone who wants to take Solana for a test -drive, as a user, token holder, app developer, or validator. +Devnet слугує тестовим майданчиком для будь-кого, хто хоче ознайомитися з Solana +як користувач, власник токенів, розробник додатків або валідатор. -- Application developers should target Devnet. -- Potential validators should first target Devnet. -- Key differences between Devnet and Mainnet Beta: - - Devnet tokens are **not real** - - Devnet includes a token faucet for airdrops for application testing - - Devnet may be subject to ledger resets - - Devnet typically runs the same software release branch version as Mainnet - Beta, but may run a newer minor release version than Mainnet Beta. -- Gossip entrypoint for Devnet: `entrypoint.devnet.solana.com:8001` +- Розробники додатків повинні орієнтуватися на Devnet. +- Потенційні валідатори повинні спочатку орієнтуватися на Devnet. +- Основні відмінності між Devnet і Mainnet Beta: + - Токени Devnet **не реальні**. + - Devnet включає крани для отримання токенів для тестування додатків. + - Devnet може піддаватися скиданням журналу. + - Devnet зазвичай працює на тій самій гілці випуску програмного забезпечення, + що й Mainnet Beta, але може працювати на новішій мінорній версії. +- Точка доступу Gossip для Devnet: `entrypoint.devnet.solana.com:8001` -### Devnet endpoint +### Точка доступу Devnet -- `https://api.devnet.solana.com` - single Solana Labs hosted API node; - rate-limited +- `https://api.devnet.solana.com` - єдиний вузол API, розміщений Solana Labs; + з обмеженнями швидкості -#### Example `solana` command-line configuration +#### Приклад конфігурації командного рядка `solana` -To connect to the `devnet` Cluster using the Solana CLI: +Щоб підключитися до кластеру `devnet` за допомогою CLI Solana: ```shell solana config set --url https://api.devnet.solana.com ``` -### Devnet rate limits +### Обмеження швидкості Devnet -- Maximum number of requests per 10 seconds per IP: 100 -- Maximum number of requests per 10 seconds per IP for a single RPC: 40 -- Maximum concurrent connections per IP: 40 -- Maximum connection rate per 10 seconds per IP: 40 -- Maximum amount of data per 30 second: 100 MB +- Максимальна кількість запитів на 10 секунд на IP: 100 +- Максимальна кількість запитів на 10 секунд на IP для одного RPC: 40 +- Максимальна кількість одночасних з'єднань на IP: 40 +- Максимальна швидкість з'єднань на 10 секунд на IP: 40 +- Максимальна кількість даних на 30 секунд: 100 МБ ## Testnet -Testnet is where the Solana core contributors stress test recent release -features on a live cluster, particularly focused on network performance, -stability and validator behavior. +Testnet - це місце, де основні учасники Solana стрес-тестують функції останніх +випусків у живому кластері, особливо зосереджуючись на продуктивності мережі, +стабільності та поведінці валідаторів. -- Testnet tokens are **not real** -- Testnet may be subject to ledger resets. -- Testnet includes a token faucet for airdrops for application testing -- Testnet typically runs a newer software release branch than both Devnet and - Mainnet Beta -- Gossip entrypoint for Testnet: `entrypoint.testnet.solana.com:8001` +- Токени Testnet **не реальні**. +- Testnet може піддаватися скиданням журналу. +- Testnet включає крани для отримання токенів для тестування додатків. +- Testnet зазвичай працює на новішій гілці випуску програмного забезпечення, + ніж Devnet і Mainnet Beta. +- Точка доступу Gossip для Testnet: `entrypoint.testnet.solana.com:8001` -### Testnet endpoint +### Точка доступу Testnet -- `https://api.testnet.solana.com` - single Solana Labs API node; rate-limited +- `https://api.testnet.solana.com` - єдиний вузол API, розміщений Solana Labs; + з обмеженнями швидкості -#### Example `solana` command-line configuration +#### Приклад конфігурації командного рядка `solana` -To connect to the `testnet` Cluster using the Solana CLI: +Щоб підключитися до кластеру `testnet` за допомогою CLI Solana: ```shell solana config set --url https://api.testnet.solana.com ``` -### Testnet rate limits +### Обмеження швидкості Testnet -- Maximum number of requests per 10 seconds per IP: 100 -- Maximum number of requests per 10 seconds per IP for a single RPC: 40 -- Maximum concurrent connections per IP: 40 -- Maximum connection rate per 10 seconds per IP: 40 -- Maximum amount of data per 30 second: 100 MB +- Максимальна кількість запитів на 10 секунд на IP: 100 +- Максимальна кількість запитів на 10 секунд на IP для одного RPC: 40 +- Максимальна кількість одночасних з'єднань на IP: 40 +- Максимальна швидкість з'єднань на 10 секунд на IP: 40 +- Максимальна кількість даних на 30 секунд: 100 МБ ## Mainnet beta -A permissionless, persistent cluster for Solana users, builders, validators and -token holders. +Безперешкодний, постійний кластер для користувачів Solana, розробників, +валідаторів та власників токенів. -- Tokens that are issued on Mainnet Beta are **real** SOL -- Gossip entrypoint for Mainnet Beta: `entrypoint.mainnet-beta.solana.com:8001` +- Токени, випущені на Mainnet Beta, є **реальними** SOL. +- Точка доступу Gossip для Mainnet Beta: `entrypoint.mainnet-beta.solana.com:8001` -### Mainnet beta endpoint +### Точка доступу Mainnet beta -- `https://api.mainnet-beta.solana.com` - Solana Labs hosted API node cluster, - backed by a load balancer; rate-limited +- `https://api.mainnet-beta.solana.com` - кластер вузлів API, розміщених Solana + Labs, із підтримкою балансувальника навантаження; з обмеженнями швидкості -#### Example `solana` command-line configuration +#### Приклад конфігурації командного рядка `solana` -To connect to the `mainnet-beta` Cluster using the Solana CLI: +Щоб підключитися до кластеру `mainnet-beta` за допомогою CLI Solana: ```shell solana config set --url https://api.mainnet-beta.solana.com ``` -### Mainnet beta rate limits +### Обмеження швидкості Mainnet beta -- Maximum number of requests per 10 seconds per IP: 100 -- Maximum number of requests per 10 seconds per IP for a single RPC: 40 -- Maximum concurrent connections per IP: 40 -- Maximum connection rate per 10 seconds per IP: 40 -- Maximum amount of data per 30 seconds: 100 MB +- Максимальна кількість запитів на 10 секунд на IP: 100 +- Максимальна кількість запитів на 10 секунд на IP для одного RPC: 40 +- Максимальна кількість одночасних з'єднань на IP: 40 +- Максимальна швидкість з'єднань на 10 секунд на IP: 40 +- Максимальна кількість даних на 30 секунд: 100 МБ -> The public RPC endpoints are not intended for production applications. Please -> use dedicated/private RPC servers when you launch your application, drop NFTs, -> etc. The public services are subject to abuse and rate limits may change -> without prior notice. Likewise, high-traffic websites may be blocked without -> prior notice. +> Публічні точки доступу RPC не призначені для виробничих додатків. Будь ласка, +> використовуйте виділені/приватні сервери RPC під час запуску додатка, випуску +> NFT тощо. Публічні сервіси піддаються зловживанням, і обмеження швидкості +> можуть змінюватися без попередження. Також, вебсайти з високим трафіком можуть +> бути заблоковані без попередження. -## Common HTTP Error Codes +## Загальні HTTP-коди помилок -- 403 -- Your IP address or website has been blocked. It is time to run your own - RPC server(s) or find a private service. -- 429 -- Your IP address is exceeding the rate limits. Slow down! Use the +- 403 -- Ваша IP-адреса або вебсайт було заблоковано. Настав час запустити власні + сервери RPC або знайти приватний сервіс. +- 429 -- Ваша IP-адреса перевищує обмеження швидкості. Зменшіть швидкість! Використовуйте [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) - HTTP response header to determine how long to wait before making another - request. + HTTP-заголовок відповіді, щоб визначити, як довго потрібно чекати перед + повторною спробою. diff --git a/docs/uk/core/cpi.md b/docs/uk/core/cpi.md index 6a6add62b..cec59477d 100644 --- a/docs/uk/core/cpi.md +++ b/docs/uk/core/cpi.md @@ -1,81 +1,79 @@ --- -title: Cross Program Invocation (CPI) -sidebarLabel: Cross Program Invocation +title: Виклики між програмами (CPI) +sidebarLabel: Виклики між програмами sidebarSortOrder: 6 description: - Learn about Cross Program Invocation (CPI) on Solana - how programs can call - instructions on other programs, handle PDA signers, and compose functionality - across the Solana network. + Дізнайтеся про виклики між програмами (CPI) у Solana - як програми можуть + викликати інструкції інших програм, обробляти підписантів PDA і складати + функціональність у мережі Solana. --- -A Cross Program Invocation (CPI) refers to when one program invokes the -instructions of another program. This mechanism allows for the composability of -Solana programs. +Виклик між програмами (CPI) відбувається, коли одна програма викликає +інструкції іншої програми. Цей механізм дозволяє складати програми Solana. -You can think of instructions as API endpoints that a program exposes to the -network and a CPI as one API internally invoking another API. +Інструкції можна уявити як API-методи, які програма надає мережі, а CPI - це +виклик одного API-методу іншим API-методом. -![Cross Program Invocation](/assets/docs/core/cpi/cpi.svg) +![Виклик між програмами](/assets/docs/core/cpi/cpi.svg) -When a program initiates a Cross Program Invocation (CPI) to another program: +Коли програма ініціює виклик між програмами (CPI) до іншої програми: -- The signer privileges from the initial transaction invoking the caller program - (A) extend to the callee (B) program -- The callee (B) program can make further CPIs to other programs, up to a - maximum depth of 4 (ex. B->C, C->D) -- The programs can "sign" on behalf of the [PDAs](/docs/core/pda.md) derived - from its program ID +- Привілеї підпису від початкової транзакції, що викликає програму (A), + розширюються на програму-отримувача (B). +- Програма-отримувач (B) може здійснювати подальші CPI до інших програм до + максимального рівня глибини 4 (наприклад, B->C, C->D). +- Програми можуть "підписувати" від імені [PDA](/docs/core/pda.md), що + створені з їхнього ID програми. -> The Solana program runtime defines a constant called +> У середовищі виконання програм Solana визначено константу під назвою > [`max_invoke_stack_height`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/program-runtime/src/compute_budget.rs#L31-L35), -> which is set to a -> [value of 5](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/program-runtime/src/compute_budget.rs#L138). -> This represents the maximum height of the program instruction invocation -> stack. The stack height begins at 1 for transaction instructions, increases by -> 1 each time a program invokes another instruction. This setting effectively -> limits invocation depth for CPIs to 4. +> яка має значення +> [5](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/program-runtime/src/compute_budget.rs#L138). +> Це обмеження встановлює максимальну висоту стеку викликів інструкцій +> програми. Висота стеку починається з 1 для інструкцій транзакції, збільшується +> на 1 кожного разу, коли програма викликає іншу інструкцію. Це ефективно +> обмежує глибину викликів для CPI до 4. -## Key Points +## Основні моменти -- CPIs enable Solana program instructions to directly invoke instructions on - another program. +- CPI дозволяє інструкціям програми Solana безпосередньо викликати інструкції + іншої програми. -- Signer privileges from a caller program are extended to the callee program. +- Привілеї підпису від програми-виклику розширюються на програму-отримувача. -- When making a CPI, programs can "sign" on behalf of PDAs derived from their - own program ID. +- Під час здійснення CPI програми можуть "підписувати" від імені PDA, + створених із їхнього власного ID програми. -- The callee program can make additional CPIs to other programs, up to a maximum - depth of 4. +- Програма-отримувач може здійснювати додаткові CPI до інших програм до + максимальної глибини 4. -## How to write a CPI +## Як написати CPI -Writing an instruction for a CPI follows the same pattern as building an -[instruction](/docs/core/transactions.md#instruction) to add to a transaction. -Under the hood, each CPI instruction must specify the following information: +Написання інструкції для CPI слідує тій самій схемі, що й побудова +[інструкції](/docs/core/transactions.md#instruction) для додавання до транзакції. +Кожна інструкція CPI повинна зазначати таку інформацію: -- **Program address**: Specifies the program being invoked -- **Accounts**: Lists every account the instruction reads from or writes to, - including other programs -- **Instruction Data**: Specifies which instruction on the program to invoke, - plus any additional data required by the instruction (function arguments) +- **Адреса програми**: Вказує програму, яка викликається +- **Облікові записи**: Перераховує кожен обліковий запис, з якого інструкція + читає або в який записує, включаючи інші програми +- **Дані інструкції**: Вказує, яку інструкцію у програмі викликати, а також + будь-які додаткові дані, необхідні для інструкції (аргументи функції) -Depending on the program you are making the call to, there may be crates -available with helper functions for building the instruction. Programs then -execute CPIs using either one of the following functions from the -`solana_program` crate: +Залежно від програми, до якої здійснюється виклик, можуть бути доступні crates +із допоміжними функціями для створення інструкції. Програми потім виконують CPI +за допомогою однієї з наступних функцій з crate `solana_program`: -- `invoke` - used when there are no PDA signers -- `invoke_signed` - used when the caller program needs to sign with a PDA - derived from its program ID +- `invoke` - використовується, коли немає підписантів PDA +- `invoke_signed` - використовується, коли програма-викликач повинна підписати + за допомогою PDA, створеного з її ID програми -### Basic CPI +### Базовий CPI -The +Функція [`invoke`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/program.rs#L132) -function is used when making a CPI that does not require PDA signers. When -making CPIs, signers provided to the caller program automatically extend to the -callee program. +використовується під час здійснення CPI, який не потребує підписантів PDA. Під час +здійснення CPI підписанти, надані програмі-виклику, автоматично розширюються на +програму-отримувача. ```rust pub fn invoke( @@ -84,22 +82,24 @@ pub fn invoke( ) -> Result<(), ProgramError> ``` -Here is an example program on -[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi-invoke) -that makes a CPI using the `invoke` function to call the transfer instruction on -the System Program. You can also reference the -[Basic CPI guide](/content/guides/getstarted/how-to-cpi.md) for further details. +Ось приклад програми на +[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi-invoke), +яка здійснює CPI за допомогою функції `invoke` для виклику інструкції передачі в +Системній Програмі. Ви також можете ознайомитися з +[Базовим посібником CPI](/content/guides/getstarted/how-to-cpi.md) для +додаткової інформації. -### CPI with PDA Signer +### CPI з підписантом PDA -The +Функція [`invoke_signed`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/program.rs#L247) -function is used when making a CPI that requires PDA signers. The seeds used to -derive the signer PDAs are passed into the `invoke_signed` function as -`signer_seeds`. +використовується під час здійснення CPI, який потребує підписантів PDA. Насіння, +що використовується для створення підписаних PDA, передається у функцію +`invoke_signed` як `signer_seeds`. -You can reference the [Program Derived Address](/docs/core/pda.md) page for -details on how PDAs are derived. +Ви можете ознайомитися з сторінкою +[Програмно Створені Адреси (PDA)](/docs/core/pda.md) для деталей про те, як PDA +створюються. ```rust pub fn invoke_signed( @@ -109,26 +109,29 @@ pub fn invoke_signed( ) -> Result<(), ProgramError> ``` -The runtime uses the privileges granted to the caller program to determine what -privileges can be extended to the callee. Privileges in this context refer to -signers and writable accounts. For example, if the instruction the caller is -processing contains a signer or writable account, then the caller can invoke an -instruction that also contains that signer and/or writable account. - -While PDAs have [no private keys](/docs/core/pda.md#what-is-a-pda), they can -still act as a signer in an instruction via a CPI. To verify that a PDA is -derived from the calling program, the seeds used to generate the PDA must be -included as `signers_seeds`. - -When the CPI is processed, the Solana runtime -[internally calls `create_program_address`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/syscalls/cpi.rs#L550) -using the `signers_seeds` and the `program_id` of the calling program. If a -valid PDA is found, the address is -[added as a valid signer](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/syscalls/cpi.rs#L552). - -Here is an example program on -[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi-invoke-signed) -that makes a CPI using the `invoke_signed` function to call the transfer -instruction on the System Program with a PDA signer. You can reference the -[CPI with PDA Signer guide](/content/guides/getstarted/how-to-cpi-with-signer.md) -for further details. +Середовище виконання використовує привілеї, надані програмі-виклику, щоб +визначити, які привілеї можуть бути розширені на програму-отримувача. У цьому +контексті привілеї стосуються підписантів і облікових записів із правом запису. +Наприклад, якщо інструкція, яку обробляє програма-викликач, містить підписанта +або обліковий запис із правом запису, то програма-викликач може викликати +інструкцію, яка також містить цього підписанта та/або обліковий запис із правом +запису. + +Хоча PDA не мають +[приватних ключів](/docs/core/pda.md#what-is-a-pda), вони все одно можуть діяти +як підписант в інструкції через CPI. Щоб підтвердити, що PDA створений із +програми, що викликає, необхідно включити насіння, використане для створення +PDA, як `signers_seeds`. + +Коли CPI обробляється, середовище виконання Solana +[викликає внутрішньо `create_program_address`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/syscalls/cpi.rs#L550) +за допомогою `signers_seeds` і `program_id` програми-виклику. Якщо виявлено +дійсний PDA, адресу додають +[як дійсного підписанта](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/syscalls/cpi.rs#L552). + +Ось приклад програми на +[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi-invoke-signed), +яка здійснює CPI за допомогою функції `invoke_signed` для виклику інструкції +передачі в Системній Програмі з підписантом PDA. Ви можете ознайомитися з +[Посібником CPI з підписантом PDA](/content/guides/getstarted/how-to-cpi-with-signer.md) +для додаткової інформації. diff --git a/docs/uk/core/fees.md b/docs/uk/core/fees.md index 8192694fa..b3eb1de75 100644 --- a/docs/uk/core/fees.md +++ b/docs/uk/core/fees.md @@ -1,17 +1,17 @@ --- -title: Fees on Solana +title: Плата на Solana sidebarSortOrder: 3 description: - Learn about Solana's fee structure including transaction fees, prioritization - fees, and rent costs. Understand how fees are calculated, collected and - distributed across the network. + Дізнайтеся про структуру плати на Solana, включаючи транзакційні збори, + пріоритизаційні збори та витрати на оренду. Зрозумійте, як обчислюється, + збирається та розподіляється плата в мережі. keywords: - - instruction fee - - processing fee - - storage fee - - rent - - gas - - gwei + - плата за інструкцію + - плата за обробку + - плата за збереження + - оренда + - газ + - гвей altRoutes: - /docs/core/rent - /docs/intro/rent @@ -20,312 +20,172 @@ altRoutes: - /docs/core/runtime --- -The Solana blockchain has a few different types of fees and costs that are -incurred to use the permissionless network. These can be segmented into a few -specific types: +Блокчейн Solana має кілька типів плати та витрат, які виникають під час використання мережі без дозволу. Вони поділяються на кілька специфічних типів: -- Transaction Fees - A fee to have validators process transactions/instructions -- Prioritization Fees - An optional fee to boost transactions processing order -- Rent - A withheld balance to keep data stored on-chain +- **Транзакційні збори** — плата за обробку транзакцій/інструкцій валідаторами. +- **Пріоритизаційні збори** — додаткова плата для підвищення порядку обробки транзакцій. +- **Оренда** — утримуваний баланс для збереження даних в ончейні. -## Transaction Fees +## Транзакційні збори -The small fee paid to process logic (instruction) within an on-chain program on -the Solana blockchain is known as a "_transaction fee_". +Мала плата, яка сплачується за обробку логіки (інструкції) у програмі в ончейні на блокчейні Solana, називається "_транзакційною платою_". -As each [transaction](/docs/core/transactions.md#transaction) (which contains -one or more [instructions](/docs/core/transactions.md#instruction)) is sent -through the network, it gets processed by the current validator leader. Once -confirmed as a global state transaction, this _transaction fee_ is paid to the -network to help support the economic design of the Solana blockchain. +Кожна [транзакція](/docs/core/transactions.md#transaction), яка містить одну або більше [інструкцій](/docs/core/transactions.md#instruction), надсилається через мережу, де її обробляє поточний лідер-валідатор. Після підтвердження як глобальної транзакції ця "транзакційна плата" сплачується мережі для підтримки економічної моделі блокчейна Solana. -> Transaction fees are different from account data storage deposit fee of -> [rent](#rent). While transaction fees are paid to process instructions on the -> Solana network, a rent deposit is withheld in an account to store its data on -> the blockchain and reclaimable. +> Транзакційні збори відрізняються від плати за збереження даних в обліковому записі, відомої як [оренда](#rent). Транзакційні збори сплачуються за обробку інструкцій у мережі Solana, а депозит оренди утримується в обліковому записі для збереження даних в блокчейні та може бути повернутий. -Currently, the base Solana transaction fee is set at a static value of 5k -lamports per signature. On top of this base fee, any additional -[prioritization fees](#prioritization-fee) can be added. +На даний момент базова транзакційна плата в Solana встановлена на рівні 5000 лампортів за підпис. На додаток до цієї базової плати, можуть бути додані додаткові [пріоритизаційні збори](#prioritization-fee). -### Why pay transaction fees? +### Навіщо сплачувати транзакційні збори? -Transaction fees offer many benefits in the Solana -[economic design](#basic-economic-design), mainly they: +Транзакційні збори пропонують багато переваг у економічній моделі Solana, зокрема вони: -- provide compensation to the validator network for the expended CPU/GPU compute - resources necessary to process transactions -- reduce network spam by introducing a real cost to transactions -- provide long-term economic stability to the network through a - protocol-captured minimum fee amount per transaction +- Забезпечують компенсацію мережі валідаторів за витрачені ресурси CPU/GPU для обробки транзакцій. +- Зменшують спам у мережі, запроваджуючи реальну вартість транзакцій. +- Забезпечують довгострокову економічну стабільність мережі через протокольно захоплену мінімальну плату за транзакцію. -### Basic economic design +### Основи економічної моделі -Many blockchain networks (including Bitcoin and Ethereum), rely on inflationary -_protocol-based rewards_ to secure the network in the short-term. Over the -long-term, these networks will increasingly rely on _transaction fees_ to -sustain security. +Багато блокчейн-мереж (включаючи Bitcoin та Ethereum) покладаються на інфляційні "протокольні нагороди" для короткострокової підтримки безпеки мережі. У довгостроковій перспективі ці мережі все більше покладаються на "транзакційні збори" для підтримки безпеки. -The same is true on Solana. Specifically: +Те саме стосується Solana. Зокрема: -- A fixed proportion (initially 50%) of each transaction fee is _burned_ - (destroyed), with the remaining going to the current - [leader](/docs/terminology.md#leader) processing the transaction. -- A scheduled global inflation rate provides a source for - [rewards](https://docs.anza.xyz/implemented-proposals/staking-rewards) - distributed to [Solana Validators](https://docs.anza.xyz/operations). - -### Fee collection - -Transactions are required to have at least one account which has signed the -transaction and is writable. These _writable signer accounts_ are serialized -first in the list of accounts and the first of these is always used as the "_fee -payer_". +- Фіксована частка (спочатку 50%) кожної транзакційної плати "спалюється" (знищується), решта надходить до поточного [лідера](/docs/terminology.md#leader), який обробляє транзакцію. +- Запланована глобальна інфляційна ставка забезпечує джерело [нагород](https://docs.anza.xyz/implemented-proposals/staking-rewards), які розподіляються серед [валідаторів Solana](https://docs.anza.xyz/operations). -Before any transaction instructions are processed, the fee payer account -[balance will be deducted](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank.rs#L4045-L4064) -to pay for transaction fees. If the fee payer balance is not sufficient to cover -transaction fees, the transaction processing will halt and result in a failed -transaction. +### Збір плати -If the balance was sufficient, the fees will be deducted and the transaction's -instructions will begin execution. Should any of the instructions result in an -error, transaction processing will halt and ultimately be recorded as a failed -transaction in the Solana ledger. The fee is still collected by the runtime for -these failed transactions. +Транзакції повинні мати щонайменше один обліковий запис, який підписав транзакцію та може бути змінений. Ці "записувані підписуючі облікові записи" серіалізуються першими у списку облікових записів, і перший з них завжди використовується як "платник плати". -Should any of the instructions return an error or violate runtime restrictions, -all account changes **_except_** the transaction fee deduction will be rolled -back. This is because the validator network has already expended computational -resources to collect transactions and begin the initial processing. +Перед обробкою будь-яких інструкцій транзакції баланс облікового запису платника плати [вираховується](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank.rs#L4045-L4064) для оплати транзакційних зборів. Якщо баланс платника плати недостатній для покриття зборів, обробка транзакції припиняється і вона визнається невдалою. -### Fee distribution +Якщо баланс був достатнім, плата буде вирахувана, і виконання інструкцій транзакції почнеться. Якщо будь-яка з інструкцій призведе до помилки, обробка транзакції буде припинена, і зрештою вона буде записана як невдала транзакція в книзі Solana. Плата все одно буде зібрана за ці невдалі транзакції. -Transaction fees are -[partially burned](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank/fee_distribution.rs#L55-L64) -and the remaining fees are collected by the validator that produced the block -that the corresponding transactions were included in. Specifically, -[50% are burned](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/fee_calculator.rs#L79) -and -[50% percent are distributed](https://github.com/anza-xyz/agave/blob/e621336acad4f5d6e5b860eaa1b074b01c99253c/runtime/src/bank/fee_distribution.rs#L58-L62) -to the validator that produced the block. +Якщо будь-яка з інструкцій повертає помилку або порушує обмеження часу виконання, всі зміни облікових записів **_крім_** вирахування транзакційної плати будуть скасовані. Це тому, що мережа валідаторів вже витратила обчислювальні ресурси для збору транзакцій та початку їх обробки. -### Why burn some fees? +### Розподіл плати -As mentioned above, a fixed proportion of each transaction fee is _burned_ -(destroyed). This is intended to cement the economic value of SOL and thus -sustain the network's security. Unlike a scheme where transactions fees are -completely burned, leaders are still incentivized to include as many -transactions as possible in their slots (opportunity to create a block). +Транзакційні збори [частково спалюються](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank/fee_distribution.rs#L55-L64), а решта зборів збираються валідатором, який створив блок, у якому включені відповідні транзакції. Зокрема, [50% спалюються](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/fee_calculator.rs#L79), а [50% розподіляються](https://github.com/anza-xyz/agave/blob/e621336acad4f5d6e5b860eaa1b074b01c99253c/runtime/src/bank/fee_distribution.rs#L58-L62) валідатору, який створив блок. -Burnt fees can also help prevent malicious validators from censoring -transactions by being considered in [fork](/docs/terminology.md#fork) selection. - -#### Example of an attack: - -In the case of a -[Proof of History (PoH)](/docs/terminology.md#proof-of-history-poh) fork with a -malicious or censoring leader: - -- due to the fees lost from censoring, we would expect the total fees burned to - be **_less than_** a comparable honest fork -- if the censoring leader is to compensate for these lost protocol fees, they - would have to replace the burnt fees on their fork themselves -- thus potentially reducing the incentive to censor in the first place - -### Calculating transaction fees - -The complete fee for a given transaction is calculated based on two main parts: - -- a statically set base fee per signature, and -- the computational resources used during the transaction, measured in - "[_compute units_](/docs/terminology.md#compute-units)" - -Since each transaction may require a different amount of computational -resources, each is allotted a maximum number of _compute units_ per transaction -as part of the _compute budget_. - -## Compute Budget - -To prevent abuse of computational resources, each transaction is allocated a -"_compute budget_". This budget specifies details about -[compute units](#compute-units) and includes: - -- the compute costs associated with different types of operations the - transaction may perform (compute units consumed per operation), -- the maximum number of compute units that a transaction can consume (compute - unit limit), -- and the operational bounds the transaction must adhere to (like account data - size limits) - -When the transaction consumes its entire compute budget (compute budget -exhaustion), or exceeds a bound such as attempting to exceed the -[max call stack depth](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L138) -or [max loaded account](#accounts-data-size-limit) data size limit, the runtime -halts the transaction processing and returns an error. Resulting in a failed -transaction and no state changes (aside from the transaction fee being -[collected](#fee-collection)). - -### Accounts data size limit - -A transaction may specify the maximum bytes of account data it is allowed to -load by including a `SetLoadedAccountsDataSizeLimit` instruction (not to exceed -the runtime's absolute max). If no `SetLoadedAccountsDataSizeLimit` is provided, -the transaction defaults to use the runtime's -[`MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L137-L139) -value. - -The `ComputeBudgetInstruction::set_loaded_accounts_data_size_limit` function can -be used to create this instruction: +### Чому спалюються частина зборів? + +Як згадано вище, фіксована частка кожної транзакційної плати "спалюється" (знищується). Це зроблено для зміцнення економічної цінності SOL і підтримки безпеки мережі. На відміну від системи, де всі транзакційні збори повністю спалюються, лідери все ще мають стимул включати якомога більше транзакцій у свої слоти (можливість створити блок). + +Спалені збори також можуть допомогти запобігти зловмисним валідаторам у цензуруванні транзакцій через врахування в [виборі форку](/docs/terminology.md#fork). + +#### Приклад атаки: + +У випадку [форку Proof of History (PoH)](/docs/terminology.md#proof-of-history-poh) з лідером, що займається цензурою або зловживанням: + +- через втрати зборів, що виникають через цензуру, очікується, що загальні збори, які будуть спалені, будуть **_меншими_**, ніж у порівнянному чесному форку; +- якщо лідер, який займається цензурою, хоче компенсувати ці втрачені протокольні збори, він повинен буде самостійно замінити спалені збори на своєму форку; +- таким чином, потенційно зменшуючи стимул до цензури в першу чергу. + +### Обчислення транзакційних зборів + +Повна плата за конкретну транзакцію розраховується на основі двох основних частин: + +- Статично встановлена базова плата за підпис, і +- Обчислювальні ресурси, використані під час транзакції, виміряні у "[обчислювальних одиницях](/docs/terminology.md#compute-units)". + +Оскільки кожна транзакція може вимагати різної кількості обчислювальних ресурсів, кожній транзакції виділяється максимальна кількість _обчислювальних одиниць_ у рамках "обчислювального бюджету". + +## Обчислювальний бюджет + +Щоб запобігти зловживанню обчислювальними ресурсами, кожній транзакції виділяється "обчислювальний бюджет". Цей бюджет визначає: + +- обчислювальні витрати, пов'язані з різними типами операцій, які може виконувати транзакція (обчислювальні одиниці, спожиті на операцію), +- максимальну кількість обчислювальних одиниць, які може спожити транзакція (ліміт обчислювальних одиниць), +- та операційні межі, яких має дотримуватися транзакція (наприклад, ліміти розміру даних облікового запису). + +Коли транзакція вичерпує свій обчислювальний бюджет (вичерпання обчислювального бюджету) або перевищує межі, наприклад, намагається перевищити [максимальну глибину стеку викликів](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L138) або [максимальний розмір завантажених даних облікового запису](#accounts-data-size-limit), виконання транзакції припиняється, і повертається помилка. Це призводить до невдалої транзакції та жодних змін стану (окрім збору плати за транзакцію). + +### Ліміт розміру даних облікового запису + +Транзакція може встановлювати максимальну кількість байтів даних облікового запису, які їй дозволено завантажувати, включивши інструкцію `SetLoadedAccountsDataSizeLimit` (не перевищуючи абсолютний максимум часу виконання). Якщо `SetLoadedAccountsDataSizeLimit` не надано, транзакція за замовчуванням використовує значення часу виконання [`MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L137-L139). + +Функцію `ComputeBudgetInstruction::set_loaded_accounts_data_size_limit` можна використовувати для створення цієї інструкції. ```rust let instruction = ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(100_000); ``` -### Compute units - -All the operations performed on-chain within a transaction require different -amounts of computation resources be expended by validators when processing -(compute cost). The smallest unit of measure for the consumption of these -resources is called a _"compute unit"_. - -As a transaction is processed, compute units are incrementally consumed by each -of its instructions being executed on-chain (consuming the budget). Since each -instruction is executing different logic (writing to accounts, cpi, performing -syscalls, etc), each may consume a -[different amount](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L133-L178) -of compute units. - -> A program can log details about its compute usage, including how much remains -> in its allotted compute budget. You can also find more information in this -> guide for -> [optimizing your compute usage](/content/guides/advanced/how-to-optimize-compute.md). - -Each transaction is allotted a [compute unit limit](#compute-unit-limit), either -with the default limit set by the runtime or by explicitly requesting a higher -limit. After a transaction exceeds its compute unit limit, its processing is -halted resulting in a transaction failure. - -The following are some common operations that incur a compute cost: - -- executing instructions -- passing data between programs -- performing syscalls -- using sysvars -- logging with the `msg!` macro -- logging pubkeys -- creating program addresses (PDAs) -- cross-program invocations (CPI) -- cryptographic operations - -> For [cross-program invocations](/docs/core/cpi.md), the instruction invoked -> inherits the compute budget and limits of their parent. If an invoked -> instruction consumes the transaction's remaining budget, or exceeds a bound, -> the entire invocation chain and the top level transaction processing are -> halted. - -You can find more details about all the operations that consume compute units -within the Solana runtime's -[`ComputeBudget`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L19-L123). - -### Compute unit limit - -Each transaction has a maximum number of compute units (CU) it can consume -called the _"compute unit limit"_. Per transaction, the Solana runtime has an -absolute max compute unit limit of -[1.4 million CU](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L19) -and sets a default requested max limit of -[200k CU per instruction](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L18). - -A transaction can request a more specific and optimal compute unit limit by -including a single `SetComputeUnitLimit` instruction. Either a higher or lower -limit. But it may never request higher than the absolute max limit per -transaction. - -While a transaction's default compute unit limit will work in most cases for -simple transactions, they are often less than optimal (both for the runtime and -the user). For more complex transactions, like invoking programs that perform -multiple CPIs, you may need to request a higher compute unit limit for the -transaction. - -Requesting the optimal compute unit limits for your transaction is essential to -help you pay less for your transaction and to help schedule your transaction -better on the network. Wallets, dApps, and other services should ensure their -compute unit requests are optimal to provide the best experience possible for -their users. - -> For more details and best practices, read this guide on -> [requesting optimal compute limits](/content/guides/advanced/how-to-request-optimal-compute.md). - -### Compute unit price - -When a transaction desires to pay a higher fee to boost its processing -prioritization, it can set a _"compute unit price"_. This price, used in -combination with [compute unit limit](#compute-unit-limit), will be used to -determine a transaction's prioritization fee. - -By default, there is -[no compute unit price set](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L38) -resulting in no additional prioritization fee. - -## Prioritization Fees - -As part of the [Compute Budget](#compute-budget), the runtime supports -transactions paying an **optional** fee known as a _"prioritization fee"_. -Paying this additional fee helps boost how a transaction is prioritized against -others when processing, resulting in faster execution times. - -### How the prioritization fee is calculated - -A transaction's prioritization fee is calculated by multiplying its **_compute -unit limit_** by the **_compute unit price_** (measured in _micro-lamports_). -These values can be set once per transaction by including the following Compute -Budget instructions: - -- [`SetComputeUnitLimit`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L47-L50) - - setting the maximum number of compute units the transaction can consume -- [`SetComputeUnitPrice`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L52-L55) - - setting the desired additional fee the transaction is willing to pay to boost - its prioritization - -If no `SetComputeUnitLimit` instruction is provided, the -[default compute unit limit](#compute-unit-limit) will be used. - -If no `SetComputeUnitPrice` instruction is provided, the transaction will -default to no additional elevated fee and the lowest priority (i.e. no -prioritization fee). - -### How to set the prioritization fee - -A transaction's prioritization fee is set by including a `SetComputeUnitPrice` -instruction, and optionally a `SetComputeUnitLimit` instruction. The runtime -will use these values to calculate the prioritization fee, which will be used to -prioritize the given transaction within the block. - -You can craft each of these instructions via their Rust or `@solana/web3.js` -functions. Each instruction can then be included in the transaction and sent to -the cluster like normal. See also the -[best practices](#prioritization-fee-best-practices) below. - -Unlike other instructions inside a Solana transaction, Compute Budget -instructions do **NOT** require any accounts. A transaction with multiple of -either of the instructions will fail. +### Обчислювальні одиниці + +Усі операції, виконані ончейн у рамках транзакції, вимагають різного обсягу обчислювальних ресурсів, які витрачаються валідаторами під час обробки (обчислювальна вартість). Найменшою одиницею виміру цих ресурсів є _"обчислювальна одиниця"_. + +Під час обробки транзакції обчислювальні одиниці поступово споживаються кожною з її інструкцій, виконуваних ончейн (вичерпуючи бюджет). Оскільки кожна інструкція виконує різну логіку (запис у облікові записи, CPI, виконання системних викликів тощо), кожна може споживати [різну кількість](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L133-L178) обчислювальних одиниць. + +> Програма може записувати деталі про використання своїх обчислювальних ресурсів, включаючи залишок у виділеному обчислювальному бюджеті. Більше інформації ви можете знайти в цьому посібнику з [оптимізації використання обчислювальних ресурсів](/content/guides/advanced/how-to-optimize-compute.md). + +Кожній транзакції виділяється [ліміт обчислювальних одиниць](#compute-unit-limit), або за замовчуванням встановлений часом виконання, або шляхом явного запиту на вищий ліміт. Якщо транзакція перевищує свій ліміт обчислювальних одиниць, її обробка зупиняється, що призводить до невдалої транзакції. + +Нижче наведено кілька поширених операцій, які мають обчислювальну вартість: + +- виконання інструкцій +- передача даних між програмами +- виконання системних викликів +- використання системних змінних (sysvars) +- логування за допомогою макросу `msg!` +- логування відкритих ключів +- створення програмних адрес (PDAs) +- міжпрограмні виклики (CPI) +- криптографічні операції + +> Для [міжпрограмних викликів](/docs/core/cpi.md) викликана інструкція успадковує обчислювальний бюджет і ліміти свого батька. Якщо викликана інструкція споживає залишок бюджету транзакції або перевищує ліміт, весь ланцюжок викликів і обробка транзакції верхнього рівня зупиняються. + +Детальнішу інформацію про всі операції, які споживають обчислювальні одиниці, ви можете знайти в [ComputeBudget](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L19-L123) в часі виконання Solana. + +### Ліміт обчислювальних одиниць + +Кожна транзакція має максимальну кількість обчислювальних одиниць (CU), які вона може спожити, що називається _"лімітом обчислювальних одиниць"_. У часі виконання Solana встановлено абсолютний максимальний ліміт [1,4 мільйона CU](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L19) на транзакцію та за замовчуванням [200 тисяч CU на інструкцію](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L18). + +Транзакція може запитувати більш конкретний і оптимальний ліміт обчислювальних одиниць, включивши одну інструкцію `SetComputeUnitLimit`. Це може бути як вищий, так і нижчий ліміт. Але він ніколи не може перевищувати абсолютний максимальний ліміт на транзакцію. + +Хоча ліміт обчислювальних одиниць за замовчуванням підходить для простих транзакцій, він часто є менш оптимальним (як для часу виконання, так і для користувача). Для складніших транзакцій, наприклад, виклику програм, що виконують декілька CPI, може знадобитися запит вищого ліміту обчислювальних одиниць для транзакції. + +Запит оптимальних лімітів обчислювальних одиниць для вашої транзакції є важливим для зменшення витрат на транзакцію та кращого планування вашої транзакції в мережі. Гаманці, dApps та інші сервіси повинні переконатися, що їхні запити на обчислювальні одиниці є оптимальними, щоб забезпечити найкращий досвід для своїх користувачів. + +> Для отримання додаткової інформації та найкращих практик прочитайте цей посібник про [запит оптимальних лімітів обчислювальних ресурсів](/content/guides/advanced/how-to-request-optimal-compute.md). + +### Ціна обчислювальної одиниці + +Якщо транзакція бажає сплатити вищу плату, щоб підвищити пріоритетність її обробки, вона може встановити _"ціну обчислювальної одиниці"_. Ця ціна, у поєднанні з [лімітом обчислювальних одиниць](#compute-unit-limit), буде використовуватися для визначення плати за пріоритизацію транзакції. + +За замовчуванням [ціна обчислювальної одиниці не встановлена](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L38), що призводить до відсутності додаткової плати за пріоритизацію. + +## Пріоритизаційні збори + +Як частина [Compute Budget](#compute-budget), час виконання підтримує транзакції, що сплачують **опціональну** плату, відому як _"плата за пріоритизацію"_. Сплата цієї додаткової плати допомагає підвищити пріоритетність транзакції у порівнянні з іншими під час обробки, що призводить до швидшого виконання. + +### Як розраховується плата за пріоритизацію + +Плата за пріоритизацію транзакції розраховується шляхом множення її **_ліміту обчислювальних одиниць_** на **_ціну обчислювальної одиниці_** (вимірюється в _мікролампортах_). Ці значення можна встановити один раз на транзакцію, включивши такі інструкції Compute Budget: + +- [`SetComputeUnitLimit`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L47-L50) — встановлення максимальної кількості обчислювальних одиниць, які може спожити транзакція. +- [`SetComputeUnitPrice`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L52-L55) — встановлення бажаної додаткової плати, яку транзакція готова сплатити для підвищення пріоритетності. + +Якщо інструкція `SetComputeUnitLimit` не надана, буде використовуватися [ліміт обчислювальних одиниць за замовчуванням](#compute-unit-limit). + +Якщо інструкція `SetComputeUnitPrice` не надана, транзакція за замовчуванням матиме найнижчий пріоритет (тобто відсутність пріоритизаційної плати). + +### Як встановити плату за пріоритизацію + +Плата за пріоритизацію транзакції встановлюється шляхом включення інструкції `SetComputeUnitPrice` та, за бажанням, інструкції `SetComputeUnitLimit`. Час виконання використовуватиме ці значення для розрахунку плати за пріоритизацію, яка буде використовуватися для пріоритизації даної транзакції у блоці. + +Ви можете створити кожну з цих інструкцій за допомогою функцій Rust або `@solana/web3.js`. Потім кожну інструкцію можна включити в транзакцію та надіслати до кластера як звичайно. Дивіться також [найкращі практики](#prioritization-fee-best-practices) нижче. + +На відміну від інших інструкцій усередині транзакції Solana, інструкції Compute Budget **НЕ** вимагають жодних облікових записів. Транзакція з кількома інструкціями одного типу завершиться невдачею. -Transactions can only contain **one of each type** of compute budget -instruction. Duplicate instruction types will result in an -[`TransactionError::DuplicateInstruction`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/transaction/error.rs#L143-L145) -error, and ultimately transaction failure. +Транзакції можуть містити лише **одну інструкцію кожного типу** інструкцій обчислювального бюджету. Дублікати інструкцій призведуть до помилки [`TransactionError::DuplicateInstruction`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/transaction/error.rs#L143-L145) і, зрештою, до невдачі транзакції. #### Rust -The rust `solana-sdk` crate includes functions within -[`ComputeBudgetInstruction`](https://docs.rs/solana-sdk/latest/solana_sdk/compute_budget/enum.ComputeBudgetInstruction.html) -to craft instructions for setting the _compute unit limit_ and _compute unit -price_: +Бібліотека `solana-sdk` включає функції в рамках [`ComputeBudgetInstruction`](https://docs.rs/solana-sdk/latest/solana_sdk/compute_budget/enum.ComputeBudgetInstruction.html) для створення інструкцій для встановлення _ліміту обчислювальних одиниць_ та _ціни обчислювальної одиниці_. ```rust let instruction = ComputeBudgetInstruction::set_compute_unit_limit(300_000); @@ -334,13 +194,9 @@ let instruction = ComputeBudgetInstruction::set_compute_unit_limit(300_000); ```rust let instruction = ComputeBudgetInstruction::set_compute_unit_price(1); ``` - #### Javascript -The `@solana/web3.js` library includes functions within the -[`ComputeBudgetProgram`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/ComputeBudgetProgram.html) -class to craft instructions for setting the _compute unit limit_ and _compute -unit price_: +Бібліотека `@solana/web3.js` включає функції в класі [`ComputeBudgetProgram`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/ComputeBudgetProgram.html) для створення інструкцій для встановлення _ліміту обчислювальних одиниць_ та _ціни обчислювальної одиниці_. ```js const instruction = ComputeBudgetProgram.setComputeUnitLimit({ @@ -354,104 +210,56 @@ const instruction = ComputeBudgetProgram.setComputeUnitPrice({ }); ``` -### Prioritization fee best practices - -Below you can find general information on the best practices for prioritization -fees. You can also find more detailed information in this guide on -[how to request optimal compute](/content/guides/advanced/how-to-request-optimal-compute.md), -including how to simulate a transaction to determine its approximate compute -usage. - -#### Request the minimum compute units - -Transactions should request the minimum amount of compute units required for -execution to minimize fees. Also note that fees are not adjusted when the number -of requested compute units exceeds the number of compute units actually consumed -by an executed transaction. - -#### Get recent prioritization fees - -Prior to sending a transaction to the cluster, you can use the -[`getRecentPrioritizationFees`](/docs/rpc/http/getRecentPrioritizationFees.mdx) -RPC method to get a list of the recent paid prioritization fees within the -recent blocks processed by the node. - -You could then use this data to estimate an appropriate prioritization fee for -your transaction to both (a) better ensure it gets processed by the cluster and -(b) minimize the fees paid. - -## Rent - -The fee deposited into every [Solana Account](/docs/core/accounts.md) to keep -its associated data available on-chain is called "_rent_". This fee is withheld -in the normal lamport balance on every account and reclaimable when the account -is closed. - -> Rent is different from [transaction fees](#transaction-fees). Rent is "paid" -> (withheld in an Account) to keep data stored on the Solana blockchain and can -> be reclaimed. Whereas transaction fees are paid to process -> [instructions](/docs/core/transactions.md#instructions) on the network. - -All accounts are required to maintain a high enough lamport balance (relative to -its allocated space) to become [rent exempt](#rent-exempt) and remain on the -Solana blockchain. Any transaction that attempts to reduce an account's balance -below its respective minimum balance for rent exemption will fail (unless the -balance is reduced to exactly zero). - -When an account's owner no longer desires to keep this data on-chain and -available in the global state, the owner can close the account and reclaim the -rent deposit. - -This is accomplished by withdrawing (transferring) the account's entire lamport -balance to another account (i.e. your wallet). By reducing the account's balance -to exactly `0`, the runtime will remove the account and its associated data from -the network in the process of _"[garbage collection](#garbage-collection)"_. - -### Rent rate - -The Solana rent rate is set on a network wide basis, primarily based on a -runtime set -"[lamports _per_ byte _per_ year](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/rent.rs#L27-L34)". -Currently, the rent rate is a static amount and stored in the -[Rent sysvar](https://docs.anza.xyz/runtime/sysvars#rent). - -This rent rate is used to calculate the exact amount of rent required to be -withheld inside an account for the space allocated to the account (i.e. the -amount of data that can be stored in the account). The more space an account -allocates, the higher the withheld rent deposit will be. - -### Rent exempt - -Accounts must maintain a lamport balance greater than the minimum required to -store its respective data on-chain. This is called "_rent exempt_" and that -balance is called the "_minimum balance for rent exemption_". - -> New accounts (and programs) on Solana are **REQUIRED** to be initialized with -> enough lamports to become _rent exempt_. This was not always the case. -> Previously, the runtime would periodically and automatically collect a fee -> from each account below its _minimum balance for rent exemption_. Eventually -> reducing those accounts to a balance of zero and garbage collecting them from -> the global state (unless manually topped up). - -In the process of creating a new account, you must ensure you deposit enough -lamports to be above this minimum balance. Anything lower that this minimum -threshold will result in a failed transaction. - -Every time an account's balance is reduced, the runtime performs a check to see -if the account will still be above this minimum balance for rent exemption. -Unless they reduce the final balance to exactly `0` (closing the account), -transactions that would cause an account's balance to drop below the rent exempt -threshold will fail. - -The specific minimum balance for an account to become rent exempt is dependant -on the blockchain's current [rent rate](#rent-rate) and the desired amount of -storage space an account wants to allocate (account size). Therefore, it is -recommended to use the -[`getMinimumBalanceForRentExemption`](/docs/rpc/http/getMinimumBalanceForRentExemption.mdx) -RPC endpoint to calculate the specific balance for a given account size. - -The required rent deposit amount can also be estimated via the -[`solana rent` CLI subcommand](https://docs.anza.xyz/cli/usage#solana-rent): +### Найкращі практики для плати за пріоритизацію + +Нижче наведено загальну інформацію про найкращі практики для пріоритизаційних зборів. Більш детальну інформацію можна знайти в цьому посібнику про [запит оптимального використання обчислювальних ресурсів](/content/guides/advanced/how-to-request-optimal-compute.md), включаючи симуляцію транзакції для визначення її приблизного використання обчислювальних ресурсів. + +#### Запитуйте мінімальну кількість обчислювальних одиниць + +Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць, необхідну для виконання, щоб мінімізувати збори. Також зауважте, що збори не коригуються, якщо кількість запитаних обчислювальних одиниць перевищує фактично спожиту кількість у виконаній транзакції. + +#### Отримуйте останні пріоритизаційні збори + +Перед надсиланням транзакції до кластеру ви можете скористатися методом RPC [`getRecentPrioritizationFees`](/docs/rpc/http/getRecentPrioritizationFees.mdx), щоб отримати список останніх сплачених пріоритизаційних зборів у нещодавно оброблених блоках вузла. + +Ви можете використовувати ці дані для оцінки відповідної плати за пріоритизацію для вашої транзакції, щоб: + +(a) підвищити ймовірність її обробки кластером та +(b) мінімізувати сплачені збори. + +## Оренда + +Плата, що депонується на кожен [Обліковий запис Solana](/docs/core/accounts.md) для збереження його пов'язаних даних в ончейні, називається "_орендою_". Ця плата утримується у звичайному балансі лампортів на кожному обліковому записі та може бути повернута під час закриття облікового запису. + +> Оренда відрізняється від [транзакційних зборів](#transaction-fees). Оренда "сплачується" (утримується в Обліковому записі) для збереження даних на блокчейні Solana та може бути повернута. У той час як транзакційні збори сплачуються за обробку [інструкцій](/docs/core/transactions.md#instructions) у мережі. + +Усі облікові записи повинні підтримувати достатньо високий баланс лампортів (відносно їх виділеного простору), щоб стати [звільненими від оренди](#rent-exempt) і залишатися на блокчейні Solana. Будь-яка транзакція, що намагається зменшити баланс облікового запису нижче його відповідного мінімального балансу для звільнення від оренди, завершиться невдачею (якщо тільки баланс не зменшується до нуля). + +Коли власник облікового запису більше не бажає зберігати ці дані в ончейні та доступними в глобальному стані, він може закрити обліковий запис і повернути орендний депозит. + +Це здійснюється шляхом виведення (переказу) усього балансу лампортів облікового запису на інший обліковий запис (наприклад, ваш гаманець). Зменшивши баланс облікового запису до рівно `0`, час виконання видалить обліковий запис і його пов'язані дані з мережі в процесі _"[збирання сміття](#garbage-collection)"_. + +### Ставка оренди + +Ставка оренди Solana встановлюється на рівні всієї мережі, головним чином базуючись на часі виконання +"[лампорти _за_ байт _за_ рік](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/rent.rs#L27-L34)". Наразі ставка оренди є статичною величиною та зберігається в +[системній змінній Rent](https://docs.anza.xyz/runtime/sysvars#rent). + +Ця ставка оренди використовується для розрахунку точної суми оренди, яка повинна бути утримана в обліковому записі для виділеного простору облікового запису (тобто кількість даних, які можуть бути збережені в обліковому записі). Чим більше простору виділяє обліковий запис, тим вищим буде утриманий орендний депозит. + +### Звільнення від оренди + +Облікові записи повинні підтримувати баланс лампортів, що перевищує мінімум, необхідний для зберігання відповідних даних в ончейні. Це називається "_звільненням від оренди_", а цей баланс називається "_мінімальним балансом для звільнення від оренди_". + +> Нові облікові записи (та програми) на Solana **ЗОБОВ'ЯЗАНІ** бути ініціалізовані з достатньою кількістю лампортів, щоб стати _звільненими від оренди_. Так було не завжди. Раніше час виконання періодично та автоматично стягував плату з кожного облікового запису, що мав баланс нижче мінімуму для звільнення від оренди. Зрештою, такі облікові записи знижувалися до нульового балансу та видалялися з глобального стану (якщо їх не поповнювали вручну). + +У процесі створення нового облікового запису необхідно переконатися, що ви депонуєте достатньо лампортів, щоб перевищити цей мінімальний баланс. Все, що нижче цього мінімального порогу, призведе до невдачі транзакції. + +Кожного разу, коли баланс облікового запису зменшується, час виконання перевіряє, чи залишиться баланс цього облікового запису вище мінімального балансу для звільнення від оренди. Якщо тільки баланс не знижується до рівно `0` (закриття облікового запису), транзакції, які спричиняють падіння балансу облікового запису нижче порогу звільнення від оренди, завершаться невдачею. + +Специфічний мінімальний баланс для облікового запису, щоб стати звільненим від оренди, залежить від поточної [ставки оренди](#rent-rate) блокчейну та бажаного обсягу простору, який обліковий запис хоче виділити (розмір облікового запису). Тому рекомендується використовувати RPC-метод [`getMinimumBalanceForRentExemption`](/docs/rpc/http/getMinimumBalanceForRentExemption.mdx) для розрахунку конкретного балансу для заданого розміру облікового запису. + +Суму необхідного орендного депозиту також можна оцінити за допомогою підкоманди CLI [`solana rent`](https://docs.anza.xyz/cli/usage#solana-rent). ```shell solana rent 15000 @@ -461,36 +269,16 @@ Rent per byte-year: 0.00000348 SOL Rent per epoch: 0.000288276 SOL Rent-exempt minimum: 0.10529088 SOL ``` +### Збирання сміття -### Garbage collection - -Accounts that do not maintain a lamport balance greater than zero are removed -from the network in a process known as _garbage collection_. This process is -done to help reduce the network wide storage of no longer used/maintained data. +Облікові записи, які не підтримують баланс лампортів більше нуля, видаляються з мережі в процесі, відомому як _збирання сміття_. Цей процес виконується, щоб зменшити загальну кількість збережених у мережі даних, які більше не використовуються або не підтримуються. -After a transaction successfully reduces an accounts balance to exactly `0`, -garbage collection happens automatically by the runtime. Any transaction that -attempts to reduce an accounts balance lower that its minimum balance for rent -exemption (that is not exactly zero) will fail. +Після успішного зменшення балансу облікового запису до рівно `0` транзакцією, збирання сміття виконується автоматично часом виконання. Будь-яка транзакція, яка намагається зменшити баланс облікового запису нижче його мінімального балансу для звільнення від оренди (що не дорівнює нулю), завершиться невдачею. - -It's important to note that garbage collection happens **after** the transaction -execution is completed. If there is an instruction to "close" an account by -reducing the account balance to zero, the account can be "reopened" within the -same transaction via a later instruction. If the account state was not cleared -in the "close" instruction, the later "reopen" instruction will have the same -account state. It's a security concern, so it's good to know the exact timing -garbage collection takes effect. - +Важливо зазначити, що збирання сміття відбувається **після** завершення виконання транзакції. Якщо є інструкція "закрити" обліковий запис, зменшивши баланс облікового запису до нуля, обліковий запис може бути "повторно відкритий" у тій самій транзакції за допомогою наступної інструкції. Якщо стан облікового запису не було очищено в інструкції "закрити", наступна інструкція "повторного відкриття" матиме той самий стан облікового запису. Це є проблемою безпеки, тому важливо знати точний момент, коли збирання сміття набирає чинності. -Even after an account has been removed from the network (via garbage -collection), it may still have transactions associated with it's address (either -past history or in the future). Even though a Solana block explorer may display -an "account not found" type of message, you may still be able to view -transaction history associated with that account. +Навіть після того, як обліковий запис було видалено з мережі (через збирання сміття), він все ще може мати транзакції, пов'язані з його адресою (або в історії, або в майбутньому). Незважаючи на те, що блокчейн-експлорер Solana може відображати повідомлення типу "обліковий запис не знайдено", ви все одно можете переглядати історію транзакцій, пов'язаних із цим обліковим записом. -You can read the validator -[implemented proposal](https://docs.anza.xyz/implemented-proposals/persistent-account-storage#garbage-collection) -for garbage collection to learn more. +Ви можете прочитати [запропоновану реалізацію](https://docs.anza.xyz/implemented-proposals/persistent-account-storage#garbage-collection) для збирання сміття, щоб дізнатися більше. \ No newline at end of file diff --git a/docs/uk/core/index.md b/docs/uk/core/index.md index 7bf9fd62a..b084e320e 100644 --- a/docs/uk/core/index.md +++ b/docs/uk/core/index.md @@ -1,117 +1,79 @@ --- -title: Core Concepts +title: Основні концепції sidebarSortOrder: 2 description: - Learn essential Solana blockchain concepts including accounts, transactions, - programs, program derived addresses, cross program invocations, and how tokens - work on Solana. + Дізнайтеся про основні концепції блокчейну Solana, включаючи облікові записи, транзакції, програми, адреси, отримані від програм, міжпрограмні виклики та як працюють токени на Solana. --- -Build a strong understanding of the core concepts that make Solana different -from other blockchains. Understanding the "Solana programming model" through -these core concepts is very important to maximize your success as a Solana -blockchain developer. +Розвивайте глибоке розуміння основних концепцій, які роблять Solana унікальним серед інших блокчейнів. Розуміння "моделі програмування Solana" через ці ключові концепції дуже важливе для максимального успіху як розробника блокчейну Solana. -## Solana Account Model +## Модель облікових записів Solana -On Solana, all data is stored in what are referred to as "accounts”. The way -data is organized on the Solana blockchain resembles a -[key-value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), -where each entry in the database is called an "account". +У Solana всі дані зберігаються в тому, що називається "обліковими записами". Організація даних у блокчейні Solana нагадує [сховище ключів і значень](https://uk.wikipedia.org/wiki/Key%E2%80%93value_%D0%B1%D0%B0%D0%B7%D0%B0_%D0%B4%D0%B0%D0%BD%D0%B8%D1%85), де кожен запис у базі даних називається "обліковим записом". -Learn more about [Accounts](/docs/core/accounts.md) here. +Дізнайтеся більше про [Облікові записи](/docs/core/accounts.md) тут. -## Transactions and Instructions +## Транзакції та інструкції -On Solana, we send [transactions](/docs/core/transactions#transaction) to -interact with the network. Transactions include one or more -[instructions](/docs/core/transactions#instruction), each representing a -specific operation to be processed. The execution logic for instructions is -stored on [programs](/docs/core/programs) deployed to the Solana network, where -each program stores its own set of instructions. +У Solana ми надсилаємо [транзакції](/docs/core/transactions#transaction), щоб взаємодіяти з мережею. Транзакції включають одну або більше [інструкцій](/docs/core/transactions#instruction), кожна з яких представляє конкретну операцію для обробки. Логіка виконання інструкцій зберігається в [програмах](/docs/core/programs), розгорнутих у мережі Solana, де кожна програма має свій власний набір інструкцій. -Learn more about [Transactions](/docs/core/transactions.md) and -[Instructions](/docs/core/transactions.md#instruction) here. +Дізнайтеся більше про [Транзакції](/docs/core/transactions.md) та [Інструкції](/docs/core/transactions.md#instruction) тут. -## Fees on Solana +## Плата на Solana -The Solana blockchain has a few different types of fees and costs that are -incurred to use the permissionless network. These can be segmented into a few -specific types: +Блокчейн Solana має кілька типів зборів та витрат, які виникають при використанні мережі без дозволу. Вони поділяються на кілька основних типів: -- [Transaction Fees](/docs/core/fees.md#transaction-fees) - A fee to have - validators process transactions/instructions -- [Prioritization Fees](/docs/core/fees.md#prioritization-fees) - An optional - fee to boost transactions processing order -- [Rent](/docs/core/fees.md#rent) - A withheld balance to keep data stored - on-chain +- [Транзакційні збори](/docs/core/fees.md#transaction-fees) — плата за обробку транзакцій/інструкцій валідаторами. +- [Пріоритизаційні збори](/docs/core/fees.md#prioritization-fees) — опціональна плата для підвищення порядку обробки транзакцій. +- [Оренда](/docs/core/fees.md#rent) — утримуваний баланс для збереження даних в ончейні. -Learn more about [Fees on Solana](/docs/core/fees.md) here. +Дізнайтеся більше про [Плату на Solana](/docs/core/fees.md) тут. -## Programs on Solana +## Програми на Solana -In the Solana ecosystem, "smart contracts" are called programs. Each program is -an on-chain account that stores executable logic, organized into specific -functions referred to as _instructions_ and called via _instruction handler_ -functions within the respective deployed program. +У екосистемі Solana "смарт-контракти" називаються програмами. Кожна програма є ончейн-обліковим записом, що зберігає виконувану логіку, організовану у функції, що називаються _інструкціями_, і викликаються через функції обробників інструкцій у відповідній розгорнутій програмі. -Learn more about [Programs on Solana](/docs/core/programs.md) here. +Дізнайтеся більше про [Програми на Solana](/docs/core/programs.md) тут. -## Program Derived Address +## Адреси, отримані від програм -Program Derived Addresses (PDAs) provide developers on Solana with two main use -cases: +Адреси, отримані від програм (Program Derived Addresses, PDAs), надають розробникам Solana дві основні можливості: -- **Deterministic Account Addresses**: PDAs provide a mechanism to - deterministically derive an address using a combination of optional "seeds" - (predefined inputs) and a specific program ID. -- **Enable Program Signing**: The Solana runtime enables programs to "sign" for - PDAs which are derived from its program ID. +- **Детерміновані адреси облікових записів**: PDAs забезпечують механізм детермінованого отримання адреси за допомогою комбінації опціональних "насіння" (заданих вхідних даних) і конкретного ідентифікатора програми. +- **Дозволити підписання програмою**: Час виконання Solana дозволяє програмам "підписувати" PDAs, які отримані від їх ідентифікатора програми. -You can think of PDAs as a way to create hashmap-like structures on-chain from a -predefined set of inputs (e.g. strings, numbers, and other account addresses). +Можна уявити PDAs як спосіб створення ончейн-структур, схожих на хеш-таблиці, з набору заданих вхідних даних (наприклад, рядків, чисел та інших адрес облікових записів). -Learn more about [Program Derived Address](/docs/core/pda.md) here. +Дізнайтеся більше про [Адреси, отримані від програм](/docs/core/pda.md) тут. -## Cross Program Invocation +## Міжпрограмні виклики -A Cross Program Invocation (CPI) refers to when one program invokes the -instructions of another program. This mechanism allows for the composability of -Solana programs. +Міжпрограмний виклик (Cross Program Invocation, CPI) означає, що одна програма викликає інструкції іншої програми. Цей механізм дозволяє програмам Solana бути композитивними. -You can think of instructions as API endpoints that a program exposes to the -network and a CPI as one API internally invoking another API. +Можна уявити інструкції як API-ендпоінти, які програма надає мережі, а CPI як один API, що викликає інший API внутрішньо. -Learn more about [Cross Program Invocation](/docs/core/cpi.md) here. +Дізнайтеся більше про [Міжпрограмні виклики](/docs/core/cpi.md) тут. -## Tokens on Solana +## Токени на Solana -Tokens are digital assets that represent ownership over diverse categories of -assets. Tokenization enables the digitalization of property rights, serving as a -fundamental component for managing both fungible and non-fungible assets. +Токени — це цифрові активи, які представляють право власності на різні категорії активів. Токенізація дозволяє оцифровувати права власності, виступаючи фундаментальним компонентом для управління як взаємозамінними, так і невзаємозамінними активами. -- Fungible Tokens represent interchangeable and divisible assets of the same - type and value (ex. USDC). -- Non-fungible Tokens (NFT) represent ownership of indivisible assets (e.g. - artwork). +- Взаємозамінні токени представляють взаємозамінні та подільні активи одного типу і вартості (наприклад, USDC). +- Невзаємозамінні токени (NFT) представляють право власності на неподільні активи (наприклад, твори мистецтва). -Learn more about [Tokens on Solana](/docs/core/tokens.md) here. +Дізнайтеся більше про [Токени на Solana](/docs/core/tokens.md) тут. -## Clusters and Endpoints +## Кластери та кінцеві точки -The Solana blockchain has several different groups of validators, known as -[Clusters](/docs/core/clusters.md). Each serving different purposes within the -overall ecosystem and containing dedicated api nodes to fulfill -[JSON-RPC](/docs/rpc/index.mdx) requests for their respective Cluster. +Блокчейн Solana має кілька різних груп валідаторів, відомих як [Кластери](/docs/core/clusters.md). Кожна з них виконує різні завдання в екосистемі та має спеціалізовані вузли API для виконання запитів [JSON-RPC](/docs/rpc/index.mdx) для свого кластеру. -The individual nodes within a Cluster are owned and operated by third parties, -with a public endpoint available for each. +Індивідуальні вузли в кластері належать і управляються третіми сторонами, причому для кожного з них доступна публічна кінцева точка. -There are three primary clusters on the Solana network, each with a different -public endpoint: +Є три основні кластери в мережі Solana, кожен з яких має свою публічну кінцеву точку: - Mainnet - `https://api.mainnet-beta.solana.com` - Devnet - `https://api.devnet.solana.com` - Testnet - `https://api.testnet.solana.com` -Learn more about [Clusters and Endpoints](/docs/core/clusters.md) here. +Дізнайтеся більше про [Кластери та кінцеві точки](/docs/core/clusters.md) тут. + diff --git a/docs/uk/core/pda.md b/docs/uk/core/pda.md index 2d0330554..3e43a9f94 100644 --- a/docs/uk/core/pda.md +++ b/docs/uk/core/pda.md @@ -1,123 +1,124 @@ --- -title: Program Derived Address (PDA) -sidebarLabel: Program Derived Address +title: Програмно Виведені Адреси (PDA) +sidebarLabel: Програмно Виведені Адреси sidebarSortOrder: 5 description: - Learn about Program Derived Addresses (PDAs) on Solana - deterministic account - addresses that enable secure program signing. Understand PDA derivation, - canonical bumps, and how to create PDA accounts. + Дізнайтеся про Програмно Виведені Адреси (PDA) в Solana — детерміновані + адреси облікових записів, які забезпечують безпечне підписання програмами. + Розберіться у виведенні PDA, канонічних бампах і створенні облікових записів PDA. --- -Program Derived Addresses (PDAs) provide developers on Solana with two main use -cases: +Програмно Виведені Адреси (PDA) надають розробникам у Solana два основних варіанти використання: -- **Deterministic Account Addresses**: PDAs provide a mechanism to - deterministically derive an address using a combination of optional "seeds" - (predefined inputs) and a specific program ID. -- **Enable Program Signing**: The Solana runtime enables programs to "sign" for - PDAs which are derived from its program ID. +- **Детерміновані адреси облікових записів**: PDA надають механізм для + детермінованого виведення адреси за допомогою комбінації необов’язкових + "сідів" (заздалегідь визначених вхідних даних) та певного ідентифікатора програми. +- **Забезпечення підписання програмами**: Рантайм Solana дозволяє програмам + "підписуватися" від імені PDA, які виведені з їхнього ідентифікатора програми. -You can think of PDAs as a way to create hashmap-like structures on-chain from a -predefined set of inputs (e.g. strings, numbers, and other account addresses). +Можна уявити PDA як спосіб створення структур, схожих на хешмапи, у блокчейні з +використанням заздалегідь визначених вхідних даних (наприклад, рядків, чисел і +інших адрес облікових записів). -The benefit of this approach is that it eliminates the need to keep track of an -exact address. Instead, you simply need to recall the specific inputs used for -its derivation. +Перевага цього підходу полягає в тому, що він усуває потребу в точному +відстеженні адреси. Натомість вам потрібно лише згадати конкретні вхідні дані, +які використовувались для її виведення. -![Program Derived Address](/assets/docs/core/pda/pda.svg) +![Програмно Виведена Адреса](/assets/docs/core/pda/pda.svg) -It's important to understand that simply deriving a Program Derived Address -(PDA) does not automatically create an on-chain account at that address. -Accounts with a PDA as the on-chain address must be explicitly created through -the program used to derive the address. You can think of deriving a PDA as -finding an address on a map. Just having an address does not mean there is -anything built at that location. +Важливо розуміти, що просте виведення Програмно Виведеної Адреси (PDA) не +автоматично створює обліковий запис у блокчейні за цією адресою. Облікові +записи з PDA як адресою в блокчейні повинні бути явно створені через програму, +яка використовувалась для виведення адреси. Можна уявити виведення PDA як +пошук адреси на карті. Мати адресу — це ще не означає, що за цією адресою +щось побудовано. -> This section will cover the details of deriving PDAs. The details on how -> programs use PDAs for signing will be addressed in the section on -> [Cross Program Invocations (CPIs)](/docs/core/cpi.md) as it requires context -> for both concepts. +> У цьому розділі буде розглянуто деталі виведення PDA. Деталі того, як +> програми використовують PDA для підписання, будуть розглянуті в розділі +> [Взаємодія між програмами (CPI)](/docs/core/cpi.md), оскільки це потребує +> контексту для обох концепцій. -## Key Points +## Основні моменти -- PDAs are addresses derived deterministically using a combination of - user-defined seeds, a bump seed, and a program's ID. +- PDA — це адреси, які виводяться детерміновано з використанням комбінації + визначених користувачем сідів, бамп сіда та ідентифікатора програми. -- PDAs are addresses that fall off the Ed25519 curve and have no corresponding - private key. +- PDA — це адреси, які виходять за межі кривої Ed25519 і не мають відповідного + приватного ключа. -- Solana programs can programmatically "sign" on behalf of PDAs that are derived - using its program ID. +- Програми Solana можуть програмно "підписуватися" від імені PDA, які виведені + за допомогою їхнього ідентифікатора програми. -- Deriving a PDA does not automatically create an on-chain account. +- Виведення PDA не створює автоматично обліковий запис у блокчейні. -- An account using a PDA as its address must be explicitly created through a - dedicated instruction within a Solana program. +- Обліковий запис з PDA як адресою повинен бути явно створений через спеціальну + інструкцію в програмі Solana. -## What is a PDA +## Що таке PDA -PDAs are addresses that are deterministically derived and look like standard -public keys, but have no associated private keys. This means that no external -user can generate a valid signature for the address. However, the Solana runtime -enables programs to programmatically "sign" for PDAs without needing a private -key. +PDA — це адреси, які виводяться детерміновано та виглядають як стандартні +публічні ключі, але не мають асоційованих приватних ключів. Це означає, що жоден +зовнішній користувач не може згенерувати дійсний підпис для цієї адреси. +Однак, рантайм Solana дозволяє програмам програмно "підписуватися" від імені +PDA без необхідності у приватному ключі. -For context, Solana -[Keypairs](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/signer/keypair.rs#L25) -are points on the Ed25519 curve (elliptic-curve cryptography) which have a -public key and corresponding private key. We often use public keys as the unique -IDs for new on-chain accounts and private keys for signing. +Для контексту, [Keypairs](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/signer/keypair.rs#L25) +у Solana є точками на кривій Ed25519 (еліптична криптографія), які мають +публічний ключ і відповідний приватний ключ. Ми часто використовуємо публічні +ключі як унікальні ідентифікатори для нових облікових записів у блокчейні, а +приватні ключі для підписання. -![On Curve Address](/assets/docs/core/pda/address-on-curve.svg) +![Адреса на кривій](/assets/docs/core/pda/address-on-curve.svg) -A PDA is a point that is intentionally derived to fall off the Ed25519 curve -using a predefined set of inputs. A point that is not on the Ed25519 curve does -not have a valid corresponding private key and cannot be used for cryptographic -operations (signing). +PDA — це точка, яка навмисно виводиться за межі кривої Ed25519 з використанням +заздалегідь визначених вхідних даних. Точка, яка не знаходиться на кривій +Ed25519, не має дійсного відповідного приватного ключа і не може бути +використана для криптографічних операцій (підписання). -A PDA can then be used as the address (unique identifier) for an on-chain -account, providing a method to easily store, map, and fetch program state. +PDA може бути використана як адреса (унікальний ідентифікатор) для облікового +запису в блокчейні, забезпечуючи спосіб зручного зберігання, мапування та +отримання стану програми. -![Off Curve Address](/assets/docs/core/pda/address-off-curve.svg) +![Адреса поза кривою](/assets/docs/core/pda/address-off-curve.svg) -## How to derive a PDA +## Як вивести PDA -The derivation of a PDA requires 3 inputs. +Виведення PDA вимагає 3 вхідних даних. -- **Optional seeds**: Predefined inputs (e.g. string, number, other account - addresses) used to derive a PDA. These inputs are converted to a buffer of - bytes. -- **Bump seed**: An additional input (with a value between 255-0) that is used - to guarantee that a valid PDA (off curve) is generated. This bump seed - (starting with 255) is appended to the optional seeds when generating a PDA to - "bump" the point off the Ed25519 curve. The bump seed is sometimes referred to - as a "nonce". -- **Program ID**: The address of the program the PDA is derived from. This is - also the program that can "sign" on behalf of the PDA +- **Необов’язкові сіди**: Заздалегідь визначені вхідні дані (наприклад, рядок, + число, інші адреси облікових записів), які використовуються для виведення + PDA. Ці вхідні дані конвертуються в буфер байтів. +- **Бамп сід**: Додатковий вхідний параметр (зі значенням між 255-0), який + використовується для забезпечення того, що згенерований PDA знаходиться поза + кривою Ed25519. Цей бамп сід (починаючи з 255) додається до необов’язкових + сідів під час генерації PDA, щоб "виштовхнути" точку за межі кривої + Ed25519. Бамп сід іноді називають "нонсом". +- **Ідентифікатор програми**: Адреса програми, з якої виведений PDA. Ця ж + програма може "підписуватися" від імені PDA. -![PDA Derivation](/assets/docs/core/pda/pda-derivation.svg) +![Виведення PDA](/assets/docs/core/pda/pda-derivation.svg) -The examples below include links to Solana Playground, where you can run the -examples in an in-browser editor. +Приклади нижче включають посилання на Solana Playground, де ви можете запустити +приклади в редакторі прямо у веббраузері. ### FindProgramAddress -To derive a PDA, we can use the +Щоб вивести PDA, ми можемо використовувати метод [`findProgramAddressSync`](https://github.com/solana-labs/solana-web3.js/blob/ca9da583a39cdf8fd874a2e03fccdc849e29de34/packages/library-legacy/src/publickey.ts#L212) -method from [`@solana/web3.js`](https://www.npmjs.com/package/@solana/web3.js). -There are equivalents of this function in other programming languages (e.g. +з пакета [`@solana/web3.js`](https://www.npmjs.com/package/@solana/web3.js). +Існують еквіваленти цієї функції на інших мовах програмування (наприклад, [Rust](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/pubkey.rs#L484)), -but in this section, we will walk through examples using Javascript. +але в цьому розділі ми розглянемо приклади з використанням Javascript. -When using the `findProgramAddressSync` method, we pass in: +Під час використання методу `findProgramAddressSync` ми передаємо: -- the predefined optional seeds converted to a buffer of bytes, and -- the program ID (address) used to derive the PDA +- заздалегідь визначені необов’язкові сіди, перетворені в буфер байтів, та +- ідентифікатор програми (адресу), використаний для виведення PDA. -Once a valid PDA is found, `findProgramAddressSync` returns both the address -(PDA) and bump seed used to derive the PDA. +Після знаходження дійсного PDA, `findProgramAddressSync` повертає як адресу +(PDA), так і бамп сід, який використовувався для виведення PDA. -The example below derives a PDA without providing any optional seeds. +Нижче наведено приклад виведення PDA без надання необов’язкових сідів. ```ts /[]/ import { PublicKey } from "@solana/web3.js"; @@ -129,17 +130,15 @@ const [PDA, bump] = PublicKey.findProgramAddressSync([], programId); console.log(`PDA: ${PDA}`); console.log(`Bump: ${bump}`); ``` - -You can run this example on -[Solana Playground](https://beta.solpg.io/66031e5acffcf4b13384cfef). The PDA and -bump seed output will always be the same: +Ви можете запустити цей приклад на +[Solana Playground](https://beta.solpg.io/66031e5acffcf4b13384cfef). Виведення PDA та +бамп сіда завжди буде однаковим: ``` PDA: Cu7NwqCXSmsR5vgGA3Vw9uYVViPi3kQvkbKByVQ8nPY9 Bump: 255 ``` - -The next example below adds an optional seed "helloWorld". +У наступному прикладі додається необов’язковий сід "helloWorld". ```ts /string/ import { PublicKey } from "@solana/web3.js"; @@ -155,37 +154,36 @@ const [PDA, bump] = PublicKey.findProgramAddressSync( console.log(`PDA: ${PDA}`); console.log(`Bump: ${bump}`); ``` - -You can also run this example on -[Solana Playground](https://beta.solpg.io/66031ee5cffcf4b13384cff0). The PDA and -bump seed output will always be the same: +Ви також можете запустити цей приклад на +[Solana Playground](https://beta.solpg.io/66031ee5cffcf4b13384cff0). Виведення PDA та +бамп сіда завжди буде однаковим: ``` PDA: 46GZzzetjCURsdFPb7rcnspbEMnCBXe9kpjrsZAkKb6X Bump: 254 ``` -Note that the bump seed is 254. This means that 255 derived a point on the -Ed25519 curve, and is not a valid PDA. +Зверніть увагу, що бамп сід дорівнює 254. Це означає, що 255 вивів точку на +кривій Ed25519 і не є дійсним PDA. -The bump seed returned by `findProgramAddressSync` is the first value (between -255-0) for the given combination of optional seeds and program ID that derives a -valid PDA. +Бамп сід, який повертається функцією `findProgramAddressSync`, — це перше +значення (у діапазоні від 255 до 0) для заданої комбінації необов’язкових сідів +та ідентифікатора програми, яке виводить дійсний PDA. -> This first valid bump seed is referred to as the "canonical bump". For program -> security, it is recommended to only use the canonical bump when working with -> PDAs. +> Це перше дійсне значення бамп сіда називається "канонічним бампом". З метою +> безпеки програм рекомендовано використовувати лише канонічний бамп при роботі +> з PDA. ### CreateProgramAddress -Under the hood, `findProgramAddressSync` will iteratively append an additional -bump seed (nonce) to the seeds buffer and call the -[`createProgramAddressSync`](https://github.com/solana-labs/solana-web3.js/blob/ca9da583a39cdf8fd874a2e03fccdc849e29de34/packages/library-legacy/src/publickey.ts#L168) -method. The bump seed starts with a value of 255 and is decreased by 1 until a -valid PDA (off curve) is found. +У своїй основі, `findProgramAddressSync` ітеративно додає додатковий бамп сід +(нонс) до буфера сідів і викликає метод +[`createProgramAddressSync`](https://github.com/solana-labs/solana-web3.js/blob/ca9da583a39cdf8fd874a2e03fccdc849e29de34/packages/library-legacy/src/publickey.ts#L168). +Значення бамп сіда починається з 255 і зменшується на 1, доки не буде знайдено +дійсний PDA (поза кривою). -You can replicate the previous example by using `createProgramAddressSync` and -explicitly passing in the bump seed of 254. +Ви можете відтворити попередній приклад, використовуючи `createProgramAddressSync` +та явно передавши бамп сід зі значенням 254. ```ts /bump/ import { PublicKey } from "@solana/web3.js"; @@ -201,23 +199,23 @@ const PDA = PublicKey.createProgramAddressSync( console.log(`PDA: ${PDA}`); ``` - -Run this example above on -[Solana Playground](https://beta.solpg.io/66031f8ecffcf4b13384cff1). Given the -same seeds and program ID, the PDA output will match the previous one: +Запустіть цей приклад вище на +[Solana Playground](https://beta.solpg.io/66031f8ecffcf4b13384cff1). За +однакових сідів та ідентифікатора програми, виведення PDA буде відповідати +попередньому прикладу: ``` PDA: 46GZzzetjCURsdFPb7rcnspbEMnCBXe9kpjrsZAkKb6X ``` -### Canonical Bump +### Канонічний бамп -The "canonical bump" refers to the first bump seed (starting from 255 and -decrementing by 1) that derives a valid PDA. For program security, it is -recommended to only use PDAs derived from a canonical bump. +"Канонічний бамп" відноситься до першого значення бамп сіда (починаючи з 255 і +зменшуючи на 1), яке виводить дійсний PDA. З метою безпеки програм +рекомендовано використовувати лише PDA, виведені з канонічного бампа. -Using the previous example as a reference, the example below attempts to derive -a PDA using every bump seed from 255-0. +Використовуючи попередній приклад як орієнтир, приклад нижче намагається +вивести PDA, використовуючи всі значення бамп сіда від 255 до 0. ```ts import { PublicKey } from "@solana/web3.js"; @@ -238,10 +236,9 @@ for (let bump = 255; bump >= 0; bump--) { } } ``` - -Run the example on -[Solana Playground](https://beta.solpg.io/66032009cffcf4b13384cff2) and you -should see the following output: +Запустіть приклад на +[Solana Playground](https://beta.solpg.io/66032009cffcf4b13384cff2), і ви +повинні побачити наступний результат: ``` bump 255: Error: Invalid seeds, address must fall off the curve @@ -253,32 +250,31 @@ bump 250: Error: Invalid seeds, address must fall off the curve ... // remaining bump outputs ``` +Як і очікувалось, бамп сід 255 викликає помилку, а перший бамп сід, який виводить +дійсний PDA, дорівнює 254. -As expected, the bump seed 255 throws an error and the first bump seed to derive -a valid PDA is 254. - -However, note that bump seeds 253-251 all derive valid PDAs with different -addresses. This means that given the same optional seeds and `programId`, a bump -seed with a different value can still derive a valid PDA. +Однак зверніть увагу, що бамп сіди 253-251 також виводять дійсні PDA з різними +адресами. Це означає, що для заданих необов’язкових сідів та `programId` бамп сід +з іншим значенням все ще може вивести дійсний PDA. - When building Solana programs, it is recommended to include security checks that - validate a PDA passed to the program is derived using the canonical bump. - Failing to do so may introduce vulnerabilities that allow for unexpected - accounts to be provided to a program. + При створенні програм на Solana рекомендовано додавати перевірки безпеки, + які підтверджують, що PDA, переданий до програми, виведений з використанням + канонічного бампа. Невиконання цього може призвести до вразливостей, які + дозволять несподіваним обліковим записам передаватися до програми. -## Create PDA Accounts +## Створення облікових записів PDA -This example program on +Ця програмна демонстрація на [Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/pda-account) -demonstrates how to create an account using a PDA as the address of the new -account. The example program is written using the Anchor framework. +показує, як створити обліковий запис, використовуючи PDA як адресу нового +облікового запису. Програма написана з використанням фреймворку Anchor. -In the `lib.rs` file, you will find the following program which includes a -single instruction to create a new account using a PDA as the address of the -account. The new account stores the address of the `user` and the `bump` seed -used to derive the PDA. +У файлі `lib.rs` ви знайдете наступну програму, яка включає єдину інструкцію +для створення нового облікового запису з використанням PDA як адреси +облікового запису. Новий обліковий запис зберігає адресу `user` та `bump` сід, +який використовувався для виведення PDA. ```rust filename="lib.rs" {11-14,26-29} use anchor_lang::prelude::*; @@ -325,10 +321,9 @@ pub struct DataAccount { pub bump: u8, } ``` - -The seeds used to derive the PDA include the hardcoded string `data` and the -address of the `user` account provided in the instruction. The Anchor framework -automatically derives the canonical `bump` seed. +Сіди, які використовуються для виведення PDA, включають зафіксований рядок `data` +та адресу облікового запису `user`, передану в інструкції. Фреймворк Anchor +автоматично виводить канонічний `bump` сід. ```rust /data/ /user.key()/ /bump/ #[account( @@ -340,10 +335,9 @@ automatically derives the canonical `bump` seed. )] pub pda_account: Account<'info, DataAccount>, ``` - -The `init` constraint instructs Anchor to invoke the System Program to create a -new account using the PDA as the address. Under the hood, this is done through a -[CPI](/docs/core/cpi.md). +Обмеження `init` вказує Anchor викликати Системну Програму для створення нового +облікового запису з використанням PDA як адреси. Це виконується за допомогою +[Взаємодії між програмами (CPI)](/docs/core/cpi.md). ```rust /init/ #[account( @@ -355,9 +349,10 @@ new account using the PDA as the address. Under the hood, this is done through a )] pub pda_account: Account<'info, DataAccount>, ``` +У тестовому файлі (`pda-account.test.ts`), розташованому за посиланням на +Solana Playground, наданим вище, ви знайдете еквівалентний код на Javascript +для виведення PDA. -In the test file (`pda-account.test.ts`) located within the Solana Playground -link provided above, you will find the Javascript equivalent to derive the PDA. ```ts /data/ /user.publicKey/ const [PDA] = PublicKey.findProgramAddressSync( @@ -365,10 +360,10 @@ const [PDA] = PublicKey.findProgramAddressSync( program.programId, ); ``` - -A transaction is then sent to invoke the `initialize` instruction to create a -new on-chain account using the PDA as the address. Once the transaction is sent, -the PDA is used to fetch the on-chain account that was created at the address. +Далі надсилається транзакція для виклику інструкції `initialize`, щоб створити +новий обліковий запис у блокчейні з використанням PDA як адреси. Після надсилання +транзакції PDA використовується для отримання облікового запису в блокчейні, +який був створений за цією адресою. ```ts /initialize()/ /PDA/ {14} it("Is initialized!", async () => { @@ -388,7 +383,6 @@ it("Fetch Account", async () => { console.log(JSON.stringify(pdaAccount, null, 2)); }); ``` - -Note that if you invoke the `initialize` instruction more than once using the -same `user` address as a seed, then the transaction will fail. This is because -an account will already exist at the derived address. +Зверніть увагу, що якщо ви викликаєте інструкцію `initialize` більше одного разу, +використовуючи ту саму адресу `user` як сід, транзакція завершиться помилкою. +Це відбувається тому, що обліковий запис вже існує за виведеною адресою. diff --git a/docs/uk/core/programs.md b/docs/uk/core/programs.md index 89e34cdad..596c9b930 100644 --- a/docs/uk/core/programs.md +++ b/docs/uk/core/programs.md @@ -1,95 +1,92 @@ --- -title: Programs -sidebarLabel: Programs on Solana +title: Програми +sidebarLabel: Програми на Solana sidebarSortOrder: 4 description: - Learn about Solana programs (smart contracts) and how to develop them using - Rust or the Anchor framework. Understand program deployment, upgrades, and - verification on the Solana network. + Дізнайтеся про програми Solana (смарт-контракти) та як розробляти їх за + допомогою Rust або фреймворку Anchor. Зрозумійте процес розгортання, оновлення + та перевірки програм у мережі Solana. --- -In the Solana ecosystem, "smart contracts" are called programs. Each -[program](/docs/core/accounts.md#program-account) is an on-chain account that -stores executable logic, organized into specific functions referred to as -[instructions](/docs/core/transactions.md#instruction). +У екосистемі Solana "смарт-контракти" називаються програмами. Кожна +[програма](/docs/core/accounts.md#program-account) є обліковим записом у блокчейні, +який зберігає виконувану логіку, організовану у вигляді конкретних функцій, які +називаються [інструкціями](/docs/core/transactions.md#instruction). -## Key Points +## Основні моменти -- Programs are on-chain accounts that contain executable code. This code is - organized into distinct functions known as instructions. +- Програми — це облікові записи у блокчейні, які містять виконуваний код. Цей код + організований у вигляді окремих функцій, відомих як інструкції. -- Programs are stateless but can include instructions to create new accounts, - which are used to store and manage program state. +- Програми не зберігають стану, але можуть включати інструкції для створення нових + облікових записів, які використовуються для зберігання та управління станом програми. -- Programs can be updated by an upgrade authority. A program becomes immutable - when the upgrade authority is set to null. +- Програми можуть оновлюватися за допомогою "авторитету оновлення". Програма стає + незмінною, коли авторитет оновлення встановлюється у значення null. -- Verifiable builds enable users to verify that onchain programs match the - publicly available source code. +- Перевірювані збірки дозволяють користувачам переконатися, що програми у блокчейні + відповідають доступному публічно вихідному коду. -## Writing Solana Programs +## Написання програм Solana -Solana programs are predominantly written in the -[Rust](https://doc.rust-lang.org/book/) programming language, with two common -approaches for development: +Програми Solana зазвичай пишуться мовою програмування +[Rust](https://doc.rust-lang.org/book/) з використанням двох підходів: -- [Anchor](/docs/programs/anchor): A framework designed for Solana program - development. It provides a faster and simpler way to write programs, using - Rust macros to significantly reduce boilerplate code. For beginners, it is - recommended to start with the Anchor framework. +- [Anchor](/docs/programs/anchor): Фреймворк, створений для розробки програм Solana. + Він забезпечує швидший і простіший спосіб написання програм, використовуючи макроси + Rust для значного зменшення обсягу шаблонного коду. Для початківців рекомендується + починати з фреймворку Anchor. -- [Native Rust](/content/guides/getstarted/intro-to-native-rust.md): This - approach involves writing Solana programs in Rust without leveraging any - frameworks. It offers more flexibility but comes with increased complexity. +- [Нативний Rust](/content/guides/getstarted/intro-to-native-rust.md): Цей підхід + передбачає написання програм Solana на Rust без використання фреймворків. Він + надає більше гнучкості, але супроводжується підвищеною складністю. -## Updating Solana Programs +## Оновлення програм Solana -On-chain programs can be -[directly modified](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L675) -by an account designated as the "upgrade authority", which is typically the -account that originally deployed the program. +Програми у блокчейні можуть бути +[безпосередньо змінені](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L675) +обліковим записом, призначеним як "авторитет оновлення", зазвичай це обліковий +запис, який початково розгорнув програму. -If the -[upgrade authority](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L865) -is revoked and set to `None`, the program becomes immutable and can no longer be -updated. +Якщо +[авторитет оновлення](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L865) +скасований і встановлений у `None`, програма стає незмінною і більше не може бути оновлена. -## Verifiable Programs +## Перевірювані програми -Ensuring the integrity and verifiability of on-chain code is essential. A -verifiable build ensures that the executable code deployed on-chain can be -independently verified to match its public source code by any third party. This -process enhances transparency and trust, making it possible to detect -discrepancies between the source code and the deployed program. +Забезпечення цілісності та перевірюваності коду у блокчейні є важливим. +Перевірювана збірка гарантує, що виконуваний код, розгорнутий у блокчейні, може +бути незалежно перевірений на відповідність його публічному вихідному коду +будь-якою третьою стороною. Цей процес підвищує прозорість і довіру, дозволяючи +виявляти розбіжності між вихідним кодом і розгорнутою програмою. -The Solana developer community has introduced tools to support verifiable -builds, enabling both developers and users to verify that onchain programs -accurately reflect their publicly shared source code. +Спільнота розробників Solana створила інструменти для підтримки перевірюваних +збірок, які дозволяють як розробникам, так і користувачам переконатися, що +програми у блокчейні точно відображають їхній публічний вихідний код. -- **Searching for Verified Programs**: To quickly check for verified programs, - users can search for a program address on the [SolanaFM](https://solana.fm/) - Explorer and navigate to the "Verification" tab. View an example of a verified - program - [here](https://solana.fm/address/PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY). +- **Пошук перевірених програм**: Для швидкої перевірки програм користувачі можуть + знайти адресу програми у [SolanaFM](https://solana.fm/) Explorer і перейти на + вкладку "Verification". Приклад перевіреної програми можна побачити + [тут](https://solana.fm/address/PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY). -- **Verification Tools**: The - [Solana Verifiable Build CLI](https://github.com/Ellipsis-Labs/solana-verifiable-build) - by Ellipsis Labs enables users to independently verify onchain programs - against published source code. +- **Інструменти перевірки**: CLI + [Solana Verifiable Build](https://github.com/Ellipsis-Labs/solana-verifiable-build) + від Ellipsis Labs дозволяє незалежно перевірити програми у блокчейні на відповідність + опублікованому вихідному коду. -- **Support for Verifiable Builds in Anchor**: Anchor provides built-in support - for verifiable builds. Details can be found in the - [Anchor documentation](https://www.anchor-lang.com/docs/verifiable-builds). +- **Підтримка перевірюваних збірок в Anchor**: Anchor має вбудовану підтримку + перевірюваних збірок. Деталі можна знайти у + [документації Anchor](https://www.anchor-lang.com/docs/verifiable-builds). ## Berkeley Packet Filter (BPF) -Solana leverages the [LLVM compiler infrastructure](https://llvm.org/) to -compile programs into -[Executable and Linkable Format (ELF)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) -files. These files include a modified version of -[Berkeley Packet Filter (eBPF)](https://en.wikipedia.org/wiki/EBPF) bytecode for -Solana programs, known as "Solana Bytecode Format" (sBPF). +Solana використовує [інфраструктуру компілятора LLVM](https://llvm.org/) для +компіляції програм у файли формату +[Executable and Linkable Format (ELF)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format). +Ці файли включають модифіковану версію байт-коду +[Berkeley Packet Filter (eBPF)](https://en.wikipedia.org/wiki/EBPF) для програм Solana, +відомого як "Solana Bytecode Format" (sBPF). -The use of LLVM enables Solana to potentially support any programming language -that can compile to LLVM's BPF backend. This significantly enhances the -flexibility of Solana as a development platform. +Використання LLVM дозволяє Solana підтримувати будь-яку мову програмування, яка +може компілюватися у BPF-бекенд LLVM. Це значно підвищує гнучкість Solana як платформи +для розробки. diff --git a/docs/uk/core/tokens.md b/docs/uk/core/tokens.md index 0cbd5cf23..370e68e56 100644 --- a/docs/uk/core/tokens.md +++ b/docs/uk/core/tokens.md @@ -1,109 +1,106 @@ --- -title: "Tokens on Solana" +title: "Токени на Solana" sidebarSortOrder: 7 description: - Learn about Solana tokens (SPL Tokens) including fungible and non-fungible - tokens, Token Program, Token Extensions Program, mint accounts, token - accounts, and practical examples for creating and managing tokens on Solana. + Дізнайтеся про токени Solana (SPL Tokens), включаючи взаємозамінні та + невзаємозамінні токени, Програму Токенів, Програму Розширень Токенів, + облікові записи випуску токенів, токен-облікові записи, а також практичні + приклади створення і управління токенами на Solana. --- -Tokens are digital assets that represent ownership over diverse categories of -assets. Tokenization enables the digitalization of property rights, serving as a -fundamental component for managing both fungible and non-fungible assets. +Токени — це цифрові активи, які представляють право власності на різні категорії +активів. Токенізація дозволяє цифровізувати права власності, виступаючи як +фундаментальний компонент для управління взаємозамінними та невзаємозамінними +активами. -- Fungible Tokens represent interchangeable and divisible assets of the same - type and value (ex. USDC). -- Non-fungible Tokens (NFT) represent ownership of indivisible assets (e.g. - artwork). +- **Взаємозамінні токени** представляють активи, які можна замінювати і ділити + (наприклад, USDC). +- **Невзаємозамінні токени (NFT)** представляють право власності на неподільні + активи (наприклад, витвори мистецтва). -This section will cover the basics of how tokens are represented on Solana. -These are referred to as SPL -([Solana Program Library](https://github.com/solana-labs/solana-program-library)) -Tokens. +У цьому розділі буде розглянуто основи представлення токенів у Solana. Ці токени +називаються SPL +([Solana Program Library](https://github.com/solana-labs/solana-program-library)). -- The [Token Program](#token-program) contains all the instruction logic for - interacting with tokens on the network (both fungible and non-fungible). +- [Програма Токенів](#token-program) містить всю логіку інструкцій для + взаємодії з токенами в мережі (як взаємозамінними, так і невзаємозамінними). -- A [Mint Account](#mint-account) represents a specific type of token and stores - global metadata about the token such as the total supply and mint authority - (address authorized to create new units of a token). +- [Обліковий запис випуску токенів](#mint-account) представляє певний тип токена + і зберігає глобальні метадані, такі як загальна кількість токенів і авторитет + випуску (адреса, уповноважена створювати нові одиниці токенів). -- A [Token Account](#token-account) keeps track of individual ownership of how - many units of a specific type of token (mint account) are owned by a specific - address. +- [Токен-обліковий запис](#token-account) відстежує індивідуальну власність на + певну кількість токенів конкретного типу (облікового запису випуску токенів). -> There are currently two versions of the Token Program. The original -> [Token Program](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) -> and the -> [Token Extensions Program](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program-2022) -> (Token2022). The Token Extensions Program functions the same as the original -> Token Program, but with additional features and improvements. The Token -> Extensions Program is the recommended version to use for creating new tokens -> (mint accounts). +> Наразі існує дві версії Програми Токенів: оригінальна +> [Програма Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) +> і +> [Програма Розширень Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program-2022) +> (Token2022). Програма Розширень Токенів працює так само, як і оригінальна +> Програма Токенів, але з додатковими функціями і покращеннями. Для створення +> нових токенів рекомендовано використовувати Програму Розширень Токенів. -## Key Points +## Основні моменти -- Tokens represent ownership over either fungible (interchangeable) or - non-fungible (unique) assets. +- Токени представляють право власності на взаємозамінні (змінні) або + невзаємозамінні (унікальні) активи. -- The Token Program contains all instruction for interacting with both fungible - and non-fungible tokens on the network. +- Програма Токенів містить усі інструкції для взаємодії з токенами в мережі. -- The Token Extensions Program is a new version of the Token Program that - includes additional features while maintaining the same core functionalities. +- Програма Розширень Токенів — це нова версія Програми Токенів, яка включає + додаткові функції, зберігаючи основну функціональність. -- A Mint Account represents a unique token on the network and stores global - metadata such as total supply. +- Обліковий запис випуску токенів представляє унікальний токен у мережі і + зберігає глобальні метадані, такі як загальна кількість токенів. -- A Token Account tracks individual ownership of tokens for a specific mint - account. +- Токен-обліковий запис відстежує індивідуальну власність на токени для певного + облікового запису випуску токенів. -- An Associated Token Account is a Token Account created with an address derived - from the owner's and mint account's addresses. +- Асоційований Токен-обліковий запис — це токен-обліковий запис, створений із + адреси, отриманої із адреси власника та адреси облікового запису випуску токенів. -## Token Program +## Програма Токенів -The -[Token Program](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) -contains all the instruction logic for interacting with tokens on the network -(both fungible and non-fungible). All tokens on Solana are effectively -[data accounts](/docs/core/accounts.md#data-account) owned by the Token Program. +[Програма Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) +містить всю логіку інструкцій для взаємодії з токенами в мережі (як +взаємозамінними, так і невзаємозамінними). Усі токени на Solana фактично є +[даними облікових записів](/docs/core/accounts.md#data-account), якими володіє Програма Токенів. -You can find the full list of Token Program instructions -[here](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/instruction.rs). +Повний список інструкцій Програми Токенів можна знайти +[тут](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/instruction.rs). -![Token Program](/assets/docs/core/tokens/token-program.svg) +![Програма Токенів](/assets/docs/core/tokens/token-program.svg) -A few commonly used instructions include: +Кілька найчастіше використовуваних інструкцій включають: - [`InitializeMint`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L29): - Create a new mint account to represent a new type of token. + Створення нового облікового запису випуску токенів для представлення нового типу токена. - [`InitializeAccount`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L84): - Create a new token account to hold units of a specific type of token (mint). + Створення нового токен-облікового запису для зберігання одиниць певного типу токенів (випуску). - [`MintTo`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L522): - Create new units of a specific type of token and add them to a token account. - This increases the supply of the token and can only be done by the mint - authority of the mint account. + Створення нових одиниць певного типу токенів і додавання їх до токен-облікового запису. + Це збільшує кількість токенів і може виконуватися лише авторитетом випуску + облікового запису випуску токенів. - [`Transfer`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L228): - Transfer units of a specific type of token from one token account to another. + Передача одиниць певного типу токенів із одного токен-облікового запису в інший. -### Mint Account +### Обліковий запис випуску токенів -Tokens on Solana are uniquely identified by the address of a -[Mint Account](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32) -owned by the Token Program. This account is effectively a global counter for a -specific token, and stores data such as: +Токени на Solana унікально ідентифікуються за адресою +[Облікового запису випуску токенів](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32), +яким володіє Програма Токенів. Цей обліковий запис фактично є глобальним лічильником +для певного токена і зберігає дані, такі як: -- Supply: Total supply of the token -- Decimals: Decimal precision of the token -- Mint authority: The account authorized to create new units of the token, thus - increasing the supply -- Freeze authority: The account authorized to freeze tokens from being - transferred from "token accounts" +- Загальна кількість: Загальна кількість токенів. +- Десяткові знаки: Точність токена у десяткових знаках. +- Авторитет випуску: Обліковий запис, уповноважений створювати нові одиниці + токенів, таким чином збільшуючи кількість. +- Авторитет замороження: Обліковий запис, уповноважений заморожувати токени, + щоб їх не можна було передати із "токен-облікових записів". -![Mint Account](/assets/docs/core/tokens/mint-account.svg) +![Обліковий запис випуску токенів](/assets/docs/core/tokens/mint-account.svg) -The full details stored on each Mint Account include the following: +Повна інформація, яка зберігається в кожному обліковому записі випуску токенів, включає: ```rust pub struct Mint { @@ -122,27 +119,25 @@ pub struct Mint { pub freeze_authority: COption, } ``` +Для довідки, ось посилання на Solana Explorer для +[Облікового запису випуску USDC](https://explorer.solana.com/address/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v). -For reference, here is a Solana Explorer link to the -[USDC Mint Account](https://explorer.solana.com/address/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v). +### Токен-обліковий запис -### Token Account +Для відстеження індивідуальної власності на кожну одиницю певного токена має бути +створений інший тип облікового запису даних, яким володіє Програма Токенів. Цей +обліковий запис називається +[Токен-обліковий запис](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L89-L110). -To track the individual ownership of each unit of a specific token, another type -of data account owned by the Token Program must be created. This account is -referred to as a -[Token Account](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L89-L110). +Найчастіше згадувані дані, які зберігаються в Токен-обліковому записі, включають: -The most commonly referenced data stored on the Token Account include the -following: +- **Випуск (Mint)**: Тип токена, одиниці якого зберігаються в Токен-обліковому записі. +- **Власник (Owner)**: Обліковий запис, уповноважений передавати токени з Токен-облікового запису. +- **Кількість (Amount)**: Кількість одиниць токена, які наразі зберігаються в Токен-обліковому записі. -- Mint: The type of token the Token Account holds units of -- Owner: The account authorized to transfer tokens out of the Token Account -- Amount: Units of the token the Token Account currently holds +![Токен-обліковий запис](/assets/docs/core/tokens/token-account.svg) -![Token Account](/assets/docs/core/tokens/token-account.svg) - -The full details stored on each Token Account includes the following: +Повна інформація, яка зберігається в кожному Токен-обліковому записі, включає: ```rust pub struct Account { @@ -168,46 +163,45 @@ pub struct Account { pub close_authority: COption, } ``` +Щоб гаманець міг володіти одиницями певного токена, потрібно створити токен-обліковий +запис для конкретного типу токена (випуску), який призначає гаманець власником +цього токен-облікового запису. Гаманець може створювати кілька токен-облікових +записів для одного і того ж типу токена, але кожен токен-обліковий запис може +належати лише одному гаманцю і зберігати одиниці лише одного типу токена. -For a wallet to own units of a certain token, it needs to create a token account -for a specific type of token (mint) that designates the wallet as the owner of -the token account. A wallet can create multiple token accounts for the same type -of token, but each token account can only be owned by one wallet and hold units -of one type of token. - -![Account Relationship](/assets/docs/core/tokens/token-account-relationship.svg) +![Взаємозв'язок облікових записів](/assets/docs/core/tokens/token-account-relationship.svg) -> Note that each Token Account's data includes an `owner` field used to identify -> who has authority over that specific Token Account. This is separate from the -> program owner specified in the -> [AccountInfo](/docs/core/accounts.md#accountinfo), which is the Token Program -> for all Token Accounts. +> Зверніть увагу, що дані кожного Токен-облікового запису містять поле `owner`, яке +> використовується для визначення того, хто має авторитет над цим Токен-обліковим записом. +> Це окремо від власника програми, зазначеного у +> [AccountInfo](/docs/core/accounts.md#accountinfo), яким є Програма Токенів для всіх +> Токен-облікових записів. -### Associated Token Account +### Асоційований токен-обліковий запис -To simplify the process of locating a token account's address for a specific -mint and owner, we often use Associated Token Accounts. +Щоб спростити процес визначення адреси токен-облікового запису для конкретного +випуску і власника, ми часто використовуємо Асоційовані Токен-облікові Записи. -An Associated Token Account is a token account whose address is -deterministically derived using the owner's address and the mint account's -address. You can think of the Associated Token Account as the "default" token -account for a specific mint and owner. +Асоційований токен-обліковий запис — це токен-обліковий запис, чия адреса +визначається детерміновано з використанням адреси власника і адреси облікового +запису випуску. Можна розглядати Асоційований токен-обліковий запис як +"стандартний" токен-обліковий запис для певного випуску і власника. -It's important to understand that an Associated Token Account isn't a different -type of token account. It's just a token account with a specific address. +Важливо розуміти, що Асоційований токен-обліковий запис не є окремим типом +токен-облікового запису. Це просто токен-обліковий запис із певною адресою. -![Associated Token Account](/assets/docs/core/tokens/associated-token-account.svg) +![Асоційований токен-обліковий запис](/assets/docs/core/tokens/associated-token-account.svg) -This introduces a key concept in Solana development: -[Program Derived Address (PDA)](/docs/core/pda.md). Conceptually, a PDA provides -a deterministic way to generate an address using some predefined inputs. This -enables us to easily find the address of an account at a later time. +Це вводить ключове поняття в розробці Solana: +[Програмно Виведена Адреса (PDA)](/docs/core/pda.md). Концептуально PDA надає +детермінований спосіб генерації адреси з використанням заздалегідь визначених +вхідних даних. Це дозволяє нам легко знайти адресу облікового запису в майбутньому. -Here is a [Solana Playground](https://beta.solpg.io/656a2dd0fb53fa325bfd0c41) -example that derives the USDC Associated Token Account address and owner. It -will always generate the -[same address](https://explorer.solana.com/address/4kokFKCFMxpCpG41yLYkLEqXW8g1WPfCt2NC9KGivY6N) -for the same mint and owner. +Ось [приклад на Solana Playground](https://beta.solpg.io/656a2dd0fb53fa325bfd0c41), +який виводить адресу і власника Асоційованого токен-облікового запису USDC. Він +завжди генерує +[одну й ту саму адресу](https://explorer.solana.com/address/4kokFKCFMxpCpG41yLYkLEqXW8g1WPfCt2NC9KGivY6N) +для одного і того ж випуску і власника. ```ts import { getAssociatedTokenAddressSync } from "@solana/spl-token"; @@ -217,11 +211,10 @@ const associatedTokenAccountAddress = getAssociatedTokenAddressSync( OWNER_ADDRESS, ); ``` - -Specifically, the address for an Associated Token Account is derived using the -following inputs. Here is a -[Solana Playground](https://beta.solpg.io/656a31d0fb53fa325bfd0c42) example that -generates the same address as the previous example. +Зокрема, адреса для Асоційованого токен-облікового запису виводиться за допомогою +наступних вхідних даних. Ось +[приклад на Solana Playground](https://beta.solpg.io/656a31d0fb53fa325bfd0c42), +який генерує ту саму адресу, що й у попередньому прикладі. ```ts import { PublicKey } from "@solana/web3.js"; @@ -235,25 +228,25 @@ const [PDA, bump] = PublicKey.findProgramAddressSync( ASSOCIATED_TOKEN_PROGRAM_ID, ); ``` +Щоб два гаманці могли зберігати одиниці одного і того ж типу токена, кожен +гаманець потребує свого токен-облікового запису для конкретного облікового запису +випуску токенів. Зображення нижче демонструє, як виглядає ця структура взаємозв'язку облікових записів. -For two wallets to hold units of the same type of token, each wallet needs its -own token account for the specific mint account. The image below demonstrates -what this account relationship looks like. - -![Accounts Relationship Expanded](/assets/docs/core/tokens/token-account-relationship-ata.svg) +![Розширений взаємозв'язок облікових записів](/assets/docs/core/tokens/token-account-relationship-ata.svg) -## Token Examples +## Приклади роботи з токенами -The [`spl-token` CLI](https://docs.anza.xyz/cli) can be used to experiment with -SPL tokens. In the examples below, we'll use the -[Solana Playground](https://beta.solpg.io/) terminal to run the CLI commands -directly in the browser without having to install the CLI locally. +CLI [`spl-token`](https://docs.anza.xyz/cli) можна використовувати для експериментів +з SPL токенами. У прикладах нижче ми використовуватимемо +[Solana Playground](https://beta.solpg.io/) для виконання CLI-команд прямо в +браузері без необхідності встановлення CLI локально. -Creating tokens and accounts requires SOL for account rent deposits and -transaction fees. If it is your first time using Solana Playground, created a -Playground wallet and run the `solana airdrop` command in the Playground -terminal. You can also get devnet SOL using the public -[web faucet](https://faucet.solana.com/). +Створення токенів і облікових записів вимагає SOL для депозитів за оренду +облікових записів та оплати транзакційних комісій. Якщо ви вперше використовуєте +Solana Playground, створіть гаманець у Playground і виконайте команду +`solana airdrop` у терміналі Playground. Ви також можете отримати SOL для +devnet, використовуючи публічний +[веб-фасет](https://faucet.solana.com/). ```sh solana airdrop 2 @@ -264,31 +257,32 @@ Run `spl-token --help` for a full description of available commands. ```sh spl-token --help ``` +Крім того, ви можете встановити CLI `spl-token` локально, використовуючи наступну +команду. Для цього спочатку потрібно +[встановити Rust](https://rustup.rs/). -Alternatively, you can install the spl-token CLI locally using the following -command. This requires first [installing Rust](https://rustup.rs/). +> У наступних розділах адреси облікових записів, які відображаються під час +> виконання CLI-команд, можуть відрізнятися від прикладів, наведених нижче. Будь ласка, +> використовуйте адреси, які відображаються у вашому терміналі Playground, під час +> виконання команд. Наприклад, адреса, отримана в результаті виконання `create-token`, +> є обліковим записом випуску токенів, де ваш гаманець Playground призначений +> авторитетом випуску. -> In the following sections, the account addresses displayed when you run the -> CLI command will differ from the example output shown below. Please use the -> address shown in your Playground terminal when following along. For example, -> the address output from the `create-token` is the mint account where your -> Playground wallet is set as the mint authority. +### Створення нового токена -### Create a New Token - -To create a new token ([mint account](#mint-account)) run the following command -in the Solana Playground terminal. +Щоб створити новий токен +([обліковий запис випуску токенів](#mint-account)), виконайте наступну команду +в терміналі Solana Playground. ```sh spl-token create-token ``` +Ви повинні побачити результат, подібний до наведеного нижче. Ви можете переглянути +деталі як токена, так і транзакції у +[Solana Explorer](https://explorer.solana.com/?cluster=devnet), використовуючи +`Address` (адресу) та `Signature` (підпис). -You should see an output similar to the following below. You can inspect both -the token and transaction details on -[Solana Explorer](https://explorer.solana.com/?cluster=devnet) using the -`Address` and `Signature`. - -In the example output below, the unique identifier (address) of the new token is +У прикладі результату нижче унікальний ідентифікатор (адреса) нового токена — `99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg`. ```shell filename="Terminal Output" /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ @@ -299,138 +293,127 @@ Decimals: 9 Signature: 44fvKfT1ezBUwdzrCys3fvCdFxbLMnNvBstds76QZyE6cXag5NupBprSXwxPTzzjrC3cA6nvUZaLFTvmcKyzxrm1 ``` - -New tokens initially have no supply. You can check the current supply of a token -using the following command: +Нові токени спочатку мають нульовий запас. Ви можете перевірити поточний запас +токена, використовуючи наступну команду: ```sh spl-token supply ``` - -Running the `supply` command for a newly created token will return a value of -`0`: +Запуск команди `supply` для новоствореного токена поверне значення `0`: ```sh /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ spl-token supply 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg ``` - -Under the hood, creating a new Mint Account requires sending a transaction with -two instructions. Here is a Javascript example on +У своїй основі створення нового облікового запису випуску токенів (Mint Account) +вимагає надсилання транзакції з двома інструкціями. Ось приклад на Javascript у [Solana Playground](https://beta.solpg.io/660ce32ecffcf4b13384d00f). -1. Invoke the System Program to create a new account with enough space for the - Mint Account data and then transfer ownership to the Token Program. +1. Виклик Системної Програми для створення нового облікового запису з достатнім + обсягом пам'яті для даних облікового запису випуску токенів, а потім передача + власності Програмі Токенів. -2. Invoke the Token Program to initialize the data of the new account as a Mint - Account +2. Виклик Програми Токенів для ініціалізації даних нового облікового запису як + облікового запису випуску токенів. -### Create Token Account +### Створення Токен-облікового запису -To hold units of a particular token, you must first create a -[token account](#token-account). To create a new token account, use the -following command: +Щоб зберігати одиниці певного токена, вам потрібно спочатку створити +[токен-обліковий запис](#token-account). Для створення нового токен-облікового +запису скористайтеся наступною командою: ```sh spl-token create-account [OPTIONS] ``` - -For example, running the following command in the Solana Playground terminal: +Наприклад, виконання наступної команди в терміналі Solana Playground: ```sh /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ spl-token create-account 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg -``` - -Returns the following output: - -- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` is the address of the token - account created to hold units of the token specified in the `create-account` - command. +```: +Виведе наступний результат +- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9`це адреса токен-облікового запису, створеного для зберігання одиниць токена, +вказаного в команді `create-account`. ```shell filename="Terminal Output" /AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9/ Creating account AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9 Signature: 2BtrynuCLX9CNofFiaw6Yzbx6hit66pup9Sk7aFjwU2NEbFz7NCHD9w9sWhrCfEd73XveAGK1DxFpJoQZPXU9tS1 ``` +За замовчуванням команда `create-account` створює +[асоційований токен-обліковий запис](#associated-token-account) з адресою вашого +гаманця як власника токен-облікового запису. -By default the `create-account` command creates an -[associated token account](#associated-token-account) with your wallet address -as the token account owner. - -You can create a token account with a different owner using the following -command: +Ви можете створити токен-обліковий запис з іншим власником, використовуючи +наступну команду: ```sh spl-token create-account --owner ``` - -For example, running the following command: - +Наприклад, виконання наступної команди: ```sh /2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR/ spl-token create-account --owner 2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg ``` -Returns the following output: +Виведе наступний результат: -- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` is the address of the token - account created to hold units of the token specified in the `create-account` - command (`99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg`) and owned by the - address specified following the `--owner` flag - (`2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR`). This is useful when you need - to create a token account for another user. +- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` — це адреса токен-облікового запису, + створеного для зберігання одиниць токена, вказаного в команді `create-account` + (`99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg`), і який належить адресі, + вказаній після прапора `--owner` + (`2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR`). Це корисно, коли вам потрібно + створити токен-обліковий запис для іншого користувача. ```shell filename="Terminal Output" /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ Creating account Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt Signature: 44vqKdfzspT592REDPY4goaRJH3uJ3Ce13G4BCuUHg35dVUbHuGTHvqn4ZjYF9BGe9QrjMfe9GmuLkQhSZCBQuEt ``` - -Under the hood, creating an Associated Token Account requires a single -instruction that invokes the -[Associated Token Program](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src). -Here is a Javascript example on +За лаштунками створення Асоційованого токен-облікового запису потребує однієї +інструкції, яка викликає +[Програму Асоційованих Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src). +Ось приклад на Javascript у [Solana Playground](https://beta.solpg.io/660ce868cffcf4b13384d011). -The Associated Token Program uses [Cross Program Invocations](/docs/core/cpi.md) -to handle: +Програма Асоційованих Токенів використовує +[Перехресні Виклики Програм (CPI)](/docs/core/cpi.md) для виконання наступного: -- [Invoking the System Program](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src/tools/account.rs#L19) - to create a new account using the provided PDA as the address of the new - account -- [Invoking the Token Program](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src/processor.rs#L138-L161) - to initialize the Token Account data for the new account. +- [Виклик Системної Програми](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src/tools/account.rs#L19) + для створення нового облікового запису, використовуючи надану PDA як адресу + нового облікового запису. +- [Виклик Програми Токенів](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src/processor.rs#L138-L161) + для ініціалізації даних токен-облікового запису для нового облікового запису. -Alternatively, creating a new Token Account using a randomly generated keypair -(not an Associated Token Account) requires sending a transaction with two -instructions. Here is a Javascript example on +Крім того, створення нового токен-облікового запису за допомогою випадково +згенерованої пари ключів (не Асоційованого токен-облікового запису) потребує +надсилання транзакції з двома інструкціями. Ось приклад на Javascript у [Solana Playground](https://beta.solpg.io/660ce716cffcf4b13384d010). -1. Invoke the System Program to create a new account with enough space for the - Token Account data and then transfer ownership to the Token Program. +1. Виклик Системної Програми для створення нового облікового запису з достатнім + обсягом пам'яті для даних токен-облікового запису, а потім передача власності + Програмі Токенів. -2. Invoke the Token Program to initialize the data of the new account as a Token - Account +2. Виклик Програми Токенів для ініціалізації даних нового облікового запису як + токен-облікового запису. -### Mint Tokens +### Випуск токенів -To create new units of a token, use the following command: +Щоб створити нові одиниці токена, використовуйте наступну команду: ```sh spl-token mint [OPTIONS] [--] [RECIPIENT_TOKEN_ACCOUNT_ADDRESS] ``` -For example, running the following command: +Наприклад, виконання наступної команди: ```sh spl-token mint 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 ``` -Returns the following output: - -- `99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg` is the address of the mint - account that tokens are being minted for (increasing total supply). +Виведе наступний результат: +- `99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg` — це адреса облікового запису + випуску токенів, для якого випускаються токени (збільшуючи загальну кількість). -- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` is the address of your wallet's - token account that units of the token are being minted to (increasing amount). +- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` — це адреса токен-облікового запису + вашого гаманця, до якого випускаються одиниці токена (збільшуючи кількість). ```shell filename="Terminal Output" /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ /AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9/ Minting 100 tokens @@ -439,21 +422,19 @@ Minting 100 tokens Signature: 2NJ1m7qCraPSBAVxbr2ssmWZmBU9Jc8pDtJAnyZsZJRcaYCYMqq1oRY1gqA4ddQno3g3xcnny5fzr1dvsnFKMEqG ``` +Щоб випустити токени до іншого токен-облікового запису, вкажіть адресу +потрібного облікового запису одержувача токенів. -To mint tokens to a different token account, specify the address of the intended -recipient token account. For example, running the following command: +Наприклад, виконання наступної команди: ```sh /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ spl-token mint 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 -- Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt ``` +Повертає наступний результат: -Returns the following output: + - 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg — це адреса облікового запису випуску токенів, для якого випускаються токени (збільшуючи загальну кількість). -- `99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg` is the address of the mint - account that tokens are being minted for (increasing total supply). - -- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` is the address of the token - account that units of the token are being minted to (increasing amount). + - Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt — це адреса токен-облікового запису, до якого випускаються одиниці токена (збільшуючи кількість). ```shell filename="Terminal Output" /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ Minting 100 tokens @@ -462,37 +443,32 @@ Minting 100 tokens Signature: 3SQvNM3o9DsTiLwcEkSPT1Edr14RgE2wC54TEjonEP2swyVCp2jPWYWdD6RwXUGpvDNUkKWzVBZVFShn5yntxVd7 ``` - -Under the hood, creating new units of a token requires invoking the `MintTo` -instruction on the Token Program. This instruction must be signed by the mint -authority. The instruction mints new units of the token to a Token Account and -increases the total supply on the Mint Account. Here is a Javascript example on +За лаштунками створення нових одиниць токена потребує виклику інструкції `MintTo` +у Програмі Токенів. Ця інструкція повинна бути підписана авторитетом випуску. +Інструкція випускає нові одиниці токена до Токен-облікового запису та збільшує +загальну кількість у Обліковому записі випуску токенів. Ось приклад на Javascript у [Solana Playground](https://beta.solpg.io/660cea45cffcf4b13384d012). -### Transfer Tokens +### Передача токенів -To transfer units of a token between two token accounts, use the following -command: +Щоб передати одиниці токена між двома токен-обліковими записами, використовуйте +наступну команду: ```sh spl-token transfer [OPTIONS] ``` - -For example, running the following command: - +Наприклад, виконання наступної команди: ```sh spl-token transfer 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt ``` +Повертає наступний результат: +- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` — це адреса токен-облікового запису, + з якого передаються токени. Це буде адреса вашого токен-облікового запису для + вказаного токена, який передається. -Returns the following output: - -- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` is the address of the token - account that tokens are being transferred from. This would be the address of - your token account for the specified token being transferred. - -- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` is the address of the token - account that tokens are being transferred to. +- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` — це адреса токен-облікового запису, + до якого передаються токени. ```shell filename="Terminal Output" /AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9/ /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ Transfer 100 tokens @@ -501,41 +477,39 @@ Transfer 100 tokens Signature: 5y6HVwV8V2hHGLTVmTmdySRiEUCZnWmkasAvJ7J6m7JR46obbGKCBqUFgLpZu5zQGwM4Xy6GZ4M5LKd1h6Padx3o ``` - -Under the hood, transferring tokens requires invoking the `Transfer` instruction -on the Token Program. This instruction must be signed by the owner of the -sender's Token Account. The instruction transfers units of a token from one -Token Account to another Token Account. Here is a Javascript example on +За лаштунками, передача токенів потребує виклику інструкції `Transfer` у Програмі Токенів. +Ця інструкція повинна бути підписана власником токен-облікового запису відправника. +Інструкція передає одиниці токена з одного Токен-облікового запису до іншого. +Ось приклад на Javascript у [Solana Playground](https://beta.solpg.io/660ced84cffcf4b13384d013). -It's important to understand that both the sender and recipient must have -existing token accounts for the specific type of token being transferred. The -sender can include additional instructions on the transaction to create the -recipient's token account, which generally is the Associated Token Account. +Важливо розуміти, що як у відправника, так і у одержувача повинні існувати токен-облікові +записи для конкретного типу токена, який передається. Відправник може додати додаткові +інструкції до транзакції для створення токен-облікового запису одержувача, який, як правило, +є Асоційованим Токен-обліковим записом. -### Create Token Metadata +### Створення метаданих токенів -The Token Extensions Program enables additional customizable metadata (such as -name, symbol, link to image) to be stored directly on the Mint Account. +Програма Розширень Токенів дозволяє додавати настроювані метадані (наприклад, назву, +символ, посилання на зображення) безпосередньо до Облікового запису випуску токенів. - To use the Token Extensions CLI flags, ensure you have a local installation of the CLI, version 3.4.0 or later: + Щоб використовувати параметри CLI для розширень токенів, переконайтеся, що ви маєте + локально встановлений CLI, версії 3.4.0 або пізнішої: `cargo install --version 3.4.0 spl-token-cli` -To create a new token with the metadata extension enabled, using the following -command: +Щоб створити новий токен із увімкненим розширенням метаданих, скористайтеся наступною командою: ```sh spl-token create-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb --enable-metadata ``` +Команда повертає наступний результат: -The command returns the following output: - -- `BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP` is the address of the new token - created with the metadata extension enabled. +- `BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP` — це адреса нового токена, + створеного з увімкненим розширенням метаданих. ```shell filename="Terminal Output" /BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP/ Creating token BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP under program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb @@ -546,35 +520,32 @@ Decimals: 9 Signature: 5iQofFeXdYhMi9uTzZghcq8stAaa6CY6saUwcdnELST13eNSifiuLbvR5DnRt311frkCTUh5oecj8YEvZSB3wfai ``` - -Once a new token is created with the metadata extension enabled, use the -following command to initialize the metadata. +Після створення нового токена з увімкненим розширенням метаданих використовуйте +наступну команду для ініціалізації метаданих: ```sh spl-token initialize-metadata ``` -The token URI is normally a link to offchain metadata you want to associate with -the token. You can find an example of the JSON format -[here](https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json). +Токен URI зазвичай є посиланням на позаблокові метадані, які ви хочете +асоціювати з токеном. Приклад формату JSON можна знайти +[тут](https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json). -For example, running the following command will store the additional metadata -directly on the specified mint account: +Наприклад, виконання наступної команди дозволить зберегти додаткові метадані +безпосередньо в зазначеному обліковому записі випуску токенів: ```sh /BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP/ spl-token initialize-metadata BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP "TokenName" "TokenSymbol" "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json" ``` -You can then look up the address of the mint account on an explorer to inspect -the metadata. For example, here is a token created with the metadata extension -enabled on the -[SolanaFm](https://solana.fm/address/BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP?cluster=devnet-solana) -explorer. - -You can learn more on the -[Metadata Extension Guide](https://solana.com/developers/guides/token-extensions/metadata-pointer). -For more details related to various Token Extensions, refer to the Token -Extensions -[Getting Started Guide](https://solana.com/developers/guides/token-extensions/getting-started) -and the [SPL documentation](https://spl.solana.com/token-2022/extensions). +Ви можете знайти адресу облікового запису випуску токенів у експлорері, щоб +переглянути метадані. Наприклад, ось токен, створений із увімкненим розширенням +метаданих, у експлорері +[SolanaFm](https://solana.fm/address/BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP?cluster=devnet-solana). + +Дізнатися більше можна у +[Посібнику з Розширення Метаданих](https://solana.com/developers/guides/token-extensions/metadata-pointer). +Деталі щодо різних Розширень Токенів ви знайдете у +[Посібнику Початківця з Розширень Токенів](https://solana.com/developers/guides/token-extensions/getting-started) +та [документації SPL](https://spl.solana.com/token-2022/extensions). From a3247319dd1abb3ad76e49a471184f48b64971b9 Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Sat, 11 Jan 2025 21:10:46 +0200 Subject: [PATCH 07/14] finished economics folder and transactions.md --- docs/uk/core/transactions.md | 397 +++++++----------- docs/uk/economics/index.md | 49 +-- .../inflation/_adjusted_staking_yield.md | 148 +------ .../economics/inflation/inflation-schedule.md | 92 +--- docs/uk/economics/inflation/terminology.md | 152 ++----- docs/uk/economics/staking/index.md | 122 +++--- docs/uk/economics/staking/stake-accounts.md | 154 ++----- .../uk/economics/staking/stake-programming.md | 27 +- 8 files changed, 353 insertions(+), 788 deletions(-) diff --git a/docs/uk/core/transactions.md b/docs/uk/core/transactions.md index 4cf2554fa..3dab1871b 100644 --- a/docs/uk/core/transactions.md +++ b/docs/uk/core/transactions.md @@ -1,267 +1,214 @@ --- -title: "Transactions and Instructions" +title: "Транзакції та Інструкції" sidebarSortOrder: 2 description: - Learn about Solana transactions and instructions - the fundamental building - blocks for interacting with the Solana blockchain. Understand transaction - structure and instruction composition with practical examples. + Дізнайтеся про транзакції та інструкції Solana — основні будівельні блоки для + взаємодії з блокчейном Solana. Зрозумійте структуру транзакцій і створення + інструкцій із практичними прикладами. --- -On Solana, we send [transactions](/docs/core/transactions#transaction) to -interact with the network. Transactions include one or more -[instructions](/docs/core/transactions#instruction), each representing a -specific operation to be processed. The execution logic for instructions is -stored on [programs](/docs/core/programs) deployed to the Solana network, where -each program stores its own set of instructions. +У Solana ми надсилаємо [транзакції](/docs/core/transactions#transaction), щоб +взаємодіяти з мережею. Транзакції включають одну або більше +[інструкцій](/docs/core/transactions#instruction), кожна з яких представляє +конкретну операцію, що має бути оброблена. Логіка виконання інструкцій зберігається +в [програмах](/docs/core/programs), розгорнутих у мережі Solana, і кожна програма +зберігає свій набір інструкцій. -Below are key details about how transactions are executed: +Нижче наведено основні деталі щодо виконання транзакцій: -- Execution Order: If a transaction includes multiple instructions, the - instructions are processed in the order they are added to the transaction. -- Atomicity: A transaction is atomic, meaning it either fully completes with all - instructions successfully processed, or fails altogether. If any instruction - within the transaction fails, none of the instructions are executed. +- Порядок виконання: Якщо транзакція містить декілька інструкцій, вони + обробляються у порядку, в якому були додані до транзакції. +- Атомарність: Транзакція є атомарною, тобто вона або повністю виконується з + успішною обробкою всіх інструкцій, або повністю провалюється. Якщо будь-яка + інструкція у транзакції не вдається, жодна з інструкцій не буде виконана. -For simplicity, a transaction can be thought of as a request to process one or -multiple instructions. +Для простоти можна уявити транзакцію як запит на обробку однієї або кількох +інструкцій. -![Transaction Simplified](/assets/docs/core/transactions/transaction-simple.svg) +![Спрощена транзакція](/assets/docs/core/transactions/transaction-simple.svg) -You can imagine a transaction as an envelope, where each instruction is a -document that you fill out and place inside the envelope. We then mail out the -envelope to process the documents, just like sending a transaction on the -network to process our instructions. +Уявіть транзакцію як конверт, де кожна інструкція — це документ, який ви +заповнюєте та кладете у конверт. Потім ми відправляємо конверт для обробки +документів, так само, як відправляємо транзакцію в мережу для обробки наших +інструкцій. -## Key Points +## Основні моменти -- Solana transactions consist of instructions that interact with various - programs on the network, where each instruction represents a specific - operation. +- Транзакції Solana складаються з інструкцій, які взаємодіють із різними + програмами в мережі, де кожна інструкція представляє конкретну операцію. -- Each instruction specifies the program to execute the instruction, the - accounts required by the instruction, and the data required for the - instruction's execution. +- Кожна інструкція вказує програму для виконання інструкції, облікові записи, + необхідні для інструкції, та дані, потрібні для виконання інструкції. -- Instructions within a transaction are processed in the order they are listed. +- Інструкції в транзакції обробляються в порядку, в якому вони вказані. -- Transactions are atomic, meaning either all instructions process successfully, - or the entire transaction fails. +- Транзакції є атомарними, тобто або всі інструкції успішно обробляються, або + вся транзакція провалюється. -- The maximum size of a transaction is 1232 bytes. +- Максимальний розмір транзакції становить 1232 байти. -## Basic Example +## Простий приклад -Below is a diagram representing a transaction with a single instruction to -transfer SOL from a sender to a receiver. +Нижче наведено діаграму, яка представляє транзакцію з однією інструкцією для +переказу SOL від відправника до отримувача. -Individual "wallets" on Solana are accounts owned by the -[System Program](/docs/core/accounts#system-program). As part of the -[Solana Account Model](/docs/core/accounts), only the program that owns an -account is allowed to modify the data on the account. +Індивідуальні "гаманці" у Solana є обліковими записами, якими володіє +[Системна програма](/docs/core/accounts#system-program). Як частина +[моделі облікових записів Solana](/docs/core/accounts), лише програма, якій +належить обліковий запис, може змінювати дані цього облікового запису. -Therefore, transferring SOL from a "wallet" account requires sending a -transaction to invoke the transfer instruction on the System Program. +Тому для переказу SOL із облікового запису "гаманця" необхідно надіслати +транзакцію для виклику інструкції переказу у Системній програмі. -![SOL Transfer](/assets/docs/core/transactions/sol-transfer.svg) +![Переказ SOL](/assets/docs/core/transactions/sol-transfer.svg) -The sender account must be included as a signer (`is_signer`) on the transaction -to approve the deduction of their lamport balance. Both the sender and recipient -accounts must be mutable (`is_writable`) because the instruction modifies the -lamport balance for both accounts. +Обліковий запис відправника має бути доданий як підписант (`is_signer`) до +транзакції, щоб схвалити списання балансу лампортів. Обидва облікові записи, +відправник і отримувач, мають бути змінюваними (`is_writable`), оскільки +інструкція змінює баланс лампортів для обох облікових записів. -Once the transaction is sent, the System Program is invoked to process the -transfer instruction. The System Program then updates the lamport balances of -both the sender and recipient accounts accordingly. +Після відправлення транзакції викликається Системна програма для обробки +інструкції переказу. Потім Системна програма оновлює баланс лампортів для обох +облікових записів відповідно. -![SOL Transfer Process](/assets/docs/core/transactions/sol-transfer-process.svg) +![Процес переказу SOL](/assets/docs/core/transactions/sol-transfer-process.svg) -### Simple SOL Transfer +### Простий переказ SOL -Here is a [Solana Playground](https://beta.solpg.io/656a0ea7fb53fa325bfd0c3e) -example of how to build a SOL transfer instruction using the -`SystemProgram.transfer` method: +Ось приклад із [Solana Playground](https://beta.solpg.io/656a0ea7fb53fa325bfd0c3e), +який демонструє, як створити інструкцію переказу SOL за допомогою методу +`SystemProgram.transfer`: ```typescript -// Define the amount to transfer +// Визначення суми переказу const transferAmount = 0.01; // 0.01 SOL -// Create a transfer instruction for transferring SOL from wallet_1 to wallet_2 +// Створення інструкції для переказу SOL з wallet_1 до wallet_2 const transferInstruction = SystemProgram.transfer({ fromPubkey: sender.publicKey, toPubkey: receiver.publicKey, - lamports: transferAmount * LAMPORTS_PER_SOL, // Convert transferAmount to lamports + lamports: transferAmount * LAMPORTS_PER_SOL, // Конвертація transferAmount у лампорти }); -// Add the transfer instruction to a new transaction +// Додавання інструкції переказу до нової транзакції const transaction = new Transaction().add(transferInstruction); ``` +Запустіть скрипт і перевірте деталі транзакції, що виводяться в консоль. У наступних розділах ми розглянемо, що відбувається "під капотом". -Run the script and inspect the transaction details logged to the console. In the -sections below, we'll walk through the details of what's happening under the -hood. - -## Transaction +## Транзакція -A Solana +Транзакція Solana [transaction](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/transaction/mod.rs#L173) -consists of: +складається з: -1. [Signatures](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/signature.rs#L27): - An array of signatures included on the transaction. -2. [Message](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L110): - List of instructions to be processed atomically. +1. [Підписів](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/signature.rs#L27): + Масиву підписів, включених у транзакцію. +2. [Повідомлення](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L110): + Переліку інструкцій, які будуть оброблятися атомарно. -![Transaction Format](/assets/docs/core/transactions/tx_format.png) +![Формат транзакції](/assets/docs/core/transactions/tx_format.png) -The structure of a transaction message comprises of: +Структура повідомлення транзакції складається з: -- [Message Header](/docs/core/transactions#message-header): Specifies the number - of signer and read-only account. -- [Account Addresses](/docs/core/transactions#array-of-account-addresses): An - array of account addresses required by the instructions on the transaction. -- [Recent Blockhash](/docs/core/transactions#recent-blockhash): Acts as a - timestamp for the transaction. -- [Instructions](/docs/core/transactions#array-of-instructions): An array of - instructions to be executed. +- [Заголовка повідомлення](/docs/core/transactions#message-header): Вказує кількість підписантів та облікових записів тільки для читання. +- [Масиву адрес облікових записів](/docs/core/transactions#array-of-account-addresses): Масив адрес облікових записів, необхідних для інструкцій у транзакції. +- [Недавнього блоку хешу](/docs/core/transactions#recent-blockhash): Використовується як мітка часу для транзакції. +- [Масиву інструкцій](/docs/core/transactions#array-of-instructions): Масив інструкцій, які слід виконати. -![Transaction Message](/assets/docs/core/transactions/legacy_message.png) +![Повідомлення транзакції](/assets/docs/core/transactions/legacy_message.png) -### Transaction Size +### Розмір транзакції -The Solana network adheres to a maximum transmission unit (MTU) size of 1280 -bytes, consistent with the [IPv6 MTU](https://en.wikipedia.org/wiki/IPv6_packet) -size constraints to ensure fast and reliable transmission of cluster information -over UDP. After accounting for the necessary headers (40 bytes for IPv6 and 8 -bytes for the fragment header), -[1232 bytes remain available for packet data](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/packet.rs#L16-L21), -such as serialized transactions. +Мережа Solana дотримується максимального розміру пакета (MTU) у 1280 байт, що відповідає +[MTU IPv6](https://en.wikipedia.org/wiki/IPv6_packet). Це забезпечує швидку та надійну передачу інформації у кластері через UDP. Після врахування необхідних заголовків (40 байт для IPv6 та 8 байт для заголовка фрагмента), +[1232 байти залишаються для даних пакета](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/packet.rs#L16-L21), таких як серіалізовані транзакції. -This means that the total size of a Solana transaction is limited to 1232 bytes. -The combination of the signatures and the message cannot exceed this limit. +Це означає, що загальний розмір транзакції Solana обмежений 1232 байтами. Підписи та повідомлення у комбінації не можуть перевищувати цей ліміт. -- Signatures: Each signature requires 64 bytes. The number of signatures can - vary, depending on the transaction's requirements. -- Message: The message includes instructions, accounts, and additional metadata, - with each account requiring 32 bytes. The combined size of the accounts plus - metadata can vary, depending on the instructions included in the transaction. +- Підписи: Кожен підпис займає 64 байти. Кількість підписів може варіювати залежно від вимог транзакції. +- Повідомлення: Повідомлення включає інструкції, облікові записи та додаткові метадані. Кожен обліковий запис займає 32 байти. Загальний розмір облікових записів плюс метадані може варіювати залежно від інструкцій у транзакції. -![Transaction Format](/assets/docs/core/transactions/issues_with_legacy_txs.png) +![Формат транзакції](/assets/docs/core/transactions/issues_with_legacy_txs.png) -### Message Header +### Заголовок повідомлення -The -[message header](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/mod.rs#L96) -specifies the privileges of accounts included in the transaction's account -address array. It is comprised of three bytes, each containing a u8 integer, -which collectively specify: +[Заголовок повідомлення](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/mod.rs#L96) +вказує на привілеї облікових записів, включених у масив адрес транзакції. Він складається з трьох байтів, кожен з яких містить ціле число типу u8, що колективно вказує: -1. The number of required signatures for the transaction. -2. The number of read-only account addresses that require signatures. -3. The number of read-only account addresses that do not require signatures. +1. Кількість необхідних підписів для транзакції. +2. Кількість облікових записів тільки для читання, які потребують підписів. +3. Кількість облікових записів тільки для читання, які не потребують підписів. -![Message Header](/assets/docs/core/transactions/message_header.png) +![Заголовок повідомлення](/assets/docs/core/transactions/message_header.png) -### Compact-Array Format +### Формат компактного масиву -A compact array in the context of a transaction message refers to an array -serialized in the following format: +Компактний масив у контексті повідомлення транзакції посилається на масив, серіалізований у наступному форматі: -1. The length of the array, encoded as +1. Довжина масиву, закодована як [compact-u16](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/short_vec.rs). -2. The individual items of the array listed sequentially after the encoded - length. +2. Окремі елементи масиву, перераховані послідовно після закодованої довжини. -![Compact array format](/assets/docs/core/transactions/compact_array_format.png) +![Формат компактного масиву](/assets/docs/core/transactions/compact_array_format.png) -This encoding method is used to specify the lengths of both the -[Account Addresses](/docs/core/transactions#array-of-account-addresses) and -[Instructions](/docs/core/transactions#array-of-instructions) arrays within a -transaction message. +Цей метод кодування використовується для вказівки довжин як +[масиву адрес облікових записів](/docs/core/transactions#array-of-account-addresses), так і +[масиву інструкцій](/docs/core/transactions#array-of-instructions) у повідомленні транзакції. -### Array of Account Addresses +### Масив адрес облікових записів -A transaction message includes an array containing all the -[account addresses](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L119) -needed for the instructions within the transaction. +Повідомлення транзакції включає масив, що містить усі +[адреси облікових записів](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L119), +необхідні для інструкцій у транзакції. -This array starts with a -[compact-u16](/docs/core/transactions#compact-array-format) encoding of the -number of account addresses, followed by the addresses ordered by the privileges -for the accounts. The metadata in the message header is used to determine the -number of accounts in each section. +Цей масив починається з кодування +[compact-u16](/docs/core/transactions#compact-array-format) довжини масиву, після чого йдуть адреси, впорядковані за привілеями облікових записів. Метадані в заголовку повідомлення використовуються для визначення кількості облікових записів у кожному розділі. -- Accounts that are writable and signers -- Accounts that are read-only and signers -- Accounts that are writable and not signers -- Accounts that are read-only and not signers +- Облікові записи, що є змінюваними та підписантами. +- Облікові записи тільки для читання, що є підписантами. +- Облікові записи, що є змінюваними, але не підписантами. +- Облікові записи тільки для читання, що не є підписантами. -![Compact array of account addresses](/assets/docs/core/transactions/compat_array_of_account_addresses.png) +![Компактний масив адрес облікових записів](/assets/docs/core/transactions/compat_array_of_account_addresses.png) -### Recent Blockhash +### Недавній блок-хеш -All transactions include a -[recent blockhash](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L122) -to act as a timestamp for the transaction. The blockhash is used to prevent -duplications and eliminate stale transactions. +Усі транзакції включають +[недавній блок-хеш](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L122), +який використовується як мітка часу для транзакції. Блок-хеш запобігає дублюванню транзакцій і виключає застарілі транзакції. -The maximum age of a transaction's blockhash is 150 blocks (~1 minute assuming -400ms block times). If a transaction's blockhash is 150 blocks older than the -latest blockhash, it is considered expired. This means that transactions not -processed within a specific timeframe will never be executed. +Максимальний вік блок-хеша для транзакції становить 150 блоків (~1 хвилина, якщо час блоку складає 400 мс). Якщо блок-хеш транзакції старіший за 150 блоків від останнього блок-хеша, вона вважається протермінованою. Це означає, що транзакції, які не були оброблені вчасно, ніколи не будуть виконані. -You can use the [`getLatestBlockhash`](/docs/rpc/http/getlatestblockhash) RPC -method to get the current blockhash and last block height at which the blockhash -will be valid. Here is an example on +Ви можете скористатися RPC-методом +[`getLatestBlockhash`](/docs/rpc/http/getlatestblockhash), +щоб отримати поточний блок-хеш і останню висоту блоку, на якій блок-хеш залишатиметься дійсним. Ось приклад у [Solana Playground](https://beta.solpg.io/661a06e1cffcf4b13384d046). +### Масив інструкцій -### Array of Instructions - -A transaction message includes an array of all -[instructions](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L128) -requesting to be processed. Instructions within a transaction message are in the -format of +Повідомлення транзакції включає масив усіх +[інструкцій](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L128), +які запитуються для обробки. Інструкції у повідомленні транзакції мають формат [CompiledInstruction](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L633). -Much like the array of account addresses, this compact array starts with a -[compact-u16](/docs/core/transactions#compact-array-format) encoding of the -number of instructions, followed by an array of instructions. Each instruction -in the array specifies the following information: - -1. **Program ID**: Identifies an on-chain program that will process the - instruction. This is represented as an u8 index pointing to an account - address within the account addresses array. -2. **Compact array of account address indexes**: Array of u8 indexes pointing to - the account addresses array for each account required by the instruction. -3. **Compact array of opaque u8 data**: A u8 byte array specific to the program - invoked. This data specifies the instruction to invoke on the program along - with any additional data that the instruction requires (such as function - arguments). +Подібно до масиву адрес облікових записів, цей компактний масив починається з кодування +[compact-u16](/docs/core/transactions#compact-array-format) кількості інструкцій, після чого йде масив інструкцій. Кожна інструкція в масиві вказує наступну інформацію: -![Compact array of Instructions](/assets/docs/core/transactions/compact_array_of_ixs.png) +1. **Program ID**: Ідентифікатор програми в мережі, яка оброблятиме інструкцію. Це представлено у вигляді індексу типу u8, що вказує на адресу програми у масиві адрес облікових записів. +2. **Компактний масив індексів адрес облікових записів**: Масив індексів типу u8, що вказує на масив адрес облікових записів для кожного облікового запису, потрібного для інструкції. +3. **Компактний масив байтів даних**: Масив байтів типу u8, специфічний для викликаної програми. Ці дані вказують, яку інструкцію викликати у програмі, разом із будь-якими додатковими даними, потрібними для виконання інструкції (наприклад, аргументами функції). -### Example Transaction Structure +![Компактний масив інструкцій](/assets/docs/core/transactions/compact_array_of_ixs.png) -Below is an example of the structure of a transaction including a single -[SOL transfer](/docs/core/transactions#basic-example) instruction. It shows the -message details including the header, account keys, blockhash, and the -instructions, along with the signature for the transaction. +### Приклад структури транзакції -- `header`: Includes data used to specify the read/write and signer privileges - in the `accountKeys` array. +Нижче наведено приклад структури транзакції, яка включає одну інструкцію для +[передачі SOL](/docs/core/transactions#basic-example). Тут показано деталі повідомлення, включаючи заголовок, ключі облікових записів, блок-хеш та інструкції, разом із підписом для транзакції. -- `accountKeys`: Array including account addresses for all instructions on the - transaction. - -- `recentBlockhash`: The blockhash included on the transaction when the - transaction was created. - -- `instructions`: Array including all the instructions on the transaction. Each - `account` and `programIdIndex` in an instruction references the `accountKeys` - array by index. - -- `signatures`: Array including signatures for all accounts required as signers - by the instructions on the transaction. A signature is created by signing the - transaction message using the corresponding private key for an account. +- `header`: Містить дані, які використовуються для вказання привілеїв читання/запису та підписання у масиві `accountKeys`. +- `accountKeys`: Масив, що включає адреси облікових записів для всіх інструкцій у транзакції. +- `recentBlockhash`: Блок-хеш, включений у транзакцію під час її створення. +- `instructions`: Масив, що включає всі інструкції у транзакції. Кожен `account` та `programIdIndex` в інструкції посилаються на масив `accountKeys` за індексом. +- `signatures`: Масив, що включає підписи для всіх облікових записів, потрібних як підписанти для інструкцій у транзакції. Підпис створюється шляхом підписання повідомлення транзакції за допомогою відповідного приватного ключа для облікового запису. ```json "transaction": { @@ -295,59 +242,46 @@ instructions, along with the signature for the transaction. ] } ``` +## Інструкція -## Instruction +[Інструкція](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L329) +— це запит на виконання конкретної дії в мережі. Це найменша неподільна одиниця логіки виконання у +[програмі](/docs/core/accounts#program-account). -An -[instruction](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L329) -is a request to process a specific action on-chain and is the smallest -contiguous unit of execution logic in a -[program](/docs/core/accounts#program-account). +При створенні інструкції для додавання до транзакції кожна інструкція повинна включати наступну інформацію: -When building an instruction to add to a transaction, each instruction must -include the following information: +- **Адреса програми**: Вказує програму, яку буде викликано. +- **Облікові записи**: Перелік кожного облікового запису, з якого інструкція читає або до якого пише, включаючи інші програми, за допомогою структури `AccountMeta`. +- **Дані інструкції**: Масив байтів, що вказує, який + [обробник інструкцій](/docs/terminology#instruction-handler) викликати у програмі, а також будь-які додаткові дані, необхідні обробнику інструкцій (аргументи функції). -- **Program address**: Specifies the program being invoked. -- **Accounts**: Lists every account the instruction reads from or writes to, - including other programs, using the `AccountMeta` struct. -- **Instruction Data**: A byte array that specifies which - [instruction handler](/docs/terminology#instruction-handler) on the program to - invoke, plus any additional data required by the instruction handler (function - arguments). - -![Transaction Instruction](/assets/docs/core/transactions/instruction.svg) +![Інструкція транзакції](/assets/docs/core/transactions/instruction.svg) ### AccountMeta -For every account required by an instruction, the following info must be -specified: +Для кожного облікового запису, необхідного для інструкції, потрібно вказати наступну інформацію: -- `pubkey`: The on-chain address of an account -- `is_signer`: Specify if the account is required as a signer on the transaction -- `is_writable`: Specify if the account data will be modified +- `pubkey`: Адреса облікового запису в мережі. +- `is_signer`: Вказує, чи є обліковий запис підписантом у транзакції. +- `is_writable`: Вказує, чи будуть змінені дані облікового запису. -This information is referred to as the +Ця інформація називається [AccountMeta](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L539). ![AccountMeta](/assets/docs/core/transactions/accountmeta.svg) -By specifying all accounts required by an instruction, and whether each account -is writable, transactions can be processed in parallel. +Завдяки вказанню всіх облікових записів, необхідних для інструкції, і зазначенню, які з них можуть бути змінені, транзакції можуть виконуватися паралельно. -For example, two transactions that do not include any accounts that write to the -same state can be executed at the same time. +Наприклад, дві транзакції, які не включають жодних облікових записів, що записують в той самий стан, можуть виконуватися одночасно. -### Example Instruction Structure +### Приклад структури інструкції -Below is an example of the structure of a -[SOL transfer](/docs/core/transactions#basic-examples) instruction which details -the account keys, program ID, and data required by the instruction. +Нижче наведено приклад структури інструкції для +[передачі SOL](/docs/core/transactions#basic-examples), яка деталізує ключі облікових записів, ідентифікатор програми та дані, необхідні для інструкції. -- `keys`: Includes the `AccountMeta` for each account required by an - instruction. -- `programId`: The address of the program which contains the execution logic for - the instruction invoked. -- `data`: The instruction data for the instruction as a buffer of bytes +- `keys`: Містить `AccountMeta` для кожного облікового запису, необхідного для інструкції. +- `programId`: Адреса програми, яка містить логіку виконання для викликаної інструкції. +- `data`: Дані інструкції у вигляді буфера байтів. ``` { @@ -367,17 +301,13 @@ the account keys, program ID, and data required by the instruction. "data": [2,0,0,0,128,150,152,0,0,0,0,0] } ``` +## Розширений приклад -## Expanded Example - -The details for building program instructions are often abstracted away by -client libraries. However, if one is not available, you can always fall back to -manually building the instruction. +Деталі створення програмних інструкцій часто приховуються клієнтськими бібліотеками. Проте, якщо такої бібліотеки немає, завжди можна вручну створити інструкцію. -### Manual SOL Transfer +### Ручна передача SOL -Here is a [Solana Playground](https://beta.solpg.io/656a102efb53fa325bfd0c3f) -example of how to manually build a SOL transfer instruction: +Ось приклад на [Solana Playground](https://beta.solpg.io/656a102efb53fa325bfd0c3f), який демонструє, як вручну створити інструкцію для передачі SOL: ```typescript // Define the amount to transfer @@ -406,10 +336,5 @@ const transferInstruction = new TransactionInstruction({ // Add the transfer instruction to a new transaction const transaction = new Transaction().add(transferInstruction); ``` +Під капотом [простий приклад](/docs/core/transactions#simple-sol-transfer) з використанням методу `SystemProgram.transfer` функціонально еквівалентний більш детальному прикладу вище. Метод `SystemProgram.transfer` просто приховує деталі створення буфера даних інструкції та `AccountMeta` для кожного облікового запису, необхідного для інструкції. -Under the hood, the -[simple example](/docs/core/transactions#simple-sol-transfer) using the -`SystemProgram.transfer` method is functionally equivalent to the more verbose -example above. The `SystemProgram.transfer` method simply abstracts away the -details of creating the instruction data buffer and `AccountMeta` for each -account required by the instruction. diff --git a/docs/uk/economics/index.md b/docs/uk/economics/index.md index 55444a801..e7ce116d4 100644 --- a/docs/uk/economics/index.md +++ b/docs/uk/economics/index.md @@ -1,52 +1,21 @@ --- -sidebarLabel: Economics -title: Solana Economics Overview +sidebarLabel: Економіка +title: Огляд Економіки Solana altRoutes: - /docs/intro/economics sidebarSortOrder: 5 --- -**Subject to change.** +**Може бути змінено.** -Solana's crypto-economic system is designed to promote a healthy, long term -self-sustaining economy with participant incentives aligned to the security and -decentralization of the network. The main participants in this economy are -validation-clients. Their contributions to the network, state validation, and -their requisite incentive mechanisms are discussed below. +Криптоекономічна система Solana розроблена для сприяння здоровій, довгостроковій самопідтримуваній економіці, в якій стимули учасників узгоджуються із забезпеченням безпеки та децентралізації мережі. Основними учасниками цієї економіки є валідаційні клієнти. Їхній внесок у мережу, перевірка стану та відповідні механізми стимулювання розглядаються нижче. -The main channels of participant remittances are referred to as protocol-based -rewards and transaction fees. Protocol-based rewards are generated from -inflationary issuances from a protocol-defined inflation schedule. These rewards -will constitute the total protocol-based reward delivered to validation clients, -the remaining sourced from transaction fees. In the early days of the network, -it is likely that protocol-based rewards, deployed based on predefined issuance -schedule, will drive the majority of participant incentives to participate in -the network. +Основними каналами винагород для учасників є винагороди, засновані на протоколі, та транзакційні комісії. Винагороди, засновані на протоколі, генеруються за рахунок інфляційного випуску згідно з визначеним протоколом графіком інфляції. Ці винагороди становитимуть загальну винагороду на основі протоколу, яка буде надаватися валідаційним клієнтам, решта забезпечується за рахунок транзакційних комісій. У перші дні роботи мережі ймовірно, що винагороди, засновані на протоколі, розподілені згідно з попередньо визначеним графіком випуску, стануть основним стимулом для учасників мережі. -These protocol-based rewards are calculated per epoch and distributed across the -active delegated stake and validator set (per validator commission). As -discussed further below, the per annum inflation rate is based on a -pre-determined disinflationary schedule. This provides the network with supply -predictability which supports long term economic stability and security. +Ці винагороди розраховуються за кожну епоху і розподіляються серед активного делегованого стейку та набору валідаторів (з урахуванням комісії валідаторів). Як описано нижче, річний рівень інфляції ґрунтується на визначеному дисінфляційному графіку. Це забезпечує мережі передбачуваність поставок, що підтримує довгострокову економічну стабільність та безпеку. -Transaction fees are participant-to-participant transfers, attached to network -interactions as a motivation and compensation for the inclusion and execution of -a proposed transaction. A mechanism for long-term economic stability and forking -protection through partial burning of each transaction fee is also discussed -below. +Транзакційні комісії є переказами між учасниками, що додаються до взаємодії з мережею як стимул та компенсація за включення і виконання запропонованої транзакції. Також обговорюється механізм довгострокової економічної стабільності та захисту від розгалужень через часткове спалювання кожної транзакційної комісії. -First, an overview of the inflation design is presented. This section starts -with defining and clarifying -[Terminology](/docs/economics/inflation/terminology.md) commonly used -subsequently in the discussion of inflation and the related components. -Following that, we outline Solana's proposed -[Inflation Schedule](/docs/economics/inflation/inflation_schedule.md), i.e. the -specific parameters that uniquely parameterize the protocol-driven inflationary -issuance over time. Next is a brief section on -[Adjusted Staking Yield](/docs/economics/inflation/_adjusted_staking_yield.md), -and how token dilution might influence staking behavior. +Спочатку подано огляд дизайну інфляції. Цей розділ починається з визначення та уточнення [Термінології](/docs/economics/inflation/terminology.md), що часто використовується у подальшому обговоренні інфляції та пов'язаних компонентів. Далі ми окреслюємо запропонований [Графік Інфляції](/docs/economics/inflation/inflation_schedule.md) Solana, тобто конкретні параметри, які унікально визначають інфляційний випуск, керований протоколом, з плином часу. Наступним є короткий розділ про [Скориговану Доходність Стейкінгу](/docs/economics/inflation/_adjusted_staking_yield.md) і те, як розбавлення токенів може вплинути на поведінку стейкінгу. -An overview of [Transaction Fees](/docs/core/fees.md#transaction-fees) on Solana -is followed by a discussion of [Storage Rent Economics](/docs/core/fees.md#rent) -in which we describe an implementation of storage rent to account for the -externality costs of maintaining the active state of the ledger. +Огляд [Транзакційних Комісій](/docs/core/fees.md#transaction-fees) у Solana супроводжується обговоренням [Економіки Оренди для Зберігання](/docs/core/fees.md#rent), у якому описується реалізація орендної плати за зберігання для обліку зовнішніх витрат на підтримання активного стану реєстру. diff --git a/docs/uk/economics/inflation/_adjusted_staking_yield.md b/docs/uk/economics/inflation/_adjusted_staking_yield.md index 33abf65a9..a515b96f7 100644 --- a/docs/uk/economics/inflation/_adjusted_staking_yield.md +++ b/docs/uk/economics/inflation/_adjusted_staking_yield.md @@ -1,170 +1,66 @@ --- -title: Adjusted Staking Yield +title: Скоригована Дохідність Стейкінгу --- -### Token Dilution +### Дилюція Токенів -Similarly we can look at the expected _Staked Dilution_ (i.e. _Adjusted Staking -Yield_) and _Un-staked Dilution_ as previously defined. Again, _dilution_ in -this context is defined as the change in fractional representation (i.e. -ownership) of a set of tokens within a larger set. In this sense, dilution can -be a positive value: an increase in fractional ownership (staked dilution / -_Adjusted Staking Yield_), or a negative value: a decrease in fractional -ownership (un-staked dilution). +Подібним чином ми можемо розглянути очікувану _Дилюцію Стейкінгу_ (тобто _Скориговану Дохідність Стейкінгу_) та _Дилюцію Нестейкінгованих Токенів_, як було визначено раніше. У цьому контексті _дилюція_ означає зміну фракційного представлення (тобто частки власності) набору токенів у рамках більшого пулу. У цьому сенсі дилюція може бути позитивною (збільшення частки власності, стейкінгова дилюція / _Скоригована Дохідність Стейкінгу_) або негативною (зменшення частки власності, нестейкінгова дилюція). -We are interested in the relative change in ownership of staked vs un-staked -tokens as the overall token pool increases with inflation issuance. As -discussed, this issuance is distributed only to staked token holders, increasing -the staked token fractional representation of the _Total Current Supply_. +Нас цікавить відносна зміна власності стейкінгованих і нестейкінгованих токенів у міру збільшення загального пулу токенів через інфляційний випуск. Як було зазначено, цей випуск розподіляється лише серед власників стейкінгованих токенів, збільшуючи їх частку у _Загальному Поточному Обсязі_. -Continuing with the same _Inflation Schedule_ parameters as above, we see the -fraction of staked supply grow as shown below. +Продовжуючи з тими ж параметрами _Графіку Інфляції_, що й раніше, ми бачимо зростання частки стейкінгового пулу, як показано нижче. -![Graph of example growth of staked supply](/assets/docs/economics/example_staked_supply_w_range_initial_stake.png) +![Графік зростання частки стейкінгового пулу](/assets/docs/economics/example_staked_supply_w_range_initial_stake.png) -Due to this relative change in representation, the proportion of stake of any -token holder will also change as a function of the _Inflation Schedule_ and the -proportion of all tokens that are staked. +Через цю відносну зміну у представництві частка стейкінгу будь-якого власника токенів також змінюється як функція _Графіку Інфляції_ та частки стейкінгованих токенів. -Of initial interest, however, is the _dilution of **un-staked** tokens_, or -$D_{us}$. In the case of un-staked tokens, token dilution is only a function of -the _Inflation Schedule_ because the amount of un-staked tokens doesn't change -over time. +### Розрахунок Дилюції Нестейкінгованих Токенів -This can be seen by explicitly calculating un-staked dilution as $D_{us}$. The -un-staked proportion of the token pool at time $t$ is $P_{us}(t_{N})$ and -$I_{t}$ is the incremental inflation rate applied between any two consecutive -time points. $SOL_{us}(t)$ and $SOL_{total}(t)$ is the amount of un-staked and -total SOL on the network, respectively, at time $t$. Therefore -$P_{us}(t) = SOL_{us}(t)/SOL_{total}(t)$. +Особливий інтерес викликає _Дилюція Нестейкінгованих Токенів_, або $D_{us}$. У випадку нестейкінгованих токенів дилюція залежить лише від _Графіку Інфляції_, оскільки кількість нестейкінгованих токенів не змінюється з часом. $$ \begin{aligned} D_{us} &= \left( \frac{P_{us}(t_{1}) - P_{us}(t_{0})}{P_{us}(t_{0})} \right)\\ &= \left( \frac{ \left( \frac{SOL_{us}(t_{2})}{SOL_{total}(t_{2})} \right) - \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})} \right)}{ \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})} \right) } \right)\\ - -\end{aligned} -$$ - -However, because inflation issuance only increases the total amount and the -un-staked supply doesn't change: - -$$ -\begin{aligned} - SOL_{us}(t_2) &= SOL_{us}(t_1)\\ - SOL_{total}(t_2) &= SOL_{total}(t_1)\times (1 + I_{t_1})\\ \end{aligned} $$ -So $D_{us}$ becomes: +Оскільки випуск інфляції лише збільшує загальну кількість токенів, а нестейкінгована кількість залишається незмінною: $$ \begin{aligned} - D_{us} &= \left( \frac{ \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})\times (1 + I_{1})} \right) - \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})} \right)}{ \left( \frac{SOL_{us}(t_{1})}{SOL_{total}(t_{1})} \right) } \right)\\ D_{us} &= \frac{1}{(1 + I_{1})} - 1\\ \end{aligned} $$ -Or generally, dilution for un-staked tokens over any time frame undergoing -inflation $I$: +Отже: $$ -D_{us} = -\frac{I}{I + 1} \\ +D_{us} = -\frac{I}{I + 1} $$ -So as guessed, this dilution is independent of the total proportion of staked -tokens and only depends on inflation rate. This can be seen with our example -_Inflation Schedule_ here: - -![Graph of an example dilution of unstaked SOL](/assets/docs/economics/example_unstaked_dilution.png) +### Оцінка Скоригованої Дохідності Стейкінгу -### Estimated Adjusted Staked Yield - -We can do a similar calculation to determine the _dilution_ of staked token -holders, or as we've defined here as the **_Adjusted Staked Yield_**, keeping in -mind that dilution in this context is an _increase_ in proportional ownership -over time. We'll use the terminology _Adjusted Staked Yield_ to avoid confusion -going forward. - -To see the functional form, we calculate, $Y_{adj}$, or the _Adjusted Staked -Yield_ (to be compared to _D\_{us}_ the dilution of un-staked tokens above), -where $P_{s}(t)$ is the staked proportion of token pool at time $t$ and $I_{t}$ -is the incremental inflation rate applied between any two consecutive time -points. The definition of $Y_{adj}$ is therefore: +Ми також можемо розрахувати _Скориговану Дохідність Стейкінгу_ $Y_{adj}$ як зміну частки стейкінгованих токенів у пулі: $$ - Y_{adj} = \frac{P_s(t_2) - P_s(t_1)}{P_s(t_1)}\\ +Y_{adj} = \frac{P_s(t_2) - P_s(t_1)}{P_s(t_1)} $$ -As seen in the plot above, the proportion of staked tokens increases with -inflation issuance. Letting $SOL_s(t)$ and $SOL_{\text{total}}(t)$ represent the -amount of staked and total SOL at time $t$ respectively: +Це спрощується до: $$ - P_s(t_2) = \frac{SOL_s(t_1) + SOL_{\text{total}}(t_1)\times I(t_1)}{SOL_{\text{total}}(t_1)\times (1 + I(t_1))}\\ +Y_{adj} = \frac{ 1 + I(t)/P_s(t) }{ 1 + I(t) } - 1 $$ -Where $SOL_{\text{total}}(t_1)\times I(t_1)$ is the additional inflation -issuance added to the staked token pool. Now we can write $Y_{adj}$ in common -terms $t_1 = t$: - -$$ -\begin{aligned} -Y_{adj} &= \frac{\frac{SOL_s(t) + SOL_{\text{total}}(t)\times I(t)}{SOL_{\text{total}}(t)\times (1 + I(t))} - \frac{SOL_s(t)}{SOL_{\text{total}}(t)} }{ \frac{SOL_s(t)}{SOL_{\text{total}}(t)} } \\ - &= \frac{ SOL_{\text{total}}(t)\times (SOL_s(t) + SOL_{\text{total}}(t)\times I(t)) }{ SOL_s(t)\times SOL_{\text{total}}\times (1 + I(t)) } -1 \\ -\end{aligned} -$$ +### Відносна Дилюція -which simplifies to: +Відношення $D_{us}/Y_{adj}$ дозволяє зрозуміти, наскільки сильніше нестейкінговані токени піддаються дилюції у порівнянні зі стейкінгованими: $$ -Y_{adj} = \frac{ 1 + I(t)/P_s(t) }{ 1 + I(t) } - 1\\ +\frac{D_{us}}{Y_{adj}} = \frac{ P_s }{ 1 - P_s } $$ -So we see that the _Adjusted Staked Yield_ is a function of the inflation rate -and the percent of staked tokens on the network. We can see this plotted for -various staking fractions here: - -![Graph of example adjusted staking yields](/assets/docs/economics/example_adjusted_staking_yields.png) - -It is also clear that in all cases, dilution of un-staked tokens $>$ adjusted -staked yield (i.e. dilution of staked tokens). Explicitly we can look at the -_relative dilution of un-staked tokens to staked tokens:_ $D_{us}/Y_{adj}$. Here -the relationship to inflation drops out and the relative dilution, i.e. the -impact of staking tokens vs not staking tokens, is purely a function of the % of -the total token supply staked. From above - -$$ -\begin{aligned} -Y_{adj} &= \frac{ 1 + I/P_s }{ 1 + I } - 1,~\text{and}\\ -D_{us} &= -\frac{I}{I + 1},~\text{so} \\ -\frac{D_{us}}{Y_{adj}} &= \frac{ \frac{I}{I + 1} }{ \frac{ 1 + I/P_s }{ 1 + I } - 1 } \\ -\end{aligned} -$$ - -which simplifies as, - -$$ - \begin{aligned} - \frac{D_{us}}{Y_{adj}} &= \frac{ I }{ 1 + \frac{I}{P_s} - (1 + I)}\\ - &= \frac{ I }{ \frac{I}{P_s} - I}\\ - \frac{D_{us}}{Y_{adj}}&= \frac{ P_s }{ 1 - P_s}\\ - \end{aligned} -$$ - -Where we can see a primary dependence of the relative dilution of un-staked -tokens to staked tokens is on the function of the proportion of total tokens -staked. As shown above, the proportion of total tokens staked changes over time -(i.e. $P_s = P_s(t)$ due to the re-staking of inflation issuance thus we see -relative dilution grow over time as: - -![Graph of example relative un-staked vs staked SOL dilution](/assets/docs/economics/example_relative_dilution.png) - -As might be intuitive, as the total fraction of staked tokens increases the -relative dilution of un-staked tokens grows dramatically. E.g. with $80\%$ of -the network tokens staked, an un-staked token holder will experience ~$400\%$ -more dilution than a staked holder. +На основі цього видно, що збільшення частки стейкінгованих токенів значно збільшує дилюцію нестейкінгованих токенів. Наприклад, якщо $80\%$ токенів мережі стейкінговано, власник нестейкінгованих токенів зіткнеться з дилюцією у $400\%$ більшою, ніж стейкінгований власник. -Again, this represents the change in fractional change in ownership of staked -tokens and illustrates the built-in incentive for token holder to stake their -tokens to earn _Staked Yield_ and avoid _Un-staked Dilution_. +Це підкреслює стимул для власників токенів до стейкінгу, щоб отримати _Дохідність Стейкінгу_ та уникнути _Дилюції Нестейкінгованих Токенів_. diff --git a/docs/uk/economics/inflation/inflation-schedule.md b/docs/uk/economics/inflation/inflation-schedule.md index e3ae311c8..29ecefd99 100644 --- a/docs/uk/economics/inflation/inflation-schedule.md +++ b/docs/uk/economics/inflation/inflation-schedule.md @@ -1,88 +1,42 @@ --- -sidebarLabel: Proposed Inflation Schedule -title: Proposed Inflation Schedule +sidebarLabel: Запропонований Графік Інфляції +title: Запропонований Графік Інфляції altRoutes: - /docs/economics/inflation/inflation_schedule - /docs/intro/economics --- -As mentioned above, the network's _Inflation Schedule_ is uniquely described by -three parameters: _Initial Inflation Rate_, _Disinflation Rate_ and _Long-term -Inflation Rate_. When considering these numbers, there are many factors to take -into account: +Як було зазначено вище, _Графік Інфляції_ мережі унікально описується трьома параметрами: _Початкова Ставка Інфляції_, _Ставка Дезінфляції_ та _Довгострокова Ставка Інфляції_. При розгляді цих значень слід враховувати багато факторів: -- A large portion of the SOL issued via inflation will be distributed to - stake-holders in proportion to the SOL they have staked. We want to ensure - that the _Inflation Schedule_ design results in reasonable _Staking Yields_ - for token holders who delegate SOL and for validation service providers (via - commissions taken from _Staking Yields_). -- The primary driver of _Staked Yield_ is the amount of SOL staked divided by - the total amount of SOL (% of total SOL staked). Therefore the distribution - and delegation of tokens across validators are important factors to understand - when determining initial inflation parameters. -- Yield throttling is a current area of research that would impact - _staking-yields_. This is not taken into consideration in the discussion here - or the modeling below. -- Overall token issuance - i.e. what do we expect the Current Total Supply to be - in 10 years, or 20 years? -- Long-term, steady-state inflation is an important consideration not only for - sustainable support for the validator ecosystem and the Solana Foundation - grant programs, but also should be tuned in consideration with expected token - losses and burning over time. -- The rate at which we expect network usage to grow, as a consideration to the - disinflationary rate. Over time, we plan for inflation to drop and expect that - usage will grow. +- Значна частина SOL, випущених через інфляцію, буде розподілена між власниками стейкінгу пропорційно до кількості стейкінгованих SOL. Ми хочемо переконатися, що дизайн _Графіку Інфляції_ забезпечує розумну _Дохідність Стейкінгу_ для власників токенів, які делегують SOL, та провайдерів послуг валідації (через комісії, які беруться з _Дохідності Стейкінгу_). +- Основний драйвер _Дохідності Стейкінгу_ — це кількість SOL у стейкінгу, поділена на загальну кількість SOL (% від загальної кількості SOL у стейкінгу). Таким чином, розподіл і делегування токенів серед валідаторів є важливими факторами при визначенні початкових параметрів інфляції. +- Обмеження дохідності — це поточна область досліджень, яка може вплинути на _Дохідність Стейкінгу_. Це не враховано у цій дискусії чи в моделюванні нижче. +- Загальний випуск токенів — тобто якою ми очікуємо _Поточну Загальну Пропозицію_ через 10 чи 20 років? +- Довгострокова, стабільна інфляція є важливим фактором не тільки для сталого підтримання екосистеми валідаторів і грантових програм Фонду Solana, але також має бути налаштована з урахуванням очікуваних втрат і спалювання токенів з часом. +- Темпи очікуваного зростання використання мережі як фактор для розгляду ставки дезінфляції. З часом ми плануємо зниження інфляції та очікуємо зростання використання. -Based on these considerations and the community discussions following the -initial design, the Solana Foundation proposes the following Inflation Schedule -parameters: +Виходячи з цих міркувань і обговорень у спільноті після початкового дизайну, Фонд Solana пропонує наступні параметри _Графіку Інфляції_: -- Initial Inflation Rate: 8% -- Disinflation Rate: -15% -- Long-term Inflation Rate: 1.5% +- Початкова Ставка Інфляції: 8% +- Ставка Дезінфляції: -15% +- Довгострокова Ставка Інфляції: 1.5% -These parameters define the proposed _Inflation Schedule_. Below we show -implications of these parameters. These plots only show the impact of inflation -issuances given the Inflation Schedule as parameterized above. They _do not -account_ for other factors that may impact the Total Supply such as fee/rent -burning, slashing or other unforeseen future token destruction events. -Therefore, what is presented here is an **upper limit** on the amount of SOL -issued via inflation. +Ці параметри визначають запропонований _Графік Інфляції_. Нижче показано наслідки цих параметрів. Ці графіки лише показують вплив інфляційного випуску, заданого _Графіком Інфляції_, як параметризовано вище. Вони _не враховують_ інші фактори, які можуть вплинути на _Загальну Пропозицію_, такі як спалювання комісій/рент, штрафи чи інші непередбачувані події знищення токенів у майбутньому. Тому тут представлено **верхню межу** кількості SOL, випущених через інфляцію. -![Example proposed inflation schedule graph](/assets/docs/economics/proposed_inflation_schedule.png) +![Графік прикладу запропонованого графіку інфляції](/assets/docs/economics/proposed_inflation_schedule.png) -In the above graph we see the annual inflation rate percentage over time, given -the inflation parameters proposed above. +На графіку вище показано відсоток річної ставки інфляції з часом, виходячи з запропонованих параметрів інфляції. -![Example proposed total supply graph](/assets/docs/economics/proposed_total_supply.png) +![Графік прикладу загальної пропозиції](/assets/docs/economics/proposed_total_supply.png) -Similarly, here we see the _Total Current Supply_ of SOL [MM] over time, -assuming an initial _Total Current Supply_ of `488,587,349 SOL` (i.e. for this -example, taking the _Total Current Supply_ as of `2020-01-25` and simulating -inflation starting from that day). +Подібним чином, тут показано _Поточну Загальну Пропозицію_ SOL [млн] з часом, за умови початкової _Поточна Загальна Пропозиція_ `488,587,349 SOL` (тобто, у цьому прикладі, взято _Поточну Загальну Пропозицію_ станом на `2020-01-25` і моделюється інфляція, починаючи з цього дня). -Setting aside validator uptime and commissions, the expected Staking Yield and -Adjusted Staking Yield metrics are then primarily a function of the % of total -SOL staked on the network. Therefore we can model _Staking Yield_, if we -introduce an additional parameter _% of Staked SOL_: +Відставляючи осторонь доступність валідаторів і комісії, очікувані показники _Дохідності Стейкінгу_ та _Скоригованої Дохідності Стейкінгу_ є в першу чергу функцією % від загального SOL у стейкінгу. Тому ми можемо моделювати _Дохідність Стейкінгу_, якщо введемо додатковий параметр _% Стейкінгованих SOL_: - + -This parameter must be estimated because it is a dynamic property of the token -holders and staking incentives. The values of _% of Staked SOL_ presented here -range from 60% - 90%, which we feel covers the likely range we expect to -observe, based on feedback from the investor and validator communities as well -as what is observed on comparable Proof-of-Stake protocols. +Цей параметр має бути оцінений, оскільки це динамічна властивість власників токенів і стимулів стейкінгу. Значення _% Стейкінгованих SOL_, представлені тут, варіюються від 60% до 90%, що, на нашу думку, охоплює ймовірний діапазон, який ми очікуємо, базуючись на зворотному зв’язку від спільнот інвесторів і валідаторів, а також спостереженнях на порівнянних протоколах Proof-of-Stake. -![Example staked yields graph](/assets/docs/economics/example_staked_yields.png) +![Графік прикладу дохідності стейкінгу](/assets/docs/economics/example_staked_yields.png) -Again, the above shows an example _Staked Yield_ that a staker might expect over -time on the Solana network with the _Inflation Schedule_ as specified. This is -an idealized _Staked Yield_ as it neglects validator uptime impact on rewards, -validator commissions, potential yield throttling and potential slashing -incidents. It additionally ignores that _% of Staked SOL_ is dynamic by design - -the economic incentives set up by this _Inflation Schedule_ are more clearly -seen when _Token Dilution_ is taken into account (see the **Adjusted Staking -Yield** section below). +На графіку вище показано приклад _Дохідності Стейкінгу_, яку може очікувати учасник стейкінгу з часом у мережі Solana з вказаним _Графіком Інфляції_. Це ідеалізована _Дохідність Стейкінгу_, оскільки вона не враховує вплив доступності валідаторів на винагороди, комісії валідаторів, можливе обмеження дохідності та можливі інциденти зі штрафами. Вона також ігнорує, що _% Стейкінгованих SOL_ є динамічним за своєю суттю — економічні стимули, створені цим _Графіком Інфляції_, стають більш зрозумілими, коли враховується _Дилюція Токенів_ (див. розділ **Скоригована Дохідність Стейкінгу** нижче). diff --git a/docs/uk/economics/inflation/terminology.md b/docs/uk/economics/inflation/terminology.md index c6d6503f9..bdd0cbe94 100644 --- a/docs/uk/economics/inflation/terminology.md +++ b/docs/uk/economics/inflation/terminology.md @@ -1,112 +1,46 @@ --- -sidebarLabel: Inflation Terminology -title: Inflation Related Terminology +sidebarLabel: Терміни, Пов’язані з Інфляцією +title: Терміни, Пов’язані з Інфляцією --- -Many terms are thrown around when discussing inflation and the related -components (e.g. rewards/yield/interest), we try to define and clarify some -commonly used concept here: - -### Total Current Supply [SOL] - -The total amount of tokens (locked or unlocked) that have been generated (via -genesis block or protocol inflation) minus any tokens that have been burnt (via -transaction fees or other mechanism) or slashed. At network launch, 500,000,000 -SOL were instantiated in the genesis block. Since then the Total Current Supply -has been reduced by the burning of transaction fees and a planned token -reduction event. Solana's _Total Current Supply_ can be found at -https://explorer.solana.com/supply - -### Inflation Rate [%] - -The Solana protocol will automatically create new tokens on a predetermined -inflation schedule (discussed below). The _Inflation Rate [%]_ is the annualized -growth rate of the _Total Current Supply_ at any point in time. - -### Inflation Schedule - -A deterministic description of token issuance over time. The Solana Foundation -is proposing a disinflationary _Inflation Schedule_. I.e. Inflation starts at -its highest value, the rate reduces over time until stabilizing at a -predetermined long-term inflation rate (see discussion below). This schedule is -completely and uniquely parameterized by three numbers: - -- **Initial Inflation Rate [%]**: The starting _Inflation Rate_ for when - inflation is first enabled. Token issuance rate can only decrease from this - point. -- **Disinflation Rate [%]**: The rate at which the _Inflation Rate_ is reduced. -- **Long-term Inflation Rate [%]**: The stable, long-term _Inflation Rate_ to be - expected. - -### Effective Inflation Rate [%] - -The inflation rate actually observed on the Solana network after accounting for -other factors that might decrease the _Total Current Supply_. Note that it is -not possible for tokens to be created outside of what is described by the -_Inflation Schedule_. - -- While the _Inflation Schedule_ determines how the protocol issues SOL, this - neglects the concurrent elimination of tokens in the ecosystem due to various - factors. The primary token burning mechanism is the burning of a portion of - each transaction fee. 50% of each transaction fee is burned, with the - remaining fee retained by the validator that processes the transaction. -- Additional factors such as loss of private keys and slashing events should - also be considered in a holistic analysis of the _Effective Inflation Rate_. - For example, it's estimated that 10-20% of all BTC have been lost and are - unrecoverable and that networks may experience similar yearly losses at the - rate of 1-2%. - -### Staking Yield [%] - -The rate of return (aka _interest_) earned on SOL staked on the network. It is -often quoted as an annualized rate (e.g. "the network _staking yield_ is -currently 10% per year"). - -- _Staking yield_ is of great interest to validators and token holders who wish - to delegate their tokens to avoid token dilution due to inflation (the extent - of which is discussed below). -- 100% of inflationary issuances are to be distributed to staked token-holders - in proportion to their staked SOL and to validators who charge a commission on - the rewards earned by their delegated SOL. - - There may be future consideration for an additional split of inflation - issuance with the introduction of _Archivers_ into the economy. _Archivers_ - are network participants who provide a decentralized storage service and - should also be incentivized with token distribution from inflation issuances - for this service. - Similarly, early designs specified a fixed percentage of - inflationary issuance to be delivered to the Foundation treasury for - operational expenses and future grants. However, inflation will be launching - without any portion allocated to the Foundation. -- _Staking yield_ can be calculated from the _Inflation Schedule_ along with the - fraction of the _Total Current Supply_ that is staked at any given time. The - explicit relationship is given by: - - - -### Token Dilution [%] - -Dilution is defined here as the change in proportional representation of a set -of tokens within a larger set due to the introduction of new tokens. In -practical terms, we discuss the dilution of staked or un-staked tokens due to -the introduction and distribution of inflation issuance across the network. As -will be shown below, while dilution impacts every token holder, the _relative_ -dilution between staked and un-staked tokens should be the primary concern to -un-staked token holders. Staking tokens, which will receive their proportional -distribution of inflation issuance, should assuage any dilution concerns for -staked token holders. I.e. dilution from 'inflation' is offset by the -distribution of new tokens to staked token holders, nullifying the 'dilutive' -effects of the inflation for that group. - -### Adjusted Staking Yield [%] - -A complete appraisal of earning potential from staking tokens should take into -account staked _Token Dilution_ and its impact on the _Staking Yield_. For this, -we define the _Adjusted Staking Yield_ as the change in fractional token supply -ownership of staked tokens due to the distribution of inflation issuance. I.e. -the positive dilutive effects of inflation. +При обговоренні інфляції та пов’язаних компонентів (наприклад, винагород/дохідності/відсотків) використовується багато термінів. Тут ми намагаємося визначити та уточнити деякі загальновживані поняття: + +### Поточна Загальна Пропозиція [SOL] + +Загальна кількість токенів (заблокованих або незаблокованих), які були створені (через генезисний блок або інфляцію протоколу) мінус будь-які токени, які були спалені (через комісії за транзакції або інші механізми) чи списані. Під час запуску мережі було створено 500,000,000 SOL у генезисному блоці. З того часу Поточна Загальна Пропозиція зменшилася через спалювання комісій за транзакції та заплановану подію зменшення кількості токенів. _Поточну Загальну Пропозицію_ Solana можна знайти за адресою: https://explorer.solana.com/supply + +### Ставка Інфляції [%] + +Протокол Solana автоматично створює нові токени за заздалегідь визначеним графіком інфляції (обговорено нижче). _Ставка Інфляції [%]_ — це річний темп зростання _Поточна Загальна Пропозиція_ на будь-який момент часу. + +### Графік Інфляції + +Детерміноване описання випуску токенів з часом. Фонд Solana пропонує дезінфляційний _Графік Інфляції_. Тобто інфляція починається з найвищого значення, а її темп зменшується з часом, доки не стабілізується на заздалегідь визначеному довгостроковому рівні (див. обговорення нижче). Цей графік повністю та унікально параметризується трьома числами: + +- **Початкова Ставка Інфляції [%]**: Початкова _Ставка Інфляції_ для моменту активації інфляції. Темп випуску токенів може тільки знижуватися з цього моменту. +- **Ставка Дезінфляції [%]**: Темп, з яким зменшується _Ставка Інфляції_. +- **Довгострокова Ставка Інфляції [%]**: Стабільна, довгострокова _Ставка Інфляції_. + +### Ефективна Ставка Інфляції [%] + +Фактична ставка інфляції, що спостерігається в мережі Solana, після врахування інших факторів, які можуть зменшити _Поточну Загальну Пропозицію_. Зазначимо, що створення токенів поза описаним _Графіком Інфляції_ неможливе. + +- Хоча _Графік Інфляції_ визначає, як протокол випускає SOL, він не враховує одночасного знищення токенів через різні фактори. Основний механізм спалювання токенів — це спалювання частини кожної комісії за транзакцію. 50% кожної комісії за транзакцію спалюється, решта залишається валідатору, який обробив транзакцію. +- Додаткові фактори, такі як втрата приватних ключів і списання токенів, також слід враховувати в комплексному аналізі _Ефективної Ставки Інфляції_. Наприклад, оцінюється, що 10–20% всіх BTC втрачені та недоступні, і мережі можуть зазнавати подібних щорічних втрат на рівні 1–2%. + +### Дохідність Стейкінгу [%] + +Темп повернення (також відомий як _відсоток_), який отримується за SOL, поставлені на стейкінг у мережі. Зазвичай він зазначається як річний темп (наприклад, "дохідність стейкінгу в мережі наразі становить 10% на рік"). + +- _Дохідність стейкінгу_ дуже цікавить валідаторів і власників токенів, які бажають делегувати свої токени, щоб уникнути розмивання токенів через інфляцію (масштаб якої обговорено нижче). +- 100% інфляційних випусків розподіляються між власниками стейкінгованих токенів пропорційно до їхнього стейкінгованого SOL, а також валідаторами, які стягують комісію з винагороди, отриманої за делегований SOL. + - Може бути враховано майбутнє розділення інфляційних випусків із введенням _Архіваторів_ у економіку. _Архіватори_ — це учасники мережі, які надають децентралізовані послуги зберігання, і їх також слід стимулювати розподілом токенів з інфляційних випусків за цю послугу. +- _Дохідність Стейкінгу_ можна розрахувати за _Графіком Інфляції_ разом із часткою _Поточна Загальна Пропозиція_, що перебуває в стейкінгу. + +### Дилюція Токенів [%] + +Розмивання визначається тут як зміна пропорційного представлення набору токенів у більшому наборі через введення нових токенів. У практичному сенсі ми обговорюємо розмивання стейкінгованих або нестейкінгованих токенів через введення та розподіл інфляційних випусків по мережі. + +### Скоригована Дохідність Стейкінгу [%] + +Повна оцінка потенціалу заробітку від стейкінгу токенів повинна враховувати стейкінговану _Дилюцію Токенів_ та її вплив на _Дохідність Стейкінгу_. Для цього ми визначаємо _Скориговану Дохідність Стейкінгу_ як зміну фракційної власності токенів у стейкінгу через розподіл інфляційних випусків. diff --git a/docs/uk/economics/staking/index.md b/docs/uk/economics/staking/index.md index b4e741f43..708dd1826 100644 --- a/docs/uk/economics/staking/index.md +++ b/docs/uk/economics/staking/index.md @@ -1,98 +1,88 @@ --- -sidebarLabel: Staking -title: Staking on Solana +sidebarLabel: Стейкінг +title: Стейкінг у Solana --- -_Note before reading: All references to increases in values are in absolute -terms with regards to balance of SOL. This document makes no suggestion as to -the monetary value of SOL at any time._ +_Примітка перед читанням: Усі згадки про збільшення значень стосуються абсолютних +показників балансу SOL. Цей документ не містить жодних припущень щодо +грошової вартості SOL у будь-який час._ -By staking your SOL tokens, you help secure the network and -[earn rewards](https://docs.anza.xyz/implemented-proposals/staking-rewards) -while doing so. +Стейкуючи ваші токени SOL, ви допомагаєте забезпечувати безпеку мережі та +[отримувати винагороди](https://docs.anza.xyz/implemented-proposals/staking-rewards) +у процесі цього. -You can stake by delegating your tokens to validators who process transactions -and run the network. +Ви можете здійснювати стейкінг, делегуючи ваші токени валідаторам, які обробляють транзакції +та забезпечують роботу мережі. -Delegating stake is a shared-risk shared-reward financial model that may provide -returns to holders of tokens delegated for a long period. This is achieved by -aligning the financial incentives of the token-holders (delegators) and the -validators to whom they delegate. +Делегування стейкінгу — це фінансова модель з розподіленим ризиком і винагородою, яка може +забезпечити дохід для власників токенів, делегованих на тривалий період. Це досягається +шляхом узгодження фінансових інтересів власників токенів (делегаторів) та валідаторів, +яким вони делегують токени. -The more stake delegated to a validator, the more often this validator is chosen -to write new transactions to the ledger. The more transactions the validator -writes, the more rewards the validator and its delegators earn. Validators who -configure their systems to be able to process more transactions earn -proportionally more rewards and because they keep the network running as fast -and as smoothly as possible. +Чим більше стейку делеговано валідатору, тим частіше цей валідатор обирається для запису +нових транзакцій до реєстру. Чим більше транзакцій записує валідатор, тим більше винагород +отримують валідатор і його делегатори. Валідатори, які налаштовують свої системи для обробки +більшої кількості транзакцій, заробляють пропорційно більше винагород і допомагають +підтримувати мережу якомога швидшою та стабільнішою. -Validators incur costs by running and maintaining their systems, and this is -passed on to delegators in the form of a fee collected as a percentage of -rewards earned. This fee is known as a _commission_. Since validators earn more -rewards the more stake is delegated to them, they may compete with one another -to offer the lowest commission for their services. +Валідатори несуть витрати на обслуговування та підтримку своїх систем, і ці витрати передаються +делегаторам у формі комісії, яка стягується як відсоток від зароблених винагород. Ця комісія +називається _комісією валідатора_. Оскільки валідатори отримують більше винагород за більше +делегованого стейку, вони можуть конкурувати між собою, пропонуючи найнижчу комісію за свої послуги. -Although this is not implemented in the Solana protocol today, in the future, -delegators could risk losing tokens when staking through a process known as -_slashing_. Slashing involves the removal and destruction of a portion of a -validator's SOL in response to intentional malicious behavior, such as creating -invalid transactions or censoring certain types of transactions or network -participants. +Хоча це не реалізовано в протоколі Solana сьогодні, у майбутньому делегатори можуть ризикувати +втратити токени через процес, відомий як _слешинг_. Слешинг передбачає вилучення та знищення частини +SOL валідатора у відповідь на навмисну зловмисну поведінку, наприклад, створення недійсних транзакцій +або цензурування певних типів транзакцій чи учасників мережі. -There is no in protocol implementation of slashing currently. For more -information on slashing see the -[slashing roadmap](https://docs.anza.xyz/proposals/optimistic-confirmation-and-slashing#slashing-roadmap). +На даний момент у протоколі Solana немає реалізації слешингу. Для отримання додаткової інформації +про слешинг перегляньте +[дорожню карту слешингу](https://docs.anza.xyz/proposals/optimistic-confirmation-and-slashing#slashing-roadmap). -## How do I stake my SOL tokens? +## Як здійснити стейкінг моїх токенів SOL? -You can stake SOL by moving your tokens into a wallet that supports staking. The -wallet provides steps to create a stake account and do the delegation. +Ви можете здійснити стейкінг SOL, перемістивши свої токени в гаманець, який підтримує стейкінг. Гаманець +надасть інструкції для створення облікового запису стейкінгу та делегування. -#### Supported Wallets +#### Підтримувані Гаманці -Many web and mobile wallets support Solana staking operations. Please check with -your favorite wallet's maintainers regarding status +Багато веб- та мобільних гаманців підтримують операції стейкінгу Solana. Будь ласка, перевірте +статус підтримки у розробників вашого улюбленого гаманця. -#### Solana command line tools +#### Інструменти командного рядка Solana -- Solana command line tools can perform all stake operations in conjunction with - a CLI-generated keypair file wallet, a paper wallet, or with a connected - Ledger Nano. - [Staking commands using the Solana Command Line Tools](https://docs.anza.xyz/cli/examples/delegate-stake). +- Інструменти командного рядка Solana дозволяють виконувати всі операції стейкінгу в поєднанні з + гаманцем у вигляді файлу ключів, паперовим гаманцем або підключеним Ledger Nano. + [Команди для стейкінгу за допомогою інструментів командного рядка Solana](https://docs.anza.xyz/cli/examples/delegate-stake). -#### Create a Stake Account +#### Створення Облікового Запису Стейкінгу -Follow the wallet's instructions for creating a staking account. This account -will be of a different type than one used to simply send and receive tokens. +Виконуйте інструкції гаманця для створення облікового запису стейкінгу. Цей обліковий запис +відрізняється від облікових записів, які використовуються для відправлення та отримання токенів. -#### Select a Validator +#### Вибір Валідатора -Follow the wallet's instructions for selecting a validator. You can get -information about potentially performant validators from the links below. The -Solana Foundation does not recommend any particular validator. +Дотримуйтесь інструкцій гаманця для вибору валідатора. Ви можете отримати інформацію про потенційно +ефективних валідаторів за посиланнями нижче. Фонд Solana не рекомендує конкретних валідаторів. -The site solanabeach.io is built and maintained by one of our validators, -Staking Facilities. It provides a some high-level graphical information about -the network as a whole, as well as a list of each validator and some recent -performance statistics about each one. +Сайт solanabeach.io створений і підтримується одним з наших валідаторів, +Staking Facilities. Він надає графічну інформацію про мережу в цілому, а також +список кожного валідатора з деякими останніми статистиками їхньої продуктивності. - https://solanabeach.io -To view block production statistics, use the Solana command-line tools: +Для перегляду статистики виробництва блоків використовуйте інструменти командного рядка Solana: - `solana validators` - `solana block-production` -The Solana team does not make recommendations on how to interpret this -information. Do your own due diligence. +Команда Solana не надає рекомендацій щодо інтерпретації цієї інформації. Виконуйте власне дослідження. -#### Delegate your Stake +#### Делегування Стейку -Follow the wallet's instructions for delegating your stake to your chosen -validator. +Виконуйте інструкції гаманця для делегування вашого стейку обраному вами валідатору. -## Stake Account Details +## Деталі Облікового Запису Стейкінгу -For more information about the operations and permissions associated with a -stake account, please see -[Stake Accounts](/docs/economics/staking/stake-accounts.md) +Для отримання додаткової інформації про операції та дозволи, пов’язані з обліковим записом стейкінгу, +дивіться [Облікові Записи Стейкінгу](/docs/economics/staking/stake-accounts.md) diff --git a/docs/uk/economics/staking/stake-accounts.md b/docs/uk/economics/staking/stake-accounts.md index 972458007..9eb222c24 100644 --- a/docs/uk/economics/staking/stake-accounts.md +++ b/docs/uk/economics/staking/stake-accounts.md @@ -1,146 +1,56 @@ --- -sidebarLabel: Stake Accounts -title: Stake Accounts +sidebarLabel: Облікові Записи Стейкінгу +title: Облікові Записи Стейкінгу --- -A stake account on Solana can be used to delegate tokens to validators on the -network to potentially earn rewards for the owner of the stake account. Stake -accounts are created and managed differently than a traditional wallet address, -known as a _system account_. A system account is only able to send and receive -SOL from other accounts on the network, whereas a stake account supports more -complex operations needed to manage a delegation of tokens. +Обліковий запис стейкінгу на Solana може використовуватися для делегування токенів валідаторам у мережі з можливістю отримання винагород для власника облікового запису стейкінгу. Облікові записи стейкінгу створюються та керуються інакше, ніж традиційні адреси гаманців, відомі як _системні облікові записи_. Системний обліковий запис здатний лише надсилати та отримувати SOL від інших облікових записів у мережі, тоді як обліковий запис стейкінгу підтримує складніші операції, необхідні для управління делегуванням токенів. -Stake accounts on Solana also work differently than those of other -Proof-of-Stake blockchain networks that you may be familiar with. This document -describes the high-level structure and functions of a Solana stake account. +Облікові записи стейкінгу на Solana також працюють інакше, ніж у інших блокчейн-мережах Proof-of-Stake, з якими ви могли бути знайомі. У цьому документі описується загальна структура та функції облікового запису стейкінгу Solana. -#### Account Address +#### Адреса Облікового Запису -Each stake account has a unique address which can be used to look up the account -information in the command line or in any network explorer tools. However, -unlike a wallet address in which the holder of the address's keypair controls -the wallet, the keypair associated with a stake account address does not -necessarily have any control over the account. In fact, a keypair or private key -may not even exist for a stake account's address. +Кожен обліковий запис стейкінгу має унікальну адресу, яка може використовуватися для перегляду інформації про обліковий запис через командний рядок або будь-які інструменти дослідження мережі. Однак, на відміну від адреси гаманця, власник ключової пари адреси не обов'язково має контроль над обліковим записом. Насправді, для адреси облікового запису стейкінгу може навіть не існувати ключова пара чи приватний ключ. -The only time a stake account's address has a keypair file is when -[creating a stake account using the command line tools](https://docs.anza.xyz/cli/examples/delegate-stake#create-a-stake-account). -A new keypair file is created first only to ensure that the stake account's -address is new and unique. +Ключова пара створюється лише під час [створення облікового запису стейкінгу за допомогою інструментів командного рядка](https://docs.anza.xyz/cli/examples/delegate-stake#create-a-stake-account). Нова ключова пара створюється виключно для забезпечення унікальності адреси облікового запису стейкінгу. -#### Understanding Account Authorities +#### Розуміння Авторитетів Облікового Запису -Certain types of accounts may have one or more _signing authorities_ associated -with a given account. An account authority is used to sign certain transactions -for the account it controls. This is different from some other blockchain -networks where the holder of the keypair associated with the account's address -controls all of the account's activity. +Деякі типи облікових записів можуть мати один або більше _авторитетів підпису_, пов’язаних з обліковим записом. Авторитет облікового запису використовується для підпису певних транзакцій для облікового запису, яким він керує. Це відрізняється від інших блокчейнів, де власник ключової пари контролює всі дії облікового запису. -Each stake account has two signing authorities specified by their respective -address, each of which is authorized to perform certain operations on the stake -account. +Кожен обліковий запис стейкінгу має два авторитети підпису, які вказані їхніми відповідними адресами: -The _stake authority_ is used to sign transactions for the following operations: +- _Авторитет стейкінгу_ використовується для підпису транзакцій, пов’язаних із: + - Делегуванням стейку + - Деактивацією делегування стейку + - Розділенням облікового запису на два окремі + - Об'єднанням двох облікових записів стейкінгу + - Призначенням нового авторитету стейкінгу -- Delegating stake -- Deactivating the stake delegation -- Splitting the stake account, creating a new stake account with a portion of - the funds in the first account -- Merging two stake accounts into one -- Setting a new stake authority +- _Авторитет виведення_ підписує транзакції для: + - Виведення неделегованого стейку + - Призначення нового авторитету виведення + - Призначення нового авторитету стейкінгу -The _withdraw authority_ signs transactions for the following: +#### Множинне Делегування -- Withdrawing un-delegated stake into a wallet address -- Setting a new withdraw authority -- Setting a new stake authority +Один обліковий запис стейкінгу може бути делегований лише одному валідатору. Усі токени в обліковому записі є або делегованими, або неделегованими. Щоб делегувати частину токенів кільком валідаторам, потрібно створити кілька облікових записів стейкінгу. -The stake authority and withdraw authority are set when the stake account is -created, and they can be changed to authorize a new signing address at any time. -The stake and withdraw authority can be the same address or two different -addresses. +#### Об'єднання Облікових Записів -The withdraw authority keypair holds more control over the account as it is -needed to liquidate the tokens in the stake account, and can be used to reset -the stake authority if the stake authority keypair becomes lost or compromised. +Два облікові записи стейкінгу з однаковими авторитетами та параметрами блокування можуть бути об’єднані в один. -Securing the withdraw authority against loss or theft is of utmost importance -when managing a stake account. +#### Розігрів та Охолодження Делегування -#### Multiple Delegations +Процес делегування або деактивації делегування не є миттєвим і може займати кілька [епох](/docs/terminology.md#epoch). -Each stake account may only be used to delegate to one validator at a time. All -of the tokens in the account are either delegated or un-delegated, or in the -process of becoming delegated or un-delegated. To delegate a fraction of your -tokens to a validator, or to delegate to multiple validators, you must create -multiple stake accounts. +#### Блокування -This can be accomplished by creating multiple stake accounts from a wallet -address containing some tokens, or by creating a single large stake account and -using the stake authority to split the account into multiple accounts with token -balances of your choosing. +Облікові записи стейкінгу можуть мати блокування, яке забороняє виведення токенів до досягнення певної дати або епохи. -The same stake and withdraw authorities can be assigned to multiple stake -accounts. +#### Видалення Облікового Запису -#### Merging stake accounts +Обліковий запис стейкінгу, баланс якого дорівнює 0 SOL, автоматично припиняє існувати. -Two stake accounts that have the same authorities and lockup can be merged into -a single resulting stake account. A merge is possible between two stakes in the -following states with no additional conditions: +#### Перегляд Облікових Записів Стейкінгу -- two deactivated stakes -- an inactive stake into an activating stake during its activation epoch - -For the following cases, the voter pubkey and vote credits observed must match: - -- two activated stakes -- two activating accounts that share an activation epoch, during the activation - epoch - -All other combinations of stake states will fail to merge, including all -"transient" states, where a stake is activating or deactivating with a non-zero -effective stake. - -#### Delegation Warmup and Cooldown - -When a stake account is delegated, or a delegation is deactivated, the operation -does not take effect immediately. - -A delegation or deactivation takes several [epochs](/docs/terminology.md#epoch) -to complete, with a fraction of the delegation becoming active or inactive at -each epoch boundary after the transaction containing the instructions has been -submitted to the cluster. - -There is also a limit on how much total stake can become delegated or -deactivated in a single epoch, to prevent large sudden changes in stake across -the network as a whole. Since warmup and cooldown are dependent on the behavior -of other network participants, their exact duration is difficult to predict. -Details on the warmup and cooldown timing can be found -[here](https://docs.anza.xyz/consensus/stake-delegation-and-rewards#stake-warmup-cooldown-withdrawal). - -#### Lockups - -Stake accounts can have a lockup which prevents the tokens they hold from being -withdrawn before a particular date or epoch has been reached. While locked up, -the stake account can still be delegated, un-delegated, or split, and its stake -authority can be changed as normal. Only withdrawal into another wallet or -updating the withdraw authority is not allowed. - -A lockup can only be added when a stake account is first created, but it can be -modified later, by the _lockup authority_ or _custodian_, the address of which -is also set when the account is created. - -#### Destroying a Stake Account - -Like other types of accounts on the Solana network, a stake account that has a -balance of 0 SOL is no longer tracked. If a stake account is not delegated and -all of the tokens it contains are withdrawn to a wallet address, the account at -that address is effectively destroyed, and will need to be manually re-created -for the address to be used again. - -#### Viewing Stake Accounts - -Stake account details can be viewed on the -[Solana Explorer](http://explorer.solana.com/accounts) by copying and pasting an -account address into the search bar. +Інформацію про обліковий запис стейкінгу можна переглянути через [Solana Explorer](http://explorer.solana.com/accounts). diff --git a/docs/uk/economics/staking/stake-programming.md b/docs/uk/economics/staking/stake-programming.md index ed9852168..f914000a2 100644 --- a/docs/uk/economics/staking/stake-programming.md +++ b/docs/uk/economics/staking/stake-programming.md @@ -1,28 +1,15 @@ --- -title: Stake Programming +title: Програмування Стейкінгу --- -To maximize stake distribution, decentralization, and censorship resistance on -the Solana network, staking can be performed programmatically. The team and -community have developed several on-chain and offchain programs to make stakes -easier to manage. +Для максимізації розподілу стейку, децентралізації та стійкості до цензури в мережі Solana, стейкінг може виконуватись програмно. Команда та спільнота розробили кілька програм для роботи як на ланцюгу, так і поза ним, щоб зробити управління стейками простішим. -#### Stake-o-matic aka Auto-delegation Bots +#### Stake-o-matic, також відомий як боти автоделегування -This offchain program manages a large population of validators staked by a -central authority. The Solana Foundation uses an auto-delegation bot to -regularly delegate its stake to "non-delinquent" validators that meet specified -performance requirements. +Ця позаланцюгова програма управляє великою кількістю валідаторів, яким делегує стейк центральний орган. Фонд Solana використовує бота автоделегування для регулярного делегування свого стейку "неспійманим" валідаторам, які відповідають визначеним вимогам продуктивності. #### Stake Pools -This on-chain program pools together SOL to be staked by a manager, allowing SOL -holders to stake and earn rewards without managing stakes. Users deposit SOL in -exchange for SPL tokens (staking derivatives) that represent their ownership in -the stake pool. The pool manager stakes deposited SOL according to their -strategy, perhaps using a variant of an auto-delegation bot as described above. -As stakes earn rewards, the pool and pool tokens grow proportionally in value. -Finally, pool token holders can send SPL tokens back to the stake pool to redeem -SOL, thereby participating in decentralization with much less work required. -More information can be found at the -[SPL stake pool documentation](https://spl.solana.com/stake-pool). +Ця програма на ланцюгу об'єднує SOL для стейкінгу, яким управляє менеджер, дозволяючи власникам SOL здійснювати стейкінг та отримувати винагороди без необхідності управляти стейками. Користувачі депонують SOL в обмін на SPL-токени (похідні стейкінгу), які представляють їхню частку в пулі стейкінгу. Менеджер пулу здійснює стейкінг внесених SOL відповідно до своєї стратегії, можливо, використовуючи варіант бота автоделегування, описаного вище. Коли стейки отримують винагороди, вартість пулу та токенів пулу пропорційно зростає. Нарешті, власники токенів пулу можуть повернути SPL-токени назад у пул стейкінгу для викупу SOL, тим самим беручи участь у децентралізації з мінімальними зусиллями. + +Детальнішу інформацію можна знайти в [документації SPL Stake Pool](https://spl.solana.com/stake-pool). From 7eabac1751b2f5fba7e43ef8c48d8f70b65a311e Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Sun, 12 Jan 2025 19:30:53 +0200 Subject: [PATCH 08/14] Finished intro folder. Fixed links in uk docs --- docs/uk/advanced/confirmation.md | 34 +- docs/uk/advanced/lookup-tables.md | 10 +- docs/uk/advanced/retry.md | 10 +- docs/uk/advanced/state-compression.md | 8 +- docs/uk/advanced/versions.md | 12 +- docs/uk/clients/javascript-reference.md | 14 +- docs/uk/clients/rust.md | 4 +- docs/uk/core/clusters.md | 4 +- docs/uk/core/fees.md | 30 +- docs/uk/core/pda.md | 4 +- docs/uk/core/programs.md | 6 +- docs/uk/core/tokens.md | 8 +- docs/uk/core/transactions.md | 38 +- docs/uk/economics/index.md | 6 +- .../economics/inflation/inflation-schedule.md | 4 +- docs/uk/economics/staking/index.md | 2 +- docs/uk/intro/dev.md | 210 ++++------ docs/uk/intro/installation.md | 303 ++++++-------- .../quick-start/cross-program-invocation.md | 262 +++++------- .../intro/quick-start/deploying-programs.md | 138 +++---- docs/uk/intro/quick-start/index.md | 108 ++--- .../quick-start/program-derived-address.md | 381 +++++++----------- .../intro/quick-start/reading-from-network.md | 231 ++++------- .../intro/quick-start/writing-to-network.md | 113 +++--- docs/uk/intro/wallets.md | 66 +-- docs/uk/terminology.md | 10 +- 26 files changed, 787 insertions(+), 1229 deletions(-) diff --git a/docs/uk/advanced/confirmation.md b/docs/uk/advanced/confirmation.md index ef49a0f9e..7134d5313 100644 --- a/docs/uk/advanced/confirmation.md +++ b/docs/uk/advanced/confirmation.md @@ -7,12 +7,12 @@ description: "Дізнайтеся, як працює підтвердження транзакцій у Solana і коли транзакція завершує дію (включаючи перевірку останніх blockhash)." altRoutes: - - /docs/advanced - - /docs/core/transactions/confirmation + - /docs/uk/advanced + - /docs/uk/core/transactions/confirmation --- Проблеми, пов'язані з -[підтвердженням транзакції](/docs/terminology.md#transaction-confirmations), +[підтвердженням транзакції](/docs/uk/terminology.md#transaction-confirmations), є поширеними серед нових розробників під час створення застосунків. Ця стаття має на меті підвищити загальне розуміння механізму підтвердження, який використовується в блокчейні Solana, включаючи деякі рекомендовані найкращі практики. ## Короткий вступ до транзакцій @@ -27,9 +27,9 @@ altRoutes: ### Що таке транзакція? Транзакції складаються з двох компонентів: -[повідомлення](/docs/terminology.md#message) +[повідомлення](/docs/uk/terminology.md#message) і -[списку підписів](/docs/terminology.md#signature). +[списку підписів](/docs/uk/terminology.md#signature). Повідомлення транзакції містить основну інформацію та складається з чотирьох компонентів: - **заголовок** з метаданими про транзакцію, @@ -38,7 +38,7 @@ altRoutes: - та **“недавній blockhash”**. У цій статті ми зосередимося на -[недавньому blockhash](/docs/terminology.md#blockhash), +[недавньому blockhash](/docs/uk/terminology.md#blockhash), оскільки він відіграє важливу роль у підтвердженні транзакції. ### Життєвий цикл транзакції @@ -55,9 +55,9 @@ altRoutes: ### Що таке Blockhash? -[“Blockhash”](/docs/terminology.md#blockhash) +[“Blockhash”](/docs/uk/terminology.md#blockhash) означає останній Proof of History (PoH) хеш для -[“слота”](/docs/terminology.md#slot) +[“слота”](/docs/uk/terminology.md#slot) (опис нижче). Оскільки Solana використовує PoH як довірений годинник, недавній blockhash транзакції можна розглядати як **мітку часу**. ### Коротке нагадування про Proof of History @@ -91,7 +91,7 @@ PoH може використовуватися як довірений годи > [нульовим індексом](https://github.com/anza-xyz/agave/blob/992a398fe8ea29ec4f04d081ceef7664960206f4/accounts-db/src/blockhash_queue.rs#L248-L274), > фактично є 151 blockhash, які вважаються "достатньо недавніми" і дійсними для обробки. -Оскільки [слоти](/docs/terminology.md#slot) (тобто періоди часу, протягом яких валідатор може створити блок) налаштовані на тривалість близько +Оскільки [слоти](/docs/uk/terminology.md#slot) (тобто періоди часу, протягом яких валідатор може створити блок) налаштовані на тривалість близько [400 мс](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L107-L109), але можуть коливатися між 400 мс і 600 мс, певний blockhash можна використовувати в транзакціях приблизно протягом 60–90 секунд, перш ніж він вважатиметься простроченим у середовищі виконання. @@ -162,7 +162,7 @@ Solana має кілька переваг у цьому підході: З огляду на короткий період закінчення строку дії, клієнти та додатки повинні допомагати користувачам створювати транзакції з blockhash, який є максимально недавнім. -Коли ви отримуєте blockhash, рекомендованим RPC API є [`getLatestBlockhash`](/docs/rpc/http/getLatestBlockhash.mdx). За замовчуванням цей API використовує рівень підтвердження `finalized`, щоб повернути blockhash останнього фіналізованого блоку. Проте ви можете змінити цю поведінку, встановивши параметр `commitment` на інший рівень підтвердження. +Коли ви отримуєте blockhash, рекомендованим RPC API є [`getLatestBlockhash`](/docs/uk/rpc/http/getLatestBlockhash.mdx). За замовчуванням цей API використовує рівень підтвердження `finalized`, щоб повернути blockhash останнього фіналізованого блоку. Проте ви можете змінити цю поведінку, встановивши параметр `commitment` на інший рівень підтвердження. **Рекомендація** @@ -171,7 +171,7 @@ Solana має кілька переваг у цьому підході: Але ви також можете розглянути інші варіанти: - Вибір `processed` дозволяє отримати найбільш недавній blockhash порівняно з іншими рівнями підтвердження, що дає більше часу на підготовку і обробку транзакції. Однак через поширеність форків у блокчейні Solana близько 5% блоків не потрапляють у фіналізований кластер, що створює ризик того, що ваша транзакція використовує blockhash, що належить до відкинутого форку. Транзакції з такими blockhash ніколи не будуть вважатися недавніми у фіналізованому блокчейні. -- Використання [рівня підтвердження за замовчуванням](/docs/rpc#default-commitment) `finalized` виключає ризик того, що вибраний blockhash належатиме до відкинутого форку. Однак це має компроміс: зазвичай є щонайменше 32 слоти різниці між найбільш недавнім підтвердженим блоком і найбільш недавнім фіналізованим блоком. Це значно зменшує строк дії ваших транзакцій приблизно на 13 секунд, що може бути ще більш суттєвим за нестабільних умов кластеру. +- Використання [рівня підтвердження за замовчуванням](/docs/uk/rpc#default-commitment) `finalized` виключає ризик того, що вибраний blockhash належатиме до відкинутого форку. Однак це має компроміс: зазвичай є щонайменше 32 слоти різниці між найбільш недавнім підтвердженим блоком і найбільш недавнім фіналізованим блоком. Це значно зменшує строк дії ваших транзакцій приблизно на 13 секунд, що може бути ще більш суттєвим за нестабільних умов кластеру. ### Використовуйте відповідний рівень підтвердження для preflight @@ -194,7 +194,7 @@ Solana має кілька переваг у цьому підході: Для запитів `sendTransaction` клієнти повинні повторно надсилати транзакцію до RPC-вузла на частих інтервалах, щоб у випадку, якщо RPC-вузол трохи відстає від кластеру, він врешті-решт виявив транзакцію та її строк дії. Для запитів `simulateTransaction` клієнти повинні використовувати параметр -[`replaceRecentBlockhash`](/docs/rpc/http/simulateTransaction.mdx), щоб інструктувати RPC-вузол замінювати blockhash симульованої транзакції на blockhash, який завжди буде дійсним для симуляції. +[`replaceRecentBlockhash`](/docs/uk/rpc/http/simulateTransaction.mdx), щоб інструктувати RPC-вузол замінювати blockhash симульованої транзакції на blockhash, який завжди буде дійсним для симуляції. ### Уникайте повторного використання застарілих blockhash @@ -217,17 +217,17 @@ RPC-вузли можуть відставати від кластеру чер Моніторте стан RPC-вузлів, використовуючи такі методи: 1. Викликайте API - [`getSlot`](/docs/rpc/http/getSlot.mdx) з рівнем підтвердження `processed` для отримання останнього обробленого слота вузла та порівняйте його з - [`getMaxShredInsertSlot`](/docs/rpc/http/getMaxShredInsertSlot.mdx), щоб оцінити відставання вузла. -2. Використовуйте RPC API `getLatestBlockhash` з рівнем підтвердження `confirmed` на кількох різних RPC-вузлах та обирайте blockhash від вузла, який повертає найвищий слот для свого [контекстного слоту](/docs/rpc/index.mdx#rpcresponse-structure). + [`getSlot`](/docs/uk/rpc/http/getSlot.mdx) з рівнем підтвердження `processed` для отримання останнього обробленого слота вузла та порівняйте його з + [`getMaxShredInsertSlot`](/docs/uk/rpc/http/getMaxShredInsertSlot.mdx), щоб оцінити відставання вузла. +2. Використовуйте RPC API `getLatestBlockhash` з рівнем підтвердження `confirmed` на кількох різних RPC-вузлах та обирайте blockhash від вузла, який повертає найвищий слот для свого [контекстного слоту](/docs/uk/rpc/index.mdx#rpcresponse-structure). ### Зачекайте достатньо довго перед закінченням терміну дії **Рекомендація** -При виклику RPC API [`getLatestBlockhash`](/docs/rpc/http/getLatestBlockhash.mdx) для отримання останнього blockhash вашої транзакції зверніть увагу на `lastValidBlockHeight` у відповіді. +При виклику RPC API [`getLatestBlockhash`](/docs/uk/rpc/http/getLatestBlockhash.mdx) для отримання останнього blockhash вашої транзакції зверніть увагу на `lastValidBlockHeight` у відповіді. -Потім викликайте RPC API [`getBlockHeight`](/docs/rpc/http/getBlockHeight.mdx) з рівнем підтвердження `confirmed`, поки він не поверне висоту блоку, більшу за попередньо отриманий `lastValidBlockHeight`. +Потім викликайте RPC API [`getBlockHeight`](/docs/uk/rpc/http/getBlockHeight.mdx) з рівнем підтвердження `confirmed`, поки він не поверне висоту блоку, більшу за попередньо отриманий `lastValidBlockHeight`. ### Розгляньте використання "довготривалих" транзакцій diff --git a/docs/uk/advanced/lookup-tables.md b/docs/uk/advanced/lookup-tables.md index 8709495bd..360f13a6a 100644 --- a/docs/uk/advanced/lookup-tables.md +++ b/docs/uk/advanced/lookup-tables.md @@ -7,7 +7,7 @@ description: Таблиці пошуку адрес, зазвичай відомі як "_lookup tables_" або скорочено "_ALTs_", дозволяють розробникам створювати колекції пов’язаних адрес для ефективного завантаження більшої кількості адрес в одній транзакції. -Оскільки кожна транзакція в блокчейні Solana вимагає переліку всіх адрес, з якими вона взаємодіє, цей перелік фактично обмежується 32 адресами на транзакцію. Завдяки [Таблицям пошуку адрес](/docs/advanced/lookup-tables.md) це обмеження можна збільшити до 64 адрес у кожній транзакції. +Оскільки кожна транзакція в блокчейні Solana вимагає переліку всіх адрес, з якими вона взаємодіє, цей перелік фактично обмежується 32 адресами на транзакцію. Завдяки [Таблицям пошуку адрес](/docs/uk/advanced/lookup-tables.md) це обмеження можна збільшити до 64 адрес у кожній транзакції. ## Стиснення адрес на блокчейні @@ -17,7 +17,7 @@ description: ## Версійні транзакції -Щоб використовувати Таблицю пошуку адрес у транзакції, розробники повинні застосовувати транзакції версії v0, які були запроваджені з новим форматом [Версійних транзакцій](/docs/advanced/versions.md). +Щоб використовувати Таблицю пошуку адрес у транзакції, розробники повинні застосовувати транзакції версії v0, які були запроваджені з новим форматом [Версійних транзакцій](/docs/uk/advanced/versions.md). ## Як створити таблицю пошуку адрес @@ -48,7 +48,7 @@ console.log("lookup table address:", lookupTableAddress.toBase58()); // send the `lookupTableInst` instruction in a transaction ``` -> ПРИМІТКА: Таблиці пошуку адрес можуть бути **створені** за допомогою як транзакцій `v0`, так і `legacy`. Але виконуюче середовище Solana може отримувати та обробляти додаткові адреси в таблиці пошуку лише під час використання [Версійних транзакцій v0](/docs/advanced/versions.md#current-transaction-versions). +> ПРИМІТКА: Таблиці пошуку адрес можуть бути **створені** за допомогою як транзакцій `v0`, так і `legacy`. Але виконуюче середовище Solana може отримувати та обробляти додаткові адреси в таблиці пошуку лише під час використання [Версійних транзакцій v0](/docs/uk/advanced/versions.md#current-transaction-versions). ## Додавання адрес до таблиці пошуку @@ -107,8 +107,8 @@ for (let i = 0; i < lookupTableAccount.state.addresses.length; i++) { Після того як ви створили таблицю пошуку і зберегли необхідні адреси в блокчейні (через розширення таблиці пошуку), ви можете створити транзакцію `v0`, щоб скористатися можливостями пошуку адрес в блокчейні. Так само, як і для старих транзакцій `legacy`, ви можете створити всі -[інструкції](/docs/terminology.md#instruction), які ваша транзакція виконуватиме в блокчейні. Потім ви можете передати масив цих інструкцій у -[Message](/docs/terminology.md#message), що використовується в транзакції `v0`. +[інструкції](/docs/uk/terminology.md#instruction), які ваша транзакція виконуватиме в блокчейні. Потім ви можете передати масив цих інструкцій у +[Message](/docs/uk/terminology.md#message), що використовується в транзакції `v0`. > **Примітка:** Інструкції, що використовуються в транзакції `v0`, можна створювати за допомогою тих самих методів і функцій, які використовувалися раніше для створення інструкцій. > Немає необхідності змінювати інструкції, пов'язані з використанням таблиці пошуку адрес. diff --git a/docs/uk/advanced/retry.md b/docs/uk/advanced/retry.md index e69f0815a..42d1ee4c8 100644 --- a/docs/uk/advanced/retry.md +++ b/docs/uk/advanced/retry.md @@ -12,7 +12,7 @@ description: # Повторна відправка транзакцій -Іноді здається, що дійсна транзакція може бути втрачена до її включення в блок. Це зазвичай трапляється під час завантаженості мережі, коли RPC-вузол не може повторно передати транзакцію до [лідера](/docs/terminology.md#leader). Для кінцевого користувача це може виглядати так, ніби транзакція повністю зникає. Хоча RPC-вузли мають універсальний алгоритм повторного передавання, розробники додатків також можуть створювати власну логіку повторної передачі. +Іноді здається, що дійсна транзакція може бути втрачена до її включення в блок. Це зазвичай трапляється під час завантаженості мережі, коли RPC-вузол не може повторно передати транзакцію до [лідера](/docs/uk/terminology.md#leader). Для кінцевого користувача це може виглядати так, ніби транзакція повністю зникає. Хоча RPC-вузли мають універсальний алгоритм повторного передавання, розробники додатків також можуть створювати власну логіку повторної передачі. ## Коротко: @@ -28,7 +28,7 @@ description: У Solana немає концепції мемпулу. Усі транзакції, незалежно від того, чи ініційовані вони програмно або користувачем, ефективно маршрутизуються до лідерів для обробки в блоках. Є два основні способи надсилання транзакцій до лідерів: -1. Через RPC-сервер за допомогою методу JSON-RPC [sendTransaction](/docs/rpc/http/sendTransaction.mdx). +1. Через RPC-сервер за допомогою методу JSON-RPC [sendTransaction](/docs/uk/rpc/http/sendTransaction.mdx). 2. Безпосередньо до лідерів через [TPU Client](https://docs.rs/solana-client/latest/solana_client/tpu_client/index.html). Більшість користувачів відправляють транзакції через RPC-сервер. Коли клієнт надсилає транзакцію, RPC-вузол намагається передати її поточному та наступному лідерам. Поки транзакція не буде оброблена лідером, вона існує лише у вигляді запису в клієнта або проміжних RPC-вузлів. У випадку використання TPU клієнтом, передавання та маршрутизація обробляються програмним забезпеченням клієнта. @@ -39,7 +39,7 @@ description: Після отримання транзакції через `sendTransaction`, RPC-вузол перетворює транзакцію в [UDP](https://uk.wikipedia.org/wiki/UDP) пакет і передає його відповідним лідерам. UDP дозволяє вузлам швидко обмінюватися даними, але не гарантує доставки пакетів. -Оскільки розклад лідерів Solana відомий заздалегідь для кожного [епоха](/docs/terminology.md#epoch) (~2 дні), RPC-вузол передає транзакції безпосередньо до поточного та наступного лідерів. За замовчуванням RPC-вузли намагаються повторно передавати транзакції кожні дві секунди, доки транзакція не буде завершена або доки термін дії її blockhash не закінчиться (~1 хвилина 19 секунд). Якщо черга для повторної передачі перевищує [10,000 транзакцій](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/send-transaction-service/src/send_transaction_service.rs#L20), нові транзакції скидаються. +Оскільки розклад лідерів Solana відомий заздалегідь для кожного [епоха](/docs/uk/terminology.md#epoch) (~2 дні), RPC-вузол передає транзакції безпосередньо до поточного та наступного лідерів. За замовчуванням RPC-вузли намагаються повторно передавати транзакції кожні дві секунди, доки транзакція не буде завершена або доки термін дії її blockhash не закінчиться (~1 хвилина 19 секунд). Якщо черга для повторної передачі перевищує [10,000 транзакцій](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/send-transaction-service/src/send_transaction_service.rs#L20), нові транзакції скидаються. ![Процес обробки транзакцій TPU](/assets/docs/rt-tpu-jito-labs.png) @@ -112,7 +112,7 @@ const sleep = async (ms: number) => { })(); ``` -При опитуванні через `getLatestBlockhash` додатки повинні вказувати бажаний рівень [зобов'язань (commitment)](/docs/rpc/index.mdx#configuring-state-commitment). Встановлюючи зобов'язання на рівень `confirmed` (підтверджений) або `finalized` (~30 блоків після `confirmed`), додаток може уникнути опитування blockhash із меншості вузлів. +При опитуванні через `getLatestBlockhash` додатки повинні вказувати бажаний рівень [зобов'язань (commitment)](/docs/uk/rpc/index.mdx#configuring-state-commitment). Встановлюючи зобов'язання на рівень `confirmed` (підтверджений) або `finalized` (~30 блоків після `confirmed`), додаток може уникнути опитування blockhash із меншості вузлів. Якщо додаток має доступ до RPC-вузлів за балансувальником навантаження, він також може розподіляти своє навантаження між конкретними вузлами. RPC-вузли, які обслуговують ресурсоємні запити, такі як [getProgramAccounts](/content/guides/javascript/get-program-accounts.md), можуть відставати і бути менш ефективними для пересилання транзакцій. Для додатків, що обробляють транзакції в реальному часі, може бути розумним використовувати спеціалізовані вузли, які обслуговують лише `sendTransaction`. @@ -133,5 +133,5 @@ const sleep = async (ms: number) => { У Solana втрачену транзакцію можна безпечно відхилити, якщо blockhash, на який вона посилається, старший за `lastValidBlockHeight`, отриманий із `getLatestBlockhash`. Розробникам слід відстежувати цей `lastValidBlockHeight`, опитуючи -[`getEpochInfo`](/docs/rpc/http/getEpochInfo.mdx) і порівнюючи з `blockHeight` у відповіді. Після того, як blockhash стане недійсним, клієнти можуть повторно підписати транзакцію з новозапитаним blockhash. +[`getEpochInfo`](/docs/uk/rpc/http/getEpochInfo.mdx) і порівнюючи з `blockHeight` у відповіді. Після того, як blockhash стане недійсним, клієнти можуть повторно підписати транзакцію з новозапитаним blockhash. diff --git a/docs/uk/advanced/state-compression.md b/docs/uk/advanced/state-compression.md index ceb6665e2..c094491db 100644 --- a/docs/uk/advanced/state-compression.md +++ b/docs/uk/advanced/state-compression.md @@ -6,9 +6,9 @@ description: "відбитків" даних поза мережею в реєстрі Solana замість дорогих облікових записів.' --- -У Solana [стиснення стану](/docs/advanced/state-compression.md) є методом створення "відбитку" (або гешу) даних поза мережею та збереження цього відбитку в мережі для безпечної перевірки. Цей процес використовує безпеку реєстру Solana для гарантування цілісності даних поза мережею, забезпечуючи їх незмінність. +У Solana [стиснення стану](/docs/uk/advanced/state-compression.md) є методом створення "відбитку" (або гешу) даних поза мережею та збереження цього відбитку в мережі для безпечної перевірки. Цей процес використовує безпеку реєстру Solana для гарантування цілісності даних поза мережею, забезпечуючи їх незмінність. -Цей метод "стиснення" дозволяє програмам та децентралізованим додаткам (dApps) використовувати дешевий простір у [реєстрі](/docs/terminology.md#ledger) блокчейну, замість більш дорогого простору [облікових записів](/docs/terminology.md#account), для безпечного зберігання даних. +Цей метод "стиснення" дозволяє програмам та децентралізованим додаткам (dApps) використовувати дешевий простір у [реєстрі](/docs/uk/terminology.md#ledger) блокчейну, замість більш дорогого простору [облікових записів](/docs/uk/terminology.md#account), для безпечного зберігання даних. Це досягається за допомогою спеціальної структури двійкового дерева, відомого як [конкурентне мерклеве дерево](#what-is-a-concurrent-merkle-tree), яке створює геш кожного фрагмента даних (названого `листком`), об'єднує ці геші і зберігає тільки фінальний геш у мережі. @@ -44,7 +44,7 @@ description: ### Що таке Конкурентне Мерклеве дерево? -У високопродуктивних застосунках, таких як [середовище виконання Solana](/docs/core/fees.md), запити на зміну ончейн _традиційного мерклевого дерева_ можуть надходити до валідаторів досить швидко (наприклад, у межах одного слота). У таких випадках кожна зміна даних у листках повинна виконуватися послідовно. Це призводить до невдачі наступних запитів на зміну, оскільки кореневий геш і підтвердження стають недійсними після попередньої зміни в слоті. +У високопродуктивних застосунках, таких як [середовище виконання Solana](/docs/uk/core/fees.md), запити на зміну ончейн _традиційного мерклевого дерева_ можуть надходити до валідаторів досить швидко (наприклад, у межах одного слота). У таких випадках кожна зміна даних у листках повинна виконуватися послідовно. Це призводить до невдачі наступних запитів на зміну, оскільки кореневий геш і підтвердження стають недійсними після попередньої зміни в слоті. Рішенням цієї проблеми є Конкурентні Мерклеві дерева. @@ -146,7 +146,7 @@ nodes_count = 2 ^ maxDepth Вартість створення Concurrent Merkle Tree залежить від його параметрів: `maxDepth`, `maxBufferSize`, і `canopyDepth`. Ці параметри визначають необхідний простір (у байтах) для дерева. Використовуючи метод -[`getMinimumBalanceForRentExemption`](/docs/rpc/http/getminimumbalanceforrentexemption), +[`getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getminimumbalanceforrentexemption), можна дізнатися вартість (у лампортах) для виділення цього простору on-chain. --- diff --git a/docs/uk/advanced/versions.md b/docs/uk/advanced/versions.md index 7effd6b6b..b3f5c5aaf 100644 --- a/docs/uk/advanced/versions.md +++ b/docs/uk/advanced/versions.md @@ -4,11 +4,11 @@ title: "Версійні Транзакції" description: "Дослідіть основні концепції Solana: транзакції, версійні транзакції, розширення функціональності в Solana Runtime, таблиці пошуку адрес та інше." altRoutes: - - /docs/core/transactions/versions + - /docs/uk/core/transactions/versions --- Версійні Транзакції - це новий формат транзакцій, який дозволяє додаткову функціональність у Solana Runtime, включаючи -[Таблиці пошуку адрес](/docs/advanced/lookup-tables.md). +[Таблиці пошуку адрес](/docs/uk/advanced/lookup-tables.md). Хоча зміни в ончейн-програмах **НЕ** потрібні для підтримки нової функціональності версійних транзакцій (або для зворотної сумісності), розробники **ПОВИННІ** оновити клієнтський код, щоб уникнути [помилок через різні версії транзакцій](#max-supported-transaction-version). @@ -19,14 +19,14 @@ Solana Runtime підтримує дві версії транзакцій: - `legacy` - старий формат транзакцій без додаткових переваг - `0` - додає підтримку - [Таблиць пошуку адрес](/docs/advanced/lookup-tables.md) + [Таблиць пошуку адрес](/docs/uk/advanced/lookup-tables.md) ## Максимально підтримувана версія транзакцій Усі RPC-запити, які повертають транзакцію, **_повинні_** вказувати найвищу версію транзакцій, яку вони підтримують у своїй програмі, використовуючи параметр `maxSupportedTransactionVersion`, включаючи -[`getBlock`](/docs/rpc/http/getBlock.mdx) та -[`getTransaction`](/docs/rpc/http/getTransaction.mdx). +[`getBlock`](/docs/uk/rpc/http/getBlock.mdx) та +[`getTransaction`](/docs/uk/rpc/http/getTransaction.mdx). RPC-запит завершиться невдачею, якщо буде повернута версійна транзакція, яка має версію вище встановленої `maxSupportedTransactionVersion`. (наприклад, якщо повертається транзакція версії `0`, а встановлено `legacy`) @@ -152,7 +152,7 @@ console.log(`https://explorer.solana.com/tx/${txId}?cluster=devnet`); ## Додаткові ресурси - Використання - [версійних транзакцій для таблиць пошуку адрес](/docs/advanced/lookup-tables.md#how-to-create-an-address-lookup-table) + [версійних транзакцій для таблиць пошуку адрес](/docs/uk/advanced/lookup-tables.md#how-to-create-an-address-lookup-table) - Перегляд [прикладу транзакції v0](https://explorer.solana.com/tx/h9WQsqSUYhFvrbJWKFPaXximJpLf6Z568NW1j6PBn3f7GPzQXe9PYMYbmWSUFHwgnUmycDNbEX9cr6WjUWkUFKx/?cluster=devnet) на Solana Explorer diff --git a/docs/uk/clients/javascript-reference.md b/docs/uk/clients/javascript-reference.md index 220d8f00a..c8631101a 100644 --- a/docs/uk/clients/javascript-reference.md +++ b/docs/uk/clients/javascript-reference.md @@ -8,7 +8,7 @@ description: ## Довідник по Web3 API Бібліотека `@solana/web3.js` забезпечує покриття -[Solana JSON RPC API](/docs/rpc). +[Solana JSON RPC API](/docs/uk/rpc). Повну документацію до бібліотеки `@solana/web3.js` можна знайти [тут](https://solana-labs.github.io/solana-web3.js/v1.x/). @@ -19,7 +19,7 @@ description: [Документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html) -Об'єкт `Connection` використовується для взаємодії з [Solana JSON RPC](/docs/rpc). Ви можете використовувати Connection для підтвердження транзакцій, отримання інформації про облікові записи тощо. +Об'єкт `Connection` використовується для взаємодії з [Solana JSON RPC](/docs/uk/rpc). Ви можете використовувати Connection для підтвердження транзакцій, отримання інформації про облікові записи тощо. Створення підключення здійснюється шляхом вказання URL-адреси RPC-кластера та бажаного рівня зобов'язань. Після цього ви можете використовувати цей об'єкт підключення для взаємодії з будь-яким із API JSON RPC Solana. @@ -381,7 +381,7 @@ await web3.sendAndConfirmTransaction(connection, transaction, [fromPublicKey]); [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Message.html) -`Message` використовується як альтернативний спосіб створення транзакцій. Ви можете створити повідомлення за допомогою облікових записів, заголовка, інструкцій та недавнього блочного хеша, які є частиною транзакції. [Transaction](/docs/clients/javascript.md#Transaction) є `Message` плюс список необхідних підписів для виконання транзакції. +`Message` використовується як альтернативний спосіб створення транзакцій. Ви можете створити повідомлення за допомогою облікових записів, заголовка, інструкцій та недавнього блочного хеша, які є частиною транзакції. [Transaction](/docs/uk/clients/javascript.md#Transaction) є `Message` плюс список необхідних підписів для виконання транзакції. #### Приклад Використання @@ -472,7 +472,7 @@ export class Fee extends Struct { [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Enum.html) -Клас `Enum` використовується для представлення сумісного з Rust енумератора у JavaScript. Енумератор буде представлений як строка при логуванні, але може бути правильно закодований/декодований при використанні разом з [Struct](/docs/clients/javascript.md#Struct). Цей клас сумісний лише з Rust-енумераторами, закодованими за допомогою Borsh. +Клас `Enum` використовується для представлення сумісного з Rust енумератора у JavaScript. Енумератор буде представлений як строка при логуванні, але може бути правильно закодований/декодований при використанні разом з [Struct](/docs/uk/clients/javascript.md#Struct). Цей клас сумісний лише з Rust-енумераторами, закодованими за допомогою Borsh. #### Приклад Використання @@ -751,13 +751,13 @@ await web3.sendAndConfirmTransaction(connection, withdrawTransaction, [ `Authorized` — це об'єкт, який використовується під час створення авторизованого облікового запису для стейкінгу в Solana. Ви можете окремо призначити `staker` і `withdrawer`, що дозволяє іншому обліковому запису виводити кошти, ніж той, що виконує стейкінг. -Більше прикладів використання об'єкта `Authorized` ви можете знайти в розділі [`StakeProgram`](/docs/clients/javascript.md#StakeProgram). +Більше прикладів використання об'єкта `Authorized` ви можете знайти в розділі [`StakeProgram`](/docs/uk/clients/javascript.md#StakeProgram). ### Lockup [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Lockup.html) -`Lockup` використовується разом із [StakeProgram](/docs/clients/javascript.md#StakeProgram) для створення облікового запису. `Lockup` визначає, як довго стейк буде заблокований або недоступний для вилучення. Якщо `Lockup` встановлений на 0 як для епохи, так і для мітки часу Unix, блокування для облікового запису буде відключено. +`Lockup` використовується разом із [StakeProgram](/docs/uk/clients/javascript.md#StakeProgram) для створення облікового запису. `Lockup` визначає, як довго стейк буде заблокований або недоступний для вилучення. Якщо `Lockup` встановлений на 0 як для епохи, так і для мітки часу Unix, блокування для облікового запису буде відключено. #### Приклад Використання @@ -785,5 +785,5 @@ let createStakeAccountInstruction = StakeProgram.createAccount({ Наведений вище код створює `createStakeAccountInstruction`, який використовується для створення облікового запису за допомогою `StakeProgram`. Блокування встановлено на 0 як для епохи, так і для мітки часу Unix, що відключає блокування для облікового запису. -Детальніше див. у розділі [StakeProgram](/docs/clients/javascript.md#StakeProgram). +Детальніше див. у розділі [StakeProgram](/docs/uk/clients/javascript.md#StakeProgram). diff --git a/docs/uk/clients/rust.md b/docs/uk/clients/rust.md index 5a15b1f78..d058363e7 100644 --- a/docs/uk/clients/rust.md +++ b/docs/uk/clients/rust.md @@ -16,7 +16,7 @@ Rust пакети для Solana - [Створіть і розгорніть вашу першу програму Solana, використовуючи тільки ваш браузер](/content/guides/getstarted/hello-world-in-your-browser.md). Інсталяція не потрібна. -- [Налаштуйте ваше локальне середовище](/docs/intro/installation) і використовуйте локальний тестовий валідатор. +- [Налаштуйте ваше локальне середовище](/docs/uk/intro/installation) і використовуйте локальний тестовий валідатор. @@ -33,7 +33,7 @@ Rust пакети для Solana що не працюють у мережі, імпортують цей пакет. - [`solana-client`] — Для взаємодії з вузлом Solana через - [JSON RPC API](/docs/rpc). + [JSON RPC API](/docs/uk/rpc). - [`solana-cli-config`] — Завантаження та збереження конфігураційного файлу Solana CLI. diff --git a/docs/uk/core/clusters.md b/docs/uk/core/clusters.md index f2f455da3..abf086ecf 100644 --- a/docs/uk/core/clusters.md +++ b/docs/uk/core/clusters.md @@ -10,9 +10,9 @@ description: --- Блокчейн Solana має кілька різних груп валідаторів, відомих як -[Кластери](/docs/core/clusters.md). Кожен з них обслуговує різні цілі в межах +[Кластери](/docs/uk/core/clusters.md). Кожен з них обслуговує різні цілі в межах загальної екосистеми та містить виділені вузли API для виконання -[JSON-RPC](/docs/rpc/index.mdx) запитів для своїх відповідних кластерів. +[JSON-RPC](/docs/uk/rpc/index.mdx) запитів для своїх відповідних кластерів. Індивідуальні вузли в межах кластера належать та управляються третіми сторонами, з публічною точкою доступу, доступною для кожного. diff --git a/docs/uk/core/fees.md b/docs/uk/core/fees.md index b3eb1de75..69689f7d0 100644 --- a/docs/uk/core/fees.md +++ b/docs/uk/core/fees.md @@ -13,11 +13,11 @@ keywords: - газ - гвей altRoutes: - - /docs/core/rent - - /docs/intro/rent - - /docs/intro/transaction_fees - - /docs/intro/transaction-fees - - /docs/core/runtime + - /docs/uk/core/rent + - /docs/uk/intro/rent + - /docs/uk/intro/transaction_fees + - /docs/uk/intro/transaction-fees + - /docs/uk/core/runtime --- Блокчейн Solana має кілька типів плати та витрат, які виникають під час використання мережі без дозволу. Вони поділяються на кілька специфічних типів: @@ -30,7 +30,7 @@ altRoutes: Мала плата, яка сплачується за обробку логіки (інструкції) у програмі в ончейні на блокчейні Solana, називається "_транзакційною платою_". -Кожна [транзакція](/docs/core/transactions.md#transaction), яка містить одну або більше [інструкцій](/docs/core/transactions.md#instruction), надсилається через мережу, де її обробляє поточний лідер-валідатор. Після підтвердження як глобальної транзакції ця "транзакційна плата" сплачується мережі для підтримки економічної моделі блокчейна Solana. +Кожна [транзакція](/docs/uk/core/transactions.md#transaction), яка містить одну або більше [інструкцій](/docs/uk/core/transactions.md#instruction), надсилається через мережу, де її обробляє поточний лідер-валідатор. Після підтвердження як глобальної транзакції ця "транзакційна плата" сплачується мережі для підтримки економічної моделі блокчейна Solana. > Транзакційні збори відрізняються від плати за збереження даних в обліковому записі, відомої як [оренда](#rent). Транзакційні збори сплачуються за обробку інструкцій у мережі Solana, а депозит оренди утримується в обліковому записі для збереження даних в блокчейні та може бути повернутий. @@ -50,7 +50,7 @@ altRoutes: Те саме стосується Solana. Зокрема: -- Фіксована частка (спочатку 50%) кожної транзакційної плати "спалюється" (знищується), решта надходить до поточного [лідера](/docs/terminology.md#leader), який обробляє транзакцію. +- Фіксована частка (спочатку 50%) кожної транзакційної плати "спалюється" (знищується), решта надходить до поточного [лідера](/docs/uk/terminology.md#leader), який обробляє транзакцію. - Запланована глобальна інфляційна ставка забезпечує джерело [нагород](https://docs.anza.xyz/implemented-proposals/staking-rewards), які розподіляються серед [валідаторів Solana](https://docs.anza.xyz/operations). ### Збір плати @@ -71,11 +71,11 @@ altRoutes: Як згадано вище, фіксована частка кожної транзакційної плати "спалюється" (знищується). Це зроблено для зміцнення економічної цінності SOL і підтримки безпеки мережі. На відміну від системи, де всі транзакційні збори повністю спалюються, лідери все ще мають стимул включати якомога більше транзакцій у свої слоти (можливість створити блок). -Спалені збори також можуть допомогти запобігти зловмисним валідаторам у цензуруванні транзакцій через врахування в [виборі форку](/docs/terminology.md#fork). +Спалені збори також можуть допомогти запобігти зловмисним валідаторам у цензуруванні транзакцій через врахування в [виборі форку](/docs/uk/terminology.md#fork). #### Приклад атаки: -У випадку [форку Proof of History (PoH)](/docs/terminology.md#proof-of-history-poh) з лідером, що займається цензурою або зловживанням: +У випадку [форку Proof of History (PoH)](/docs/uk/terminology.md#proof-of-history-poh) з лідером, що займається цензурою або зловживанням: - через втрати зборів, що виникають через цензуру, очікується, що загальні збори, які будуть спалені, будуть **_меншими_**, ніж у порівнянному чесному форку; - якщо лідер, який займається цензурою, хоче компенсувати ці втрачені протокольні збори, він повинен буде самостійно замінити спалені збори на своєму форку; @@ -86,7 +86,7 @@ altRoutes: Повна плата за конкретну транзакцію розраховується на основі двох основних частин: - Статично встановлена базова плата за підпис, і -- Обчислювальні ресурси, використані під час транзакції, виміряні у "[обчислювальних одиницях](/docs/terminology.md#compute-units)". +- Обчислювальні ресурси, використані під час транзакції, виміряні у "[обчислювальних одиницях](/docs/uk/terminology.md#compute-units)". Оскільки кожна транзакція може вимагати різної кількості обчислювальних ресурсів, кожній транзакції виділяється максимальна кількість _обчислювальних одиниць_ у рамках "обчислювального бюджету". @@ -132,7 +132,7 @@ let instruction = ComputeBudgetInstruction::set_loaded_accounts_data_size_limit( - міжпрограмні виклики (CPI) - криптографічні операції -> Для [міжпрограмних викликів](/docs/core/cpi.md) викликана інструкція успадковує обчислювальний бюджет і ліміти свого батька. Якщо викликана інструкція споживає залишок бюджету транзакції або перевищує ліміт, весь ланцюжок викликів і обробка транзакції верхнього рівня зупиняються. +> Для [міжпрограмних викликів](/docs/uk/core/cpi.md) викликана інструкція успадковує обчислювальний бюджет і ліміти свого батька. Якщо викликана інструкція споживає залишок бюджету транзакції або перевищує ліміт, весь ланцюжок викликів і обробка транзакції верхнього рівня зупиняються. Детальнішу інформацію про всі операції, які споживають обчислювальні одиниці, ви можете знайти в [ComputeBudget](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L19-L123) в часі виконання Solana. @@ -220,7 +220,7 @@ const instruction = ComputeBudgetProgram.setComputeUnitPrice({ #### Отримуйте останні пріоритизаційні збори -Перед надсиланням транзакції до кластеру ви можете скористатися методом RPC [`getRecentPrioritizationFees`](/docs/rpc/http/getRecentPrioritizationFees.mdx), щоб отримати список останніх сплачених пріоритизаційних зборів у нещодавно оброблених блоках вузла. +Перед надсиланням транзакції до кластеру ви можете скористатися методом RPC [`getRecentPrioritizationFees`](/docs/uk/rpc/http/getRecentPrioritizationFees.mdx), щоб отримати список останніх сплачених пріоритизаційних зборів у нещодавно оброблених блоках вузла. Ви можете використовувати ці дані для оцінки відповідної плати за пріоритизацію для вашої транзакції, щоб: @@ -229,9 +229,9 @@ const instruction = ComputeBudgetProgram.setComputeUnitPrice({ ## Оренда -Плата, що депонується на кожен [Обліковий запис Solana](/docs/core/accounts.md) для збереження його пов'язаних даних в ончейні, називається "_орендою_". Ця плата утримується у звичайному балансі лампортів на кожному обліковому записі та може бути повернута під час закриття облікового запису. +Плата, що депонується на кожен [Обліковий запис Solana](/docs/uk/core/accounts.md) для збереження його пов'язаних даних в ончейні, називається "_орендою_". Ця плата утримується у звичайному балансі лампортів на кожному обліковому записі та може бути повернута під час закриття облікового запису. -> Оренда відрізняється від [транзакційних зборів](#transaction-fees). Оренда "сплачується" (утримується в Обліковому записі) для збереження даних на блокчейні Solana та може бути повернута. У той час як транзакційні збори сплачуються за обробку [інструкцій](/docs/core/transactions.md#instructions) у мережі. +> Оренда відрізняється від [транзакційних зборів](#transaction-fees). Оренда "сплачується" (утримується в Обліковому записі) для збереження даних на блокчейні Solana та може бути повернута. У той час як транзакційні збори сплачуються за обробку [інструкцій](/docs/uk/core/transactions.md#instructions) у мережі. Усі облікові записи повинні підтримувати достатньо високий баланс лампортів (відносно їх виділеного простору), щоб стати [звільненими від оренди](#rent-exempt) і залишатися на блокчейні Solana. Будь-яка транзакція, що намагається зменшити баланс облікового запису нижче його відповідного мінімального балансу для звільнення від оренди, завершиться невдачею (якщо тільки баланс не зменшується до нуля). @@ -257,7 +257,7 @@ const instruction = ComputeBudgetProgram.setComputeUnitPrice({ Кожного разу, коли баланс облікового запису зменшується, час виконання перевіряє, чи залишиться баланс цього облікового запису вище мінімального балансу для звільнення від оренди. Якщо тільки баланс не знижується до рівно `0` (закриття облікового запису), транзакції, які спричиняють падіння балансу облікового запису нижче порогу звільнення від оренди, завершаться невдачею. -Специфічний мінімальний баланс для облікового запису, щоб стати звільненим від оренди, залежить від поточної [ставки оренди](#rent-rate) блокчейну та бажаного обсягу простору, який обліковий запис хоче виділити (розмір облікового запису). Тому рекомендується використовувати RPC-метод [`getMinimumBalanceForRentExemption`](/docs/rpc/http/getMinimumBalanceForRentExemption.mdx) для розрахунку конкретного балансу для заданого розміру облікового запису. +Специфічний мінімальний баланс для облікового запису, щоб стати звільненим від оренди, залежить від поточної [ставки оренди](#rent-rate) блокчейну та бажаного обсягу простору, який обліковий запис хоче виділити (розмір облікового запису). Тому рекомендується використовувати RPC-метод [`getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx) для розрахунку конкретного балансу для заданого розміру облікового запису. Суму необхідного орендного депозиту також можна оцінити за допомогою підкоманди CLI [`solana rent`](https://docs.anza.xyz/cli/usage#solana-rent). diff --git a/docs/uk/core/pda.md b/docs/uk/core/pda.md index 3e43a9f94..3221b2f8f 100644 --- a/docs/uk/core/pda.md +++ b/docs/uk/core/pda.md @@ -35,7 +35,7 @@ description: > У цьому розділі буде розглянуто деталі виведення PDA. Деталі того, як > програми використовують PDA для підписання, будуть розглянуті в розділі -> [Взаємодія між програмами (CPI)](/docs/core/cpi.md), оскільки це потребує +> [Взаємодія між програмами (CPI)](/docs/uk/core/cpi.md), оскільки це потребує > контексту для обох концепцій. ## Основні моменти @@ -337,7 +337,7 @@ pub pda_account: Account<'info, DataAccount>, ``` Обмеження `init` вказує Anchor викликати Системну Програму для створення нового облікового запису з використанням PDA як адреси. Це виконується за допомогою -[Взаємодії між програмами (CPI)](/docs/core/cpi.md). +[Взаємодії між програмами (CPI)](/docs/uk/core/cpi.md). ```rust /init/ #[account( diff --git a/docs/uk/core/programs.md b/docs/uk/core/programs.md index 596c9b930..fc4d35564 100644 --- a/docs/uk/core/programs.md +++ b/docs/uk/core/programs.md @@ -9,9 +9,9 @@ description: --- У екосистемі Solana "смарт-контракти" називаються програмами. Кожна -[програма](/docs/core/accounts.md#program-account) є обліковим записом у блокчейні, +[програма](/docs/uk/core/accounts.md#program-account) є обліковим записом у блокчейні, який зберігає виконувану логіку, організовану у вигляді конкретних функцій, які -називаються [інструкціями](/docs/core/transactions.md#instruction). +називаються [інструкціями](/docs/uk/core/transactions.md#instruction). ## Основні моменти @@ -32,7 +32,7 @@ description: Програми Solana зазвичай пишуться мовою програмування [Rust](https://doc.rust-lang.org/book/) з використанням двох підходів: -- [Anchor](/docs/programs/anchor): Фреймворк, створений для розробки програм Solana. +- [Anchor](/docs/uk/programs/anchor): Фреймворк, створений для розробки програм Solana. Він забезпечує швидший і простіший спосіб написання програм, використовуючи макроси Rust для значного зменшення обсягу шаблонного коду. Для початківців рекомендується починати з фреймворку Anchor. diff --git a/docs/uk/core/tokens.md b/docs/uk/core/tokens.md index 370e68e56..62700b186 100644 --- a/docs/uk/core/tokens.md +++ b/docs/uk/core/tokens.md @@ -64,7 +64,7 @@ description: [Програма Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) містить всю логіку інструкцій для взаємодії з токенами в мережі (як взаємозамінними, так і невзаємозамінними). Усі токени на Solana фактично є -[даними облікових записів](/docs/core/accounts.md#data-account), якими володіє Програма Токенів. +[даними облікових записів](/docs/uk/core/accounts.md#data-account), якими володіє Програма Токенів. Повний список інструкцій Програми Токенів можна знайти [тут](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/instruction.rs). @@ -174,7 +174,7 @@ pub struct Account { > Зверніть увагу, що дані кожного Токен-облікового запису містять поле `owner`, яке > використовується для визначення того, хто має авторитет над цим Токен-обліковим записом. > Це окремо від власника програми, зазначеного у -> [AccountInfo](/docs/core/accounts.md#accountinfo), яким є Програма Токенів для всіх +> [AccountInfo](/docs/uk/core/accounts.md#accountinfo), яким є Програма Токенів для всіх > Токен-облікових записів. ### Асоційований токен-обліковий запис @@ -193,7 +193,7 @@ pub struct Account { ![Асоційований токен-обліковий запис](/assets/docs/core/tokens/associated-token-account.svg) Це вводить ключове поняття в розробці Solana: -[Програмно Виведена Адреса (PDA)](/docs/core/pda.md). Концептуально PDA надає +[Програмно Виведена Адреса (PDA)](/docs/uk/core/pda.md). Концептуально PDA надає детермінований спосіб генерації адреси з використанням заздалегідь визначених вхідних даних. Це дозволяє нам легко знайти адресу облікового запису в майбутньому. @@ -374,7 +374,7 @@ Signature: 44vqKdfzspT592REDPY4goaRJH3uJ3Ce13G4BCuUHg35dVUbHuGTHvqn4ZjYF9BGe9Qrj [Solana Playground](https://beta.solpg.io/660ce868cffcf4b13384d011). Програма Асоційованих Токенів використовує -[Перехресні Виклики Програм (CPI)](/docs/core/cpi.md) для виконання наступного: +[Перехресні Виклики Програм (CPI)](/docs/uk/core/cpi.md) для виконання наступного: - [Виклик Системної Програми](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src/tools/account.rs#L19) для створення нового облікового запису, використовуючи надану PDA як адресу diff --git a/docs/uk/core/transactions.md b/docs/uk/core/transactions.md index 3dab1871b..610c168fd 100644 --- a/docs/uk/core/transactions.md +++ b/docs/uk/core/transactions.md @@ -7,11 +7,11 @@ description: інструкцій із практичними прикладами. --- -У Solana ми надсилаємо [транзакції](/docs/core/transactions#transaction), щоб +У Solana ми надсилаємо [транзакції](/docs/uk/core/transactions#transaction), щоб взаємодіяти з мережею. Транзакції включають одну або більше -[інструкцій](/docs/core/transactions#instruction), кожна з яких представляє +[інструкцій](/docs/uk/core/transactions#instruction), кожна з яких представляє конкретну операцію, що має бути оброблена. Логіка виконання інструкцій зберігається -в [програмах](/docs/core/programs), розгорнутих у мережі Solana, і кожна програма +в [програмах](/docs/uk/core/programs), розгорнутих у мережі Solana, і кожна програма зберігає свій набір інструкцій. Нижче наведено основні деталі щодо виконання транзакцій: @@ -53,8 +53,8 @@ description: переказу SOL від відправника до отримувача. Індивідуальні "гаманці" у Solana є обліковими записами, якими володіє -[Системна програма](/docs/core/accounts#system-program). Як частина -[моделі облікових записів Solana](/docs/core/accounts), лише програма, якій +[Системна програма](/docs/uk/core/accounts#system-program). Як частина +[моделі облікових записів Solana](/docs/uk/core/accounts), лише програма, якій належить обліковий запис, може змінювати дані цього облікового запису. Тому для переказу SOL із облікового запису "гаманця" необхідно надіслати @@ -110,10 +110,10 @@ const transaction = new Transaction().add(transferInstruction); Структура повідомлення транзакції складається з: -- [Заголовка повідомлення](/docs/core/transactions#message-header): Вказує кількість підписантів та облікових записів тільки для читання. -- [Масиву адрес облікових записів](/docs/core/transactions#array-of-account-addresses): Масив адрес облікових записів, необхідних для інструкцій у транзакції. -- [Недавнього блоку хешу](/docs/core/transactions#recent-blockhash): Використовується як мітка часу для транзакції. -- [Масиву інструкцій](/docs/core/transactions#array-of-instructions): Масив інструкцій, які слід виконати. +- [Заголовка повідомлення](/docs/uk/core/transactions#message-header): Вказує кількість підписантів та облікових записів тільки для читання. +- [Масиву адрес облікових записів](/docs/uk/core/transactions#array-of-account-addresses): Масив адрес облікових записів, необхідних для інструкцій у транзакції. +- [Недавнього блоку хешу](/docs/uk/core/transactions#recent-blockhash): Використовується як мітка часу для транзакції. +- [Масиву інструкцій](/docs/uk/core/transactions#array-of-instructions): Масив інструкцій, які слід виконати. ![Повідомлення транзакції](/assets/docs/core/transactions/legacy_message.png) @@ -152,8 +152,8 @@ const transaction = new Transaction().add(transferInstruction); ![Формат компактного масиву](/assets/docs/core/transactions/compact_array_format.png) Цей метод кодування використовується для вказівки довжин як -[масиву адрес облікових записів](/docs/core/transactions#array-of-account-addresses), так і -[масиву інструкцій](/docs/core/transactions#array-of-instructions) у повідомленні транзакції. +[масиву адрес облікових записів](/docs/uk/core/transactions#array-of-account-addresses), так і +[масиву інструкцій](/docs/uk/core/transactions#array-of-instructions) у повідомленні транзакції. ### Масив адрес облікових записів @@ -162,7 +162,7 @@ const transaction = new Transaction().add(transferInstruction); необхідні для інструкцій у транзакції. Цей масив починається з кодування -[compact-u16](/docs/core/transactions#compact-array-format) довжини масиву, після чого йдуть адреси, впорядковані за привілеями облікових записів. Метадані в заголовку повідомлення використовуються для визначення кількості облікових записів у кожному розділі. +[compact-u16](/docs/uk/core/transactions#compact-array-format) довжини масиву, після чого йдуть адреси, впорядковані за привілеями облікових записів. Метадані в заголовку повідомлення використовуються для визначення кількості облікових записів у кожному розділі. - Облікові записи, що є змінюваними та підписантами. - Облікові записи тільки для читання, що є підписантами. @@ -180,7 +180,7 @@ const transaction = new Transaction().add(transferInstruction); Максимальний вік блок-хеша для транзакції становить 150 блоків (~1 хвилина, якщо час блоку складає 400 мс). Якщо блок-хеш транзакції старіший за 150 блоків від останнього блок-хеша, вона вважається протермінованою. Це означає, що транзакції, які не були оброблені вчасно, ніколи не будуть виконані. Ви можете скористатися RPC-методом -[`getLatestBlockhash`](/docs/rpc/http/getlatestblockhash), +[`getLatestBlockhash`](/docs/uk/rpc/http/getlatestblockhash), щоб отримати поточний блок-хеш і останню висоту блоку, на якій блок-хеш залишатиметься дійсним. Ось приклад у [Solana Playground](https://beta.solpg.io/661a06e1cffcf4b13384d046). ### Масив інструкцій @@ -191,7 +191,7 @@ const transaction = new Transaction().add(transferInstruction); [CompiledInstruction](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L633). Подібно до масиву адрес облікових записів, цей компактний масив починається з кодування -[compact-u16](/docs/core/transactions#compact-array-format) кількості інструкцій, після чого йде масив інструкцій. Кожна інструкція в масиві вказує наступну інформацію: +[compact-u16](/docs/uk/core/transactions#compact-array-format) кількості інструкцій, після чого йде масив інструкцій. Кожна інструкція в масиві вказує наступну інформацію: 1. **Program ID**: Ідентифікатор програми в мережі, яка оброблятиме інструкцію. Це представлено у вигляді індексу типу u8, що вказує на адресу програми у масиві адрес облікових записів. 2. **Компактний масив індексів адрес облікових записів**: Масив індексів типу u8, що вказує на масив адрес облікових записів для кожного облікового запису, потрібного для інструкції. @@ -202,7 +202,7 @@ const transaction = new Transaction().add(transferInstruction); ### Приклад структури транзакції Нижче наведено приклад структури транзакції, яка включає одну інструкцію для -[передачі SOL](/docs/core/transactions#basic-example). Тут показано деталі повідомлення, включаючи заголовок, ключі облікових записів, блок-хеш та інструкції, разом із підписом для транзакції. +[передачі SOL](/docs/uk/core/transactions#basic-example). Тут показано деталі повідомлення, включаючи заголовок, ключі облікових записів, блок-хеш та інструкції, разом із підписом для транзакції. - `header`: Містить дані, які використовуються для вказання привілеїв читання/запису та підписання у масиві `accountKeys`. - `accountKeys`: Масив, що включає адреси облікових записів для всіх інструкцій у транзакції. @@ -246,14 +246,14 @@ const transaction = new Transaction().add(transferInstruction); [Інструкція](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L329) — це запит на виконання конкретної дії в мережі. Це найменша неподільна одиниця логіки виконання у -[програмі](/docs/core/accounts#program-account). +[програмі](/docs/uk/core/accounts#program-account). При створенні інструкції для додавання до транзакції кожна інструкція повинна включати наступну інформацію: - **Адреса програми**: Вказує програму, яку буде викликано. - **Облікові записи**: Перелік кожного облікового запису, з якого інструкція читає або до якого пише, включаючи інші програми, за допомогою структури `AccountMeta`. - **Дані інструкції**: Масив байтів, що вказує, який - [обробник інструкцій](/docs/terminology#instruction-handler) викликати у програмі, а також будь-які додаткові дані, необхідні обробнику інструкцій (аргументи функції). + [обробник інструкцій](/docs/uk/terminology#instruction-handler) викликати у програмі, а також будь-які додаткові дані, необхідні обробнику інструкцій (аргументи функції). ![Інструкція транзакції](/assets/docs/core/transactions/instruction.svg) @@ -277,7 +277,7 @@ const transaction = new Transaction().add(transferInstruction); ### Приклад структури інструкції Нижче наведено приклад структури інструкції для -[передачі SOL](/docs/core/transactions#basic-examples), яка деталізує ключі облікових записів, ідентифікатор програми та дані, необхідні для інструкції. +[передачі SOL](/docs/uk/core/transactions#basic-examples), яка деталізує ключі облікових записів, ідентифікатор програми та дані, необхідні для інструкції. - `keys`: Містить `AccountMeta` для кожного облікового запису, необхідного для інструкції. - `programId`: Адреса програми, яка містить логіку виконання для викликаної інструкції. @@ -336,5 +336,5 @@ const transferInstruction = new TransactionInstruction({ // Add the transfer instruction to a new transaction const transaction = new Transaction().add(transferInstruction); ``` -Під капотом [простий приклад](/docs/core/transactions#simple-sol-transfer) з використанням методу `SystemProgram.transfer` функціонально еквівалентний більш детальному прикладу вище. Метод `SystemProgram.transfer` просто приховує деталі створення буфера даних інструкції та `AccountMeta` для кожного облікового запису, необхідного для інструкції. +Під капотом [простий приклад](/docs/uk/core/transactions#simple-sol-transfer) з використанням методу `SystemProgram.transfer` функціонально еквівалентний більш детальному прикладу вище. Метод `SystemProgram.transfer` просто приховує деталі створення буфера даних інструкції та `AccountMeta` для кожного облікового запису, необхідного для інструкції. diff --git a/docs/uk/economics/index.md b/docs/uk/economics/index.md index e7ce116d4..ecfa6d94f 100644 --- a/docs/uk/economics/index.md +++ b/docs/uk/economics/index.md @@ -2,7 +2,7 @@ sidebarLabel: Економіка title: Огляд Економіки Solana altRoutes: - - /docs/intro/economics + - /docs/uk/intro/economics sidebarSortOrder: 5 --- @@ -16,6 +16,6 @@ sidebarSortOrder: 5 Транзакційні комісії є переказами між учасниками, що додаються до взаємодії з мережею як стимул та компенсація за включення і виконання запропонованої транзакції. Також обговорюється механізм довгострокової економічної стабільності та захисту від розгалужень через часткове спалювання кожної транзакційної комісії. -Спочатку подано огляд дизайну інфляції. Цей розділ починається з визначення та уточнення [Термінології](/docs/economics/inflation/terminology.md), що часто використовується у подальшому обговоренні інфляції та пов'язаних компонентів. Далі ми окреслюємо запропонований [Графік Інфляції](/docs/economics/inflation/inflation_schedule.md) Solana, тобто конкретні параметри, які унікально визначають інфляційний випуск, керований протоколом, з плином часу. Наступним є короткий розділ про [Скориговану Доходність Стейкінгу](/docs/economics/inflation/_adjusted_staking_yield.md) і те, як розбавлення токенів може вплинути на поведінку стейкінгу. +Спочатку подано огляд дизайну інфляції. Цей розділ починається з визначення та уточнення [Термінології](/docs/uk/economics/inflation/terminology.md), що часто використовується у подальшому обговоренні інфляції та пов'язаних компонентів. Далі ми окреслюємо запропонований [Графік Інфляції](/docs/uk/economics/inflation/inflation_schedule.md) Solana, тобто конкретні параметри, які унікально визначають інфляційний випуск, керований протоколом, з плином часу. Наступним є короткий розділ про [Скориговану Доходність Стейкінгу](/docs/uk/economics/inflation/_adjusted_staking_yield.md) і те, як розбавлення токенів може вплинути на поведінку стейкінгу. -Огляд [Транзакційних Комісій](/docs/core/fees.md#transaction-fees) у Solana супроводжується обговоренням [Економіки Оренди для Зберігання](/docs/core/fees.md#rent), у якому описується реалізація орендної плати за зберігання для обліку зовнішніх витрат на підтримання активного стану реєстру. +Огляд [Транзакційних Комісій](/docs/uk/core/fees.md#transaction-fees) у Solana супроводжується обговоренням [Економіки Оренди для Зберігання](/docs/uk/core/fees.md#rent), у якому описується реалізація орендної плати за зберігання для обліку зовнішніх витрат на підтримання активного стану реєстру. diff --git a/docs/uk/economics/inflation/inflation-schedule.md b/docs/uk/economics/inflation/inflation-schedule.md index 29ecefd99..f9d69885d 100644 --- a/docs/uk/economics/inflation/inflation-schedule.md +++ b/docs/uk/economics/inflation/inflation-schedule.md @@ -2,8 +2,8 @@ sidebarLabel: Запропонований Графік Інфляції title: Запропонований Графік Інфляції altRoutes: - - /docs/economics/inflation/inflation_schedule - - /docs/intro/economics + - /docs/uk/economics/inflation/inflation_schedule + - /docs/uk/intro/economics --- Як було зазначено вище, _Графік Інфляції_ мережі унікально описується трьома параметрами: _Початкова Ставка Інфляції_, _Ставка Дезінфляції_ та _Довгострокова Ставка Інфляції_. При розгляді цих значень слід враховувати багато факторів: diff --git a/docs/uk/economics/staking/index.md b/docs/uk/economics/staking/index.md index 708dd1826..09160d228 100644 --- a/docs/uk/economics/staking/index.md +++ b/docs/uk/economics/staking/index.md @@ -85,4 +85,4 @@ Staking Facilities. Він надає графічну інформацію пр ## Деталі Облікового Запису Стейкінгу Для отримання додаткової інформації про операції та дозволи, пов’язані з обліковим записом стейкінгу, -дивіться [Облікові Записи Стейкінгу](/docs/economics/staking/stake-accounts.md) +дивіться [Облікові Записи Стейкінгу](/docs/uk/economics/staking/stake-accounts.md) diff --git a/docs/uk/intro/dev.md b/docs/uk/intro/dev.md index 37a5f1b85..ac56bb2d1 100644 --- a/docs/uk/intro/dev.md +++ b/docs/uk/intro/dev.md @@ -1,74 +1,46 @@ --- -sidebarLabel: Intro to Development -title: "Getting Started with Solana Development" -description: "Learn how to get started building on Solana" +sidebarLabel: Вступ до Розробки +title: "Початок Розробки на Solana" +description: "Дізнайтеся, як почати розробляти на Solana" sidebarSortOrder: 2 keywords: - - solana basics - - tutorial - - intro to solana development - - blockchain developer - - web3 developer + - основи solana + - посібник + - вступ до розробки solana + - розробник блокчейну + - розробник web3 --- -Welcome to the Solana developer docs! +Ласкаво просимо до документації для розробників Solana! -This page has everything you need to know to get started with Solana -development, including basic requirements, how Solana development works, and the -tools you'll need to get started. +На цій сторінці зібрано все, що вам потрібно знати для початку розробки на Solana, включаючи основні вимоги, принципи роботи та інструменти, необхідні для старту. -## High Level Developer Overview +## Огляд Розробки на Високому Рівні -Development on Solana can be broken down into two main parts: +Розробку на Solana можна розділити на дві основні частини: -1. **Onchain Program Development**: This is where you create and deploy custom - programs directly to the blockchain. Once deployed, anyone who knows how to - communicate with them can use them. You can write these programs in Rust, C, - or C++. Rust has the most support for onchain program development today. -2. **Client Development**: This is where you write software (called - decentralized applications, or dApps) that communicates with onchain - programs. Your apps can submit transactions to perform actions onchain. - Client development can be written in any programming language. +1. **Розробка Програм на Блокчейні**: Тут ви створюєте та розгортаєте користувацькі програми безпосередньо у блокчейні. Після розгортання будь-хто, хто знає, як із ними працювати, може їх використовувати. Ці програми можна писати на Rust, C або C++. Rust наразі має найбільшу підтримку для розробки програм на блокчейні. +2. **Клієнтська Розробка**: Це створення програмного забезпечення (децентралізованих додатків або dApps), яке взаємодіє з програмами на блокчейні. Ваші додатки можуть надсилати транзакції для виконання дій у блокчейні. Клієнтську розробку можна виконувати на будь-якій мові програмування. -The "glue" between the client side and the onchain side is the -[Solana JSON RPC API](https://solana.com/docs/rpc). The client-side sends RPC -requests to the Solana network to interact with onchain programs. This is very -similar to normal development between a frontend and backend. The major -difference with working on Solana is that the backend is a global permissionless -blockchain. This means that anyone can interact with your onchain program -without the need of issuing API keys or any other form of permission. +"Зв'язок" між клієнтською та блокчейн-частиною забезпечується [Solana JSON RPC API](https://solana.com/docs/rpc). Клієнтська частина надсилає запити RPC до мережі Solana для взаємодії з програмами на блокчейні. Це дуже схоже на звичайний процес розробки між frontend і backend. Головна відмінність у роботі з Solana — це те, що backend є глобальним блокчейном без дозволів. Це означає, що будь-хто може взаємодіяти з вашою програмою на блокчейні без необхідності видачі API-ключів або будь-яких інших форм дозволів. -![How clients work with the Solana blockchain](/assets/docs/intro/developer_flow.png) +![Як клієнти працюють із блокчейном Solana](/assets/docs/intro/developer_flow.png) -Solana development is a bit different from other blockchains because of its -highly composable onchain programs. This means you can build on top of any -program already deployed, and often you can do so without needing to do any -custom onchain program development. For example, if you wanted to work with -tokens, you could use the [Token Program](/docs/core/tokens.md) that is already -deployed on the network. All development on your application would be -client-side in your language of choice. +Розробка на Solana відрізняється від інших блокчейнів завдяки своїм високо-композитним програмам на блокчейні. Це означає, що ви можете будувати на базі вже існуючих програм, часто без необхідності створення власних. Наприклад, якщо ви хочете працювати з токенами, ви можете використовувати [Token Program](/docs/uk/core/tokens.md), який вже розгорнутий у мережі. Уся розробка вашого додатка буде клієнтською, на обраній вами мові програмування. -Developers looking to build on Solana will find that the development stack is -very similar to any other development stack. The main difference is that you'll -be working with a blockchain and have to think about how users potentially -interact with your application onchain instead of just on the frontend. -Developing on Solana still has CI/CD pipelines, testing, debugging tools, a -frontend and backend, and anything you'd find in a normal development flow. +Розробники, які хочуть будувати на Solana, знайдуть, що стек розробки дуже схожий на інші. Основна відмінність у тому, що ви працюєте з блокчейном і повинні враховувати, як користувачі взаємодіють із вашим додатком на блокчейні, а не тільки у frontend. Розробка на Solana все ще включає CI/CD, тестування, інструменти для налагодження, frontend і backend, як і будь-який звичайний процес розробки. -## What You'll Need to Get Started +## Що Вам Потрібно для Початку -To get started with Solana development, you'll need different tools based on -whether you are developing for client-side, onchain programs, or both. +Для початку розробки на Solana вам знадобляться різні інструменти залежно від того, чи ви розробляєте клієнтські додатки, програми на блокчейні або обидва. -### Client-side Development +### Клієнтська Розробка -If you're developing onchain apps, you should know Rust. +Якщо ви розробляєте програми на блокчейні, вам потрібно знати Rust. -If you're developing on the client-side, you can work with any programming -language you're comfortable with. Solana has community-contributed SDKs to help -developers interact with the Solana network in most popular languages : +Якщо ж ви розробляєте клієнтські додатки, ви можете працювати на будь-якій мові програмування, з якою вам зручно. Solana має SDK, створені спільнотою, щоб допомогти розробникам взаємодіяти з мережею Solana на більшості популярних мов: -| Language | SDK | +| Мова | SDK | | ---------- | -------------------------------------------------------------------------------------------------------- | | RUST | [solana_sdk](https://docs.rs/solana-sdk/latest/solana_sdk/) | | Typescript | [@solana/web3.js](https://github.com/solana-labs/solana-web3.js) | @@ -81,115 +53,71 @@ developers interact with the Solana network in most popular languages : | C# | [solnet](https://github.com/bmresearch/Solnet) | | GdScript | [godot](https://github.com/Virus-Axel/godot-solana-sdk/) | -You'll also need a connection with an RPC to interact with the network. You can -either work with a [RPC infrastructure provider](https://solana.com/rpc) or -[run your own RPC node](https://docs.anza.xyz/operations/setup-an-rpc-node). +Вам також знадобиться підключення до RPC для взаємодії з мережею. Ви можете скористатися [провайдером RPC](https://solana.com/rpc) або [запустити власний RPC-вузол](https://docs.anza.xyz/operations/setup-an-rpc-node). -To quickly get started with a front-end for your application, you can generate a -customizable Solana scaffold by typing the following into your CLI: +Щоб швидко розпочати роботу з фронтендом для вашого додатка, ви можете згенерувати налаштовуваний каркас Solana, ввівши наступну команду у ваш CLI: ```bash npx create-solana-dapp ``` -This will create a new project with all the necessary files and basic -configuration to get started building on Solana. The scaffold will include both -an example frontend and an onchain program template (if you selected one). You -can read the -[`create-solana-dapp` docs](https://github.com/solana-developers/create-solana-dapp?tab=readme-ov-file#create-solana-dapp) -to learn more. +Ця команда створить новий проєкт із усіма необхідними файлами та базовою конфігурацією для початку розробки на Solana. Каркас включатиме як приклад фронтенда, так і шаблон програми на блокчейні (якщо ви його обрали). Ви можете ознайомитися з [документацією `create-solana-dapp`](https://github.com/solana-developers/create-solana-dapp?tab=readme-ov-file#create-solana-dapp), щоб дізнатися більше. -### Onchain Program Development +### Розробка Програм на Блокчейні -Onchain program development consists of either writing programs in Rust, C, or -C++. First you'll need to make sure you have Rust installed on your machine. You -can do this with the following command: +Розробка програм на блокчейні включає написання програм на Rust, C або C++. Спочатку переконайтеся, що у вас встановлений Rust. Ви можете зробити це за допомогою наступної команди: ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -You'll then need to have the [Solana CLI installed](/docs/intro/installation.md) -to compile and deploy your programs. You can install the Solana CLI by running -the following command: +Вам також потрібно встановити [Solana CLI](/docs/uk/intro/installation.md), щоб компілювати та розгортати ваші програми. Ви можете встановити Solana CLI, виконавши наступну команду: + ```bash sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)" ``` -Using the Solana CLI, it is recommended to run a local validator for testing -your program. To run a local validator after installing the Solana CLI, run the -following command: +Використовуючи Solana CLI, рекомендується запускати локальний валідатор для тестування вашої програми. Щоб запустити локальний валідатор після встановлення Solana CLI, виконайте наступну команду: + ```bash solana-test-validator ``` -This will start a local validator on your machine that you can use to test your -programs. You can -[read more about local development in this guide](/docs/intro/installation.md). - -When building onchain programs, you have a choice to either build with native -Rust (ie, without a framework) or use the Anchor framework. Anchor is a -framework that makes it easier to build on Solana by providing a higher-level -API for developers. Think of Anchor like building with React for your websites -instead of raw Javascript and HTML. While Javascript and HTML give you more -control over your website, React accelerates your development and makes -developing easy. You can read more about [Anchor](https://www.anchor-lang.com/) -on their website. - -You'll need a way to test your program. There are a few different ways to test -your program based on your language preference: - -- [solana-program-test](https://docs.rs/solana-program-test/latest/solana_program_test/) - - Testing framework built in Rust -- [solana-bankrun](https://kevinheavey.github.io/solana-bankrun/) - Testing - framework built for writing Typescript tests -- [bankrun](https://kevinheavey.github.io/solders/tutorials/bankrun.html) - - Testing framework built for writing Python tests - -If you do not want to develop your programs locally, there's also the -[online IDE Solana Playground](https://beta.solpg.io). Solana Playground allows -you to write, test, and deploy programs on Solana. You can get started with -Solana Playground by [following our quick start guide](/docs/intro/quick-start). - -### Developer Environments - -Choosing the right environment based on your work is very important. On Solana, -there are a few different network environments (called clusters) to facilitate -mature testing and CI/CD practices: - -- **Mainnet Beta**: The production network where all the action happens. - Transactions cost real money here. -- **Devnet**: The quality assurance network where you deploy your programs to - test before deploying to production. Think "staging environment". -- **Local**: The local network that you run on your machine using - `solana-test-validator` to test your programs. This should be your first - choice when developing programs. - -## Build by Example - -While you get started building on Solana, there's a few more resources available -to help accelerate your journey: - -- [Solana Cookbook](https://solana.com/developers/cookbook): A collection of - references and code snippets to help you build on Solana. -- [Solana Program Examples](https://github.com/solana-developers/program-examples): - A repository of example programs providing building blocks for different - actions on your programs. -- [Guides](https://solana.com/developers/guides): Tutorials and guides to walk - you through building on Solana. - -## Getting Support - -The best support you can find is on -[Solana StackExchange](https://solana.stackexchange.com/). Search for your -question there first - there's a good chance there will already be a question -asked by someone else, with an answer. If it's not there, add a new question! -Remember to include as much detail as you can in your question, and please use -text (not screenshots) to show error messages, so other people with the same -problem can find your question! - -## Next steps - -[You're now ready to get started building on Solana!](/docs/intro/quick-start) +Це запустить локальний валідатор на вашій машині, який ви можете використовувати для тестування ваших програм. Ви можете [докладніше прочитати про локальну розробку в цьому посібнику](/docs/uk/intro/installation.md). + +Під час розробки програм на блокчейні ви можете вибрати між написанням програм на чистому Rust (без фреймворку) або використанням фреймворку Anchor. Anchor спрощує розробку на Solana, надаючи високорівневий API для розробників. Подумайте про Anchor як про використання React для створення вебсайтів замість чистого Javascript і HTML. Хоча Javascript і HTML дають вам більше контролю, React прискорює розробку та робить її простішою. Докладніше про [Anchor](https://www.anchor-lang.com/) можна дізнатися на їхньому сайті. + +Вам знадобиться спосіб тестування вашої програми. Ось кілька способів тестування залежно від ваших уподобань щодо мови програмування: + +- [solana-program-test](https://docs.rs/solana-program-test/latest/solana_program_test/) — фреймворк для тестування, написаний на Rust. +- [solana-bankrun](https://kevinheavey.github.io/solana-bankrun/) — фреймворк для тестування, написаний для тестів на Typescript. +- [bankrun](https://kevinheavey.github.io/solders/tutorials/bankrun.html) — фреймворк для тестування, написаний для тестів на Python. + +Якщо ви не хочете розробляти програми локально, існує також [онлайн IDE Solana Playground](https://beta.solpg.io). Solana Playground дозволяє писати, тестувати та розгортати програми на Solana. Ви можете розпочати роботу з Solana Playground, [слідувавши нашому посібнику швидкого старту](/docs/uk/intro/quick-start). + +### Середовища Розробки + +Вибір правильного середовища залежно від вашої роботи дуже важливий. У Solana є кілька середовищ (кластерів) для забезпечення якісного тестування та CI/CD практик: + +- **Mainnet Beta**: Продуктивна мережа, де відбувається вся дія. Транзакції тут коштують реальних грошей. +- **Devnet**: Мережа для забезпечення якості, де ви розгортаєте ваші програми для тестування перед розгортанням у продуктивне середовище. Це як "середовище для постановки". +- **Local**: Локальна мережа, яку ви запускаєте на своїй машині за допомогою `solana-test-validator` для тестування ваших програм. Це має бути вашим першим вибором під час розробки. + +## Побудова на Основі Прикладів + +Під час початку розробки на Solana є кілька ресурсів, які допоможуть прискорити ваш шлях: + +- [Solana Cookbook](https://solana.com/developers/cookbook): Збірка довідників і фрагментів коду для допомоги у розробці на Solana. +- [Приклади Програм Solana](https://github.com/solana-developers/program-examples): Репозиторій прикладів програм, що надають будівельні блоки для різних дій у ваших програмах. +- [Посібники](https://solana.com/developers/guides): Посібники та інструкції, які проведуть вас через процес розробки на Solana. + +## Отримання Підтримки + +Найкращу підтримку ви можете знайти на [Solana StackExchange](https://solana.stackexchange.com/). Спочатку пошукайте своє питання там — є велика ймовірність, що вже існує схоже питання з відповіддю. Якщо його там немає, додайте нове питання! Не забудьте включити якомога більше деталей у ваше питання, і, будь ласка, використовуйте текст (а не скріншоти) для відображення повідомлень про помилки, щоб інші люди з такою ж проблемою могли знайти ваше питання! + +## Наступні кроки + +[Тепер ви готові почати створювати на Solana!](/docs/uk/intro/quick-start) + diff --git a/docs/uk/intro/installation.md b/docs/uk/intro/installation.md index 9f359e042..fb7dce6fc 100644 --- a/docs/uk/intro/installation.md +++ b/docs/uk/intro/installation.md @@ -3,96 +3,82 @@ title: Installation seoTitle: Install the Solana CLI and Anchor sidebarSortOrder: 1 description: - A comprehensive guide to setting up your local Solana development environment. - Learn how to install Rust, the Solana CLI, and Anchor Framework on Windows - (WSL), Linux, and Mac. Includes step-by-step instructions for creating - wallets, requesting airdrops, and running a local validator. + Покроковий посібник з налаштування локального середовища розробки для Solana. + Дізнайтеся, як встановити Rust, Solana CLI та Anchor Framework на Windows + (WSL), Linux і Mac. Включає інструкції зі створення гаманців, запиту airdrop і + запуску локального валідатора. altRoutes: - /developers/guides/getstarted/setup-local-development - - /docs/install + - /docs/uk/install - /install - /setup --- -This section covers the steps to set up your local environment for Solana -development. +Цей розділ охоплює етапи налаштування локального середовища для розробки на Solana. -## Install Dependencies +## Встановлення Залежностей -- Windows users must first install WSL (Windows subsystem for Linux) and then - install the dependencies specified in the Linux section below. -- Linux users should first install the dependencies specified in the Linux - section below. -- Mac users should start with the Rust installation instructions below. +- Користувачі Windows повинні спочатку встановити WSL (Windows Subsystem for Linux), а потім встановити залежності, зазначені в розділі Linux нижче. +- Користувачі Linux повинні спочатку встановити залежності, зазначені в розділі Linux нижче. +- Користувачі Mac повинні почати з інструкцій з установки Rust нижче. -To develop Solana programs on Windows **you must use -[WSL](https://learn.microsoft.com/en-us/windows/wsl/install)** (Windows -subsystem for Linux). All additional dependencies must be installed through the -Linux terminal. +Для розробки програм Solana на Windows **необхідно використовувати +[WSL](https://learn.microsoft.com/en-us/windows/wsl/install)** (Windows Subsystem for Linux). Усі додаткові залежності необхідно встановлювати через термінал Linux. -Once WSL is installed, install the dependencies specified in the Linux section -below before proceeding to install Rust, Solana CLI, and Anchor CLI. +Після встановлення WSL встановіть залежності, зазначені в розділі Linux нижче, перш ніж переходити до установки Rust, Solana CLI та Anchor CLI. + +Щоб встановити WSL, виконайте наступну команду у Windows PowerShell: -To install WSL, run the following command in Windows PowerShell: ```shell wsl --install ``` -The install process will prompt you to create a default user account. +Процес встановлення запропонує вам створити обліковий запис користувача за замовчуванням. ![WSL Install](/assets/docs/intro/installation/wsl-install.png) -By default, WSL installs Ubuntu. You can open a Linux terminal by searching -"Ubuntu" in the Search bar. +За замовчуванням WSL встановлює Ubuntu. Ви можете відкрити термінал Linux, ввівши "Ubuntu" у пошуковому рядку. ![WSL Ubuntu](/assets/docs/intro/installation/wsl-ubuntu-search.png) -If your Ubuntu terminal looks like the image below, you may encounter an issue -where `ctrl + v` (paste keyboard shortcut) doesn't work in the terminal. +Якщо ваш термінал Ubuntu виглядає так, як на зображенні нижче, ви можете зіткнутися з проблемою, коли комбінація `ctrl + v` (вставити) не працює у терміналі. ![Ubuntu Terminal](/assets/docs/intro/installation/wsl-ubuntu-terminal-1.png) -If you encounter this issue, open Windows Terminal by searching for "Terminal" -in the Search bar. +Якщо виникла ця проблема, відкрийте Windows Terminal, ввівши "Terminal" у пошуковому рядку. ![Windows Terminal](/assets/docs/intro/installation/wsl-windows-terminal.png) -Next, close the Windows Terminal and reopen a Linux terminal by searching for -Ubuntu again. The terminal should now look like the image below, where -`ctrl + v` (paste keyboard shortcut) works. +Далі закрийте Windows Terminal і знову відкрийте термінал Linux, ввівши "Ubuntu" у пошуку. Тепер термінал має виглядати так, як на зображенні нижче, і комбінація `ctrl + v` (вставити) має працювати. ![Ubuntu Terminal](/assets/docs/intro/installation/wsl-ubuntu-terminal-2.png) -If you are using VS Code, the -[WSL extension](https://code.visualstudio.com/docs/remote/wsl-tutorial) enables -you to use WSL and VS Code together. +Якщо ви використовуєте VS Code, розширення [WSL extension](https://code.visualstudio.com/docs/remote/wsl-tutorial) дозволяє використовувати WSL та VS Code разом. ![WSL Setup in VS Code](/assets/docs/intro/installation/wsl-vscode.png) -You should then see the following in the VS Code status bar: +У статусному рядку VS Code ви повинні побачити наступне: ![WSL: Ubuntu](/assets/docs/intro/installation/wsl-vscode-ubuntu.png) -Once you have WSL set up, all additional dependencies must be installed through -the Linux terminal. Install the dependencies specified in the Linux section -below before proceeding to install Rust, Solana CLI, and Anchor CLI. +Після налаштування WSL всі додаткові залежності потрібно встановлювати через термінал Linux. Встановіть залежності, зазначені в розділі Linux нижче, перш ніж переходити до встановлення Rust, Solana CLI та Anchor CLI. -The following dependencies are required for the Anchor CLI installation. +Для встановлення Anchor CLI необхідно виконати наступні залежності. -First, run the following command: +Спочатку виконайте наступну команду: ```shell sudo apt-get update ``` +Далі встановіть наступні залежності: -Next, install the following dependencies: ```shell sudo apt-get install -y \ @@ -101,9 +87,7 @@ sudo apt-get install -y \ libudev-dev llvm libclang-dev \ protobuf-compiler libssl-dev ``` - -If you encounter the following error when installing `protobuf-compiler`, make -sure you first run `sudo apt-get update`: +Якщо під час встановлення `protobuf-compiler` ви зіткнетеся з такою помилкою, спочатку переконайтеся, що виконали команду `sudo apt-get update`: ``` Package protobuf-compiler is not available, but is referred to by another package. @@ -116,21 +100,19 @@ is only available from another source -### Install Rust +### Встановлення Rust -Solana programs are written in the -[Rust programming language](https://www.rust-lang.org/). +Програми Solana пишуться на [мові програмування Rust](https://www.rust-lang.org/). -The recommended installation method for Rust is -[rustup](https://www.rust-lang.org/tools/install). +Рекомендований метод встановлення Rust — це [rustup](https://www.rust-lang.org/tools/install). -Run the following command to install Rust: +Виконайте наступну команду для встановлення Rust: ```shell curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ``` -You should see the following message after the installation completes: +Після завершення встановлення ви повинні побачити таке повідомлення: @@ -153,42 +135,37 @@ source "$HOME/.cargo/env.fish" # For fish -Run the following command to reload your PATH environment variable to include -Cargo's bin directory: +Виконайте наступну команду, щоб оновити змінну середовища PATH і включити директорію `bin` Cargo: ```shell . "$HOME/.cargo/env" ``` -To verify that the installation was successful, check the Rust version: +Щоб перевірити, чи встановлення було успішним, перевірте версію Rust: ```shell rustc --version ``` -You should see output similar to the following: +Ви повинні побачити результат, схожий на наступний: ``` rustc 1.80.1 (3f5fd8dd4 2024-08-06) ``` -### Install the Solana CLI +### Встановлення Solana CLI -The Solana CLI provides all the tools required to build and deploy Solana -programs. +Solana CLI надає всі необхідні інструменти для створення та розгортання програм Solana. -Install the Solana CLI tool suite using the official install command: +Встановіть набір інструментів Solana CLI за допомогою офіційної команди встановлення: ```shell sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)" ``` -You can replace `stable` with the release tag matching the software version of -your desired release (i.e. `v2.0.3`), or use one of the three symbolic channel -names: `stable`, `beta`, or `edge`. +Ви можете замінити `stable` на тег релізу, який відповідає версії програмного забезпечення потрібного релізу (наприклад, `v2.0.3`), або використовувати один із трьох символічних назв каналів: `stable`, `beta` або `edge`. -If it is your first time installing the Solana CLI, you may see the following -message prompting you to add a PATH environment variable: +Якщо ви встановлюєте Solana CLI вперше, ви можете побачити таке повідомлення із запитом на додавання змінної середовища PATH: ``` Close and reopen your terminal to apply the PATH changes or run the following in your existing shell: @@ -199,9 +176,7 @@ export PATH="/Users/test/.local/share/solana/install/active_release/bin:$PATH" -If you are using a Linux or WSL terminal, you can add the PATH environment -variable to your shell configuration file by running the command logged from the -installation or by restarting your terminal. +Якщо ви використовуєте термінал Linux або WSL, ви можете додати змінну середовища PATH у файл конфігурації вашої оболонки, виконавши команду, зазначену під час встановлення, або перезапустивши термінал. ```shell export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" @@ -210,18 +185,16 @@ export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" -If you're on Mac using `zsh`, running the default `export PATH` command logged -from the installation does not persist once you close your terminal. +Якщо ви використовуєте Mac із оболонкою `zsh`, виконання стандартної команди `export PATH`, зазначеної під час встановлення, не зберігається після закриття термінала. -Instead, you can add the PATH to your shell configuration file by running the -following command: +Замість цього ви можете додати PATH у файл конфігурації оболонки, виконавши наступну команду: ```shell echo 'export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"' >> ~/.zshrc ``` -Then run the following command to refresh the terminal session or restart your -terminal. +Далі виконайте наступну команду, щоб оновити сесію термінала, або перезапустіть термінал. + ```shell source ~/.zshrc @@ -230,76 +203,68 @@ source ~/.zshrc -To verify that the installation was successful, check the Solana CLI version: +Щоб перевірити, чи встановлення було успішним, перевірте версію Solana CLI: + ```shell solana --version ``` +Ви повинні побачити результат, схожий на наступний: -You should see output similar to the following: ``` solana-cli 1.18.22 (src:9efdd74b; feat:4215500110, client:Agave) ``` -You can view all available versions on the -[Agave Github repo](https://github.com/anza-xyz/agave/releases). +Ви можете переглянути всі доступні версії у [репозиторії Agave на Github](https://github.com/anza-xyz/agave/releases). -Agave is the validator client from [Anza](https://www.anza.xyz/), formerly known -as Solana Labs validator client. +Agave — це клієнт валідатора від [Anza](https://www.anza.xyz/), раніше відомий як клієнт валідатора Solana Labs. -To later update the Solana CLI to the latest version, you can use the following -command: +Щоб оновити Solana CLI до останньої версії, ви можете використати наступну команду: + ```shell agave-install update ``` -### Install Anchor CLI +### Встановлення Anchor CLI -[Anchor](https://www.anchor-lang.com/) is a framework for developing Solana -programs. The Anchor framework leverages Rust macros to simplify the process of -writing Solana programs. +[Anchor](https://www.anchor-lang.com/) — це фреймворк для розробки програм на Solana. Anchor використовує макроси Rust, щоб спростити процес написання програм на Solana. -There are two ways to install the Anchor CLI and tooling: +Існує два способи встановлення Anchor CLI та інструментів: -1. Using Anchor Version Manager (AVM) - is the **recommended installation** - method since it simplifies updating Anchor versions in the future -2. Without AVM - this requires more a manual process to update Anchor versions - later +1. За допомогою Anchor Version Manager (AVM) — **рекомендований спосіб встановлення**, оскільки він спрощує оновлення версій Anchor у майбутньому. +2. Без AVM — вимагає більш ручного процесу для оновлення версій Anchor у майбутньому. -The Anchor version manager (AVM) allows you to install and manage different -Anchor versions on your system, including more easily updating Anchor versions -in the future. +Менеджер версій Anchor (AVM) дозволяє встановлювати та керувати різними версіями Anchor на вашій системі, включаючи зручне оновлення версій у майбутньому. -Install AVM with the following command: +Встановіть AVM за допомогою наступної команди: ```shell cargo install --git https://github.com/coral-xyz/anchor avm --force ``` +Перевірте, щоб переконатися, що AVM було встановлено та він доступний: -Test to ensure AVM was installed and is accessible: ```shell avm --version ``` +Встановіть останню версію Anchor CLI за допомогою AVM: -Install the latest version of Anchor CLI using AVM: ```shell avm install latest avm use latest ``` +Або встановіть конкретну версію Anchor CLI, вказавши бажану версію: -Or install a specific version of the Anchor CLI by declaring which version you -want to install: ```shell avm install 0.30.1 @@ -316,7 +281,7 @@ avm use 0.30.1 -Install a specific version of the Anchor CLI with the following command: +Встановіть конкретну версію Anchor CLI за допомогою наступної команди: ```shell cargo install --git https://github.com/coral-xyz/anchor --tag v0.30.1 anchor-cli @@ -325,8 +290,7 @@ cargo install --git https://github.com/coral-xyz/anchor --tag v0.30.1 anchor-cli -You may see the following warning during installation. However, it does not -affect the installation process. +Під час встановлення ви можете побачити таке попередження. Однак це не впливає на процес встановлення. @@ -353,66 +317,63 @@ warning: `anchor-cli` (lib) generated 1 warning -To verify that the installation was successful, check the Anchor CLI version: +Щоб перевірити, чи встановлення було успішним, перевірте версію Anchor CLI: ```shell anchor --version ``` -You should see output similar to the following: +Ви повинні побачити результат, схожий на наступний: ``` anchor-cli 0.30.1 ``` -When installing the Anchor CLI on Linux or WSL, you may encounter this error: +Під час встановлення Anchor CLI на Linux або WSL ви можете зіткнутися з такою помилкою: ``` error: could not exec the linker cc = note: Permission denied (os error 13) ``` -If you see this error message, follow these steps: +Якщо ви бачите це повідомлення про помилку, виконайте наступні кроки: -1. Install the dependencies listed in the Linux section at the top of this page. -2. Retry installing the Anchor CLI. +1. Встановіть залежності, зазначені в розділі Linux на початку цієї сторінки. +2. Повторіть спробу встановлення Anchor CLI. -#### Node.js and Yarn +#### Node.js та Yarn -Node.js and Yarn are required to run the default Anchor project test file -(TypeScript) created with the `anchor init` command. (Rust test template is also -available using `anchor init --test-template rust`) +Node.js та Yarn необхідні для запуску тестового файлу (TypeScript), створеного за допомогою команди `anchor init`. (Шаблон тестів на Rust також доступний за допомогою `anchor init --test-template rust`) - + -The recommended way to install node is using -[Node Version Manager (nvm)](https://github.com/nvm-sh/nvm). +Рекомендований спосіб встановлення Node — використання [Node Version Manager (nvm)](https://github.com/nvm-sh/nvm). -Install nvm using the following command: +Встановіть nvm за допомогою наступної команди: ```shell curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash ``` -Restart your terminal and verify that nvm is installed: +Перезапустіть ваш термінал і перевірте, чи встановлено nvm: ```shell command -v nvm ``` -Next, use `nvm` to install node: +Далі використовуйте `nvm`, щоб встановити Node.js: ```shell nvm install node ``` -To verify that the installation was successful, check the Node version: +Щоб перевірити, чи встановлення було успішним, перевірте версію Node.js: ``` node --version ``` -You should see output similar to the following: +Ви повинні побачити результат, схожий на наступний: ``` v22.7.0 @@ -421,19 +382,17 @@ v22.7.0 -Install Yarn: +Встановіть Yarn: ```shell npm install --global yarn ``` - -To verify that the installation was successful, check the Yarn version: +Щоб перевірити, чи встановлення було успішним, перевірте версію Yarn: ``` yarn --version ``` - -You should the following output: +Ви повинні побачити наступний результат: ``` 1.22.1 @@ -442,7 +401,7 @@ You should the following output: -When running `anchor build`, if you encounter similar errors following: +Під час виконання команди `anchor build`, якщо ви стикаєтеся з такими помилками: @@ -450,16 +409,15 @@ When running `anchor build`, if you encounter similar errors following: ``` error: not a directory: '.../solana-release/bin/sdk/sbf/dependencies/platform-tools/rust/lib' ``` +Спробуйте ці рішення: -Try these solutions: - -1. Force install using the following command: +1. Примусове встановлення за допомогою наступної команди: ```shell cargo build-sbf --force-tools-install ``` -2. If the above doesn't work, clear the Solana cache: +2. Якщо це не спрацювало, очистіть кеш Solana: ```shell rm -rf ~/.cache/solana/* @@ -468,24 +426,23 @@ rm -rf ~/.cache/solana/* -You can fix this by changing the version field of `Cargo.lock` file + +Ви можете виправити це, змінивши поле версії у файлі `Cargo.lock`: ``` version = 3 ``` -See [this issue](https://github.com/coral-xyz/anchor/issues/3392) for more -information. +Дивіться [це обговорення](https://github.com/coral-xyz/anchor/issues/3392) для отримання додаткової інформації. + -After applying either solution, attempt to run `anchor build` again. +Після застосування будь-якого з рішень спробуйте знову виконати команду `anchor build`. -If you are on Linux or WSL and encounter the following errors when running -`anchor test` after creating a new Anchor project, it's may be due to missing -Node.js or Yarn: +Якщо ви використовуєте Linux або WSL і стикаєтеся з такими помилками під час виконання команди `anchor test` після створення нового проєкту Anchor, це може бути через відсутність Node.js або Yarn: ``` Permission denied (os error 13) @@ -497,22 +454,22 @@ No such file or directory (os error 2) -## Solana CLI Basics +## Основи Solana CLI -This section will walk through some common Solana CLI commands to get you -started. +Цей розділ ознайомить вас із деякими поширеними командами Solana CLI для початку роботи. -### Solana Config +### Конфігурація Solana + +Щоб переглянути вашу поточну конфігурацію: -To see your current config: ```shell solana config get ``` -You should see output similar to the following: +Ви повинні побачити результат, схожий на наступний: ``` Config File: /Users/test/.config/solana/cli/config.yml @@ -522,10 +479,9 @@ Keypair Path: /Users/test/.config/solana/id.json Commitment: confirmed ``` -The RPC URL and Websocket URL specify the Solana cluster the CLI will make -requests to. By default this will be mainnet-beta. +RPC URL та Websocket URL вказують кластер Solana, до якого CLI надсилатиме запити. За замовчуванням це буде mainnet-beta. -You can update the Solana CLI cluster using the following commands: +Ви можете оновити кластер Solana CLI за допомогою наступних команд: ``` solana config set --url mainnet-beta @@ -533,8 +489,7 @@ solana config set --url devnet solana config set --url localhost solana config set --url testnet ``` - -You can also use the following short options: +Ви також можете використовувати наступні скорочені опції: ``` solana config set -um # For mainnet-beta @@ -543,23 +498,20 @@ solana config set -ul # For localhost solana config set -ut # For testnet ``` -The Keypair Path specifies the location of the default wallet used by the Solana -CLI (to pay transaction fees and deploy programs). The default path is -`~/.config/solana/id.json`. The next step walks through how to generate a -keypair at the default location. +Шлях до ключової пари (Keypair Path) вказує розташування гаманця за замовчуванням, який використовується Solana CLI (для оплати комісій за транзакції та розгортання програм). Шлях за замовчуванням: `~/.config/solana/id.json`. У наступному кроці описано, як створити ключову пару за цим шляхом. -### Create Wallet +### Створення Гаманця -To interact with the Solana network using the Solana CLI, you need a Solana -wallet funded with SOL. +Для взаємодії з мережею Solana за допомогою Solana CLI вам потрібен гаманець Solana, поповнений SOL. + +Щоб створити ключову пару за замовчуванням у Keypair Path, виконайте наступну команду: -To generate a keypair at the default Keypair Path, run the following command: ```shell solana-keygen new ``` -You should see output similar to the following: +Ви повинні побачити результат, схожий на наступний: ``` Generating a new keypair @@ -582,14 +534,11 @@ cream bleak tortoise ocean nasty game gift forget fancy salon mimic amazing -If you already have a file system wallet saved at the default location, this -command will **NOT** override it unless you explicitly force override using the -`--force` flag. +Якщо у вас вже є гаманець у файловій системі, збережений у місці за замовчуванням, ця команда **НЕ** перезапише його, якщо ви явно не використаєте прапорець `--force`. -Once a keypair is generated, you can get the address (public key) of the keypair -with the following command: +Після створення ключової пари ви можете отримати адресу (публічний ключ) цієї пари за допомогою наступної команди: ```shell solana address @@ -597,22 +546,24 @@ solana address ### Airdrop SOL -Once you've set up your local wallet, request an airdrop of SOL to fund your -wallet. You need SOL to pay for transaction fees and to deploy programs. +Після налаштування локального гаманця запросіть airdrop SOL для поповнення вашого гаманця. SOL потрібні для оплати комісій за транзакції та розгортання програм. + +Встановіть ваш кластер на devnet: -Set your cluster to the devnet: ```shell solana config set -ud ``` -Then request an airdrop of devnet SOL: +Далі запросіть airdrop SOL у devnet: + ```shell solana airdrop 2 ``` -To check your wallet's SOL balance, run the following command: +Щоб перевірити баланс SOL вашого гаманця, виконайте наступну команду: + ```shell solana balance @@ -620,22 +571,18 @@ solana balance -The `solana airdrop` command is currently limited to 5 SOL per request on -devnet. Errors are likely due to rate limits. +Команда `solana airdrop` наразі обмежена 5 SOL за запит у devnet. Помилки можуть виникати через обмеження частоти запитів. -Alternatively, you can get devnet SOL using the -[Solana Web Faucet](https://faucet.solana.com). +Як альтернативу, ви можете отримати SOL у devnet за допомогою [Solana Web Faucet](https://faucet.solana.com). -### Run Local Validator +### Запуск Локального Валідатора -The Solana CLI comes with the -[test validator](https://docs.anza.xyz/cli/examples/test-validator) built-in. -Running a local validator will allow you to deploy and test your programs -locally. +Solana CLI постачається з вбудованим [тестовим валідатором](https://docs.anza.xyz/cli/examples/test-validator). Запуск локального валідатора дозволить вам розгортати та тестувати програми локально. + +У окремому терміналі виконайте наступну команду, щоб запустити локальний валідатор: -In a separate terminal, run the following command to start a local validator: ```shell solana-test-validator @@ -643,8 +590,8 @@ solana-test-validator -In WSL you may need to first navigate to a folder where you have default write -access: +У WSL вам може знадобитися спочатку перейти до папки, де у вас є права запису за замовчуванням: + ```shell cd ~ @@ -655,7 +602,7 @@ solana-test-validator -Make sure to update the Solana CLI config to localhost before commands. +Переконайтеся, що оновили конфігурацію Solana CLI до `localhost` перед виконанням команд: ```shell solana config set -ul diff --git a/docs/uk/intro/quick-start/cross-program-invocation.md b/docs/uk/intro/quick-start/cross-program-invocation.md index f3aafb4c9..58f36f10d 100644 --- a/docs/uk/intro/quick-start/cross-program-invocation.md +++ b/docs/uk/intro/quick-start/cross-program-invocation.md @@ -1,35 +1,35 @@ --- -sidebarLabel: Cross Program Invocation -title: Cross Program Invocation +sidebarLabel: Крос-програмні виклики +title: Крос-програмні виклики sidebarSortOrder: 5 description: - Learn how to implement Cross Program Invocations (CPIs) in Solana programs - using the Anchor framework. This tutorial demonstrates how to transfer SOL - between accounts, interact with the System Program, and handle Program Derived - Addresses (PDAs) in CPIs. Perfect for developers looking to build composable - Solana programs. + Дізнайтеся, як реалізувати крос-програмні виклики (CPIs) у програмах Solana + за допомогою фреймворку Anchor. У цьому підручнику демонструється, як + здійснювати переказ SOL між акаунтами, взаємодіяти з Системною програмою та + працювати з адресами, отриманими від програми (PDAs), у CPIs. Ідеально + підходить для розробників, які хочуть створювати інтегровані програми Solana. --- -In this section, we'll update the CRUD program from the previous PDA section to -include Cross Program Invocations (CPIs). We'll modify the program to transfer -SOL between accounts in the `update` and `delete` instructions, demonstrating -how to interact with other programs (in this case, the System Program) from -within our program. +У цьому розділі ми оновимо програму CRUD з попереднього розділу про PDA, щоб +додати крос-програмні виклики (CPIs). Ми модифікуємо програму, щоб +забезпечити переказ SOL між акаунтами в інструкціях `update` та `delete`, +демонструючи, як взаємодіяти з іншими програмами (у цьому випадку з +Системною програмою) зсередини нашої програми. -The purpose of this section is to walk through the process of implementing CPIs -in a Solana program using the Anchor framework, building upon the PDA concepts -we explored in the previous section. For more details, refer to the -[Cross Program Invocation](/docs/core/cpi) page. +Метою цього розділу є покрокове пояснення процесу реалізації CPIs у програмі +Solana за допомогою фреймворку Anchor, спираючись на концепції PDA, які ми +розглядали в попередньому розділі. Для отримання додаткової інформації +перейдіть на сторінку [Крос-програмні виклики](/docs/uk/core/cpi). -### Modify Update Instruction +### Модифікація інструкції Update -First, we'll implement a simple "pay-to-update" mechanism by modifying the -`Update` struct and `update` function. +Спочатку ми реалізуємо простий механізм "оплати за оновлення" шляхом +модифікації структури `Update` та функції `update`. -Begin by updating the `lib.rs` file to bring into scope items from the -`system_program` module. +Розпочнемо з оновлення файлу `lib.rs`, щоб включити до області видимості +елементи з модуля `system_program`. ```rs filename="lib.rs" use anchor_lang::system_program::{transfer, Transfer}; @@ -46,9 +46,7 @@ use anchor_lang::system_program::{transfer, Transfer}; -Next, update the `Update` struct to include an additional account called -`vault_account`. This account, controlled by our program, will receive SOL from -a user when they update their message account. +Далі оновіть структуру Update, щоб включити додатковий акаунт під назвою `vault_account`. Цей акаунт, який контролюється нашою програмою, отримуватиме SOL від користувача, коли той оновлює свій акаунт повідомлень. ```rs filename="lib.rs" #[account( @@ -90,38 +88,38 @@ pub struct Update<'info> { +Ми додаємо новий акаунт під назвою `vault_account` до нашої структури `Update`. Цей акаунт служить програмно-контрольованим "сейфом", який буде отримувати SOL від користувачів, коли вони оновлюють свої повідомлення. -We're adding a new account called `vault_account` to our `Update` struct. This -account serves as a program-controlled "vault" that will receive SOL from users -when they update their messages. - -By using a PDA for the vault, we create a program-controlled account unique to -each user, enabling us to manage user funds within our program's logic. +Використовуючи PDA (Program Derived Address) для сейфа, ми створюємо програмно-контрольований акаунт, унікальний для кожного користувача, що дозволяє нам управляти коштами користувачів у межах логіки нашої програми. --- -Key aspects of the `vault_account`: +Основні аспекти `vault_account`: -- The address of the account is a PDA derived using seeds +- **Адреса акаунта**: + Адреса акаунта є PDA, що отримується за допомогою сідів: `[b"vault", user.key().as_ref()]` -- As a PDA, it has no private key, so only our program can "sign" for the - address when performing CPIs -- As a `SystemAccount` type, it's owned by the System Program like regular - wallet accounts +- **Відсутність приватного ключа**: + Оскільки це PDA, він не має приватного ключа, тому лише наша програма може "підписуватися" за цю адресу під час виконання CPIs. +- **Тип акаунта**: + Це акаунт типу `SystemAccount`, який належить до Системної програми, як і звичайні гаманці. -This setup allows our program to: +--- -- Generate unique, deterministic addresses for each user's "vault" -- Control funds without needing a private key to sign for transactions. +Ця структура дозволяє нашій програмі: -In the `delete` instruction, we'll demonstrate how our program can "sign" for -this PDA in a CPI. +- Генерувати унікальні, детерміновані адреси для кожного "сейфа" користувача. +- Контролювати кошти без необхідності використання приватного ключа для підписання транзакцій. - - +--- -Next, implement the CPI logic in the `update` instruction to transfer 0.001 SOL -from the user's account to the vault account. +У інструкції `delete` ми покажемо, як наша програма може "підписуватися" за цей PDA під час CPI. + +--- + +Далі: реалізуйте логіку CPI в інструкції `update` + +Реалізуйте логіку CPI для переказу **0.001 SOL** з акаунта користувача на акаунт сейфа. ```rs filename="lib.rs" let transfer_accounts = Transfer { @@ -160,16 +158,12 @@ transfer(cpi_context, 1_000_000)?; -In the `update` instruction, we implement a Cross Program Invocation (CPI) to -invoke the System Program's `transfer` instruction. This demonstrates how to -perform a CPI from within our program, enabling the composability of Solana -programs. +В інструкції `update` ми реалізуємо виклик між програмами (CPI), щоб викликати інструкцію `transfer` Системної програми. Це демонструє, як виконати CPI у межах нашої програми, забезпечуючи композиційність програм у Solana. -The `Transfer` struct specifies the required accounts for the System Program's -transfer instruction: +Структура `Transfer` визначає необхідні акаунти для інструкції `transfer` Системної програми: -- `from` - The user's account (source of funds) -- `to` - The vault account (destination of funds) +- `from` - Акаунт користувача (джерело коштів) +- `to` - Акаунт сейфа (ціль для переказу коштів) ```rs filename="lib.rs" let transfer_accounts = Transfer { @@ -177,11 +171,10 @@ transfer instruction: to: ctx.accounts.vault_account.to_account_info(), }; ``` +`CpiContext` визначає: -The `CpiContext` specifies: - -- The program to be invoked (System Program) -- The accounts required in the CPI (defined in the `Transfer` struct) +- Програму, яку потрібно викликати (Системна програма) +- Акаунти, необхідні для CPI (визначені у структурі `Transfer`) ```rs filename="lib.rs" let cpi_context = CpiContext::new( @@ -190,40 +183,32 @@ The `CpiContext` specifies: ); ``` -The `transfer` function then invokes the transfer instruction on the System -Program, passing in the: +Функція `transfer` викликає інструкцію переказу у Системній програмі, передаючи: + +- `cpi_context` (програму та акаунти) +- Суму для переказу (1,000,000 лампортів, що еквівалентно 0.001 SOL) -- The `cpi_context` (program and accounts) -- The `amount` to transfer (1,000,000 lamports, equivalent to 0.001 SOL) ```rs filename="lib.rs" transfer(cpi_context, 1_000_000)?; ``` --- - -The setup for a CPI matches how client-side instructions are built, where we -specify the program, accounts, and instruction data for a particular instruction -to invoke. When our program's `update` instruction is invoked, it internally -invokes the System Program's transfer instruction. +Налаштування для CPI відповідає тому, як створюються інструкції на стороні клієнта, де ми вказуємо програму, акаунти та дані інструкції для виклику конкретної інструкції. Коли викликається інструкція `update` нашої програми, вона внутрішньо викликає інструкцію переказу Системної програми. -Rebuild the program. +Перекомпілюйте програму. ```shell filename="Terminal" build ``` +### Змініть Інструкцію Delete -### Modify Delete Instruction - -We'll now implement a "refund on delete" mechanism by modifying the `Delete` -struct and `delete` function. +Ми реалізуємо механізм "повернення коштів при видаленні", змінивши структуру `Delete` та функцію `delete`. -First, update the `Delete` struct to include the `vault_account`. This allows us -to transfer any SOL in the vault back to the user when they close their message -account. +Спершу оновіть структуру `Delete`, додавши до неї `vault_account`. Це дозволить нам переказати всі SOL із сейфа назад користувачеві, коли він закриває свій акаунт повідомлення. ```rs filename="lib.rs" #[account( @@ -234,8 +219,7 @@ account. pub vault_account: SystemAccount<'info>, ``` -Also add the `system_program` as the CPI for the transfer requires invoking the -System Program. +Також додайте `system_program`, оскільки CPI для переказу вимагає виклику Системної програми. ```rs filename="lib.rs" pub system_program: Program<'info, System>, @@ -270,17 +254,14 @@ pub struct Delete<'info> { -The `vault_account` uses the same PDA derivation as in the Update struct. +Акаунт `vault_account` використовує той самий PDA, що і в структурі `Update`. -Add the `vault_account` to the Delete struct enables our program to access the -user's vault account during the delete instruction to transfer any accumulated -SOL back to the user. +Додавання `vault_account` до структури `Delete` дозволяє нашій програмі отримати доступ до сейфа користувача під час виконання інструкції видалення, щоб переказати накопичені SOL назад користувачеві. -Next, implement the CPI logic in the `delete` instruction to transfer SOL from -the vault account back to the user's account. +Далі реалізуйте логіку CPI в інструкції `delete`, щоб переказати SOL із сейфа назад на акаунт користувача. ```rs filename="lib.rs" let user_key = ctx.accounts.user.key(); @@ -298,8 +279,7 @@ let cpi_context = CpiContext::new( transfer(cpi_context, ctx.accounts.vault_account.lamports())?; ``` -Note that we updated `_ctx: Context` to `ctx: Context` as we'll -be using the context in the body of the function. +Зверніть увагу, що ми оновили `_ctx: Context` до `ctx: Context`, оскільки будемо використовувати контекст у тілі функції. @@ -329,24 +309,20 @@ be using the context in the body of the function. +В інструкції `delete` ми реалізуємо ще один виклик між програмами (CPI), щоб викликати інструкцію переказу Системної програми. Цей CPI демонструє, як здійснити переказ, який потребує підписувача на основі Program Derived Address (PDA). -In the delete instruction, we implement another Cross Program Invocation (CPI) -to invoke the System Program's transfer instruction. This CPI demonstrates how -to make a transfer that requires a Program Derived Address (PDA) signer. - -First, we define the signer seeds for the vault PDA: +Спершу ми визначаємо сіди для підпису PDA сейфа: ```rs filename="lib.rs" let user_key = ctx.accounts.user.key(); let signer_seeds: &[&[&[u8]]] = &[&[b"vault", user_key.as_ref(), &[ctx.bumps.vault_account]]]; ``` +Структура `Transfer` визначає необхідні акаунти для інструкції переказу Системної програми: -The `Transfer` struct specifies the required accounts for the System Program's -transfer instruction: +- `from`: Акаунт сейфа (джерело коштів) +- `to`: Акаунт користувача (ціль для переказу коштів) -- from: The vault account (source of funds) -- to: The user's account (destination of funds) ```rs filename="lib.rs" let transfer_accounts = Transfer { @@ -354,12 +330,11 @@ transfer instruction: to: ctx.accounts.user.to_account_info(), }; ``` +`CpiContext` визначає: -The `CpiContext` specifies: - -- The program to be invoked (System Program) -- The accounts involved in the transfer (defined in the Transfer struct) -- The signer seeds for the PDA +- Програму, яку потрібно викликати (Системна програма) +- Акаунти, задіяні у переказі (визначені у структурі `Transfer`) +- Сіди для підпису PDA ```rs filename="lib.rs" let cpi_context = CpiContext::new( @@ -367,36 +342,28 @@ The `CpiContext` specifies: transfer_accounts, ).with_signer(signer_seeds); ``` +Функція `transfer` викликає інструкцію переказу в Системній програмі, передаючи: -The transfer function then invokes the transfer instruction on the System -Program, passing: - -- The `cpi_context` (program, accounts, and PDA signer) -- The amount to transfer (the entire balance of the vault account) +- `cpi_context` (програму, акаунти та підписувач на основі PDA) +- Суму для переказу (весь баланс акаунта сейфа) ```rs filename="lib.rs" transfer(cpi_context, ctx.accounts.vault_account.lamports())?; ``` - -This CPI implementation demonstrates how programs can utilize PDAs to manage -funds. When our program's delete instruction is invoked, it internally calls the -System Program's transfer instruction, signing for the PDA to authorize the -transfer of all funds from the vault back to the user. +Ця реалізація CPI демонструє, як програми можуть використовувати PDA для управління коштами. Коли викликається інструкція `delete` нашої програми, вона внутрішньо викликає інструкцію переказу Системної програми, підписуючи за PDA, щоб авторизувати переказ усіх коштів із сейфа назад користувачеві. -Rebuild the program. +Перекомпілюйте програму. ```shell filename="Terminal" build ``` -### Redeploy Program +### Розгортання Програми -After making these changes, we need to redeploy our updated program. This -ensures that our modified program is available for testing. On Solana, updating -a program simply requires deploying the compiled program at the same program ID. +Після внесення цих змін нам потрібно повторно розгорнути оновлену програму. Це забезпечує доступність модифікованої програми для тестування. У Solana оновлення програми вимагає лише розгортання скомпільованої програми за тим самим ідентифікатором програми (program ID). ```shell filename="Terminal" deploy @@ -414,26 +381,21 @@ Deployment successful. Completed in 17s. -Only the upgrade authority of the program can update it. The upgrade authority -is set when the program is deployed, and it's the only account with permission -to modify or close the program. If the upgrade authority is revoked, then the -program becomes immutable and can never be closed or upgraded. +Лише орган влади оновлення (upgrade authority) програми може її оновити. Орган влади оновлення встановлюється під час розгортання програми, і це єдиний акаунт, який має дозвіл модифікувати або закривати програму. Якщо орган влади оновлення відкликається, програма стає незмінною і її ніколи не можна буде закрити або оновити. -When deploying programs on Solana Playground, your Playground wallet is the -upgrade authority for all your programs. +Під час розгортання програм у Solana Playground гаманцем Playground є орган влади оновлення для всіх ваших програм. -### Update Test File +### Оновлення Файлу Тестів + +Далі ми оновимо наш файл `anchor.test.ts`, щоб включити новий акаунт сейфа у наші інструкції. Це вимагає отримання PDA сейфа та його включення до викликів інструкцій `update` і `delete`. -Next, we'll update our `anchor.test.ts` file to include the new vault account in -our instructions. This requires deriving the vault PDA and including it in our -update and delete instruction calls. +#### Отримання PDA Сейфа -#### Derive Vault PDA +Спершу додайте код для отримання PDA сейфа: -First, add the vault PDA derivation: ```ts filename="anchor.test.ts" const [vaultPda, vaultBump] = PublicKey.findProgramAddressSync( @@ -466,10 +428,9 @@ describe("pda", () => { +#### Зміна Тесту Update -#### Modify Update Test - -Then, update the update instruction to include the `vaultAccount`. +Далі оновіть інструкцію `update`, щоб включити `vaultAccount`. ```ts filename="anchor.test.ts" {5} const transactionSignature = await program.methods @@ -497,9 +458,9 @@ const transactionSignature = await program.methods -#### Modify Delete Test +#### Зміна Тесту Delete -Then, update the delete instruction to include the `vaultAccount`. +Далі оновіть інструкцію `delete`, щоб включити `vaultAccount`. ```ts filename="anchor.test.ts" {5} const transactionSignature = await program.methods @@ -526,11 +487,9 @@ const transactionSignature = await program.methods +### Перезапуск Тестів -### Rerun Test - -After making these changes, run the tests to ensure everything is working as -expected: +Після внесення цих змін запустіть тести, щоб переконатися, що все працює, як очікувалося: ```shell filename="Terminal" test @@ -566,43 +525,28 @@ Running tests... - -You can then inspect the SolanFM links to view the transaction details, where -you'll find the CPIs for the transfer instructions within the update and delete -instructions. +Після цього ви можете переглянути посилання SolanFM, щоб побачити деталі транзакції, де ви знайдете CPI для інструкцій переказу в межах інструкцій `update` і `delete`. ![Update CPI](/assets/docs/intro/quickstart/cpi-update.png) ![Delete CPI](/assets/docs/intro/quickstart/cpi-delete.png) -If you encounter any errors, you can reference the -[final code](https://beta.solpg.io/668304cfcffcf4b13384d20a). +Якщо ви зіткнулися з помилками, ви можете переглянути [фінальний код](https://beta.solpg.io/668304cfcffcf4b13384d20a). -## Next Steps +## Наступні Кроки -You've completed the Solana Quickstart guide! You've learned about accounts, -transactions, PDAs, CPIs, and deployed your own programs. +Ви завершили посібник з швидкого старту Solana! Ви дізналися про акаунти, транзакції, PDA, CPI та розгорнули власні програми. -Visit the [Core Concepts](/docs/core/accounts) pages for more comprehensive -explanations of the topics covered in this guide. +Відвідайте сторінки [Основні Концепції](/docs/uk/core/accounts) для більш детального пояснення тем, розглянутих у цьому посібнику. -Additional learning resources can be found on the -[Developer Resources](/developers) page. +Додаткові навчальні матеріали доступні на сторінці [Ресурси для Розробників](/developers). -### Explore More Examples +### Досліджуйте Більше Прикладів -If you prefer learning by example, check out the -[Program Examples Repository](https://github.com/solana-developers/program-examples) -for a variety of example programs. +Якщо ви віддаєте перевагу навчанню через приклади, перегляньте [Репозиторій з Прикладами Програм](https://github.com/solana-developers/program-examples) для різноманітних прикладів програм. -Solana Playground offers a convenient feature allowing you to import or view -projects using their GitHub links. For example, open this -[Solana Playground link](https://beta.solpg.io/https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor) -to view the Anchor project from this -[Github repo](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor). +Solana Playground пропонує зручну функцію, яка дозволяє імпортувати або переглядати проєкти за їх посиланнями на GitHub. Наприклад, відкрийте це [посилання Solana Playground](https://beta.solpg.io/https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor), щоб переглянути Anchor-проєкт із цього [репозиторію GitHub](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor). -Click the `Import` button and enter a project name to add it to your list of -projects in Solana Playground. Once a project is imported, all changes are -automatically saved and persisted within the Playground environment. +Натисніть кнопку `Import` і введіть ім'я проєкту, щоб додати його до свого списку проєктів у Solana Playground. Після імпорту проєкту всі зміни автоматично зберігаються та залишаються у середовищі Playground. diff --git a/docs/uk/intro/quick-start/deploying-programs.md b/docs/uk/intro/quick-start/deploying-programs.md index 57c78a01d..ddcbbc83a 100644 --- a/docs/uk/intro/quick-start/deploying-programs.md +++ b/docs/uk/intro/quick-start/deploying-programs.md @@ -1,36 +1,30 @@ --- -sidebarLabel: Deploying Programs -title: Deploying Your First Solana Program +sidebarLabel: Розгортання Програм +title: Розгортання Вашої Першої Програми Solana sidebarSortOrder: 3 description: - Learn how to build, deploy, and test your first Solana program using the - Anchor framework and Solana Playground. This beginner-friendly guide walks - through creating a simple program, deploying it to devnet, running tests, and - closing the program. + Дізнайтеся, як створити, розгорнути та протестувати вашу першу програму Solana за допомогою + фреймворку Anchor та Solana Playground. Цей посібник для початківців демонструє, як створити просту програму, + розгорнути її на devnet, виконати тести та закрити програму. --- -In this section, we'll build, deploy, and test a simple Solana program using the -Anchor framework. By the end, you'll have deployed your first program to the -Solana blockchain! +У цьому розділі ми створимо, розгорнемо та протестуємо просту програму Solana за допомогою фреймворку Anchor. Наприкінці ви розгорнете свою першу програму у блокчейні Solana! -The purpose of this section is to familiarize you with the Solana Playground. -We'll walk through a more detailed example in the PDA and CPI sections. For more -details, refer to the [Programs on Solana](/docs/core/programs) page. +Мета цього розділу — ознайомити вас із Solana Playground. Ми розглянемо більш детальний приклад у розділах про PDA та CPI. Для отримання додаткової інформації відвідайте сторінку [Програми на Solana](/docs/core/programs). -### Create Anchor Project +### Створення Проєкту Anchor -First, open https://beta.solpg.io in a new browser tab. +Спочатку відкрийте https://beta.solpg.io у новій вкладці браузера. -- Click the "Create a new project" button on the left-side panel. +- Натисніть кнопку "Create a new project" у лівій панелі. -- Enter a project name, select Anchor as the framework, then click the "Create" - button. +- Введіть назву проєкту, виберіть Anchor як фреймворк, потім натисніть кнопку "Create". -![New Project](/assets/docs/intro/quickstart/pg-new-project.gif) +![Новий Проєкт](/assets/docs/intro/quickstart/pg-new-project.gif) -You'll see a new project created with the program code in the `src/lib.rs` file. +Ви побачите створений проєкт із кодом програми у файлі `src/lib.rs`. ```rust filename="lib.rs" use anchor_lang::prelude::*; @@ -70,18 +64,14 @@ pub struct NewAccount { +На даний момент ми розглянемо лише загальний огляд коду програми: -For now, we'll only cover the high-level overview of the program code: - -- The `declare_id!` macro specifies the on-chain address of your program. It - will be automatically updated when we build the program in the next step. +- Макрос `declare_id!` визначає адресy вашої програми у блокчейні. Ця адреса буде автоматично оновлена, коли ми скомпілюємо програму на наступному етапі. ```rs declare_id!("11111111111111111111111111111111"); ``` - -- The `#[program]` macro annotates a module containing functions that represent - the program's instructions. +- Макрос `#[program]` позначає модуль, який містить функції, що представляють інструкції програми. ```rs #[program] @@ -94,24 +84,16 @@ For now, we'll only cover the high-level overview of the program code: } } ``` +У цьому прикладі інструкція `initialize` приймає два параметри: - In this example, the `initialize` instruction takes two parameters: - - 1. `ctx: Context` - Provides access to the accounts required for - this instruction, as specified in the `Initialize` struct. - 2. `data: u64` - An instruction parameter that will be passed in when the - instruction is invoked. +1. `ctx: Context` — надає доступ до акаунтів, необхідних для цієї інструкції, як це зазначено у структурі `Initialize`. +2. `data: u64` — параметр інструкції, який передається під час виклику інструкції. - The function body sets the `data` field of `new_account` to the provided - `data` argument and then prints a message to the program logs. +Тіло функції встановлює значення поля `data` для `new_account` відповідно до переданого аргументу `data`, а потім виводить повідомлення до журналу програми. -- The `#[derive(Accounts)]` macro is used to define a struct that specifies the - accounts required for a particular instruction, where each field represents a - separate account. +- Макрос `#[derive(Accounts)]` використовується для визначення структури, яка задає акаунти, необхідні для певної інструкції, де кожне поле представляє окремий акаунт. - The field types (ex. `Signer<'info>`) and constraints (ex. `#[account(mut)]`) - are used by Anchor to automatically handle common security checks related to - account validation. +Типи полів (наприклад, `Signer<'info>`) і обмеження (наприклад, `#[account(mut)]`) використовуються Anchor для автоматичного виконання стандартних перевірок безпеки, пов'язаних із валідацією акаунтів. ```rs #[derive(Accounts)] @@ -123,9 +105,7 @@ For now, we'll only cover the high-level overview of the program code: pub system_program: Program<'info, System>, } ``` - -- The `#[account]` macro is used to define a struct that represents the data - structure of an account created and owned by the program. +- Макрос `#[account]` використовується для визначення структури, яка представляє структуру даних акаунта, створеного та керованого програмою. ```rs #[account] @@ -137,16 +117,14 @@ For now, we'll only cover the high-level overview of the program code: -### Build and Deploy Program +### Скомпілюйте та Розгорніть Програму -To build the program, simply run `build` in the terminal. +Щоб скомпілювати програму, просто виконайте команду `build` у терміналі. ```shell filename="Terminal" build ``` - -Notice that the address in `declare_id!()` has been updated. This is your -program's on-chain address. +Зверніть увагу, що адреса у `declare_id!()` була оновлена. Це адреса вашої програми у блокчейні. @@ -159,14 +137,9 @@ Build successful. Completed in 1.46s. +Після компіляції програми виконайте команду `deploy` у терміналі, щоб розгорнути програму в мережі (за замовчуванням devnet). Для розгортання програми необхідно виділити SOL для акаунта у блокчейні, який зберігатиме програму. -Once the program is built, run `deploy` in the terminal to deploy the program to -the network (devnet by default). To deploy a program, SOL must be allocated to -the on-chain account that stores the program. - -Before deployment, ensure you have enough SOL. You can get devnet SOL by either -running `solana airdrop 5` in the Playground terminal or using the -[Web Faucet](https://faucet.solana.com/). +Перед розгортанням переконайтеся, що у вас достатньо SOL. Ви можете отримати devnet SOL, виконавши команду `solana airdrop 5` у терміналі Playground або скориставшись [веб-фонтаном](https://faucet.solana.com/). ```shell filename="Terminal" deploy @@ -185,18 +158,15 @@ Deployment successful. Completed in 19s. -Alternatively, you can also use the `Build` and `Deploy` buttons on the -left-side panel. +Альтернативно, ви також можете скористатися кнопками `Build` і `Deploy` на лівій панелі. ![Build and Deploy](/assets/docs/intro/quickstart/pg-build-deploy.png) -Once the program is deployed, you can now invoke its instructions. +Після розгортання програми ви можете викликати її інструкції. -### Test Program +### Тестування Програми -Included with the starter code is a test file found in `tests/anchor.test.ts`. -This file demonstrates how to invoke the `initialize` instruction on the starter -program from the client. +Разом із стартовим кодом включений тестовий файл, який знаходиться у `tests/anchor.test.ts`. У цьому файлі показано, як викликати інструкцію `initialize` у стартовій програмі з клієнта. ```ts filename="anchor.test.ts" // No imports needed: web3, anchor, pg and more are globally available @@ -234,14 +204,12 @@ describe("Test", () => { }); }); ``` - -To run the test file once the program is deployed, run `test` in the terminal. +Щоб запустити тестовий файл після розгортання програми, виконайте команду `test` у терміналі. ```shell filename="Terminal" test ``` - -You should see an output indicating that the test passed successfully. +Ви повинні побачити результат, який вказує, що тест пройшов успішно. @@ -259,19 +227,17 @@ Running tests... - -You can also use the `Test` button on the left-side panel. +Ви також можете скористатися кнопкою `Test` на лівій панелі. ![Run Test](/assets/docs/intro/quickstart/pg-test.png) -You can then view the transaction logs by running the `solana confirm -v` -command and specifying the transaction hash (signature) from the test output: +Потім ви можете переглянути журнали транзакцій, виконавши команду `solana confirm -v` та вказавши хеш транзакції (підпис) із результатів тесту: ```shell filename="Terminal" solana confirm -v [TxHash] ``` -For example: +Наприклад: ```shell filename="Terminal" solana confirm -v 3TewJtiUz1EgtT88pLJHvKFzqrzDNuHVi8CfD2mWmHEBAaMfC5NAaHdmr19qQYfTiBace6XUmADvR4Qrhe8gH5uc @@ -323,29 +289,23 @@ Confirmed -Alternatively, you can view the transaction details on -[SolanaFM](https://solana.fm/) or -[Solana Explorer](https://explorer.solana.com/?cluster=devnet) by searching for -the transaction signature (hash). +Альтернативно, ви можете переглянути деталі транзакції на [SolanaFM](https://solana.fm/) або [Solana Explorer](https://explorer.solana.com/?cluster=devnet), здійснивши пошук за підписом (хешем) транзакції. - Reminder to update the cluster (network) connection on the Explorer you are - using to match Solana Playground. Solana Playground's default cluster is devnet. + Нагадуємо, що потрібно оновити підключення до кластеру (мережі) у вибраному Explorer, щоб воно відповідало кластеру Solana Playground. За замовчуванням у Solana Playground використовується кластер devnet. -### Close Program +### Закриття Програми -Lastly, the SOL allocated to the on-chain program can be fully recovered by -closing the program. +Нарешті, SOL, виділений для програми у блокчейні, може бути повністю повернутий шляхом закриття програми. -You can close a program by running the following command and specifying the -program address found in `declare_id!()`: +Ви можете закрити програму, виконавши наступну команду та вказавши адресу програми, яка знаходиться у `declare_id!()`: ```shell filename="Terminal" solana program close [ProgramID] ``` -For example: +Наприклад: ```shell filename="Terminal" solana program close 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r @@ -362,18 +322,14 @@ Closed Program Id 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r, 2.79511512 SOL r -Only the upgrade authority of the program can close it. The upgrade authority is -set when the program is deployed, and it's the only account with permission to -modify or close the program. If the upgrade authority is revoked, then the -program becomes immutable and can never be closed or upgraded. +Тільки орган влади оновлення програми може її закрити. Орган влади оновлення встановлюється під час розгортання програми, і це єдиний акаунт, який має дозвіл модифікувати або закривати програму. Якщо орган влади оновлення відкликається, програма стає незмінною і її ніколи не можна буде закрити або оновити. -When deploying programs on Solana Playground, your Playground wallet is the -upgrade authority for all your programs. +Під час розгортання програм у Solana Playground гаманцем Playground є орган влади оновлення для всіх ваших програм. -Congratulations! You've just built and deployed your first Solana program using -the Anchor framework! +Вітаємо! Ви щойно створили та розгорнули свою першу програму Solana за допомогою фреймворку Anchor! + diff --git a/docs/uk/intro/quick-start/index.md b/docs/uk/intro/quick-start/index.md index b582d3258..1a164ae56 100644 --- a/docs/uk/intro/quick-start/index.md +++ b/docs/uk/intro/quick-start/index.md @@ -1,118 +1,92 @@ --- -sidebarLabel: Quick Start -title: Solana Quick Start Guide +sidebarLabel: Швидкий Старт +title: Посібник з Швидкого Старту Solana sidebarSortOrder: 0 description: - Learn Solana development basics. Create your first program, understand - accounts, send transactions, and explore PDAs and CPIs using Solana Playground - - no installation required. + Вивчіть основи розробки на Solana. Створіть свою першу програму, дізнайтеся + про акаунти, надсилайте транзакції та досліджуйте PDA та CPI за допомогою + Solana Playground – без необхідності встановлення. --- -Welcome to the Solana Quick Start Guide! This hands-on guide will introduce you -to the core concepts for building on Solana, regardless of your prior -experience. By the end of this tutorial, you'll have a basic foundation in -Solana development and be ready to explore more advanced topics. +Ласкаво просимо до посібника з швидкого старту Solana! Цей практичний посібник ознайомить вас із ключовими концепціями створення програм на Solana, незалежно від вашого попереднього досвіду. Після завершення цього уроку у вас буде базове розуміння розробки на Solana, і ви зможете досліджувати більш складні теми. -## What You'll Learn +## Чого Ви Навчитеся -In this tutorial, you'll learn about: +У цьому уроці ви дізнаєтеся про: -- Understanding Accounts: Explore how data is stored on the Solana network. -- Sending Transactions: Learn to interact with the Solana network by sending - transactions. -- Building and Deploying Programs: Create your first Solana program and deploy - it to the network. -- Program Derived Addresses (PDAs): Learn how to use PDAs to create - deterministic addresses for accounts. -- Cross-Program Invocations (CPIs): Learn how to make your programs interact - with other programs on Solana. +- **Розуміння акаунтів**: Дослідження зберігання даних у мережі Solana. +- **Надсилання транзакцій**: Взаємодія з мережею Solana шляхом надсилання транзакцій. +- **Створення та розгортання програм**: Створіть свою першу програму Solana та розгорніть її в мережі. +- **Program Derived Addresses (PDA)**: Як використовувати PDA для створення детермінованих адрес акаунтів. +- **Cross-Program Invocations (CPI)**: Як зробити так, щоб ваші програми взаємодіяли з іншими програмами на Solana. -The best part? You don't need to install anything! We'll be using Solana -Playground, a browser-based development environment, for all our examples. This -means you can follow along, copy and paste code, and see results immediately, -all from your web browser. Basic programming knowledge is helpful but not -required. +Найкраще те, що вам нічого не потрібно встановлювати! Ми будемо використовувати Solana Playground, браузерне середовище розробки, для всіх наших прикладів. Це означає, що ви можете слідувати урокам, копіювати та вставляти код і одразу бачити результати прямо у вашому браузері. Базові знання програмування бажані, але не обов’язкові. -Let's dive in and start building on Solana! +Давайте почнемо будувати на Solana! ## Solana Playground -Solana Playground (Solpg) is a browser-based development environment that allows -you to quickly develop, deploy, and test Solana programs! +Solana Playground (Solpg) – це браузерне середовище розробки, яке дозволяє швидко розробляти, розгортати та тестувати програми Solana! -Open a new tab in your web browser and navigate to https://beta.solpg.io/. +Відкрийте нову вкладку у своєму браузері та перейдіть на [https://beta.solpg.io/](https://beta.solpg.io/). -### Create Playground Wallet +### Створення Гаманця Playground -If you're new to Solana Playground, the first step is to create your Playground -Wallet. This wallet will allow you to interact with the Solana network right -from your browser. +Якщо ви новачок у Solana Playground, першим кроком буде створення гаманця Playground. Цей гаманець дозволить вам взаємодіяти з мережею Solana безпосередньо з вашого браузера. -#### Step 1. Connect to Playground +#### Крок 1. Підключіться до Playground -Click the "Not connected" button at the bottom left of the screen. +Натисніть кнопку "Not connected" у нижньому лівому куті екрана. ![Not Connected](/assets/docs/intro/quickstart/pg-not-connected.png) -#### Step 2. Create Your Wallet +#### Крок 2. Створіть Свій Гаманець -You'll see an option to save your wallet's keypair. Optionally, save your -wallet's keypair for backup and then click "Continue". +Вам буде запропоновано зберегти ключову пару вашого гаманця. За бажанням збережіть ключову пару для резервної копії, а потім натисніть "Continue". ![Create Playground Wallet](/assets/docs/intro/quickstart/pg-create-wallet.png) -You should now see your wallet's address, SOL balance, and connected cluster -(devnet by default) at the bottom of the window. +Тепер ви повинні побачити адресу вашого гаманця, баланс SOL і підключений кластер (за замовчуванням devnet) у нижній частині вікна. ![Connected](/assets/docs/intro/quickstart/pg-connected.png) - Your Playground Wallet will be saved in your browser's local storage. Clearing - your browser cache will remove your saved wallet. + Ваш гаманець Playground зберігається у локальному сховищі вашого браузера. Очистка кешу браузера видалить ваш збережений гаманець. -Some definitions you may find helpful: +Декілька корисних визначень: -- _wallet address_: a unique identifier for a digital wallet, used to send or - receive crypto assets on a blockchain. Each wallet address is a string of - alphanumeric characters that represents a specific destination on the network. - Think of it like an email address or bank account number—if someone wants to - send you cryptocurrency, they need your wallet address to direct the funds. -- _connected cluster_: a set of network nodes that work together to maintain a - synchronized copy of the blockchain. These clusters are essential for - providing a decentralized, distributed ledger and powering the Solana network - by validating transactions, securing the chain, and executing programs (smart - contracts). +- **_адреса гаманця_**: Унікальний ідентифікатор цифрового гаманця, який використовується для надсилання або отримання криптоактивів у блокчейні. Це схоже на електронну адресу чи номер банківського рахунку – щоб хтось надіслав вам криптовалюту, йому потрібна ваша адреса гаманця. +- **_підключений кластер_**: Набір вузлів мережі, які працюють разом, щоб підтримувати синхронізовану копію блокчейна. Кластери важливі для надання децентралізованого розподіленого реєстру, перевірки транзакцій, забезпечення безпеки ланцюга та виконання програм (смарт-контрактів). -### Get Devnet SOL +### Отримання Devnet SOL -Before we start building, we first need some devnet SOL. +Перед тим як почати розробку, нам потрібен devnet SOL. -From a developer's perspective, SOL is required for two main use cases: +З точки зору розробника, SOL потрібен для двох основних цілей: -- To create accounts where we can store data or deploy programs -- To pay for transaction fees when we interact with the network +- Для створення акаунтів, де можна зберігати дані або розгортати програми +- Для сплати комісій за транзакції під час взаємодії з мережею -Below are two methods to fund your wallet with devnet SOL: +Нижче наведено два способи поповнити ваш гаманець devnet SOL: -#### Option 1: Using the Playground Terminal +#### Варіант 1: Використання Терміналу Playground + +Щоб поповнити ваш гаманець Playground devnet SOL, виконайте у терміналі Playground команду: -To fund your Playground wallet with devnet SOL. In the Playground terminal, run: ```shell filename="Terminal" solana airdrop 5 ``` -#### Option 2: Using the Devnet Faucet +#### Варіант 2: Використання Devnet Faucet -If the airdrop command doesn't work (due to rate limits or errors), you can use -the [Web Faucet](https://faucet.solana.com/). +Якщо команда airdrop не працює (через обмеження або помилки), скористайтеся [Web Faucet](https://faucet.solana.com/). -- Enter your wallet address (found at the bottom of the Playground screen) and - select an amount -- Click "Confirm Airdrop" to receive your devnet SOL +- Введіть адресу свого гаманця (знаходиться в нижній частині екрана Playground) і виберіть суму +- Натисніть "Confirm Airdrop", щоб отримати ваш devnet SOL ![Faucet Airdrop](/assets/docs/intro/quickstart/faucet-airdrop.gif) diff --git a/docs/uk/intro/quick-start/program-derived-address.md b/docs/uk/intro/quick-start/program-derived-address.md index 18a4886e5..e025756e1 100644 --- a/docs/uk/intro/quick-start/program-derived-address.md +++ b/docs/uk/intro/quick-start/program-derived-address.md @@ -1,41 +1,31 @@ --- sidebarLabel: Program Derived Address -title: Program Derived Address +title: Програма Derived Address sidebarSortOrder: 4 description: - Learn how to build a CRUD (Create, Read, Update, Delete) Solana program using - Program Derived Addresses (PDAs) and the Anchor framework. This step-by-step - guide demonstrates how to create, update, and delete on-chain message accounts - using PDAs, implement account validation, and write tests. Perfect for - developers looking to understand how to use PDAs in Solana programs. + Дізнайтеся, як створити CRUD (Create, Read, Update, Delete) програму Solana, + використовуючи Program Derived Addresses (PDAs) і фреймворк Anchor. Цей + покроковий посібник демонструє, як створювати, оновлювати та видаляти акаунти + повідомлень у блокчейні за допомогою PDAs, реалізувати валідацію акаунтів і + писати тести. Ідеально для розробників, які хочуть зрозуміти, як + використовувати PDAs у програмах Solana. --- -In this section, we'll walk through how to build a basic CRUD (Create, Read, -Update, Delete) program. The program will store a user's message using a Program -Derived Address (PDA) as the account's address. +У цьому розділі ми розглянемо, як створити базову CRUD (Create, Read, Update, Delete) програму. Програма зберігатиме повідомлення користувача, використовуючи Program Derived Address (PDA) як адресу акаунта. -The purpose of this section is to guide you through the steps for building and -testing a Solana program using the Anchor framework and demonstrating how to use -PDAs within a program. For more details, refer to the -[Programs Derived Address](/docs/core/pda) page. +Мета цього розділу – провести вас через етапи створення і тестування програми Solana, використовуючи фреймворк Anchor, і показати, як використовувати PDA у програмі. Для отримання додаткової інформації відвідайте сторінку [Programs Derived Address](/docs/uk/core/pda). -For reference, here is the -[final code](https://beta.solpg.io/668304cfcffcf4b13384d20a) after completing -both the PDA and CPI sections. +Для довідки ось [фінальний код](https://beta.solpg.io/668304cfcffcf4b13384d20a), завершений після розгляду розділів PDA і CPI. -### Starter Code +### Стартовий Код -Begin by opening this -[Solana Playground link](https://beta.solpg.io/66734b7bcffcf4b13384d1ad) with -the starter code. Then click the "Import" button, which will add the program to -your list of projects on Solana Playground. +Почніть, відкривши це [посилання на Solana Playground](https://beta.solpg.io/66734b7bcffcf4b13384d1ad) зі стартовим кодом. Потім натисніть кнопку "Import", щоб додати програму до вашого списку проєктів у Solana Playground. ![Import](/assets/docs/intro/quickstart/pg-import.png) -In the `lib.rs` file, you'll find a program scaffolded with the `create`, -`update`, and `delete` instructions we'll implement in the following steps. +У файлі `lib.rs` ви знайдете шаблон програми з інструкціями `create`, `update` і `delete`, які ми реалізуємо на наступних етапах. ```rs filename="lib.rs" use anchor_lang::prelude::*; @@ -71,9 +61,7 @@ pub struct Delete {} #[account] pub struct MessageAccount {} ``` - -Before we begin, run `build` in the Playground terminal to check the starter -program builds successfully. +Перед початком виконайте команду `build` у терміналі Playground, щоб переконатися, що стартова програма успішно компілюється. ```shell filename="Terminal" build @@ -91,12 +79,11 @@ Build successful. Completed in 3.50s. -### Define Message Account Type +### Визначення Типу Акаунта Повідомлення -First, let's define the structure for the message account that our program will -create. This is the data that we'll store in the account created by the program. +Спочатку визначимо структуру акаунта повідомлення, який створюватиме наша програма. Це дані, які ми зберігатимемо в акаунті, створеному програмою. -In `lib.rs`, update the `MessageAccount` struct with the following: +У файлі `lib.rs` оновіть структуру `MessageAccount` наступним кодом: ```rs filename="lib.rs" #[account] @@ -125,43 +112,33 @@ pub struct MessageAccount { -The `#[account]` macro in an Anchor program is used to annotate structs that -represent account data (data type to store in the AccountInfo's data field). +Макрос `#[account]` у програмі Anchor використовується для позначення структур, які представляють дані акаунта (тип даних, що зберігається у полі даних `AccountInfo`). + +У цьому прикладі ми визначаємо структуру `MessageAccount` для зберігання повідомлення, створеного користувачами, яка містить три поля: -In this example, we're defining a `MessageAccount` struct to store a message -created by users that contains three fields: +- `user` — `Pubkey`, який представляє користувача, що створив акаунт повідомлення. +- `message` — `String`, який містить повідомлення користувача. +- `bump` — `u8`, що зберігає ["bump" seed](/docs/uk/core/pda#canonical-bump), використаний для отримання адреси, створеної програмою (PDA). Зберігання цього значення економить обчислювальні ресурси, оскільки усуває необхідність повторного обчислення для кожного використання в наступних інструкціях. -- `user` - A Pubkey representing the user who created the message account. -- `message` - A String containing the user's message. -- `bump` - A u8 storing the ["bump" seed](/docs/core/pda#canonical-bump) used in - deriving the program derived address (PDA). Storing this value saves compute - by eliminating the need to rederive it for each use in subsequent - instructions. When an account is created, the `MessageAccount` data will be - serialized and stored in the new account's data field. +Коли акаунт створюється, дані `MessageAccount` будуть серіалізовані та збережені у полі даних нового акаунта. -Later, when reading from the account, this data can be deserialized back into -the `MessageAccount` data type. The process of creating and reading the account -data will be demonstrated in the testing section. +Пізніше, під час читання з акаунта, ці дані можна буде десеріалізувати назад у тип даних `MessageAccount`. Процес створення та читання даних акаунта буде продемонстровано у розділі тестування. -Build the program again by running `build` in the terminal. +Скомпілюйте програму знову, виконавши команду `build` у терміналі. ```shell filename="Terminal" build ``` +Ми визначили, як виглядатиме наш акаунт повідомлення. Далі ми реалізуємо інструкції програми. -We've defined what our message account will look like. Next, we'll implement the -program instructions. +### Реалізація Інструкції Create -### Implement Create Instruction +Тепер реалізуємо інструкцію `create` для створення та ініціалізації `MessageAccount`. -Now, let's implement the `create` instruction to create and initialize the -`MessageAccount`. - -Start by defining the accounts required for the instruction by updating the -`Create` struct with the following: +Почніть із визначення акаунтів, необхідних для цієї інструкції, оновивши структуру `Create` наступним кодом: ```rs filename="lib.rs" #[derive(Accounts)] @@ -209,81 +186,62 @@ pub struct Create<'info> { +Макрос `#[derive(Accounts)]` у програмі Anchor використовується для позначення структур, які представляють список акаунтів, необхідних для інструкції, де кожне поле в структурі є акаунтом. -The `#[derive(Accounts)]` macro in an Anchor program is used to annotate structs -that represent a list of accounts required by an instruction where each field in -the struct is an account. - -Each account (field) in the struct is annotated with an account type (ex. -`Signer<'info>`) and can be further annotated with constraints (ex. -`#[account(mut)]`). The account type along with account constraints are used to -perform security checks on the accounts passed to the instruction. +Кожен акаунт (поле) у структурі позначається типом акаунта (наприклад, `Signer<'info>`) і може бути додатково позначений обмеженнями (наприклад, `#[account(mut)]`). Тип акаунта разом із обмеженнями акаунта використовуються для виконання перевірок безпеки акаунтів, переданих до інструкції. -The naming of each field is only for our understanding and has no effect on -account validation, however, it is recommended to use descriptive account names. +Назви кожного поля використовуються лише для нашого розуміння і не впливають на валідацію акаунтів, однак рекомендується використовувати описові імена акаунтів. --- -The `Create` struct defines the accounts required for the `create` instruction. +Структура `Create` визначає акаунти, необхідні для інструкції `create`. 1. `user: Signer<'info>` - - Represents the user creating the message account - - Marked as mutable (`#[account(mut)]`) as it pays for the new account - - Must be a signer to approve the transaction, as lamports are deducted from - the account + - Представляє користувача, який створює акаунт повідомлення. + - Позначений як змінний (`#[account(mut)]`), оскільки оплачує створення нового акаунта. + - Повинен бути підписувачем, щоб підтвердити транзакцію, оскільки лампорти будуть списані з акаунта. 2. `message_account: Account<'info, MessageAccount>` - - The new account created to store the user's message - - `init` constraint indicates the account will be created in the instruction - - `seeds` and `bump` constraints indicate the address of the account is a - Program Derived Address (PDA) - - `payer = user` specifies the account paying for the creation of the new - account - - `space` specifies the number of bytes allocated to the new account's data - field + - Новий акаунт, створений для зберігання повідомлення користувача. + - Обмеження `init` вказує, що акаунт буде створено в інструкції. + - Обмеження `seeds` і `bump` вказують, що адреса акаунта є Program Derived Address (PDA). + - `payer = user` вказує акаунт, який оплачує створення нового акаунта. + - `space` вказує кількість байтів, виділених для поля даних нового акаунта. 3. `system_program: Program<'info, System>` - - Required for creating new accounts - - Under the hood, the `init` constraint invokes the System Program to create - a new account allocated with the specified `space` and reassigns the - program owner to the current program. + - Необхідна для створення нових акаунтів. + - На рівні механіки обмеження `init` викликає Системну програму для створення нового акаунта з виділенням вказаного `space` та переназначає власника програми на поточну програму. --- -The `#[instruction(message: String)]` annotation enables the `Create` struct to -access the `message` parameter from the `create` instruction. +Анотація `#[instruction(message: String)]` дозволяє структурі `Create` отримувати доступ до параметра `message` з інструкції `create`. --- -The `seeds` and `bump` constraints are used together to specify that an -account's address is a Program Derived Address (PDA). +Обмеження `seeds` і `bump` використовуються разом для вказівки, що адреса акаунта є Program Derived Address (PDA). ```rs filename="lib.rs" seeds = [b"message", user.key().as_ref()], bump, ``` +Обмеження `seeds` визначає необов’язкові вхідні значення, які використовуються для отримання PDA: -The `seeds` constraint defines the optional inputs used to derive the PDA. +- `b"message"` — Жорстко закодований рядок як перше значення seed. +- `user.key().as_ref()` — Публічний ключ акаунта `user` як друге значення seed. -- `b"message"` - A hardcoded string as the first seed. -- `user.key().as_ref()` - The public key of the `user` account as the second - seed. - -The `bump` constraint tells Anchor to automatically find and use the correct -bump seed. Anchor will use the `seeds` and `bump` to derive the PDA. +Обмеження `bump` вказує Anchor автоматично знайти та використовувати правильний bump seed. Anchor використовує `seeds` і `bump` для отримання PDA. --- -The `space` calculation (8 + 32 + 4 + message.len() + 1) allocates space for -`MessageAccount` data type: +Розрахунок `space` (8 + 32 + 4 + message.len() + 1) виділяє простір для даних типу `MessageAccount`: -- Anchor Account discriminator (identifier): 8 bytes -- User Address (Pubkey): 32 bytes -- User Message (String): 4 bytes for length + variable message length -- PDA Bump seed (u8): 1 byte +- Дискримінатор акаунта Anchor (ідентифікатор): 8 байтів +- Адреса користувача (Pubkey): 32 байти +- Повідомлення користувача (String): 4 байти для довжини + змінна довжина повідомлення +- Bump seed для PDA (u8): 1 байт ```rs filename="lib.rs" #[account] @@ -293,19 +251,14 @@ pub struct MessageAccount { pub bump: u8, } ``` +Усі акаунти, створені за допомогою програми Anchor, вимагають 8 байтів для дискримінатора акаунта, який є ідентифікатором типу акаунта і генерується автоматично під час створення акаунта. -All accounts created through an Anchor program require 8 bytes for an account -discriminator, which is an identifier for the account type that is automatically -generated when the account is created. - -A `String` type requires 4 bytes to store the length of the string, and the -remaining length is the actual data. +Тип `String` вимагає 4 байти для зберігання довжини рядка, а решта — це фактичні дані. -Next, implement the business logic for the `create` instruction by updating the -`create` function with the following: +Далі реалізуйте бізнес-логіку для інструкції `create`, оновивши функцію `create` наступним кодом: ```rs filename="lib.rs" pub fn create(ctx: Context, message: String) -> Result<()> { @@ -339,43 +292,37 @@ pub fn create(ctx: Context, message: String) -> Result<()> { -The `create` function implements the logic for initializing a new message -account's data. It takes two parameters: +Функція `create` реалізує логіку для ініціалізації даних нового акаунта повідомлення. Вона приймає два параметри: -1. `ctx: Context` - Provides access to the accounts specified in the - `Create` struct. -2. `message: String` - The user's message to be stored. +1. `ctx: Context` — Надає доступ до акаунтів, зазначених у структурі `Create`. +2. `message: String` — Повідомлення користувача, яке буде збережено. -The body of the function then performs the following logic: +Тіло функції виконує наступну логіку: -1. Print a message to program logs using the `msg!()` macro. +1. Виводить повідомлення у журнали програми за допомогою макроса `msg!()`. ```rs msg!("Create Message: {}", message); ``` +2. Ініціалізація Даних Акаунта: -2. Initializing Account Data: - - - Accesses the `message_account` from the context. - + - Отримує доступ до `message_account` з контексту. + ```rs let account_data = &mut ctx.accounts.message_account; ``` - - - Sets the `user` field to the public key of the `user` account. - + - Встановлює поле `user` як публічний ключ акаунта `user`. + ```rs account_data.user = ctx.accounts.user.key(); ``` - - Sets the `message` field to the `message` from the function argument. + - Встановлює поле `message` значенням аргумента `message` функції. ```rs account_data.message = message; ``` - - - Sets the `bump` value used to derive the PDA, retrieved from - `ctx.bumps.message_account`. + - Встановлює значення `bump`, використане для отримання PDA, отримане з `ctx.bumps.message_account`. ```rs account_data.bump = ctx.bumps.message_account; @@ -384,21 +331,18 @@ The body of the function then performs the following logic: -Rebuild the program. +Перекомпілюйте програму. ```shell filename="Terminal" build ``` +### Реалізація Інструкції Update -### Implement Update Instruction - -Next, implement the `update` instruction to update the `MessageAccount` with a -new message. +Далі реалізуйте інструкцію `update` для оновлення `MessageAccount` новим повідомленням. -Just as before, the first step is to specify the accounts required by the -`update` instruction. +Як і раніше, першим кроком є визначення акаунтів, необхідних для інструкції `update`. -Update the `Update` struct with the following: +Оновіть структуру `Update` наступним кодом: ```rs filename="lib.rs" #[derive(Accounts)] @@ -448,42 +392,38 @@ pub struct Update<'info> { - -The `Update` struct defines the accounts required for the `update` instruction. +Структура `Update` визначає акаунти, необхідні для інструкції `update`. 1. `user: Signer<'info>` - - Represents the user updating the message account - - Marked as mutable (`#[account(mut)]`) as it may pay for additional space - for the `message_account` if needed - - Must be a signer to approve the transaction + - Представляє користувача, який оновлює акаунт повідомлення. + - Позначений як змінний (`#[account(mut)]`), оскільки може оплачувати додатковий простір для `message_account`, якщо це необхідно. + - Повинен бути підписувачем для підтвердження транзакції. 2. `message_account: Account<'info, MessageAccount>` - - The existing account storing the user's message that will be updated - - `mut` constraint indicates this account's data will be modified - - `realloc` constraint allows for resizing the account's data - - `seeds` and `bump` constraints ensure the account is the correct PDA + - Існуючий акаунт, який зберігає повідомлення користувача і буде оновлений. + - Обмеження `mut` вказує, що дані цього акаунта будуть змінені. + - Обмеження `realloc` дозволяє змінювати розмір даних акаунта. + - Обмеження `seeds` і `bump` гарантують, що акаунт є правильним PDA. 3. `system_program: Program<'info, System>` - - Required for potential reallocation of account space - - The `realloc` constraint invokes the System Program to adjust the account's - data size + + - Необхідна для можливої зміни розміру простору акаунта. + - Обмеження `realloc` викликає Системну програму для налаштування розміру даних акаунта. --- -Note that the `bump = message_account.bump` constraint uses the bump seed stored -on the `message_account`, rather than having Anchor recalculate it. +Зверніть увагу, що обмеження `bump = message_account.bump` використовує bump seed, який зберігається в `message_account`, замість того, щоб Anchor обчислював його знову. --- -`#[instruction(message: String)]` annotation enables the `Update` struct to -access the `message` parameter from the `update` instruction. +Анотація `#[instruction(message: String)]` дозволяє структурі `Update` отримувати доступ до параметра `message` з інструкції `update`. -Next, implement the logic for the `update` instruction. +Далі реалізуйте логіку для інструкції `update`. ```rs filename="lib.rs" pub fn update(ctx: Context, message: String) -> Result<()> { @@ -512,36 +452,32 @@ pub fn update(ctx: Context, message: String) -> Result<()> { +Функція `update` реалізує логіку для модифікації існуючого акаунта повідомлення. Вона приймає два параметри: -The `update` function implements the logic for modifying an existing message -account. It takes two parameters: +1. `ctx: Context` — Надає доступ до акаунтів, зазначених у структурі `Update`. +2. `message: String` — Нове повідомлення, яке замінить існуюче. -1. `ctx: Context` - Provides access to the accounts specified in the - `Update` struct. -2. `message: String` - The new message to replace the existing one. +Тіло функції виконує такі дії: -The body of the function then: +1. Виводить повідомлення у журнали програми за допомогою макроса `msg!()`. -1. Print a message to program logs using the `msg!()` macro. - -2. Updates Account Data: - - Accesses the `message_account` from the context. - - Sets the `message` field to the new `message` from the function argument. +2. Оновлює Дані Акаунта: + - Отримує доступ до `message_account` з контексту. + - Встановлює поле `message` як нове значення `message` із аргумента функції. -Rebuild the program +Перекомпілюйте програму. ```shell filename="Terminal" build ``` +### Реалізація Інструкції Delete -### Implement Delete Instruction - -Next, implement the `delete` instruction to close the `MessageAccount`. +Далі реалізуйте інструкцію `delete` для закриття `MessageAccount`. -Update the `Delete` struct with the following: +Оновіть структуру `Delete` наступним кодом: ```rs filename="lib.rs" #[derive(Accounts)] @@ -584,28 +520,25 @@ pub struct Delete<'info> { -The `Delete` struct defines the accounts required for the `delete` instruction: +Структура `Delete` визначає акаунти, необхідні для інструкції `delete`: 1. `user: Signer<'info>` - - Represents the user closing the message account - - Marked as mutable (`#[account(mut)]`) as it will receive the lamports from - the closed account - - Must be a signer to ensure only the correct user can close their message - account + - Представляє користувача, який закриває акаунт повідомлення. + - Позначений як змінний (`#[account(mut)]`), оскільки він отримуватиме лампорти з закритого акаунта. + - Повинен бути підписувачем, щоб гарантувати, що тільки відповідний користувач може закрити свій акаунт повідомлення. 2. `message_account: Account<'info, MessageAccount>` - - The account being closed - - `mut` constraint indicates this account will be modified - - `seeds` and `bump` constraints ensure the account is the correct PDA - - `close = user` constraint specifies that this account will be closed and - its lamports transferred to the `user` account + - Акаунт, який буде закритий. + - Обмеження `mut` вказує, що цей акаунт буде змінено. + - Обмеження `seeds` і `bump` гарантують, що акаунт є правильним PDA. + - Обмеження `close = user` вказує, що цей акаунт буде закритий, а його лампорти передані в акаунт `user`. -Next, implement the logic for the `delete` instruction. +Далі реалізуйте логіку для інструкції `delete`. ```rs filename="lib.rs" pub fn delete(_ctx: Context) -> Result<()> { @@ -631,30 +564,24 @@ pub fn delete(_ctx: Context) -> Result<()> { -The `delete` function takes one parameter: +Функція `delete` приймає один параметр: -1. `_ctx: Context` - Provides access to the accounts specified in the - `Delete` struct. The `_ctx` syntax indicates we won't be using the Context in - the body of the function. +1. `_ctx: Context` — Надає доступ до акаунтів, зазначених у структурі `Delete`. Використання `_ctx` вказує, що контекст не буде використовуватися в тілі функції. -The body of the function only prints a message to program logs using the -`msg!()` macro. The function does not require any additional logic because the -actual closing of the account is handled by the `close` constraint in the -`Delete` struct. +Тіло функції лише виводить повідомлення у журнали програми за допомогою макроса `msg!()`. Додаткова логіка не потрібна, оскільки фактичне закриття акаунта виконується за допомогою обмеження `close` у структурі `Delete`. -Rebuild the program. +Перекомпілюйте програму. ```shell filename="Terminal" build ``` -### Deploy Program +### Розгортання Програми -The basic CRUD program is now complete. Deploy the program by running `deploy` -in the Playground terminal. +Базова CRUD-програма завершена. Розгорніть програму, виконавши команду `deploy` у терміналі Playground. ```shell filename="Terminal" deploy @@ -672,9 +599,9 @@ Deployment successful. Completed in 17s. -### Set Up Test File +### Налаштування Тестового Файлу -Included with the starter code is also a test file in `anchor.test.ts`. +Разом зі стартовим кодом також включений тестовий файл у `anchor.test.ts`. ```ts filename="anchor.test.ts" import { PublicKey } from "@solana/web3.js"; @@ -687,8 +614,7 @@ describe("pda", () => { it("Delete Message Account", async () => {}); }); ``` - -Add the code below inside `describe`, but before the `it` sections. +Додайте наведений нижче код всередину блоку `describe`, але перед секціями `it`. ```ts filename="anchor.test.ts" const program = pg.program; @@ -726,19 +652,17 @@ const [messagePda, messageBump] = PublicKey.findProgramAddressSync( -In this section, we are simply setting up the test file. +У цьому розділі ми просто налаштовуємо тестовий файл. -Solana Playground removes some boilerplate setup where `pg.program` allows us to -access the client library for interacting with the program, while `pg.wallet` is -your playground wallet. +Solana Playground спрощує початкову підготовку: `pg.program` дозволяє отримати доступ до клієнтської бібліотеки для взаємодії з програмою, а `pg.wallet` представляє ваш гаманець у Playground. ```ts filename="anchor.test.ts" const program = pg.program; const wallet = pg.wallet; ``` -As part of the setup, we derive the message account PDA. This demonstrates how -to derive the PDA in Javascript using the seeds specified in the program. +У рамках налаштування ми отримуємо PDA акаунта повідомлення. Це демонструє, як отримати PDA у Javascript, використовуючи сіди, визначені у програмі. + ```ts filename="anchor.test.ts" const [messagePda, messageBump] = PublicKey.findProgramAddressSync( @@ -750,8 +674,8 @@ const [messagePda, messageBump] = PublicKey.findProgramAddressSync( -Run the test file by running `test` in the Playground terminal to check the file -runs as expected. We will implement the tests in the following steps. +Запустіть тестовий файл, виконавши команду `test` у терміналі Playground, щоб переконатися, що файл працює, як очікувалося. Ми реалізуємо тести на наступних етапах. + ```shell filename="Terminal" test @@ -774,9 +698,10 @@ Running tests... -### Invoke Create Instruction +### Виклик Інструкції Create + +Оновіть перший тест наступним кодом: -Update the first test with the following: ```ts filename="anchor.test.ts" it("Create Message Account", async () => { @@ -832,8 +757,8 @@ it("Create Message Account", async () => { -First, we send a transaction that invokes the `create` instruction, passing in -"Hello, World!" as the message. +Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `create`, передаючи "Hello, World!" як повідомлення. + ```ts filename="anchor.test.ts" const message = "Hello, World!"; @@ -845,8 +770,8 @@ const transactionSignature = await program.methods .rpc({ commitment: "confirmed" }); ``` -Once the transaction is sent and the account is created, we then fetch the -account using its address (`messagePda`). +Після надсилання транзакції та створення акаунта ми отримуємо акаунт за його адресою (`messagePda`). + ```ts filename="anchor.test.ts" const messageAccount = await program.account.messageAccount.fetch( @@ -855,7 +780,8 @@ const messageAccount = await program.account.messageAccount.fetch( ); ``` -Lastly, we log the account data and a link to view the transaction details. +Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей транзакції. + ```ts filename="anchor.test.ts" console.log(JSON.stringify(messageAccount, null, 2)); @@ -868,9 +794,10 @@ console.log( -### Invoke Update Instruction +### Виклик Інструкції Update + +Оновіть другий тест наступним кодом: -Update the second test with the following: ```ts filename="anchor.test.ts" it("Update Message Account", async () => { @@ -926,8 +853,8 @@ it("Update Message Account", async () => { -First, we send a transaction that invokes the `update` instruction, passing in -"Hello, Solana!" as the new message. +Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `update`, передаючи "Hello, Solana!" як нове повідомлення. + ```ts filename="anchor.test.ts" const message = "Hello, Solana!"; @@ -939,8 +866,7 @@ const transactionSignature = await program.methods .rpc({ commitment: "confirmed" }); ``` -Once the transaction is sent and the account is updated, we then fetch the -account using its address (`messagePda`). +Після надсилання транзакції та оновлення акаунта ми отримуємо акаунт за його адресою (`messagePda`). ```ts filename="anchor.test.ts" const messageAccount = await program.account.messageAccount.fetch( @@ -949,7 +875,8 @@ const messageAccount = await program.account.messageAccount.fetch( ); ``` -Lastly, we log the account data and a link to view the transaction details. +Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей транзакції. + ```ts filename="anchor.test.ts" console.log(JSON.stringify(messageAccount, null, 2)); @@ -962,9 +889,10 @@ console.log( -### Invoke Delete Instruction +### Виклик Інструкції Delete + +Оновіть третій тест наступним кодом: -Update the third test with the following: ```ts filename="anchor.test.ts" it("Delete Message Account", async () => { @@ -1018,8 +946,8 @@ it("Delete Message Account", async () => { -First, we send a transaction that invokes the `delete` instruction to close the -message account. +Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `delete` для закриття акаунта повідомлення. + ```ts filename="anchor.test.ts" const transactionSignature = await program.methods @@ -1030,9 +958,8 @@ const transactionSignature = await program.methods .rpc({ commitment: "confirmed" }); ``` -Once the transaction is sent and the account is closed, we attempt to fetch the -account using its address (`messagePda`) using `fetchNullable` since we expect -the return value to be null because the account is closed. +Після надсилання транзакції та закриття акаунта ми намагаємося отримати акаунт за його адресою (`messagePda`), використовуючи `fetchNullable`, оскільки ми очікуємо, що результат буде `null`, тому що акаунт закритий. + ```ts filename="anchor.test.ts" const messageAccount = await program.account.messageAccount.fetchNullable( @@ -1041,8 +968,8 @@ const messageAccount = await program.account.messageAccount.fetchNullable( ); ``` -Lastly, we log the account data and a link to view the transaction details where -the account data should be logged as null. +Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей транзакції, де дані акаунта повинні бути відображені як `null`. + ```ts filename="anchor.test.ts" console.log(JSON.stringify(messageAccount, null, 2)); @@ -1055,10 +982,10 @@ console.log( -### Run Test +### Запуск Тестів + +Після налаштування тестів запустіть тестовий файл, виконавши команду `test` у терміналі Playground. -Once the tests are set up, run the test file by running `test` in the Playground -terminal. ```shell filename="Terminal" test diff --git a/docs/uk/intro/quick-start/reading-from-network.md b/docs/uk/intro/quick-start/reading-from-network.md index e65d0abdb..1403a31ef 100644 --- a/docs/uk/intro/quick-start/reading-from-network.md +++ b/docs/uk/intro/quick-start/reading-from-network.md @@ -1,50 +1,36 @@ --- -sidebarLabel: Reading from Network -title: Reading from Network +sidebarLabel: Читання з Мережі +title: Читання з Мережі sidebarSortOrder: 1 description: - Learn how to read data from the Solana blockchain network. This guide covers - fetching wallet accounts, program accounts, and token mint accounts using - JavaScript/TypeScript, with practical examples using the Solana web3.js - library. + Дізнайтеся, як зчитувати дані з блокчейн-мережі Solana. Цей посібник охоплює + отримання акаунтів гаманців, програмних акаунтів і акаунтів випуску токенів + за допомогою JavaScript/TypeScript із практичними прикладами на основі + бібліотеки Solana web3.js. --- -Now, let's explore how to read data from the Solana network. We'll fetch a few -different accounts to understand the structure of a Solana account. +Давайте розглянемо, як зчитувати дані з мережі Solana. Ми отримаємо кілька різних акаунтів, щоб зрозуміти структуру акаунта Solana. -On Solana, all data is contained in what we call "accounts". You can think of -data on Solana as a public database with a single "Accounts" table, where each -entry in this table is an individual account. +У Solana всі дані містяться у так званих "акаунтах". Ви можете думати про дані в Solana як про загальнодоступну базу даних із єдиною таблицею "Accounts", де кожен запис у цій таблиці є окремим акаунтом. -Accounts on Solana can store "state" or "executable" programs, all of which can -be thought of as entries in the same "Accounts" table. Each account has an -"address" (public key) that serves as its unique ID used to locate its -corresponding on-chain data. +Акаунти Solana можуть містити "стан" або виконувані програми, які можна розглядати як записи в одній таблиці "Accounts". Кожен акаунт має "адресу" (публічний ключ), яка є унікальним ідентифікатором для доступу до відповідних даних у блокчейні. -Solana accounts contain either: +Акаунти Solana можуть містити: -- State: This is data that's meant to be read from and persisted. It could be - information about tokens, user data, or any other type of data defined within - a program. -- Executable Programs: These are accounts that contain the actual code of Solana - programs. They contain the instructions that can be executed on the network. +- **Стан**: Дані, які призначені для зчитування і зберігання. Це може бути інформація про токени, дані користувачів або будь-які інші дані, визначені у програмі. +- **Виконувані програми**: Акаунти, які містять фактичний код програм Solana. Вони включають інструкції, які можна виконувати у мережі. -This separation of program code and program state is a key feature of Solana's -Account Model. For more details, refer to the -[Solana Account Model](/docs/core/accounts) page. +Цей поділ програмного коду та стану програми є ключовою особливістю Моделі Акаунтів Solana. Для отримання додаткової інформації відвідайте сторінку [Модель Акаунтів Solana](/docs/uk/core/accounts). -## Fetch Playground Wallet +## Отримання Гаманця Playground -Let's start by looking at a familiar account - your own Playground Wallet! We'll -fetch this account and examine its structure to understand what a basic Solana -account looks like. +Почнемо з розгляду знайомого акаунта — вашого власного гаманця Playground! Ми отримаємо цей акаунт і розглянемо його структуру, щоб зрозуміти, як виглядає базовий акаунт Solana. -### Open Example 1 +### Відкриття Прикладу 1 -Click this [link](https://beta.solpg.io/6671c5e5cffcf4b13384d198) to open the -example in Solana Playground. You'll see this code: +Натисніть це [посилання](https://beta.solpg.io/6671c5e5cffcf4b13384d198), щоб відкрити приклад у Solana Playground. Ви побачите такий код: ```ts filename="client.ts" const address = pg.wallet.publicKey; @@ -56,21 +42,21 @@ console.log(JSON.stringify(accountInfo, null, 2)); -This code does three simple things: +Цей код виконує три прості дії: -- Gets your Playground wallet's address +- Отримує адресу вашого гаманця Playground: ```ts const address = pg.wallet.publicKey; ``` -- Fetches the `AccountInfo` for the account at that address +- Отримує `AccountInfo` для акаунта за цією адресою: ```ts const accountInfo = await pg.connection.getAccountInfo(address); ``` -- Prints out the `AccountInfo` to the Playground terminal +- Виводить `AccountInfo` у термінал Playground: ```ts console.log(JSON.stringify(accountInfo, null, 2)); @@ -79,16 +65,15 @@ This code does three simple things: -### Run Example 1 +### Запуск Прикладу 1 -In the Playground terminal, type the `run` command and hit enter: +У терміналі Playground введіть команду `run` і натисніть Enter: ```shell filename="Terminal" run ``` -You should see details about your wallet account, including its balance in -lamports, with output similar to the following: +Ви повинні побачити деталі вашого акаунта гаманця, включаючи його баланс у лампортах, із результатом, схожим на наступний: @@ -113,55 +98,38 @@ Running client... -Your wallet is actually just an account owned by the System Program, where the -main purpose of the wallet account is to store your SOL balance (amount in the -`lamports` field). +Ваш гаманець насправді є лише акаунтом, яким керує Системна програма. Основна мета акаунта гаманця — зберігати баланс SOL (значення у полі `lamports`). --- -At its core, all Solana accounts are represented in a standard format called the -`AccountInfo`. The -[AccountInfo](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/account_info.rs#L19-L36) -data type is the base data structure for all Solana Accounts. - -Let's break down the fields in the output: - -- `data` - This field contains what we generally refer to as the account "data". - For a wallet, it's empty (0 bytes), but other accounts use this field to store - any arbitrary data as a serialized buffer of bytes. - -> When data is "buffered" in this way, it maintains its integrity and can be -> later deserialized back into its original form for use in applications. This -> process is widely used in blockchain for efficient data handling. - -- `executable` - A flag that indicates whether the account is an executable - program. For wallets and any accounts that store state, this is `false`. -- `owner` - This field shows which program controls the account. For wallets, - it's always the System Program, with the address - `11111111111111111111111111111111`. -- `lamports` - The account's balance in lamports (1 SOL = 1,000,000,000 - lamports). -- `rentEpoch` - A legacy field related to Solana's deprecated rent collection - mechanism (currently not in use). -- `space` - Indicates byte capacity (length) of the `data` field, but is not a - field in the `AccountInfo` type +В основі всі акаунти Solana представлені у стандартному форматі, який називається `AccountInfo`. Тип даних [AccountInfo](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/account_info.rs#L19-L36) є базовою структурою даних для всіх акаунтів Solana. + +Розберемо поля у виведених даних: + +- `data` — Це поле містить те, що ми зазвичай називаємо "даними" акаунта. Для гаманця воно порожнє (0 байтів), але інші акаунти використовують це поле для зберігання будь-яких довільних даних у вигляді серіалізованого буфера байтів. + +> Коли дані "буферизуються" таким чином, вони зберігають свою цілісність і можуть пізніше бути десеріалізовані назад у свій початковий вигляд для використання у програмах. Цей процес широко використовується в блокчейні для ефективної обробки даних. + +- `executable` — Прапорець, який вказує, чи є акаунт виконуваною програмою. Для гаманців та будь-яких акаунтів, які зберігають стан, значення `false`. +- `owner` — Це поле показує, яка програма контролює акаунт. Для гаманців це завжди Системна програма з адресою `11111111111111111111111111111111`. +- `lamports` — Баланс акаунта у лампортах (1 SOL = 1,000,000,000 лампортів). +- `rentEpoch` — Поле, пов’язане зі старим механізмом збору оренди Solana (наразі не використовується). +- `space` — Вказує ємність (довжину) поля `data`, але не є полем типу `AccountInfo`. -## Fetch Token Program +## Отримання Програми Token Program -Next, we'll examine the Token Extensions program, an executable program for -interacting with tokens on Solana. +Далі ми розглянемо програму Token Extensions, яка є виконуваною програмою для взаємодії з токенами на Solana. -### Open Example 2 +### Відкриття Прикладу 2 -Click this [link](https://beta.solpg.io/6671c6e7cffcf4b13384d199) to open the -example in Solana Playground. You'll see this code: +Натисніть це [посилання](https://beta.solpg.io/6671c6e7cffcf4b13384d199), щоб відкрити приклад у Solana Playground. Ви побачите такий код: ```ts filename="client.ts" {3} import { PublicKey } from "@solana/web3.js"; @@ -171,20 +139,17 @@ const accountInfo = await pg.connection.getAccountInfo(address); console.log(JSON.stringify(accountInfo, null, 2)); ``` +Замість отримання вашого гаманця Playground, тут ми отримуємо адресу акаунта програми Token Extensions. -Instead of fetching your Playground wallet, here we fetch the address of the -Token Extensions Program account. +### Запуск Прикладу 2 -### Run Example 2 +Запустіть код, виконавши команду `run` у терміналі. -Run the code using the `run` command in the terminal. ```shell filename="Terminal" run ``` - -Examine the output and how this program account differs from your wallet -account. +Ознайомтеся з виведеними даними та тим, чим цей акаунт програми відрізняється від вашого акаунта гаманця. @@ -215,47 +180,39 @@ Running client... -The Token Extensions program is an executable program account, but note that it -has the same `AccountInfo` structure. +Програма Token Extensions є виконуваним акаунтом програми, але має таку ж структуру `AccountInfo`. -Key differences in the `AccountInfo`: +Основні відмінності в `AccountInfo`: -- `executable` - Set to `true`, indicating this account represents an executable - program. -- `data` - Contains serialized data (unlike the empty data in a wallet account). - The data for a program account stores the address of another account (Program - Executable Data Account) that contains the program's bytecode. -- `owner` - The account is owned by the Upgradable BPF Loader - (`BPFLoaderUpgradeab1e11111111111111111111111`), a special program that - manages executable accounts. +- **`executable`** — Встановлено у `true`, що вказує на те, що цей акаунт є виконуваною програмою. +- **`data`** — Містить серіалізовані дані (на відміну від порожніх даних у акаунті гаманця). Дані для акаунта програми зберігають адресу іншого акаунта (Program Executable Data Account), який містить байт-код програми. +- **`owner`** — Акаунт належить завантажувачу Upgradable BPF Loader (`BPFLoaderUpgradeab1e11111111111111111111111`), спеціальній програмі, яка управляє виконуваними акаунтами. --- -You can inspect the Solana Explorer for the -[Token Extensions Program Account](https://explorer.solana.com/address/TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb) -and its corresponding +Ви можете перевірити Solana Explorer для +[акаунта програми Token Extensions](https://explorer.solana.com/address/TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb) +та його відповідного [Program Executable Data Account](https://explorer.solana.com/address/DoU57AYuPFu2QU514RktNPG22QhApEjnKxnBcu4BHDTY). -The Program Executable Data Account contains the compiled bytecode for the Token -Extensions Program -[source code](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program-2022/src). +Program Executable Data Account містить скомпільований байт-код програми Token Extensions +[вихідний код](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program-2022/src). -## Fetch Mint Account +## Отримання Акаунта Mint -In this step, we'll examine a Mint account, which represents a unique token on -the Solana network. +На цьому етапі ми розглянемо акаунт Mint, який представляє унікальний токен у мережі Solana. -### Open Example 3 +### Відкриття Прикладу 3 + +Натисніть це [посилання](https://beta.solpg.io/6671c9aecffcf4b13384d19a), щоб відкрити приклад у Solana Playground. Ви побачите такий код: -Click this [link](https://beta.solpg.io/6671c9aecffcf4b13384d19a) to open the -example in Solana Playground. You'll see this code: ```ts filename="client.ts" {3} import { PublicKey } from "@solana/web3.js"; @@ -265,12 +222,12 @@ const accountInfo = await pg.connection.getAccountInfo(address); console.log(JSON.stringify(accountInfo, null, 2)); ``` +У цьому прикладі ми отримаємо адресу існуючого акаунта Mint у devnet. -In this example, we'll fetch the address of an existing Mint account on devnet. +### Запуск Прикладу 3 -### Run Example 3 +Запустіть код, виконавши команду `run`. -Run the code using the `run` command. ```shell filename="Terminal" run @@ -305,34 +262,22 @@ Running client... -Key differences in the `AccountInfo`: +Основні відмінності в `AccountInfo`: -- `owner` - The mint account is owned by the Token Extensions program - (`TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`). -- `executable` - Set to `false`, as this account stores state rather than - executable code. -- `data`: Contains serialized data about the token (mint authority, supply, - decimals, etc.). +- **`owner`** — Акаунт mint належить програмі Token Extensions (`TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`). +- **`executable`** — Встановлено у `false`, оскільки цей акаунт зберігає стан, а не виконуваний код. +- **`data`** — Містить серіалізовані дані про токен (авторитет випуску, загальну кількість, кількість знаків після коми тощо). -### Deserialize Mint Account Data +### Десеріалізація Даних Акаунта Mint -To read the `data` field from any account, you need to deserialize the data -buffer into the expected data type. This is often done using helper functions -from client libraries for a particular program. +Щоб зчитати поле `data` з будь-якого акаунта, потрібно десеріалізувати буфер даних у очікуваний тип даних. Це часто виконується за допомогою допоміжних функцій клієнтських бібліотек для конкретної програми. -**Deserialization** is the process of converting data from a stored format (like -raw bytes or JSON) back into a usable, structured format in a program. In -blockchain, it involves taking raw, encoded data from the network and -transforming it back into objects, classes, or readable structures so developers -can access and manipulate specific information within a program. Deserialization -is essential for interpreting account or transaction data received from a -network in a form that a program can process and display meaningfully. +**Десеріалізація** — це процес перетворення даних зі збереженого формату (наприклад, необроблених байтів або JSON) назад у використовуваний структурований формат у програмі. У блокчейні це включає взяття необроблених, закодованих даних із мережі та їх перетворення назад в об'єкти, класи або читабельні структури, щоб розробники могли отримати доступ до конкретної інформації та маніпулювати нею у програмі. Десеріалізація є важливою для інтерпретації даних акаунтів або транзакцій, отриманих із мережі, у формі, яку програма може обробляти і відображати осмислено. -Open this next [example](https://beta.solpg.io/6671cd8acffcf4b13384d19b) in -Solana Playground. You'll see this code: +Відкрийте цей [приклад](https://beta.solpg.io/6671cd8acffcf4b13384d19b) у Solana Playground. Ви побачите такий код: ```ts filename="client.ts" import { PublicKey } from "@solana/web3.js"; @@ -349,16 +294,14 @@ const mintData = await getMint( console.log(mintData); ``` -This example uses the `getMint` helper function to automatically deserialize the -data field of the Mint account. +Цей приклад використовує функцію `getMint`, яка автоматично десеріалізує поле `data` акаунта Mint. -Run the code using the `run` command. +Запустіть код, виконавши команду `run`. ```shell filename="Terminal" run ``` - -You should see the following deserialized Mint account data. +Ви повинні побачити наступні десеріалізовані дані акаунта Mint. @@ -378,24 +321,20 @@ Running client... -The `getMint` function deserializes the account data into the -[Mint](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32) -data type defined in the Token Extensions program source code. +Функція `getMint` десеріалізує дані акаунта у тип даних [Mint](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32), визначений у вихідному коді програми Token Extensions. -- `address` - The Mint account's address -- `mintAuthority` - The authority allowed to mint new tokens -- `supply` - The total supply of tokens -- `decimals` - The number of decimal places for the token -- `isInitialized` - Whether the Mint data has been initialized -- `freezeAuthority` - The authority allowed to freeze token accounts -- `tlvData` - Additional data for Token Extensions (requires further - deserialization) +- **`address`** — Адреса акаунта Mint. +- **`mintAuthority`** — Авторитет, який може випускати нові токени. +- **`supply`** — Загальна кількість токенів в обігу. +- **`decimals`** — Кількість десяткових знаків для токена. +- **`isInitialized`** — Чи були дані Mint ініціалізовані. +- **`freezeAuthority`** — Авторитет, який має право заморожувати акаунти токенів. +- **`tlvData`** — Додаткові дані для Token Extensions (вимагають подальшої десеріалізації). -You can view the fully deserialized -[Mint Account](https://explorer.solana.com/address/C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR?cluster=devnet) -data, including enabled Token Extensions, on the Solana Explorer. +Ви можете переглянути повністю десеріалізовані [дані акаунта Mint](https://explorer.solana.com/address/C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR?cluster=devnet), включаючи активовані Token Extensions, у Solana Explorer. + diff --git a/docs/uk/intro/quick-start/writing-to-network.md b/docs/uk/intro/quick-start/writing-to-network.md index 8d3e55154..1e17da27f 100644 --- a/docs/uk/intro/quick-start/writing-to-network.md +++ b/docs/uk/intro/quick-start/writing-to-network.md @@ -1,34 +1,26 @@ --- -sidebarLabel: Writing to Network -title: Writing to Network +sidebarLabel: Запис у Мережу +title: Запис у Мережу sidebarSortOrder: 2 description: - Learn how to interact with the Solana network by sending transactions and - instructions. Follow step-by-step examples to transfer SOL tokens and create - new tokens using the System Program and Token Extensions Program. + Дізнайтеся, як взаємодіяти з мережею Solana шляхом надсилання транзакцій та + інструкцій. Слідуйте покроковим прикладам для переказу токенів SOL та створення + нових токенів за допомогою System Program та Token Extensions Program. --- -Now that we've explored reading from the Solana network, let's learn how to -write data to it. On Solana, we interact with the network by sending -transactions made up of instructions. These instructions are defined by -programs, which contain the business logic for how accounts should be updated. +Тепер, коли ми розглянули зчитування даних із мережі Solana, давайте навчимося записувати дані до неї. У Solana взаємодія з мережею здійснюється шляхом надсилання транзакцій, що складаються з інструкцій. Ці інструкції визначаються програмами, які містять бізнес-логіку про те, як мають оновлюватися акаунти. -Let's walk through two common operations, transferring SOL and creating a token, -to demonstrate how to build and send transactions. For more details, refer to -the [Transactions and Instructions](/docs/core/transactions) and -[Fees on Solana](/docs/core/fees) pages. +Розглянемо два поширені операції, переказ SOL і створення токена, щоб продемонструвати, як створювати і надсилати транзакції. Для отримання додаткової інформації відвідайте сторінки [Транзакції та Інструкції](/docs/uk/core/transactions) і [Комісії у Solana](/docs/uk/core/fees). -## Transfer SOL +## Переказ SOL -We'll start with a simple SOL transfer from your wallet to another account. This -requires invoking the transfer instruction on the System Program. +Почнемо із простої операції переказу SOL з вашого гаманця на інший акаунт. Це вимагає виклику інструкції переказу у System Program. -### Open Example 1 +### Відкриття Прикладу 1 -Click this [link](https://beta.solpg.io/6671d85ecffcf4b13384d19e) to open the -example in Solana Playground. You'll see this code: +Натисніть це [посилання](https://beta.solpg.io/6671d85ecffcf4b13384d19e), щоб відкрити приклад у Solana Playground. Ви побачите такий код: ```ts filename="client.ts" import { @@ -65,21 +57,21 @@ console.log( -This script does the following: +Цей скрипт виконує наступні дії: -- Set your Playground wallet as the sender +- Встановлює ваш гаманець Playground як відправника: ```ts const sender = pg.wallet.keypair; ``` -- Creates a new keypair as the receiver +- Створює нову ключову пару як отримувача: ```ts const receiver = new Keypair(); ``` -- Constructs a transfer instruction to transfer 0.01 SOL +- Створює інструкцію переказу для переказу 0.01 SOL: ```ts const transferInstruction = SystemProgram.transfer({ @@ -89,13 +81,13 @@ This script does the following: }); ``` -- Builds a transaction including the transfer instruction +- Формує транзакцію, включаючи інструкцію переказу: ```ts const transaction = new Transaction().add(transferInstruction); ``` -- Sends and confirms the transaction +- Відправляє та підтверджує транзакцію: ```ts const transactionSignature = await sendAndConfirmTransaction( @@ -105,8 +97,7 @@ This script does the following: ); ``` -- Prints out a link to the SolanaFM explorer in the Playground terminal to view - the transaction details +- Виводить посилання на SolanaFM у термінал Playground для перегляду деталей транзакції. ```ts console.log( @@ -118,16 +109,16 @@ This script does the following: -### Run Example 1 +### Запуск Прикладу 1 + +Запустіть код, виконавши команду `run`. -Run the code using the `run` command. ```shell filename="Terminal" run ``` -Click on the output link to view the transaction details on the SolanaFM -explorer. +Натисніть на посилання у виведених даних, щоб переглянути деталі транзакції у SolanaFM Explorer. @@ -143,26 +134,22 @@ Running client... ![Transfer SOL](/assets/docs/intro/quickstart/transfer-sol.png) -You've just sent your first transaction on Solana! Notice how we created an -instruction, added it to a transaction, and then sent that transaction to the -network. This is the basic process for building any transaction. +Ви щойно надіслали свою першу транзакцію у Solana! Зверніть увагу, як ми створили інструкцію, додали її до транзакції, а потім відправили цю транзакцію до мережі. Це базовий процес для створення будь-якої транзакції. -## Create a Token +## Створення Токена -Now, let's create a new token by creating and initializing a Mint account. This -requires two instructions: +Тепер створимо новий токен шляхом створення та ініціалізації акаунта Mint. Для цього потрібні дві інструкції: -- Invoke the System Program to create a new account -- Invoke the Token Extensions Program to initialize the account data +- Виклик System Program для створення нового акаунта. +- Виклик Token Extensions Program для ініціалізації даних акаунта. -### Open Example 2 +### Відкриття Прикладу 2 -Click this [link](https://beta.solpg.io/6671da4dcffcf4b13384d19f) to open the -example in Solana Playground. You'll see the following code: +Натисніть це [посилання](https://beta.solpg.io/6671da4dcffcf4b13384d19f), щоб відкрити приклад у Solana Playground. Ви побачите наступний код: ```ts filename="client.ts" import { @@ -236,30 +223,27 @@ console.log( -This script performs the following steps: - -- Sets up your Playground wallet and a connection to the Solana devnet +Цей скрипт виконує наступні кроки: +- Налаштовує ваш гаманець Playground і з'єднання з devnet Solana: ```ts const wallet = pg.wallet; const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); ``` -- Generates a new keypair for the mint account +- Генерує нову ключову пару для акаунта mint: ```ts const mint = new Keypair(); ``` -- Calculates the minimum lamports needed for a Mint account +- Розраховує мінімальну кількість лампортів, необхідну для акаунта Mint: ```ts const rentLamports = await getMinimumBalanceForRentExemptMint(connection); ``` -- Creates an instruction to create a new account for the mint, specifying the - Token Extensions program (`TOKEN_2022_PROGRAM_ID`) as the owner of the new - account +- Створює інструкцію для створення нового акаунта mint, вказуючи програму Token Extensions (TOKEN_2022_PROGRAM_ID) як власника нового акаунта: ```ts const createAccountInstruction = SystemProgram.createAccount({ @@ -271,7 +255,7 @@ This script performs the following steps: }); ``` -- Creates an instruction to initialize the mint account data +- Створює інструкцію для ініціалізації даних акаунта mint: ```ts const initializeMintInstruction = createInitializeMint2Instruction( @@ -283,7 +267,7 @@ This script performs the following steps: ); ``` -- Adds both instructions to a single transaction +- Додає обидві інструкції до однієї транзакції: ```ts const transaction = new Transaction().add( @@ -292,10 +276,7 @@ This script performs the following steps: ); ``` -- Sends and confirms the transaction. Both the wallet and mint keypair are - passed in as signers on the transaction. The wallet is required to pay for the - creation of the new account. The mint keypair is required because we are using - its publickey as the address of the new account. +- Відправляє та підтверджує транзакцію. Гаманець і ключова пара mint передаються як підписувачі транзакції. Гаманець потрібен для оплати створення нового акаунта, а ключова пара mint потрібна, оскільки її публічний ключ використовується як адреса нового акаунта: ```ts const transactionSignature = await sendAndConfirmTransaction( @@ -305,7 +286,7 @@ This script performs the following steps: ); ``` -- Prints out links to view the transaction and mint account details on SolanaFM +- Виводить посилання для перегляду транзакції та деталей акаунта mint на SolanaFM: ```ts console.log( @@ -322,21 +303,20 @@ This script performs the following steps: -### Run Example 2 +### Запуск Прикладу 2 -Run the code using the `run` command. +Запустіть код, виконавши команду `run`. ```shell filename="Terminal" run ``` -You'll see two links printed to the Playground terminal: +Ви побачите два посилання, виведених у термінал Playground: -- One for the transaction details -- One for the newly created mint account +- Одне для деталей транзакції +- Інше для новоствореного акаунта mint -Click the links to inspect the transaction details and the newly created mint -account on SolanaFM. +Натисніть на посилання, щоб переглянути деталі транзакції та новостворений акаунт mint у SolanaFM. @@ -357,9 +337,6 @@ Mint Account: https://solana.fm/address/CoZ3Nz488rmATDhy1hPk5fvwSZaipCngvf8rYBYV ![Mint Account](/assets/docs/intro/quickstart/mint-account.png) -Notice how we built a transaction with multiple instructions this time. We first -created a new account and then initialized its data as a mint. This is how you -build more complex transactions that involve instructions from multiple -programs. +Зверніть увагу, як цього разу ми створили транзакцію з кількома інструкціями. Спочатку ми створили новий акаунт, а потім ініціалізували його дані як mint. Таким чином створюються складніші транзакції, які включають інструкції з кількох програм. diff --git a/docs/uk/intro/wallets.md b/docs/uk/intro/wallets.md index 5c690a950..f12d22c36 100644 --- a/docs/uk/intro/wallets.md +++ b/docs/uk/intro/wallets.md @@ -1,69 +1,35 @@ --- -sidebarLabel: Wallets -title: Solana Wallet Guide +sidebarLabel: Гаманці +title: Посібник із Гаманців Solana sidebarSortOrder: 3 --- -This document describes the different wallet options that are available to users -of Solana who want to be able to send, receive and interact with SOL tokens on -the Solana blockchain. +Цей документ описує різні варіанти гаманців, доступних користувачам Solana, які хочуть надсилати, отримувати та взаємодіяти з токенами SOL у блокчейні Solana. -## What is a Wallet? +## Що таке Гаманець? -A crypto wallet is a device or application that stores a collection of keys and -can be used to send, receive, and track ownership of cryptocurrencies. Wallets -can take many forms. A wallet might be a directory or file in your computer's -file system, a piece of paper, or a specialized device called a _hardware -wallet_. There are also various smartphone apps and computer programs that -provide a user-friendly way to create and manage wallets. +Криптогаманець — це пристрій або програма, яка зберігає набір ключів і може використовуватися для надсилання, отримання та відстеження володіння криптовалютами. Гаманці можуть мати різні форми. Гаманець може бути каталогом або файлом у файловій системі вашого комп’ютера, аркушем паперу або спеціалізованим пристроєм, який називається _апаратний гаманець_. Також існують різні програми для смартфонів і комп’ютерів, які надають зручний спосіб створення та управління гаманцями. ### Keypair -A [_keypair_](/docs/terminology.md#keypair) is a securely generated -[_secret key_](#secret-key) and its cryptographically-derived -[_public key_](#public-key). A secret key and its corresponding public key are -together known as a _keypair_. A wallet contains a collection of one or more -keypairs and provides some means to interact with them. +[_Keypair_](/docs/uk/terminology.md#keypair) — це безпечно згенерований [_секретний ключ_](#secret-key) і його криптографічно виведений [_публічний ключ_](#public-key). Секретний ключ та його відповідний публічний ключ разом називаються _ключовою парою_. Гаманець містить колекцію однієї або кількох ключових пар і надає засоби для взаємодії з ними. -### Public key +### Публічний ключ -The [_public key_](/docs/terminology.md#public-key-pubkey) (commonly shortened -to _pubkey_) is known as the wallet's _receiving address_ or simply its -_address_. The wallet address **may be shared and displayed freely**. When -another party is going to send some amount of cryptocurrency to a wallet, they -need to know the wallet's receiving address. Depending on a blockchain's -implementation, the address can also be used to view certain information about a -wallet, such as viewing the balance, but has no ability to change anything about -the wallet or withdraw any tokens. +[_Публічний ключ_](/docs/uk/terminology.md#public-key-pubkey) (часто скорочується до _pubkey_) відомий як _адреса для отримання_ гаманця або просто його _адреса_. Адресу гаманця **можна вільно передавати та показувати**. Коли інша сторона збирається надіслати певну кількість криптовалюти на гаманець, їй потрібно знати адресу для отримання. Залежно від реалізації блокчейну, адреса також може використовуватися для перегляду певної інформації про гаманець, наприклад, балансу, але вона не дозволяє змінювати гаманець або знімати з нього токени. -### Secret key +### Секретний ключ -The [_secret key_](/docs/terminology.md#private-key) (also referred to as -_private key_) is required to digitally sign any transactions to send -cryptocurrencies to another address or to make any changes to the wallet. The -secret key **must never be shared**. If someone gains access to the secret key -to a wallet, they can withdraw all the tokens it contains. If the secret key for -a wallet is lost, any tokens that have been sent to that wallet's address are -**permanently lost**. +[_Секретний ключ_](/docs/uk/terminology.md#private-key) (також називається _приватним ключем_) потрібен для цифрового підпису будь-яких транзакцій для відправлення криптовалюти на іншу адресу або внесення змін до гаманця. Секретний ключ **ніколи не повинен бути переданий іншим**. Якщо хтось отримає доступ до секретного ключа гаманця, він може зняти всі токени, які він містить. Якщо секретний ключ гаманця втрачено, будь-які токени, відправлені на адресу цього гаманця, **назавжди втрачені**. -## Security +## Безпека -Different wallet solutions offer different approaches to keypair security, -interacting with the keypair, and signing transactions to use/spend the tokens. -Some are easier to use than others. Some store and back up secret keys more -securely. Solana supports multiple types of wallets so you can choose the right -balance of security and convenience. +Різні рішення для гаманців пропонують різні підходи до безпеки ключової пари, взаємодії з нею та підписання транзакцій для використання/витрачання токенів. Деякі є простішими у використанні, ніж інші. Деякі забезпечують більш безпечне зберігання та резервне копіювання секретних ключів. Solana підтримує кілька типів гаманців, тому ви можете обрати правильний баланс між безпекою та зручністю. -**If you want to be able to receive SOL tokens on the Solana blockchain, you -first will need to create a wallet.** +**Якщо ви хочете отримувати токени SOL у блокчейні Solana, вам спочатку потрібно створити гаманець.** -## Supported Wallets +## Підтримувані Гаманці -Several browser and mobile app based wallets support Solana. Find some options -that might be right for you on the [Solana Wallets](https://solana.com/wallets) -page. +Кілька гаманців на основі браузера та мобільних додатків підтримують Solana. Знайдіть варіанти, які можуть підійти вам, на сторінці [Solana Wallets](https://solana.com/wallets). -For advanced users or developers, the -[command-line wallets](https://docs.anza.xyz/cli/wallets) may be more -appropriate, as new features on the Solana blockchain will always be supported -on the command line first before being integrated into third-party solutions. +Для досвідчених користувачів або розробників більше підходять [гаманці командного рядка](https://docs.anza.xyz/cli/wallets), оскільки нові функції в блокчейні Solana завжди спочатку підтримуються в командному рядку, перш ніж бути інтегрованими у сторонні рішення. diff --git a/docs/uk/terminology.md b/docs/uk/terminology.md index f6f8eb13a..39d74a750 100644 --- a/docs/uk/terminology.md +++ b/docs/uk/terminology.md @@ -62,7 +62,7 @@ isSkippedInNav: true ## Завантажувач BPF (BPF loader) -Програма Solana, яка завантажує [програми на основі BPF](/docs/core/programs#berkeley-packet-filter-bpf) в [блокчейн](#onchain-program), дозволяючи їм взаємодіяти з середовищем виконання. +Програма Solana, яка завантажує [програми на основі BPF](/docs/uk/core/programs#berkeley-packet-filter-bpf) в [блокчейн](#onchain-program), дозволяючи їм взаємодіяти з середовищем виконання. ## Клієнт (client) @@ -107,7 +107,7 @@ isSkippedInNav: true ## Виклик між програмами (CPI) -Виклик однієї [програми на блокчейні](#onchain-program) до іншої. Докладніше див. [Виклик між програмами](/docs/core/cpi.md). +Виклик однієї [програми на блокчейні](#onchain-program) до іншої. Докладніше див. [Виклик між програмами](/docs/uk/core/cpi.md). ## Площина даних (data plane) @@ -219,7 +219,7 @@ isSkippedInNav: true Структурований вміст [транзакції](#transaction), зазвичай містить заголовок, масив адрес облікових записів, недавній [блокхеш](#blockhash) та масив [інструкцій](#instruction). Докладніше про -[форматування повідомлень у транзакціях](/docs/core/transactions.md#message-header). +[форматування повідомлень у транзакціях](/docs/uk/core/transactions.md#message-header). ## Коефіцієнт Накамото (Nakamoto coefficient) @@ -240,7 +240,7 @@ isSkippedInNav: true ## Програма на блокчейні (onchain program) -Виконуваний код у блокчейні Solana, який інтерпретує [інструкції](#instruction), надіслані в кожній [транзакції](#transaction), щоб читати та змінювати облікові записи, якими він управляє. Ці програми часто називають "[розумними контрактами](/docs/core/programs.md)" на інших блокчейнах. +Виконуваний код у блокчейні Solana, який інтерпретує [інструкції](#instruction), надіслані в кожній [транзакції](#transaction), щоб читати та змінювати облікові записи, якими він управляє. Ці програми часто називають "[розумними контрактами](/docs/uk/core/programs.md)" на інших блокчейнах. ## PoH (Proof of History) @@ -282,7 +282,7 @@ isSkippedInNav: true Комісія, яку сплачують [облікові записи](#account) і [програми](#program) за зберігання даних у блокчейні. Якщо на рахунку недостатньо балансу для оплати оренди, він може бути видалений. -Див. також [звільнення від оренди](#rent-exempt). Докладніше про оренду: [Що таке оренда?](/docs/intro/rent.md). +Див. також [звільнення від оренди](#rent-exempt). Докладніше про оренду: [Що таке оренда?](/docs/uk/intro/rent.md). ## Звільнення від оренди (rent exempt) From 2844a1a4c2c1a83b1e716c296f10e8cfba164fdc Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Sun, 12 Jan 2025 19:57:59 +0200 Subject: [PATCH 09/14] Translated exchange.md and testing.md --- docs/uk/more/exchange.md | 810 +++++++++++------------------------- docs/uk/more/index.md | 2 +- docs/uk/programs/testing.md | 150 ++----- 3 files changed, 293 insertions(+), 669 deletions(-) diff --git a/docs/uk/more/exchange.md b/docs/uk/more/exchange.md index e59d2b065..19a773cbc 100644 --- a/docs/uk/more/exchange.md +++ b/docs/uk/more/exchange.md @@ -1,31 +1,25 @@ --- -title: Add Solana to Your Exchange +title: Додати Solana на Вашу Біржу --- -This guide describes how to add Solana's native token SOL to your cryptocurrency -exchange. +Цей посібник описує, як додати нативний токен Solana (SOL) до вашої криптовалютної біржі. -## Node Setup +## Налаштування Ноди -We highly recommend setting up at least two nodes on high-grade computers/cloud -instances, upgrading to newer versions promptly, and keeping an eye on service -operations with a bundled monitoring tool. +Ми наполегливо рекомендуємо налаштувати щонайменше дві ноди на високопродуктивних комп’ютерах або хмарних інстанціях, своєчасно оновлювати їх до нових версій і відстежувати роботу сервісу за допомогою вбудованих інструментів моніторингу. -This setup enables you: +Це налаштування дозволяє вам: -- to have a self-administered gateway to the Solana mainnet-beta cluster to get - data and submit withdrawal transactions -- to have full control over how much historical block data is retained -- to maintain your service availability even if one node fails +- мати самостійно керований шлюз до кластеру Solana mainnet-beta для отримання даних і надсилання транзакцій на виведення +- мати повний контроль над тим, скільки історичних даних блоків зберігається +- забезпечувати доступність вашого сервісу навіть у разі відмови однієї з нод -Solana nodes demand relatively high computing power to handle our fast blocks -and high TPS. For specific requirements, please see -[hardware recommendations](https://docs.anza.xyz/operations/requirements). +Ноди Solana вимагають відносно високої обчислювальної потужності для обробки швидких блоків і високої пропускної здатності (TPS). Для конкретних вимог дивіться [рекомендації щодо апаратного забезпечення](https://docs.anza.xyz/operations/requirements). -To run an api node: +Щоб запустити ноду API: -1. [Install the Solana command-line tool suite](/docs/intro/installation.md) -2. Start the validator with at least the following parameters: +1. [Встановіть набір інструментів командного рядка Solana](/docs/uk/intro/installation.md) +2. Запустіть валідатор щонайменше з наступними параметрами: ```shell solana-validator \ @@ -41,132 +35,70 @@ solana-validator \ --only-known-rpc ``` -Customize `--ledger` to your desired ledger storage location, and `--rpc-port` -to the port you want to expose. +Налаштуйте параметр `--ledger` для бажаного розташування зберігання леджера та параметр `--rpc-port` для порту, який ви хочете зробити доступним. -The `--entrypoint` and `--expected-genesis-hash` parameters are all specific to -the cluster you are joining. -[Current parameters for Mainnet Beta](https://docs.anza.xyz/clusters/available#example-solana-validator-command-line-2) +Параметри `--entrypoint` та `--expected-genesis-hash` є специфічними для кластера, до якого ви приєднуєтеся. +[Поточні параметри для Mainnet Beta](https://docs.anza.xyz/clusters/available#example-solana-validator-command-line-2) -The `--limit-ledger-size` parameter allows you to specify how many ledger -[shreds](/docs/terminology.md#shred) your node retains on disk. If you do not -include this parameter, the validator will keep the entire ledger until it runs -out of disk space. The default value attempts to keep the ledger disk usage -under 500GB. More or less disk usage may be requested by adding an argument to -`--limit-ledger-size` if desired. Check `solana-validator --help` for the -default limit value used by `--limit-ledger-size`. More information about -selecting a custom limit value is -[available here](https://github.com/solana-labs/solana/blob/583cec922b6107e0f85c7e14cb5e642bc7dfb340/core/src/ledger_cleanup_service.rs#L15-L26). +Параметр `--limit-ledger-size` дозволяє вказати, скільки [шредів](/docs/uk/terminology.md#shred) леджера ваша нода зберігатиме на диску. Якщо цей параметр не вказано, валідатор зберігатиме весь леджер, доки не закінчиться місце на диску. Значення за замовчуванням намагається обмежити використання місця на диску леджером до 500 ГБ. За потреби можна змінити це значення, додавши аргумент до параметра `--limit-ledger-size`. Для перегляду значення за замовчуванням, яке використовується параметром `--limit-ledger-size`, виконайте команду `solana-validator --help`. Більше інформації про вибір власного значення обмеження можна знайти [тут](https://github.com/solana-labs/solana/blob/583cec922b6107e0f85c7e14cb5e642bc7dfb340/core/src/ledger_cleanup_service.rs#L15-L26). -Specifying one or more `--known-validator` parameters can protect you from -booting from a malicious snapshot. -[More on the value of booting with known validators](https://docs.anza.xyz/operations/guides/validator-start#known-validators) +Вказівка одного або кількох параметрів `--known-validator` може захистити вас від запуску з підробленого знімку. +[Більше про цінність запуску з відомими валідаторами](https://docs.anza.xyz/operations/guides/validator-start#known-validators) -Optional parameters to consider: +Додаткові параметри, які варто розглянути: -- `--private-rpc` prevents your RPC port from being published for use by other - nodes -- `--rpc-bind-address` allows you to specify a different IP address to bind the - RPC port +- `--private-rpc` забороняє публікацію вашого RPC-порту для використання іншими нодами +- `--rpc-bind-address` дозволяє вказати іншу IP-адресу для прив’язки RPC-порту -### Automatic Restarts and Monitoring +### Автоматичний Перезапуск та Моніторинг -We recommend configuring each of your nodes to restart automatically on exit, to -ensure you miss as little data as possible. Running the solana software as a -systemd service is one great option. +Ми рекомендуємо налаштувати кожну з ваших нод на автоматичний перезапуск після завершення роботи, щоб мінімізувати втрату даних. Запуск програмного забезпечення Solana як служби systemd є одним із чудових варіантів. -For monitoring, we provide -[`solana-watchtower`](https://github.com/solana-labs/solana/blob/master/watchtower/README.md), -which can monitor your validator and detect with the `solana-validator` process -is unhealthy. It can directly be configured to alert you via Slack, Telegram, -Discord, or Twillio. For details, run `solana-watchtower --help`. +Для моніторингу ми надаємо інструмент +[`solana-watchtower`](https://github.com/solana-labs/solana/blob/master/watchtower/README.md), +який може моніторити ваш валідатор і визначати, чи є процес `solana-validator` несправним. Він може бути налаштований для сповіщень через Slack, Telegram, Discord або Twilio. Для деталей виконайте команду `solana-watchtower --help`. ```shell solana-watchtower --validator-identity ``` +> Додаткову інформацію про [найкращі практики для Solana Watchtower](https://docs.anza.xyz/operations/best-practices/monitoring#solana-watchtower) можна знайти у документації. + +#### Оголошення про Нові Релізи ПЗ + +Ми випускаємо нове програмне забезпечення часто (приблизно один реліз на тиждень). Іноді нові версії містять несумісні протокольні зміни, які вимагають своєчасного оновлення ПЗ, щоб уникнути помилок при обробці блоків. + +Наші офіційні оголошення про всі види релізів (звичайні та пов’язані з безпекою) публікуються в [каналі Discord](https://solana.com/discord) під назвою `#mb-announcement` (`mb` означає `mainnet-beta`). + +Як і для валідаторів зі ставками, ми очікуємо, що валідатори, які обслуговуються біржами, будуть оновлюватися протягом одного-двох робочих днів після оголошення про звичайний реліз. Для релізів, пов’язаних із безпекою, може знадобитися більш термінове реагування. + +### Цілісність Леджера + +За замовчуванням кожна з ваших нод завантажується зі знімку, наданого одним із ваших відомих валідаторів. Цей знімок відображає поточний стан ланцюга, але не містить повного історичного леджера. Якщо одна з ваших нод зупиняється та завантажується з нового знімка, у леджері цієї ноди може з’явитися прогалина. Щоб уникнути цієї проблеми, додайте параметр `--no-snapshot-fetch` до команди `solana-validator`, щоб отримувати історичні дані леджера замість знімка. + +Не додавайте параметр `--no-snapshot-fetch` під час початкового завантаження, оскільки неможливо завантажити ноду від самого генезис-блоку. Спочатку завантажтеся зі знімка, а потім додайте параметр `--no-snapshot-fetch` для наступних перезавантажень. + +Варто зазначити, що обсяг доступного історичного леджера від інших нод у мережі обмежений. Якщо ваші валідатори зазнають значних простоїв, вони можуть не змогти синхронізуватися з мережею і будуть змушені завантажити новий знімок від відомого валідатора, що створить прогалину в історичному леджері, яку неможливо заповнити. + +### Мінімізація Доступу до Портів Валідатора + +Валідатору необхідно, щоб різні UDP- і TCP-порти були відкриті для вхідного трафіку від усіх інших валідаторів Solana. Хоча це найефективніший режим роботи і настійно рекомендується, можливо обмежити валідатор лише для вхідного трафіку від одного іншого валідатора Solana. + +Спочатку додайте аргумент `--restricted-repair-only-mode`. Це призведе до роботи валідатора в обмеженому режимі, в якому він не отримуватиме push-повідомлення від інших валідаторів і замість цього постійно опитуватиме інші валідатори для отримання блоків. Валідатор буде передавати UDP-пакети іншим валідаторам лише через порти _Gossip_ та _ServeR_ ("serve repair") і отримуватиме UDP-пакети лише через порти _Gossip_ та _Repair_. + +Порт _Gossip_ є двостороннім і дозволяє вашому валідатору підтримувати зв’язок із рештою кластеру. Ваш валідатор передаватиме запити на ремонт через порт _ServeR_, щоб отримувати нові блоки від решти мережі, оскільки Turbine тепер відключено. Ваш валідатор отримуватиме відповіді на запити ремонту через порт _Repair_ від інших валідаторів. + +Щоб додатково обмежити валідатор для запитів блоків лише від одного або кількох валідаторів, спочатку визначте публічний ключ (pubkey) цього валідатора та додайте аргументи `--gossip-pull-validator PUBKEY --repair-validator PUBKEY` для кожного PUBKEY. Це створить навантаження на кожен валідатор, який ви додаєте, тому робіть це обережно і лише після консультації з цільовим валідатором. + +Ваш валідатор тепер повинен спілкуватися лише з чітко вказаними валідаторами і лише через порти _Gossip_, _Repair_ та _ServeR_. + +## Налаштування Депозитних Акаунтів + +Акаунти Solana не потребують жодної ініціалізації в мережі; як тільки вони містять деяку кількість SOL, вони існують. Щоб налаштувати депозитний акаунт для вашої біржі, просто створіть ключову пару Solana за допомогою будь-якого з наших [інструментів для гаманців](https://docs.anza.xyz/cli/wallets). + +Рекомендуємо використовувати унікальний депозитний акаунт для кожного з ваших користувачів. + +Акаунти Solana мають бути звільнені від оренди, містячи еквівалент 2-річної [оренди](/docs/uk/core/fees.md#rent) у SOL. Щоб визначити мінімальний баланс для звільнення від оренди для ваших депозитних акаунтів, виконайте запит до [ендпоінту `getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx): -> You can find more information about the -> [best practices for Solana Watchtower](https://docs.anza.xyz/operations/best-practices/monitoring#solana-watchtower) -> here in the docs. - -#### New Software Release Announcements - -We release new software frequently (around 1 release / week). Sometimes newer -versions include incompatible protocol changes, which necessitate timely -software update to avoid errors in processing blocks. - -Our official release announcements for all kinds of releases (normal and -security) are communicated via a [discord](https://solana.com/discord) channel -called `#mb-announcement` (`mb` stands for `mainnet-beta`). - -Like staked validators, we expect any exchange-operated validators to be updated -at your earliest convenience within a business day or two after a normal release -announcement. For security-related releases, more urgent action may be needed. - -### Ledger Continuity - -By default, each of your nodes will boot from a snapshot provided by one of your -known validators. This snapshot reflects the current state of the chain, but -does not contain the complete historical ledger. If one of your node exits and -boots from a new snapshot, there may be a gap in the ledger on that node. In -order to prevent this issue, add the `--no-snapshot-fetch` parameter to your -`solana-validator` command to receive historical ledger data instead of a -snapshot. - -Do not pass the `--no-snapshot-fetch` parameter on your initial boot as it's not -possible to boot the node all the way from the genesis block. Instead boot from -a snapshot first and then add the `--no-snapshot-fetch` parameter for reboots. - -It is important to note that the amount of historical ledger available to your -nodes from the rest of the network is limited at any point in time. Once -operational if your validators experience significant downtime they may not be -able to catch up to the network and will need to download a new snapshot from a -known validator. In doing so your validators will now have a gap in its -historical ledger data that cannot be filled. - -### Minimizing Validator Port Exposure - -The validator requires that various UDP and TCP ports be open for inbound -traffic from all other Solana validators. While this is the most efficient mode -of operation, and is strongly recommended, it is possible to restrict the -validator to only require inbound traffic from one other Solana validator. - -First add the `--restricted-repair-only-mode` argument. This will cause the -validator to operate in a restricted mode where it will not receive pushes from -the rest of the validators, and instead will need to continually poll other -validators for blocks. The validator will only transmit UDP packets to other -validators using the _Gossip_ and _ServeR_ ("serve repair") ports, and only -receive UDP packets on its _Gossip_ and _Repair_ ports. - -The _Gossip_ port is bi-directional and allows your validator to remain in -contact with the rest of the cluster. Your validator transmits on the _ServeR_ -to make repair requests to obtaining new blocks from the rest of the network, -since Turbine is now disabled. Your validator will then receive repair responses -on the _Repair_ port from other validators. - -To further restrict the validator to only requesting blocks from one or more -validators, first determine the identity pubkey for that validator and add the -`--gossip-pull-validator PUBKEY --repair-validator PUBKEY` arguments for each -PUBKEY. This will cause your validator to be a resource drain on each validator -that you add, so please do this sparingly and only after consulting with the -target validator. - -Your validator should now only be communicating with the explicitly listed -validators and only on the _Gossip_, _Repair_ and _ServeR_ ports. - -## Setting up Deposit Accounts - -Solana accounts do not require any on-chain initialization; once they contain -some SOL, they exist. To set up a deposit account for your exchange, simply -generate a Solana keypair using any of our -[wallet tools](https://docs.anza.xyz/cli/wallets). - -We recommend using a unique deposit account for each of your users. - -Solana accounts must be made rent-exempt by containing 2-years worth of -[rent](/docs/core/fees.md#rent) in SOL. In order to find the minimum rent-exempt -balance for your deposit accounts, query the -[`getMinimumBalanceForRentExemption` endpoint](/docs/rpc/http/getMinimumBalanceForRentExemption.mdx): ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -183,57 +115,35 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - { "jsonrpc": "2.0", "result": 890880, "id": 1 } ``` -### Offline Accounts +### Офлайн Акаунти -You may wish to keep the keys for one or more collection accounts offline for -greater security. If so, you will need to move SOL to hot accounts using our -[offline methods](https://docs.anza.xyz/cli/examples/offline-signing). +Ви можете залишити ключі для одного або декількох акаунтів колекції офлайн для підвищення безпеки. У цьому випадку вам потрібно буде переміщати SOL до "гарячих" акаунтів за допомогою наших [офлайн-методів](https://docs.anza.xyz/cli/examples/offline-signing). -## Listening for Deposits +## Відстеження Депозитів -When a user wants to deposit SOL into your exchange, instruct them to send a -transfer to the appropriate deposit address. +Коли користувач хоче внести SOL на вашу біржу, інструктуйте його виконати переказ на відповідну депозитну адресу. -### Versioned Transaction Migration +### Міграція Транзакцій із Версіями -When the Mainnet Beta network starts processing versioned transactions, -exchanges **MUST** make changes. If no changes are made, deposit detection will -no longer work properly because fetching a versioned transaction or a block -containing versioned transactions will return an error. +Коли мережа Mainnet Beta почне обробляти транзакції із версіями, біржі **ЗОБОВ'ЯЗАНІ** внести зміни. Якщо не внести змін, виявлення депозитів працюватиме неправильно, оскільки отримання транзакції з версією або блоку, що містить такі транзакції, призведе до помилки. - `{"maxSupportedTransactionVersion": 0}` - The `maxSupportedTransactionVersion` parameter must be added to `getBlock` and - `getTransaction` requests to avoid disruption to deposit detection. The latest - transaction version is `0` and should be specified as the max supported - transaction version value. + Параметр `maxSupportedTransactionVersion` потрібно додати до запитів `getBlock` і `getTransaction`, щоб уникнути порушення роботи виявлення депозитів. Остання версія транзакції — `0`, і саме її слід зазначати як максимальну підтримувану версію транзакції. -It's important to understand that versioned transactions allow users to create -transactions that use another set of account keys loaded from on-chain address -lookup tables. +Важливо розуміти, що транзакції з версіями дозволяють користувачам створювати транзакції, які використовують інший набір ключів акаунтів, завантажених з ончейн таблиць пошуку адрес. - `{"encoding": "jsonParsed"}` - When fetching blocks and transactions, it's now recommended to use the - `"jsonParsed"` encoding because it includes all transaction account keys - (including those from lookup tables) in the message `"accountKeys"` list. This - makes it straightforward to resolve balance changes detailed in `preBalances` - / `postBalances` and `preTokenBalances` / `postTokenBalances`. + При отриманні блоків і транзакцій тепер рекомендується використовувати кодування `"jsonParsed"`, оскільки воно включає всі ключі акаунтів транзакції (включаючи ті, що з таблиць пошуку) у список `"accountKeys"` повідомлення. Це спрощує розв'язання змін балансу, описаних у `preBalances` / `postBalances` і `preTokenBalances` / `postTokenBalances`. - If the `"json"` encoding is used instead, entries in `preBalances` / - `postBalances` and `preTokenBalances` / `postTokenBalances` may refer to - account keys that are **NOT** in the `"accountKeys"` list and need to be - resolved using `"loadedAddresses"` entries in the transaction metadata. + Якщо використовується кодування `"json"`, записи у `preBalances` / `postBalances` і `preTokenBalances` / `postTokenBalances` можуть посилатися на ключі акаунтів, які **НЕ** входять до списку `"accountKeys"` і потребують розв'язання за допомогою записів `"loadedAddresses"` у метаданих транзакції. -### Poll for Blocks +### Опитування Блоків -To track all the deposit accounts for your exchange, poll for each confirmed -block and inspect for addresses of interest, using the JSON-RPC service of your -Solana API node. +Для відстеження всіх депозитних акаунтів вашої біржі регулярно опитуйте кожен підтверджений блок і перевіряйте адреси, що вас цікавлять, використовуючи JSON-RPC сервіс вашої ноди API Solana. -- To identify which blocks are available, send a - [`getBlocks`](/docs/rpc/http/getBlocks.mdx) request, passing the last block - you have already processed as the start-slot parameter: +- Щоб визначити, які блоки доступні, надішліть запит [`getBlocks`](/docs/uk/rpc/http/getBlocks.mdx), передавши останній блок, який ви вже обробили, як параметр start-slot: ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -255,26 +165,19 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - "id": 1 } ``` +Не кожен слот створює блок, тому в послідовності чисел можуть бути прогалини. -Not every slot produces a block, so there may be gaps in the sequence of -integers. +- Для кожного блоку запитуйте його вміст за допомогою запиту [`getBlock`](/docs/uk/rpc/http/getBlock.mdx): -- For each block, request its contents with a - [`getBlock`](/docs/rpc/http/getBlock.mdx) request: - -### Block Fetching Tips +### Поради для Отримання Блоків - `{"rewards": false}` -By default, fetched blocks will return information about validator fees on each -block and staking rewards on epoch boundaries. If you don't need this -information, disable it with the "rewards" parameter. +За замовчуванням отримані блоки містять інформацію про комісії валідаторів за кожен блок і нагороди за стейкінг на межах епох. Якщо ця інформація вам не потрібна, вимкніть її за допомогою параметра `"rewards"`. - `{"transactionDetails": "accounts"}` -By default, fetched blocks will return a lot of transaction info and metadata -that isn't necessary for tracking account balances. Set the "transactionDetails" -parameter to speed up block fetching. +За замовчуванням отримані блоки містять багато інформації про транзакції та метадані, які не потрібні для відстеження балансів акаунтів. Встановіть параметр `"transactionDetails"` для прискорення отримання блоків. ```shell curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' -d '{ @@ -360,28 +263,15 @@ curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' - } ``` -The `preBalances` and `postBalances` fields allow you to track the balance -changes in every account without having to parse the entire transaction. They -list the starting and ending balances of each account in -[lamports](/docs/terminology.md#lamport), indexed to the `accountKeys` list. For -example, if the deposit address of interest is -`G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o`, this transaction represents a -transfer of 1040000000 - 1030000000 = 10,000,000 lamports = 0.01 SOL +Поля `preBalances` і `postBalances` дозволяють відстежувати зміни балансу кожного акаунта без необхідності аналізувати всю транзакцію. Вони містять початкові та кінцеві баланси кожного акаунта у [лампортах](/docs/uk/terminology.md#lamport), проіндексовані до списку `accountKeys`. Наприклад, якщо депозитна адреса, яка вас цікавить, — це `G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o`, то ця транзакція представляє переказ 1040000000 - 1030000000 = 10,000,000 лампортів = 0.01 SOL. -If you need more information about the transaction type or other specifics, you -can request the block from RPC in binary format, and parse it using either our -[Rust SDK](https://github.com/solana-labs/solana) or -[Javascript SDK](https://github.com/solana-labs/solana-web3.js). +Якщо вам потрібна додаткова інформація про тип транзакції або інші специфічні дані, ви можете запросити блок із RPC у бінарному форматі та проаналізувати його за допомогою нашого [Rust SDK](https://github.com/solana-labs/solana) або [JavaScript SDK](https://github.com/solana-labs/solana-web3.js). -### Address History +### Історія Адрес -You can also query the transaction history of a specific address. This is -generally _not_ a viable method for tracking all your deposit addresses over all -slots, but may be useful for examining a few accounts for a specific period of -time. +Ви також можете запитати історію транзакцій для певної адреси. Це, як правило, _не_ є життєздатним методом для відстеження всіх ваших депозитних адрес за всіма слотами, але може бути корисним для аналізу кількох акаунтів за певний період часу. -- Send a [`getSignaturesForAddress`](/docs/rpc/http/getSignaturesForAddress.mdx) - request to the api node: +- Надішліть запит [`getSignaturesForAddress`](/docs/uk/rpc/http/getSignaturesForAddress.mdx) до API-ноди: ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -431,9 +321,7 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - "id": 1 } ``` - -- For each signature returned, get the transaction details by sending a - [`getTransaction`](/docs/rpc/http/getTransaction.mdx) request: +- Для кожного отриманого підпису отримайте деталі транзакції, надіславши запит [`getTransaction`](/docs/uk/rpc/http/getTransaction.mdx): ```shell curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' -d '{ @@ -530,71 +418,46 @@ curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' - } ``` -## Sending Withdrawals +## Відправлення Виведення -To accommodate a user's request to withdraw SOL, you must generate a Solana -transfer transaction, and send it to the api node to be forwarded to your -cluster. +Щоб виконати запит користувача на виведення SOL, ви повинні створити транзакцію переказу Solana та надіслати її на API-ноду для передачі в кластер. -### Synchronous +### Синхронний Переказ -Sending a synchronous transfer to the Solana cluster allows you to easily ensure -that a transfer is successful and finalized by the cluster. +Відправлення синхронного переказу до кластера Solana дозволяє легко переконатися, що переказ успішно завершено та підтверджено кластером. + +Інструмент командного рядка Solana пропонує просту команду `solana transfer` для створення, подання та підтвердження транзакцій переказу. За замовчуванням цей метод чекатиме та відстежуватиме прогрес через stderr, доки транзакція не буде підтверджена кластером. У разі невдачі транзакції буде повідомлено про будь-які помилки. -Solana's command-line tool offers a simple command, `solana transfer`, to -generate, submit, and confirm transfer transactions. By default, this method -will wait and track progress on stderr until the transaction has been finalized -by the cluster. If the transaction fails, it will report any transaction errors. ```shell solana transfer --allow-unfunded-recipient --keypair --url http://localhost:8899 ``` -The [Solana Javascript SDK](https://github.com/solana-labs/solana-web3.js) -offers a similar approach for the JS ecosystem. Use the `SystemProgram` to build -a transfer transaction, and submit it using the `sendAndConfirmTransaction` -method. +[Solana Javascript SDK](https://github.com/solana-labs/solana-web3.js) пропонує схожий підхід для екосистеми JS. Використовуйте `SystemProgram` для створення транзакції переказу та надсилайте її за допомогою методу `sendAndConfirmTransaction`. -### Asynchronous +### Асинхронний Переказ -For greater flexibility, you can submit withdrawal transfers asynchronously. In -these cases, it is your responsibility to verify that the transaction succeeded -and was finalized by the cluster. +Для більшої гнучкості ви можете надсилати перекази на виведення асинхронно. У цьому випадку саме ви несете відповідальність за перевірку успішності транзакції та її підтвердження кластером. -**Note:** Each transaction contains a -[recent blockhash](/docs/core/transactions.md#recent-blockhash) to indicate its -liveness. It is **critical** to wait until this blockhash expires before -retrying a withdrawal transfer that does not appear to have been confirmed or -finalized by the cluster. Otherwise, you risk a double spend. See more on -[blockhash expiration](#blockhash-expiration) below. +**Примітка:** Кожна транзакція містить [recent blockhash](/docs/uk/core/transactions.md#recent-blockhash), що вказує на її актуальність. Важливо **дочекатися**, поки цей blockhash не стане недійсним, перш ніж повторювати спробу переказу, який, схоже, не було підтверджено або завершено кластером. Інакше ви ризикуєте створити подвійний витрату. Дивіться більше про [термін дії blockhash](#blockhash-expiration) нижче. -First, get a recent blockhash using the -[`getFees`](/docs/rpc/deprecated/getFees.mdx) endpoint or the CLI command: +Спочатку отримайте недавній blockhash за допомогою ендпоінту [`getFees`](/docs/uk/rpc/deprecated/getFees.mdx) або команди CLI: ```shell solana fees --url http://localhost:8899 ``` +У командному рядку передайте аргумент `--no-wait`, щоб відправити переказ асинхронно, і додайте ваш недавній blockhash за допомогою аргументу `--blockhash`: -In the command-line tool, pass the `--no-wait` argument to send a transfer -asynchronously, and include your recent blockhash with the `--blockhash` -argument: ```shell solana transfer --no-wait --allow-unfunded-recipient --blockhash --keypair --url http://localhost:8899 ``` -You can also build, sign, and serialize the transaction manually, and fire it -off to the cluster using the JSON-RPC -[`sendTransaction`](/docs/rpc/http/sendTransaction.mdx) endpoint. +Ви також можете створити, підписати та серіалізувати транзакцію вручну, а потім надіслати її до кластера за допомогою ендпоінта JSON-RPC [`sendTransaction`](/docs/uk/rpc/http/sendTransaction.mdx). -#### Transaction Confirmations & Finality +#### Підтвердження Транзакцій та Фінальність -Get the status of a batch of transactions using the -[`getSignatureStatuses`](/docs/rpc/http/getSignatureStatuses.mdx) JSON-RPC -endpoint. The `confirmations` field reports how many -[confirmed blocks](/docs/terminology.md#confirmed-block) have elapsed since the -transaction was processed. If `confirmations: null`, it is -[finalized](/docs/terminology.md#finality). +Отримайте статус групи транзакцій за допомогою ендпоінта JSON-RPC [`getSignatureStatuses`](/docs/uk/rpc/http/getSignatureStatuses.mdx). Поле `confirmations` вказує, скільки [підтверджених блоків](/docs/uk/terminology.md#confirmed-block) минуло з моменту обробки транзакції. Якщо `confirmations: null`, це означає, що транзакція є [фіналізованою](/docs/uk/terminology.md#finality). ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -642,54 +505,37 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - } ``` -#### Blockhash Expiration +#### Термін Дії Blockhash -You can check whether a particular blockhash is still valid by sending a -[`getFeeCalculatorForBlockhash`](/docs/rpc/deprecated/getFeeCalculatorForBlockhash.mdx) -request with the blockhash as a parameter. If the response value is `null`, the -blockhash is expired, and the withdrawal transaction using that blockhash should -never succeed. +Ви можете перевірити, чи є конкретний blockhash ще дійсним, надіславши запит [`getFeeCalculatorForBlockhash`](/docs/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx) з blockhash як параметром. Якщо значення у відповіді `null`, blockhash недійсний, і транзакція на виведення, яка використовує цей blockhash, не має шансів на успіх. -### Validating User-supplied Account Addresses for Withdrawals +### Перевірка Адрес Акаунтів, Наданих Користувачами, для Виведення -As withdrawals are irreversible, it may be a good practice to validate a -user-supplied account address before authorizing a withdrawal in order to -prevent accidental loss of user funds. +Оскільки транзакції на виведення є незворотними, хорошою практикою може бути перевірка адреси акаунта, наданої користувачем, перед авторизацією виведення, щоб запобігти випадковій втраті коштів користувача. -#### Basic verification +#### Основна Перевірка -Solana addresses a 32-byte array, encoded with the bitcoin base58 alphabet. This -results in an ASCII text string matching the following regular expression: +Адреси Solana — це 32-байтовий масив, закодований за допомогою алфавіту base58 від Bitcoin. Це призводить до отримання ASCII-рядка, що відповідає наступному регулярному виразу: ```text [1-9A-HJ-NP-Za-km-z]{32,44} ``` -This check is insufficient on its own as Solana addresses are not checksummed, -so typos cannot be detected. To further validate the user's input, the string -can be decoded and the resulting byte array's length confirmed to be 32. -However, there are some addresses that can decode to 32 bytes despite a typo -such as a single missing character, reversed characters and ignored case +Ця перевірка сама по собі є недостатньою, оскільки адреси Solana не мають контрольної суми, тому помилки друку не можуть бути виявлені. Для додаткової перевірки введення користувачем можна декодувати рядок і підтвердити, що довжина отриманого байтового масиву дорівнює 32. Однак існують адреси, які можуть декодуватися у 32 байти, незважаючи на помилки, наприклад, пропущений символ, перестановка символів або ігнорування регістру. -#### Advanced verification +#### Розширена Перевірка -Due to the vulnerability to typos described above, it is recommended that the -balance be queried for candidate withdraw addresses and the user prompted to -confirm their intentions if a non-zero balance is discovered. +Через вразливість до помилок друку, описану вище, рекомендується запитувати баланс для можливих адрес виведення та запитувати у користувача підтвердження, якщо буде виявлено ненульовий баланс. -#### Valid ed25519 pubkey check +#### Перевірка Валідного ed25519 Публічного Ключа -The address of a normal account in Solana is a Base58-encoded string of a -256-bit ed25519 public key. Not all bit patterns are valid public keys for the -ed25519 curve, so it is possible to ensure user-supplied account addresses are -at least correct ed25519 public keys. +Адреса звичайного акаунта в Solana — це Base58-кодований рядок 256-бітного публічного ключа ed25519. Не всі бітові патерни є валідними публічними ключами для кривої ed25519, тому можна забезпечити, що адреси акаунтів, надані користувачем, принаймні є правильними публічними ключами ed25519. #### Java -Here is a Java example of validating a user-supplied address as a valid ed25519 -public key: +Ось приклад на Java для перевірки адреси, наданої користувачем, як валідного публічного ключа ed25519: -The following code sample assumes you're using the Maven. +Наступний приклад коду передбачає використання Maven. `pom.xml`: @@ -742,13 +588,12 @@ public class PubkeyValidator } ``` -## Minimum Deposit & Withdrawal Amounts +## Мінімальні Суми Депозиту та Виведення + +Кожен депозит та виведення SOL повинні бути більшими або дорівнювати мінімальному балансу, звільненому від оренди, для акаунта за адресою гаманця (базовий акаунт SOL, який не містить даних), який наразі складає: **0.000890880 SOL**. -Every deposit and withdrawal of SOL must be greater or equal to the minimum -rent-exempt balance for the account at the wallet address (a basic SOL account -holding no data), currently: 0.000890880 SOL +Аналогічно, кожен депозитний акаунт повинен містити принаймні цей баланс. -Similarly, every deposit account must contain at least this balance. ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -765,124 +610,67 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - { "jsonrpc": "2.0", "result": 890880, "id": 1 } ``` -## Prioritization Fees and Compute Units +## Пріоритетні Комісії та Обчислювальні Одиниці -In periods of high demand, it's possible for a transaction to expire before a -validator has included such transactions in their block because they chose other -transactions with higher economic value. Valid Transactions on Solana may be -delayed or dropped if Prioritization Fees are not implemented properly. +У періоди високого попиту транзакція може стати недійсною до того, як валідатор включить її до блоку, оскільки були обрані інші транзакції з вищою економічною цінністю. Валідні транзакції в Solana можуть бути затримані або скасовані, якщо Пріоритетні Комісії не впроваджені належним чином. -[Prioritization Fees](/docs/terminology.md#prioritization-fee) are additional -fees that can be added on top of the -[base Transaction Fee](/docs/core/fees.md#transaction-fees) to ensure -transaction inclusion within blocks and in these situations and help ensure -deliverability. +[Пріоритетні Комісії](/docs/uk/terminology.md#prioritization-fee) — це додаткові комісії, які можна додати до [базової комісії за транзакцію](/docs/uk/core/fees.md#transaction-fees), щоб забезпечити включення транзакцій у блоки і їх доставку. -These priority fees are added to transaction by adding a special Compute Budget -instruction that sets the desired priority fee to be paid. +Ці пріоритетні комісії додаються до транзакції шляхом додавання спеціальної інструкції `Compute Budget`, яка встановлює бажану суму комісії. - + -Failure to implement these instructions may result in network disruptions and -dropped transactions. It is strongly recommended that every exchange supporting -Solana make use of priority fees to avoid disruption. +Якщо ці інструкції не впровадити, це може призвести до збоїв у роботі мережі та скасування транзакцій. Наполегливо рекомендується кожній біржі, що підтримує Solana, використовувати пріоритетні комісії для уникнення збоїв. -### What is a Prioritization Fee? - -Prioritization Fees are priced in micro-lamports per Compute Unit (e.g. small -amounts of SOL) prepended to transactions to make them economically compelling -for validator nodes to include within blocks on the network. - -### How much should the Prioritization Fee be? - -The method for setting your prioritization fee should involve querying recent -prioritization fees to set a fee which is likely to be compelling for the -network. Using the -[`getRecentPrioritizationFees`](/docs/rpc/http/getrecentprioritizationfees) RPC -method, you can query for the prioritization fees required to land a transaction -in a recent block. +### Що таке Пріоритетна Комісія? -Pricing strategy for these priority fees will vary based on your use case. There -is no canonical way to do so. One strategy for setting your Prioritization Fees -might be to calculate your transaction success rate and then increase your -Prioritization Fee against a query to the recent transaction fees API and adjust -accordingly. Pricing for Prioritization Fees will be dynamic based on the -activity on the network and bids placed by other participants, only knowable -after the fact. +Пріоритетні комісії виражаються у мікролампортах за обчислювальну одиницю (наприклад, невеликі суми SOL) і додаються до транзакцій, щоб зробити їх економічно привабливими для валідаторів і забезпечити їх включення до блоків у мережі. -One challenge with using the `getRecentPrioritizationFees` API call is that it -may only return the lowest fee for each block. This will often be zero, which is -not a fully useful approximation of what Prioritization Fee to use in order to -avoid being rejected by validator nodes. +### Якою має бути Пріоритетна Комісія? -The `getRecentPrioritizationFees` API takes accounts' pubkeys as parameters, and -then returns the highest of the minimum prioritization fees for these accounts. -When no account is specified, the API will return the lowest fee to land to -block, which is usually zero (unless the block is full). +Метод встановлення пріоритетної комісії має включати запити до недавніх значень пріоритетних комісій, щоб встановити розмір комісії, яка буде привабливою для мережі. Використовуючи метод RPC [`getRecentPrioritizationFees`](/docs/uk/rpc/http/getrecentprioritizationfees), можна отримати дані про пріоритетні комісії, необхідні для підтвердження транзакції в недавньому блоці. -Exchanges and applications should query the RPC endpoint with the accounts that -a transaction is going to write-lock. The RPC endpoint will return the -`max(account_1_min_fee, account_2_min_fee, ... account_n_min_fee)`, which should -be the base point for the user to set the prioritization fee for that -transaction. +Стратегія ціноутворення пріоритетних комісій залежить від ваших потреб. Універсального підходу не існує. Однією зі стратегій може бути розрахунок рівня успішності ваших транзакцій і коригування пріоритетної комісії відповідно до даних з API про комісії. Ціноутворення на пріоритетні комісії є динамічним і залежить від активності в мережі та ставок інших учасників. -There are different approaches to setting Prioritization Fees and some -[third-party APIs](https://docs.helius.dev/solana-rpc-nodes/alpha-priority-fee-api) -are available to determine the best fee to apply. Given the dynamic nature of -the network, there will not be a “perfect” way to go about pricing your -Prioritization fees and careful analysis should be applied before choosing a -path forward. +### Як Впровадити Пріоритетні Комісії -### How to Implement Prioritization Fees +Додавання пріоритетних комісій до транзакції включає додавання двох інструкцій Compute Budget: -Adding priority fees on a transaction consists of prepending two Compute Budget -instructions on a given transaction: +- для встановлення ціни за обчислювальну одиницю +- для встановлення ліміту обчислювальних одиниць -- one to set the compute unit price, and -- another to set the compute unit limit +> Детальний [посібник для розробників про використання пріоритетних комісій](/content/guides/advanced/how-to-use-priority-fees.md) доступний для додаткової інформації. -> Here, you can also find a more detailed developer -> [guide on how to use priority fees](/content/guides/advanced/how-to-use-priority-fees.md) -> which includes more information about implementing priority fees. - -Create a `setComputeUnitPrice` instruction to add a Prioritization Fee above the -Base Transaction Fee (5,000 Lamports). +Створіть інструкцію `setComputeUnitPrice`, щоб додати Пріоритетну Комісію понад Базову Комісію за Транзакцію (5,000 лампортів). ```typescript // import { ComputeBudgetProgram } from "@solana/web3.js" ComputeBudgetProgram.setComputeUnitPrice({ microLamports: number }); ``` -The value provided in micro-lamports will be multiplied by the Compute Unit (CU) -budget to determine the Prioritization Fee in Lamports. For example, if your CU -budget is 1M CU, and you add `1 microLamport/CU`, the Prioritization Fee will be -1 lamport (1M \* 0. 000001). The total fee will then be 5001 lamports. +Значення, надане в мікролампортах, буде множитися на обчислювальний бюджет (Compute Unit, CU), щоб визначити Пріоритетну Комісію в лампортах. Наприклад, якщо ваш бюджет CU становить 1M CU, і ви додаєте `1 мікролампорта/CU`, Пріоритетна Комісія становитиме 1 лампорт (1M \* 0.000001). Загальна комісія складе 5001 лампорт. + +Щоб встановити новий обчислювальний бюджет для транзакції, створіть інструкцію `setComputeUnitLimit`. -To set a new compute unit budget for the transaction, create a -`setComputeUnitLimit` instruction ```typescript // import { ComputeBudgetProgram } from "@solana/web3.js" ComputeBudgetProgram.setComputeUnitLimit({ units: number }); ``` -The `units` value provided will replace the Solana runtime's default compute -budget value. +Значення `units`, яке ви надаєте, замінить стандартне значення обчислювального бюджету (Compute Budget) в середовищі виконання Solana. - + -Transactions should request the minimum amount of compute units (CU) required -for execution to maximize throughput and minimize overall fees. +Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць (CU), необхідну для виконання, щоб максимізувати пропускну здатність і мінімізувати загальні комісії. -You can get the CU consumed by a transaction by sending the transaction on a -different Solana cluster, like devnet. For example, a -[simple token transfer](https://explorer.solana.com/tx/5scDyuiiEbLxjLUww3APE9X7i8LE3H63unzonUwMG7s2htpoAGG17sgRsNAhR1zVs6NQAnZeRVemVbkAct5myi17) -takes 300 CU. +Ви можете дізнатися, скільки CU споживає транзакція, надіславши її в інший кластер Solana, наприклад, devnet. Наприклад, [простий переказ токенів](https://explorer.solana.com/tx/5scDyuiiEbLxjLUww3APE9X7i8LE3H63unzonUwMG7s2htpoAGG17sgRsNAhR1zVs6NQAnZeRVemVbkAct5myi17) займає 300 CU. + ```typescript // import { ... } from "@solana/web3.js" @@ -907,104 +695,76 @@ const transaction = new Transaction() ); ``` -### Prioritization Fees And Durable Nonces +### Пріоритетні Комісії та Транзакції з Durable Nonces -If your setup uses Durable Nonce Transactions, it is important to properly -implement Prioritization Fees in combination with Durable Transaction Nonces to -ensure successful transactions. Failure to do so will cause intended Durable -Nonce transactions not to be detected as such. +Якщо у вашій системі використовуються транзакції з Durable Nonces, важливо правильно впровадити Пріоритетні Комісії разом із Durable Transaction Nonces, щоб забезпечити успішне виконання транзакцій. Якщо цього не зробити, заплановані Durable Nonce транзакції не будуть розпізнані належним чином. -If you ARE using Durable Transaction Nonces, the `AdvanceNonceAccount` -instruction MUST be specified FIRST in the instructions list, even when the -compute budget instructions are used to specify priority fees. +Якщо ви ВИКОРИСТОВУЄТЕ Durable Transaction Nonces, інструкція `AdvanceNonceAccount` МАЄ бути зазначена ПЕРШОЮ у списку інструкцій, навіть якщо використовуються інструкції обчислювального бюджету для встановлення пріоритетних комісій. -You can find a specific code example -[using durable nonces and priority fees together](/content/guides/advanced/how-to-use-priority-fees.md#special-considerations) -in this developer guide. +Специфічний приклад коду, що демонструє використання durable nonces і пріоритетних комісій разом, можна знайти у [керівництві для розробників](/content/guides/advanced/how-to-use-priority-fees.md#special-considerations). -## Supporting the SPL Token Standard +## Підтримка Стандарту SPL Token -[SPL Token](https://spl.solana.com/token) is the standard for wrapped/synthetic -token creation and exchange on the Solana blockchain. +[SPL Token](https://spl.solana.com/token) є стандартом для створення і обміну обгорнутих/синтетичних токенів у блокчейні Solana. -The SPL Token workflow is similar to that of native SOL tokens, but there are a -few differences which will be discussed in this section. +Робочий процес SPL Token схожий на той, що використовується для нативних SOL токенів, але є кілька відмінностей, які будуть розглянуті в цьому розділі. -### Token Mints +### Токен Mints -Each _type_ of SPL Token is declared by creating a _mint_ account. This account -stores metadata describing token features like the supply, number of decimals, -and various authorities with control over the mint. Each SPL Token account -references its associated mint and may only interact with SPL Tokens of that -type. +Кожен _тип_ SPL Token декларується шляхом створення акаунта _mint_. Цей акаунт зберігає метадані, які описують характеристики токена, такі як пропозиція, кількість десяткових знаків і різні повноваження з контролю за mint. Кожен акаунт SPL Token посилається на відповідний mint і може взаємодіяти лише з SPL Token цього типу. -### Installing the `spl-token` CLI Tool +### Встановлення CLI Інструменту `spl-token` -SPL Token accounts are queried and modified using the `spl-token` command line -utility. The examples provided in this section depend upon having it installed -on the local system. +Акаунти SPL Token можна запитувати та змінювати за допомогою утиліти командного рядка `spl-token`. Приклади, наведені в цьому розділі, залежать від того, що вона встановлена на вашій локальній системі. -`spl-token` is distributed from Rust -[crates.io](https://crates.io/crates/spl-token) via the Rust `cargo` command -line utility. The latest version of `cargo` can be installed using a handy -one-liner for your platform at [rustup.rs](https://rustup.rs). Once `cargo` is -installed, `spl-token` can be obtained with the following command: +`spl-token` розповсюджується з Rust [crates.io](https://crates.io/crates/spl-token) через утиліту командного рядка Rust `cargo`. Останню версію `cargo` можна встановити за допомогою простого скрипта для вашої платформи на [rustup.rs](https://rustup.rs). Після встановлення `cargo`, утиліту `spl-token` можна отримати за допомогою такої команди: ```shell cargo install spl-token-cli ``` -You can then check the installed version to verify +Після цього ви можете перевірити встановлену версію, щоб переконатися у правильності встановлення: ```shell spl-token --version ``` -Which should result in something like +Результат має виглядати приблизно так: ```text spl-token-cli 2.0.1 ``` +### Створення Акаунтів -### Account Creation +Акаунти SPL Token мають додаткові вимоги, яких не мають нативні акаунти System Program: -SPL Token accounts carry additional requirements that native System Program -accounts do not: +1. Акаунти SPL Token мають бути створені до того, як у них можна буде внести токени. Акаунти токенів можна створити явно за допомогою команди `spl-token create-account` або неявно за допомогою команди `spl-token transfer --fund-recipient ...`. +2. Акаунти SPL Token повинні залишатися [звільненими від оренди](/docs/uk/core/fees.md#rent-exempt) протягом усього періоду їх існування, а отже, вимагають внесення невеликої кількості нативних SOL токенів під час створення акаунта. Для акаунтів SPL Token ця сума становить 0.00203928 SOL (2,039,280 лампортів). -1. SPL Token accounts must be created before an amount of tokens can be - deposited. Token accounts can be created explicitly with the - `spl-token create-account` command, or implicitly by the - `spl-token transfer --fund-recipient ...` command. -1. SPL Token accounts must remain [rent-exempt](/docs/core/fees.md#rent-exempt) - for the duration of their existence and therefore require a small amount of - native SOL tokens be deposited at account creation. For SPL Token accounts, - this amount is 0.00203928 SOL (2,039,280 lamports). +#### Командний Рядок -#### Command Line +Щоб створити акаунт SPL Token з такими властивостями: -To create an SPL Token account with the following properties: - -1. Associated with the given mint -1. Owned by the funding account's keypair +1. Асоційований із зазначеним mint +2. Належить ключовій парі фінансуючого акаунта ```shell spl-token create-account ``` -#### Example +#### Приклад ```shell spl-token create-account AkUFCWTXb3w9nY2n6SFJvBV6VwvFUCe4KBMCcgLsa2ir ``` -Giving an output similar to: +Результат: ``` Creating account 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV Signature: 4JsqZEPra2eDTHtHpB4FMWSfk3UgcCVmkKkP7zESZeMrKmFFkDkNd91pKP3vPVVZZPiu5XxyJwS73Vi5WsZL88D7 ``` - -Or to create an SPL Token account with a specific keypair: +Або щоб створити акаунт SPL Token з конкретною ключовою парою: ```shell solana-keygen new -o token-account.json @@ -1012,56 +772,54 @@ solana-keygen new -o token-account.json spl-token create-account AkUFCWTXb3w9nY2n6SFJvBV6VwvFUCe4KBMCcgLsa2ir token-account.json ``` -Giving an output similar to: +Результат: ```shell Creating account 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV Signature: 4JsqZEPra2eDTHtHpB4FMWSfk3UgcCVmkKkP7zESZeMrKmFFkDkNd91pKP3vPVVZZPiu5XxyJwS73Vi5WsZL88D7 ``` +### Перевірка Балансу Акаунта -### Checking an Account's Balance +#### Командний Рядок -#### Command Line +Щоб перевірити баланс акаунта SPL Token, використовуйте наступну команду: ```shell spl-token balance ``` -#### Example +#### Приклад ```shell solana balance 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV ``` -Giving an output similar to: +Результат: ``` 0 ``` +### Переказ Токенів -### Token Transfers +Вихідним акаунтом для переказу є фактичний акаунт токенів, який містить необхідну суму. -The source account for a transfer is the actual token account that contains the -amount. +Однак адресою отримувача може бути звичайний гаманець. Якщо асоційований токен акаунт для вказаного mint ще не існує для цього гаманця, переказ створить його, якщо буде вказаний аргумент `--fund-recipient`. -The recipient address however can be a normal wallet account. If an associated -token account for the given mint does not yet exist for that wallet, the -transfer will create it provided that the `--fund-recipient` argument as -provided. +#### Командний Рядок -#### Command Line +Щоб виконати переказ токенів, використовуйте наступну команду: ```shell spl-token transfer --fund-recipient ``` -#### Example +#### Приклад ```shell spl-token transfer 6B199xxzw3PkAm25hGJpjj3Wj3WNYNHzDAnt1tEqg5BN 1 ``` -Giving an output similar to: +Результат: ```shell 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV @@ -1071,224 +829,148 @@ Transfer 1 tokens Signature: 3R6tsog17QM8KfzbcbdP4aoMfwgo6hBggJDVy7dZPVmH2xbCWjEj31JKD53NzMrf25ChFjY7Uv2dfCDq4mGFFyAj ``` -### Depositing - -Since each `(wallet, mint)` pair requires a separate account onchain. It is -recommended that the addresses for these accounts be derived from SOL deposit -wallets using the -[Associated Token Account](https://spl.solana.com/associated-token-account) -(ATA) scheme and that _only_ deposits from ATA addresses be accepted. - -Monitoring for deposit transactions should follow the -[block polling](#poll-for-blocks) method described above. Each new block should -be scanned for successful transactions referencing user token-account derived -addresses. The `preTokenBalance` and `postTokenBalance` fields from the -transaction's metadata must then be used to determine the effective balance -change. These fields will identify the token mint and account owner (main wallet -address) of the affected account. - -Note that if a receiving account is created during the transaction, it will have -no `preTokenBalance` entry as there is no existing account state. In this case, -the initial balance can be assumed to be zero. - -### Withdrawing - -The withdrawal address a user provides must be that of their SOL wallet. - -Before executing a withdrawal [transfer](#token-transfers), the exchange should -check the address as -[described above](#validating-user-supplied-account-addresses-for-withdrawals). -Additionally this address must be owned by the System Program and have no -account data. If the address has no SOL balance, user confirmation should be -obtained before proceeding with the withdrawal. All other withdrawal addresses -must be rejected. - -From the withdrawal address, the -[Associated Token Account](https://spl.solana.com/associated-token-account) -(ATA) for the correct mint is derived and the transfer issued to that account -via a -[TransferChecked](https://github.com/solana-labs/solana-program-library/blob/fc0d6a2db79bd6499f04b9be7ead0c400283845e/token/program/src/instruction.rs#L268) -instruction. Note that it is possible that the ATA address does not yet exist, -at which point the exchange should fund the account on behalf of the user. For -SPL Token accounts, funding the withdrawal account will require 0.00203928 SOL -(2,039,280 lamports). - -Template `spl-token transfer` command for a withdrawal: +### Депозити + +Оскільки кожна пара `(гаманець, mint)` потребує окремого акаунта в ончейні, рекомендується, щоб адреси для цих акаунтів були отримані з гаманців для депозиту SOL за допомогою схеми [Associated Token Account (ATA)](https://spl.solana.com/associated-token-account), і приймалися _лише_ депозити з ATA адрес. + +Відстеження транзакцій депозиту має використовувати метод [опитування блоків](#poll-for-blocks), описаний вище. Кожен новий блок слід сканувати на наявність успішних транзакцій, що посилаються на адреси акаунтів, отриманих для користувачів. Поля `preTokenBalance` і `postTokenBalance` з метаданих транзакцій необхідно використовувати для визначення ефективної зміни балансу. Ці поля ідентифікують mint токена та власника акаунта (основну адресу гаманця) відповідного акаунта. + +Зауважте, що якщо акаунт для отримання створюється під час транзакції, у нього не буде запису `preTokenBalance`, оскільки стан акаунта раніше не існував. У цьому випадку початковий баланс можна вважати нульовим. + +### Виведення + +Адреса для виведення, надана користувачем, має бути адресою їх SOL гаманця. + +Перед виконанням [переказу](#token-transfers) для виведення біржа повинна перевірити адресу, як це [описано вище](#validating-user-supplied-account-addresses-for-withdrawals). Крім того, ця адреса має належати System Program і не мати даних акаунта. Якщо на цій адресі відсутній баланс SOL, перед виконанням виведення слід отримати підтвердження користувача. Усі інші адреси для виведення повинні бути відхилені. + +З адреси для виведення [Associated Token Account (ATA)](https://spl.solana.com/associated-token-account) для відповідного mint отримується, і переказ виконується на цей акаунт за допомогою інструкції [TransferChecked](https://github.com/solana-labs/solana-program-library/blob/fc0d6a2db79bd6499f04b9be7ead0c400283845e/token/program/src/instruction.rs#L268). Зауважте, що ATA адреса може ще не існувати, у цьому випадку біржа повинна профінансувати акаунт від імені користувача. Для акаунтів SPL Token фінансування акаунта для виведення потребує 0.00203928 SOL (2,039,280 лампортів). + +Шаблон команди `spl-token transfer` для виведення: ```shell spl-token transfer --fund-recipient ``` -### Other Considerations +### Інші Міркування -#### Freeze Authority +#### Freeze Authority (Замороження Акаунтів) -For regulatory compliance reasons, an SPL Token issuing entity may optionally -choose to hold "Freeze Authority" over all accounts created in association with -its mint. This allows them to -[freeze](https://spl.solana.com/token#freezing-accounts) the assets in a given -account at will, rendering the account unusable until thawed. If this feature is -in use, the freeze authority's pubkey will be registered in the SPL Token's mint -account. +Для дотримання регуляторних вимог емітент токенів SPL може опціонально мати "Freeze Authority" (повноваження замороження) для всіх акаунтів, створених у зв'язку з його mint. Це дозволяє йому [заморожувати](https://spl.solana.com/token#freezing-accounts) активи в певному акаунті за бажанням, роблячи акаунт недоступним до моменту його розморожування. Якщо ця функція використовується, публічний ключ freeze authority буде зареєстрований у акаунті mint токену SPL. -### Basic Support for the SPL Token-2022 (Token-Extensions) Standard +### Основна Підтримка Стандарту SPL Token-2022 (Token-Extensions) -[SPL Token-2022](https://spl.solana.com/token-2022) is the newest standard for -wrapped/synthetic token creation and exchange on the Solana blockchain. +[SPL Token-2022](https://spl.solana.com/token-2022) є новим стандартом для створення й обміну обгорнутих/синтетичних токенів у блокчейні Solana. -Also known as "Token Extensions", the standard contains many new features that -token creators and account holders may optionally enable. These features include -confidential transfers, fees on transfer, closing mints, metadata, permanent -delegates, immutable ownership, and much more. Please see the -[extension guide](https://spl.solana.com/token-2022/extensions) for more -information. +Відомий також як "Token Extensions", цей стандарт включає багато нових функцій, які можуть бути опціонально увімкнені творцями токенів та власниками акаунтів. До таких функцій належать конфіденційні перекази, комісії за переказ, закриття mint, метадані, постійні делегати, незмінна власність тощо. Більше інформації дивіться в [керівництві з розширень](https://spl.solana.com/token-2022/extensions). -If your exchange supports SPL Token, there isn't a lot more work required to -support SPL Token-2022: +Якщо ваша біржа підтримує SPL Token, багато додаткових зусиль для підтримки SPL Token-2022 не знадобиться: -- the CLI tool works seamlessly with both programs starting with version 3.0.0. -- `preTokenBalances` and `postTokenBalances` include SPL Token-2022 balances -- RPC indexes SPL Token-2022 accounts, but they must be queried separately with - program id `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` +- CLI інструмент безпроблемно працює з обома програмами, починаючи з версії 3.0.0. +- Поля `preTokenBalances` та `postTokenBalances` включають баланси SPL Token-2022. +- RPC індексує акаунти SPL Token-2022, але їх потрібно запитувати окремо за програмним ідентифікатором `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`. -The Associated Token Account works the same way, and properly calculates the -required deposit amount of SOL for the new account. +Програма Associated Token Account працює так само, і правильно розраховує необхідну суму депозиту SOL для нового акаунта. -Because of extensions, however, accounts may be larger than 165 bytes, so they -may require more than 0.00203928 SOL to fund. +Однак через розширення акаунти можуть бути більшими за 165 байтів, тому вони можуть потребувати більше ніж 0.00203928 SOL для фінансування. -For example, the Associated Token Account program always includes the "immutable -owner" extension, so accounts take a minimum of 170 bytes, which requires -0.00207408 SOL. +Наприклад, програма Associated Token Account завжди включає розширення "immutable owner", тому акаунти займають мінімум 170 байтів, що вимагає 0.00207408 SOL. -### Extension-Specific Considerations +### Міркування Щодо Розширень -The previous section outlines the most basic support for SPL Token-2022. Since -the extensions modify the behavior of tokens, exchanges may need to change how -they handle tokens. +Попередній розділ описує базову підтримку SPL Token-2022. Оскільки розширення змінюють поведінку токенів, біржам, можливо, доведеться змінити, як вони обробляють токени. -It is possible to see all extensions on a mint or token account: +Можливо побачити всі розширення на mint або токен акаунті за допомогою наступної команди: ```shell spl-token display ``` -#### Transfer Fee +#### Комісія за Переказ -A token may be configured with a transfer fee, where a portion of transferred -tokens are withheld at the destination for future collection. +Токен може бути налаштований з комісією за переказ, при якій частина переданих токенів утримується на адресі отримувача для подальшого стягнення. -If your exchange transfers these tokens, beware that they may not all arrive at -the destination due to the withheld amount. +Якщо ваша біржа здійснює переказ цих токенів, зверніть увагу, що не всі токени можуть надійти на адресу отримувача через утриману суму. -It is possible to specify the expected fee during a transfer to avoid any -surprises: +Під час переказу можна вказати очікувану комісію, щоб уникнути несподіванок: ```shell spl-token transfer --expected-fee --fund-recipient ``` -#### Mint Close Authority +#### Повноваження Закриття Mint -With this extension, a token creator may close a mint, provided the supply of -tokens is zero. +З цим розширенням творець токена може закрити mint, якщо пропозиція токенів дорівнює нулю. -When a mint is closed, there may still be empty token accounts in existence, and -they will no longer be associated to a valid mint. +Коли mint закривається, можуть залишатися порожні токен акаунти, які більше не будуть асоційовані з дійсним mint. -It is safe to simply close these token accounts: +Ці токен акаунти можна безпечно закрити за допомогою наступної команди: ```shell spl-token close --address ``` -#### Confidential Transfer +#### Конфіденційні Перекази -Mints may be configured for confidential transfers, so that token amounts are -encrypted, but the account owners are still public. +Mint може бути налаштований для конфіденційних переказів, при яких суми токенів шифруються, але власники акаунтів залишаються публічними. -Exchanges may configure token accounts to send and receive confidential -transfers, to hide user amounts. It is not required to enable confidential -transfers on token accounts, so exchanges can force users to send tokens -non-confidentially. +Біржі можуть налаштувати токен акаунти для відправлення та отримання конфіденційних переказів, щоб приховати суми користувачів. Увімкнення конфіденційних переказів для токен акаунтів не є обов’язковим, тому біржі можуть змусити користувачів надсилати токени неконфіденційно. -To enable confidential transfers, the account must be configured for it: +Щоб увімкнути конфіденційні перекази, акаунт має бути налаштований відповідним чином: ```shell spl-token configure-confidential-transfer-account --address ``` -And to transfer: +Для переказу: ```shell spl-token transfer --confidential ``` -During a confidential transfer, the `preTokenBalance` and `postTokenBalance` -fields will show no change. In order to sweep deposit accounts, you must decrypt -the new balance to withdraw the tokens: +Під час конфіденційного переказу поля `preTokenBalance` та `postTokenBalance` не показуватимуть змін. Щоб виконати операцію з депозитними акаунтами, необхідно розшифрувати новий баланс, щоб вивести токени: ```shell spl-token apply-pending-balance --address spl-token withdraw-confidential-tokens --address ``` -#### Default Account State +#### Стандартний Стан Акаунтів -Mints may be configured with a default account state, such that all new token -accounts are frozen by default. These token creators may require users to go -through a separate process to thaw the account. +Mint може бути налаштований із стандартним станом акаунтів, коли всі нові токен акаунти за замовчуванням заморожені. Творці токенів можуть вимагати від користувачів проходження окремого процесу для розморожування акаунта. -#### Non-Transferable +#### Непередавані Токени -Some tokens are non-transferable, but they may still be burned and the account -can be closed. +Деякі токени є непередаваними, але їх все ще можна спалити, а акаунт закрити. -#### Permanent Delegate +#### Постійний Делегат -Token creators may designate a permanent delegate for all of their tokens. The -permanent delegate may transfer or burn tokens from any account, potentially -stealing funds. +Творці токенів можуть призначити постійного делегата для всіх своїх токенів. Постійний делегат може передавати або спалювати токени з будь-якого акаунта, потенційно викрадаючи кошти. -This is a legal requirement for stablecoins in certain jurisdictions, or could -be used for token repossession schemes. +Це може бути юридичною вимогою для стейблкоїнів у певних юрисдикціях або використовуватися для схем повернення токенів. -Beware that these tokens may be transferred without your exchange's knowledge. +Будьте уважні, оскільки ці токени можуть бути передані без відома вашої біржі. -#### Transfer Hook +#### Перехоплювач Переказів (Transfer Hook) -Tokens may be configured with an additional program that must be called during -transfers, in order to validate the transfer or perform any other logic. +Токени можуть бути налаштовані з додатковою програмою, яку необхідно викликати під час переказів для перевірки транзакції або виконання іншої логіки. -Since the Solana runtime requires all accounts to be explicitly passed to a -program, and transfer hooks require additional accounts, the exchange needs to -create transfer instructions differently for these tokens. +Оскільки середовище виконання Solana вимагає, щоб усі акаунти були явно передані до програми, а перехоплювачі переказів вимагають додаткових акаунтів, біржа повинна створювати інструкції для переказу цих токенів по-іншому. -The CLI and instruction creators such as -`createTransferCheckedWithTransferHookInstruction` add the extra accounts -automatically, but the additional accounts may also be specified explicitly: +CLI та творці інструкцій, такі як `createTransferCheckedWithTransferHookInstruction`, додають додаткові акаунти автоматично, але також можна вказати додаткові акаунти явно: ```shell spl-token transfer --transfer-hook-account --transfer-hook-account ... ``` +#### Обов'язкова Нотатка (Memo) при Переказі -#### Required Memo on Transfer - -Users may configure their token accounts to require a memo on transfer. +Користувачі можуть налаштувати свої токен акаунти так, щоб перекази вимагали нотатку (memo). -Exchanges may need to prepend a memo instruction before transferring tokens back -to users, or they may require users to prepend a memo instruction before sending -to the exchange: +Біржі можуть додавати інструкцію нотатки перед тим, як переказати токени користувачам, або вимагати, щоб користувачі додавали нотатку перед відправкою токенів на біржу: ```shell spl-token transfer --with-memo ``` +## Тестування Інтеграції -## Testing the Integration +Обов'язково протестуйте весь свій робочий процес у кластерах Solana devnet та testnet [clusters](/docs/uk/core/clusters.md) перед переходом до продакшну на mainnet-beta. Devnet є найбільш відкритим і гнучким, і ідеально підходить для початкової розробки, тоді як testnet пропонує більш реалістичну конфігурацію кластера. Обидва кластери devnet та testnet підтримують faucet. Використовуйте команду `solana airdrop 1`, щоб отримати трохи SOL для devnet або testnet для розробки та тестування. -Be sure to test your complete workflow on Solana devnet and testnet -[clusters](/docs/core/clusters.md) before moving to production on mainnet-beta. -Devnet is the most open and flexible, and ideal for initial development, while -testnet offers more realistic cluster configuration. Both devnet and testnet -support a faucet, run `solana airdrop 1` to obtain some devnet or testnet SOL -for development and testing. diff --git a/docs/uk/more/index.md b/docs/uk/more/index.md index 0c7f22484..6243eccd2 100644 --- a/docs/uk/more/index.md +++ b/docs/uk/more/index.md @@ -1,6 +1,6 @@ --- metaOnly: true -title: More Information +title: Більше інформації # note: sort order is set to a really high number so this section is at the bottom of the sidebar sidebarSortOrder: 9999 --- diff --git a/docs/uk/programs/testing.md b/docs/uk/programs/testing.md index 622364e92..dbd7711fa 100644 --- a/docs/uk/programs/testing.md +++ b/docs/uk/programs/testing.md @@ -1,87 +1,42 @@ ---- -title: "Testing with NodeJS" -description: "Testing native solana programs written with rust using NodeJS" -sidebarSortOrder: 5 ---- - -When developing programs on Solana, ensuring their correctness and reliability -is crucial. Until now devs have been using `solana-test-validator` for testing. -This document covers testing your Solana program with Node.js -using `solana-bankrun`. - -## Overview - -There are two ways to test programs on Solana: - -1. [solana-test-validator](https://docs.anza.xyz/cli/examples/test-validator): - That spins up a local emulator of the Solana Blockchain on your local machine - which receives the transactions to be processed by the validator. -2. The various - [BanksClient-based](https://docs.rs/solana-banks-client/latest/solana_banks_client/) - test frameworks for SBF (Solana Bytecode Format) programs: Bankrun is a - framework that simulates a Solana bank's operations, enabling developers to - deploy, interact with, and assess the behavior of programs under test - conditions that mimic the mainnet. It helps set up the test environment and - offers tools for detailed transaction insights, enhancing debugging and - verification. With the client, we can load programs, and simulate and process - transactions seamlessly. - [solana-program-test](https://docs.rs/solana-program-test) (Rust), - [solana-bankrun](https://github.com/kevinheavey/solana-bankrun) (Rust, - JavaScript), [anchor-bankrun](https://www.npmjs.com/package/anchor-bankrun) - (Anchor, JavaScript), - [solders.bankrun](https://kevinheavey.github.io/solders/api_reference/bankrun.html) - (Python) are examples of the BanksClient-based testing framework. - -> [`pnpm create solana-program`](https://github.com/solana-program/create-solana-program) -> can help you generate JS and Rust clients including tests. Anchor is not yet -> supported. - -In this guide, we are using Solana Bankrun. `Bankrun` is a superfast, powerful, -and lightweight framework for testing Solana programs in Node.js. - -- The biggest advantage of using Solana Bankrun is that you don't have to set - up - an environment to test programs like you'd have to do while using the - `solana-test-validator`. Instead, you can do that with a piece of code, - inside - the tests. -- It also dynamically sets time and account data, which isn't possible with - `solana-test-validator` - -## Installation - -Add `solana-bankrun` as a dev dependency to your node project. If your Solana -program is not a node project yet, you can initialize it using `npm init`. +## Тестування з NodeJS -```bash -npm i -D solana-bankrun -``` +Коли ви розробляєте програми на Solana, важливо забезпечити їхню правильність і надійність. До цього часу розробники використовували `solana-test-validator` для тестування. Цей документ описує тестування вашої програми Solana за допомогою Node.js і бібліотеки `solana-bankrun`. -## Usage +## Огляд -### Program Directory +Є два способи тестування програм на Solana: -Firstly, the program's `.so` file must be present in one of the following -directories: +1. [solana-test-validator](https://docs.anza.xyz/cli/examples/test-validator): Локальний емулятор блокчейна Solana, який обробляє транзакції, що надсилаються на валідацію. +2. Різні фреймворки для тестування програм SBF (Solana Bytecode Format) на базі BanksClient: + - `Bankrun` — це фреймворк, що імітує роботу Solana bank, дозволяючи розробникам розгортати програми, взаємодіяти з ними та оцінювати їх поведінку у тестових умовах, що нагадують mainnet. + - Підтримуються фреймворки як [solana-program-test](https://docs.rs/solana-program-test) (Rust), [solana-bankrun](https://github.com/kevinheavey/solana-bankrun) (Rust, JavaScript), [anchor-bankrun](https://www.npmjs.com/package/anchor-bankrun) (Anchor, JavaScript), [solders.bankrun](https://kevinheavey.github.io/solders/api_reference/bankrun.html) (Python). -- `./tests/fixtures` (just create this directory if it doesn't exist already). -- Your current working directory. -- A directory you define in the `BPF_OUT_DIR` or `SBF_OUT_DIR` environment - variables. `export BPF_OUT_DIR='/path/to/binary'` -- Build your program specifying the correct directory so that library can pick - the file up from directory just from the name. - `cargo build-sbf --manifest-path=./program/Cargo.toml --sbf-out-dir=./tests/fixtures` +> [`pnpm create solana-program`](https://github.com/solana-program/create-solana-program) +> може допомогти створити клієнти для JS і Rust, включаючи тести. Anchor ще не підтримується. -### Testing Framework +У цьому керівництві ми використовуємо `Solana Bankrun`. +`Bankrun` — це дуже швидкий, потужний та легкий фреймворк для тестування програм Solana у Node.js. -solana-bankrun is used in JavaScript or TypeScript with testing frameworks like -[ts-mocha](https://www.npmjs.com/package/ts-mocha), -[ava](https://github.com/avajs/ava), [Jest](https://jestjs.io/), -etc. Make sure to get started with any of the above. +- Основна перевага використання `Solana Bankrun` полягає в тому, що вам не потрібно налаштовувати середовище для тестування програм, як це потрібно при використанні `solana-test-validator`. Це можна зробити за допомогою коду всередині тестів. +- `Bankrun` динамічно встановлює час та дані акаунтів, що неможливо при використанні `solana-test-validator`. -Add an [npm script](https://docs.npmjs.com/cli/v9/using-npm/scripts) to test -your program and create your `test.ts` file inside `tests` folder. +## Інсталяція +Додайте `solana-bankrun` як dev-залежність до вашого Node.js проекту. Якщо ваша Solana програма ще не є Node.js проектом, ви можете ініціалізувати її за допомогою команди `npm init`: + +```bash +npm i -D solana-bankrun +``` +## Використання + +### Директорія для Програми + +Перш за все, `.so` файл вашої програми повинен бути присутнім в одній із наступних директорій: + +- `./tests/fixtures` (створіть цю директорію, якщо її ще не існує). +- Ваша поточна робоча директорія. +- Директорія, яку ви визначите в змінних середовища `BPF_OUT_DIR` або `SBF_OUT_DIR`. + Наприклад: ```json { "scripts": { @@ -89,11 +44,11 @@ your program and create your `test.ts` file inside `tests` folder. } } ``` +### Початок Роботи -### Start +Функція `start` з бібліотеки `solana-bankrun` запускає `BanksServer` і `BanksClient`, розгортає програми та додає акаунти відповідно до ваших інструкцій. -`start` function from `solana-bankrun` spins up a BanksServer and a BanksClient, -deploy programs and add accounts as instructed. +Приклад використання: ```typescript import { start } from "solana-bankrun"; @@ -108,22 +63,12 @@ test("testing program instruction", async () => { // write tests }); ``` +### `context` у Bankrun -### Bankrun `context` - -- We get access to the Bankrun `context` from the `start` function. Context - contains a BanksClient, a recent blockhash and a funded payer keypair. -- `context` has a `payer`, which is a funded keypair that can be used to sign - transactions. -- `context` also has `context.lastBlockhash` or `context.getLatestBlockhash` to - make fetching [Blockhash](https://solana.com/docs/terminology#blockhash) - convenient during tests. -- `context.banksClient` is used to send transactions and query account data from - the ledger state. For example, sometimes - [Rent](https://solana.com/docs/terminology#rent) (in lamports) is - required to build a transaction to be submitted, for example, when using the - SystemProgram's - createAccount() instruction. You can do that using BanksClient: +- Ми отримуємо доступ до `context` з функції `start`. `context` містить `BanksClient`, останній blockhash та профінансовану keypair для підпису транзакцій. +- У `context` є `payer`, який є профінансованою парою ключів і може використовуватися для підпису транзакцій. +- `context` також містить `context.lastBlockhash` або `context.getLatestBlockhash`, що спрощує отримання [Blockhash](https://solana.com/docs/terminology#blockhash) під час тестів. +- `context.banksClient` використовується для надсилання транзакцій і отримання даних акаунтів зі стану реєстру. Наприклад, іноді потрібна [оренда (Rent)](https://solana.com/docs/terminology#rent) (в лампортах) для створення транзакції, наприклад, при використанні інструкції `createAccount()` з `SystemProgram`. Це можна зробити за допомогою `BanksClient`: ```typescript const rent = await client.getRent(); @@ -134,26 +79,24 @@ test("testing program instruction", async () => { //.... }); ``` +- Ви можете зчитувати дані акаунта з `BanksClient`, використовуючи функцію `getAccount`. -- You can read account data from BanksClient using `getAccount` function ```typescript AccountInfo = await client.getAccount(counter); ``` -### Process Transaction +### Обробка Транзакції -The `processTransaction()` function executes the transaction with the loaded -programs -and accounts from the start function and will return a transaction. +Функція `processTransaction()` виконує транзакцію з використанням завантажених програм і акаунтів, отриманих із функції `start`. Вона повертає результат виконаної транзакції. ```typescript let transaction = await client.processTransaction(tx); ``` +## Приклад -## Example +Ось приклад тесту для програми +[hello world](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/native): -Here's an example to write test for -a [hello world program](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/native) : ```typescript import { @@ -209,9 +152,8 @@ describe("hello-solana", async () => { }); }); ``` - -This is how the output looks like after running the tests for -[hello world program](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/native). +Ось як виглядає результат після запуску тестів для +[hello world програми](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/native): ```text [2024-06-04T12:57:36.188822000Z INFO solana_program_test] "hello_solana_program" SBF program from tests/fixtures/hello_solana_program.so, modified 3 seconds, 20 ms, 687 µs and 246 ns ago From ec80f786d42f2d367917e31cbcb986d3dca86a54 Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Tue, 14 Jan 2025 22:05:42 +0200 Subject: [PATCH 10/14] Finished translation of main folders. Reverted file structure to keep backward compatibility --- docs/{en => }/advanced/actions.md | 0 docs/{en => }/advanced/confirmation.md | 0 docs/{en => }/advanced/index.md | 0 docs/{en => }/advanced/lookup-tables.md | 0 docs/{en => }/advanced/retry.md | 0 docs/{en => }/advanced/state-compression.md | 0 docs/{en => }/advanced/versions.md | 0 docs/{en => }/clients/index.md | 0 docs/{en => }/clients/javascript-reference.md | 0 docs/{en => }/clients/javascript.md | 0 docs/{en => }/clients/rust.md | 0 docs/{en => }/core/accounts.md | 0 docs/{en => }/core/clusters.md | 0 docs/{en => }/core/cpi.md | 0 docs/{en => }/core/fees.md | 0 docs/{en => }/core/index.md | 0 docs/{en => }/core/pda.md | 0 docs/{en => }/core/programs.md | 0 docs/{en => }/core/tokens.md | 0 docs/{en => }/core/transactions.md | 0 docs/{en => }/economics/index.md | 0 .../inflation/_adjusted_staking_yield.md | 0 .../economics/inflation/inflation-schedule.md | 0 .../economics/inflation/terminology.md | 0 docs/{en => }/economics/staking/index.md | 0 .../economics/staking/stake-accounts.md | 0 .../economics/staking/stake-programming.md | 0 docs/{en => }/index.md | 0 docs/{en => }/intro/dev.md | 0 docs/{en => }/intro/index.md | 0 docs/{en => }/intro/installation.md | 0 .../quick-start/cross-program-invocation.md | 0 .../intro/quick-start/deploying-programs.md | 0 docs/{en => }/intro/quick-start/index.md | 0 .../quick-start/program-derived-address.md | 0 .../intro/quick-start/reading-from-network.md | 0 .../intro/quick-start/writing-to-network.md | 0 docs/{en => }/intro/wallets.md | 0 docs/{ => locales}/uk/advanced/actions.md | 0 .../{ => locales}/uk/advanced/confirmation.md | 0 docs/{ => locales}/uk/advanced/index.md | 0 .../uk/advanced/lookup-tables.md | 0 docs/{ => locales}/uk/advanced/retry.md | 0 .../uk/advanced/state-compression.md | 0 docs/{ => locales}/uk/advanced/versions.md | 0 docs/{ => locales}/uk/clients/index.md | 0 .../uk/clients/javascript-reference.md | 0 docs/{ => locales}/uk/clients/javascript.md | 0 docs/{ => locales}/uk/clients/rust.md | 0 docs/{ => locales}/uk/core/accounts.md | 0 docs/{ => locales}/uk/core/clusters.md | 0 docs/{ => locales}/uk/core/cpi.md | 0 docs/{ => locales}/uk/core/fees.md | 0 docs/{ => locales}/uk/core/index.md | 0 docs/{ => locales}/uk/core/pda.md | 0 docs/{ => locales}/uk/core/programs.md | 0 docs/{ => locales}/uk/core/tokens.md | 0 docs/{ => locales}/uk/core/transactions.md | 0 docs/{ => locales}/uk/economics/index.md | 0 .../inflation/_adjusted_staking_yield.md | 0 .../economics/inflation/inflation-schedule.md | 0 .../uk/economics/inflation/terminology.md | 0 .../uk/economics/staking/index.md | 0 .../uk/economics/staking/stake-accounts.md | 0 .../uk/economics/staking/stake-programming.md | 0 docs/{ => locales}/uk/index.md | 0 docs/{ => locales}/uk/intro/dev.md | 0 docs/{ => locales}/uk/intro/index.md | 0 docs/{ => locales}/uk/intro/installation.md | 0 .../quick-start/cross-program-invocation.md | 0 .../intro/quick-start/deploying-programs.md | 0 .../uk/intro/quick-start/index.md | 0 .../quick-start/program-derived-address.md | 0 .../intro/quick-start/reading-from-network.md | 0 .../intro/quick-start/writing-to-network.md | 0 docs/{ => locales}/uk/intro/wallets.md | 0 docs/{ => locales}/uk/more/exchange.md | 0 docs/{ => locales}/uk/more/index.md | 0 .../uk/programs/anchor/client-typescript.md | 325 +++++++++++ docs/locales/uk/programs/anchor/cpi.md | 541 +++++++++++++++++ docs/locales/uk/programs/anchor/idl.md | 504 ++++++++++++++++ docs/locales/uk/programs/anchor/index.md | 361 ++++++++++++ docs/locales/uk/programs/anchor/pda.md | 315 ++++++++++ .../uk/programs/anchor/program-structure.md | 373 ++++++++++++ docs/locales/uk/programs/deploying.md | 299 ++++++++++ docs/locales/uk/programs/examples.md | 151 +++++ docs/locales/uk/programs/faq.md | 186 ++++++ docs/{en => locales/uk}/programs/index.md | 0 docs/locales/uk/programs/limitations.md | 79 +++ docs/locales/uk/programs/rust/index.md | 462 +++++++++++++++ .../uk/programs/rust/program-structure.md | 390 ++++++------- docs/{ => locales}/uk/programs/testing.md | 0 docs/{ => locales}/uk/rpc.md | 0 .../uk}/rpc/deprecated/confirmTransaction.mdx | 0 .../uk}/rpc/deprecated/getConfirmedBlock.mdx | 0 .../uk}/rpc/deprecated/getConfirmedBlocks.mdx | 0 .../getConfirmedBlocksWithLimit.mdx | 0 .../getConfirmedSignaturesForAddress2.mdx | 0 .../deprecated/getConfirmedTransaction.mdx | 0 .../getFeeCalculatorForBlockhash.mdx | 0 .../uk}/rpc/deprecated/getFeeRateGovernor.mdx | 0 .../uk}/rpc/deprecated/getFees.mdx | 0 .../uk}/rpc/deprecated/getRecentBlockhash.mdx | 0 .../deprecated/getSignatureConfirmation.mdx | 0 .../uk}/rpc/deprecated/getSignatureStatus.mdx | 0 .../uk}/rpc/deprecated/getSnapshotSlot.mdx | 0 .../uk}/rpc/deprecated/getStakeActivation.mdx | 0 .../uk}/rpc/deprecated/index.mdx | 0 .../uk}/rpc/http/getAccountInfo.mdx | 0 .../uk}/rpc/http/getBalance.mdx | 0 docs/{en => locales/uk}/rpc/http/getBlock.mdx | 0 .../uk}/rpc/http/getBlockCommitment.mdx | 0 .../uk}/rpc/http/getBlockHeight.mdx | 0 .../uk}/rpc/http/getBlockProduction.mdx | 0 .../uk}/rpc/http/getBlockTime.mdx | 0 .../{en => locales/uk}/rpc/http/getBlocks.mdx | 0 .../uk}/rpc/http/getBlocksWithLimit.mdx | 0 .../uk}/rpc/http/getClusterNodes.mdx | 0 .../uk}/rpc/http/getEpochInfo.mdx | 0 .../uk}/rpc/http/getEpochSchedule.mdx | 0 .../uk}/rpc/http/getFeeForMessage.mdx | 0 .../uk}/rpc/http/getFirstAvailableBlock.mdx | 0 .../uk}/rpc/http/getGenesisHash.mdx | 0 .../{en => locales/uk}/rpc/http/getHealth.mdx | 0 .../uk}/rpc/http/getHighestSnapshotSlot.mdx | 0 .../uk}/rpc/http/getIdentity.mdx | 0 .../uk}/rpc/http/getInflationGovernor.mdx | 0 .../uk}/rpc/http/getInflationRate.mdx | 0 .../uk}/rpc/http/getInflationReward.mdx | 0 .../uk}/rpc/http/getLargestAccounts.mdx | 0 .../uk}/rpc/http/getLatestBlockhash.mdx | 0 .../uk}/rpc/http/getLeaderSchedule.mdx | 0 .../uk}/rpc/http/getMaxRetransmitSlot.mdx | 0 .../uk}/rpc/http/getMaxShredInsertSlot.mdx | 0 .../getMinimumBalanceForRentExemption.mdx | 0 .../uk}/rpc/http/getMultipleAccounts.mdx | 0 .../uk}/rpc/http/getProgramAccounts.mdx | 0 .../rpc/http/getRecentPerformanceSamples.mdx | 0 .../rpc/http/getRecentPrioritizationFees.mdx | 0 .../uk}/rpc/http/getSignatureStatuses.mdx | 0 .../uk}/rpc/http/getSignaturesForAddress.mdx | 0 docs/{en => locales/uk}/rpc/http/getSlot.mdx | 0 .../uk}/rpc/http/getSlotLeader.mdx | 0 .../uk}/rpc/http/getSlotLeaders.mdx | 0 .../rpc/http/getStakeMinimumDelegation.mdx | 0 .../{en => locales/uk}/rpc/http/getSupply.mdx | 0 .../uk}/rpc/http/getTokenAccountBalance.mdx | 0 .../rpc/http/getTokenAccountsByDelegate.mdx | 0 .../uk}/rpc/http/getTokenAccountsByOwner.mdx | 0 .../uk}/rpc/http/getTokenLargestAccounts.mdx | 0 .../uk}/rpc/http/getTokenSupply.mdx | 0 .../uk}/rpc/http/getTransaction.mdx | 0 .../uk}/rpc/http/getTransactionCount.mdx | 0 .../uk}/rpc/http/getVersion.mdx | 0 .../uk}/rpc/http/getVoteAccounts.mdx | 0 docs/{en => locales/uk}/rpc/http/index.mdx | 0 .../uk}/rpc/http/isBlockhashValid.mdx | 0 .../uk}/rpc/http/minimumLedgerSlot.mdx | 0 .../uk}/rpc/http/requestAirdrop.mdx | 0 .../uk}/rpc/http/sendTransaction.mdx | 0 .../uk}/rpc/http/simulateTransaction.mdx | 0 docs/{en => locales/uk}/rpc/index.mdx | 0 .../uk}/rpc/json-structures.mdx | 0 .../uk}/rpc/websocket/accountSubscribe.mdx | 0 .../uk}/rpc/websocket/accountUnsubscribe.mdx | 0 .../uk}/rpc/websocket/blockSubscribe.mdx | 0 .../uk}/rpc/websocket/blockUnsubscribe.mdx | 0 .../uk}/rpc/websocket/index.mdx | 0 .../uk}/rpc/websocket/logsSubscribe.mdx | 0 .../uk}/rpc/websocket/logsUnsubscribe.mdx | 0 .../uk}/rpc/websocket/programSubscribe.mdx | 0 .../uk}/rpc/websocket/programUnsubscribe.mdx | 0 .../uk}/rpc/websocket/rootSubscribe.mdx | 0 .../uk}/rpc/websocket/rootUnsubscribe.mdx | 0 .../uk}/rpc/websocket/signatureSubscribe.mdx | 0 .../rpc/websocket/signatureUnsubscribe.mdx | 0 .../uk}/rpc/websocket/slotSubscribe.mdx | 0 .../uk}/rpc/websocket/slotUnsubscribe.mdx | 0 .../rpc/websocket/slotsUpdatesSubscribe.mdx | 0 .../rpc/websocket/slotsUpdatesUnsubscribe.mdx | 0 .../uk}/rpc/websocket/voteSubscribe.mdx | 0 .../uk}/rpc/websocket/voteUnsubscribe.mdx | 0 docs/{ => locales}/uk/terminology.md | 0 docs/{en => }/more/exchange.md | 0 docs/{en => }/more/index.md | 0 .../programs/anchor/client-typescript.md | 0 docs/{en => }/programs/anchor/cpi.md | 0 docs/{en => }/programs/anchor/idl.md | 0 docs/{en => }/programs/anchor/index.md | 0 docs/{en => }/programs/anchor/pda.md | 0 .../programs/anchor/program-structure.md | 0 docs/{en => }/programs/deploying.md | 0 docs/{en => }/programs/examples.md | 0 docs/{en => }/programs/faq.md | 0 docs/{uk => }/programs/index.md | 0 docs/{en => }/programs/limitations.md | 0 docs/{en => }/programs/rust/index.md | 0 .../programs/rust/program-structure.md | 0 docs/{en => }/programs/testing.md | 0 docs/{en => }/rpc.md | 0 .../rpc/deprecated/confirmTransaction.mdx | 0 .../rpc/deprecated/getConfirmedBlock.mdx | 0 .../rpc/deprecated/getConfirmedBlocks.mdx | 0 .../getConfirmedBlocksWithLimit.mdx | 0 .../getConfirmedSignaturesForAddress2.mdx | 0 .../deprecated/getConfirmedTransaction.mdx | 0 .../getFeeCalculatorForBlockhash.mdx | 0 .../rpc/deprecated/getFeeRateGovernor.mdx | 0 docs/{uk => }/rpc/deprecated/getFees.mdx | 0 .../rpc/deprecated/getRecentBlockhash.mdx | 0 .../deprecated/getSignatureConfirmation.mdx | 0 .../rpc/deprecated/getSignatureStatus.mdx | 0 .../rpc/deprecated/getSnapshotSlot.mdx | 0 .../rpc/deprecated/getStakeActivation.mdx | 0 docs/{uk => }/rpc/deprecated/index.mdx | 0 docs/{uk => }/rpc/http/getAccountInfo.mdx | 0 docs/{uk => }/rpc/http/getBalance.mdx | 0 docs/{uk => }/rpc/http/getBlock.mdx | 0 docs/{uk => }/rpc/http/getBlockCommitment.mdx | 0 docs/{uk => }/rpc/http/getBlockHeight.mdx | 0 docs/{uk => }/rpc/http/getBlockProduction.mdx | 0 docs/{uk => }/rpc/http/getBlockTime.mdx | 0 docs/{uk => }/rpc/http/getBlocks.mdx | 0 docs/{uk => }/rpc/http/getBlocksWithLimit.mdx | 0 docs/{uk => }/rpc/http/getClusterNodes.mdx | 0 docs/{uk => }/rpc/http/getEpochInfo.mdx | 0 docs/{uk => }/rpc/http/getEpochSchedule.mdx | 0 docs/{uk => }/rpc/http/getFeeForMessage.mdx | 0 .../rpc/http/getFirstAvailableBlock.mdx | 0 docs/{uk => }/rpc/http/getGenesisHash.mdx | 0 docs/{uk => }/rpc/http/getHealth.mdx | 0 .../rpc/http/getHighestSnapshotSlot.mdx | 0 docs/{uk => }/rpc/http/getIdentity.mdx | 0 .../rpc/http/getInflationGovernor.mdx | 0 docs/{uk => }/rpc/http/getInflationRate.mdx | 0 docs/{uk => }/rpc/http/getInflationReward.mdx | 0 docs/{uk => }/rpc/http/getLargestAccounts.mdx | 0 docs/{uk => }/rpc/http/getLatestBlockhash.mdx | 0 docs/{uk => }/rpc/http/getLeaderSchedule.mdx | 0 .../rpc/http/getMaxRetransmitSlot.mdx | 0 .../rpc/http/getMaxShredInsertSlot.mdx | 0 .../getMinimumBalanceForRentExemption.mdx | 0 .../{uk => }/rpc/http/getMultipleAccounts.mdx | 0 docs/{uk => }/rpc/http/getProgramAccounts.mdx | 0 .../rpc/http/getRecentPerformanceSamples.mdx | 0 .../rpc/http/getRecentPrioritizationFees.mdx | 0 .../rpc/http/getSignatureStatuses.mdx | 0 .../rpc/http/getSignaturesForAddress.mdx | 0 docs/{uk => }/rpc/http/getSlot.mdx | 0 docs/{uk => }/rpc/http/getSlotLeader.mdx | 0 docs/{uk => }/rpc/http/getSlotLeaders.mdx | 0 .../rpc/http/getStakeMinimumDelegation.mdx | 0 docs/{uk => }/rpc/http/getSupply.mdx | 0 .../rpc/http/getTokenAccountBalance.mdx | 0 .../rpc/http/getTokenAccountsByDelegate.mdx | 0 .../rpc/http/getTokenAccountsByOwner.mdx | 0 .../rpc/http/getTokenLargestAccounts.mdx | 0 docs/{uk => }/rpc/http/getTokenSupply.mdx | 0 docs/{uk => }/rpc/http/getTransaction.mdx | 0 .../{uk => }/rpc/http/getTransactionCount.mdx | 0 docs/{uk => }/rpc/http/getVersion.mdx | 0 docs/{uk => }/rpc/http/getVoteAccounts.mdx | 0 docs/{uk => }/rpc/http/index.mdx | 0 docs/{uk => }/rpc/http/isBlockhashValid.mdx | 0 docs/{uk => }/rpc/http/minimumLedgerSlot.mdx | 0 docs/{uk => }/rpc/http/requestAirdrop.mdx | 0 docs/{uk => }/rpc/http/sendTransaction.mdx | 0 .../{uk => }/rpc/http/simulateTransaction.mdx | 0 docs/{uk => }/rpc/index.mdx | 0 docs/{uk => }/rpc/json-structures.mdx | 0 .../rpc/websocket/accountSubscribe.mdx | 0 .../rpc/websocket/accountUnsubscribe.mdx | 0 .../{uk => }/rpc/websocket/blockSubscribe.mdx | 0 .../rpc/websocket/blockUnsubscribe.mdx | 0 docs/{uk => }/rpc/websocket/index.mdx | 0 docs/{uk => }/rpc/websocket/logsSubscribe.mdx | 0 .../rpc/websocket/logsUnsubscribe.mdx | 0 .../rpc/websocket/programSubscribe.mdx | 0 .../rpc/websocket/programUnsubscribe.mdx | 0 docs/{uk => }/rpc/websocket/rootSubscribe.mdx | 0 .../rpc/websocket/rootUnsubscribe.mdx | 0 .../rpc/websocket/signatureSubscribe.mdx | 0 .../rpc/websocket/signatureUnsubscribe.mdx | 0 docs/{uk => }/rpc/websocket/slotSubscribe.mdx | 0 .../rpc/websocket/slotUnsubscribe.mdx | 0 .../rpc/websocket/slotsUpdatesSubscribe.mdx | 0 .../rpc/websocket/slotsUpdatesUnsubscribe.mdx | 0 docs/{uk => }/rpc/websocket/voteSubscribe.mdx | 0 .../rpc/websocket/voteUnsubscribe.mdx | 0 docs/{en => }/terminology.md | 0 docs/uk/programs/anchor/client-typescript.md | 354 ----------- docs/uk/programs/anchor/cpi.md | 551 ------------------ docs/uk/programs/anchor/idl.md | 516 ---------------- docs/uk/programs/anchor/index.md | 384 ------------ docs/uk/programs/anchor/pda.md | 325 ----------- docs/uk/programs/anchor/program-structure.md | 399 ------------- docs/uk/programs/deploying.md | 331 ----------- docs/uk/programs/examples.md | 157 ----- docs/uk/programs/faq.md | 194 ------ docs/uk/programs/limitations.md | 112 ---- docs/uk/programs/rust/index.md | 474 --------------- 301 files changed, 3774 insertions(+), 4009 deletions(-) rename docs/{en => }/advanced/actions.md (100%) rename docs/{en => }/advanced/confirmation.md (100%) rename docs/{en => }/advanced/index.md (100%) rename docs/{en => }/advanced/lookup-tables.md (100%) rename docs/{en => }/advanced/retry.md (100%) rename docs/{en => }/advanced/state-compression.md (100%) rename docs/{en => }/advanced/versions.md (100%) rename docs/{en => }/clients/index.md (100%) rename docs/{en => }/clients/javascript-reference.md (100%) rename docs/{en => }/clients/javascript.md (100%) rename docs/{en => }/clients/rust.md (100%) rename docs/{en => }/core/accounts.md (100%) rename docs/{en => }/core/clusters.md (100%) rename docs/{en => }/core/cpi.md (100%) rename docs/{en => }/core/fees.md (100%) rename docs/{en => }/core/index.md (100%) rename docs/{en => }/core/pda.md (100%) rename docs/{en => }/core/programs.md (100%) rename docs/{en => }/core/tokens.md (100%) rename docs/{en => }/core/transactions.md (100%) rename docs/{en => }/economics/index.md (100%) rename docs/{en => }/economics/inflation/_adjusted_staking_yield.md (100%) rename docs/{en => }/economics/inflation/inflation-schedule.md (100%) rename docs/{en => }/economics/inflation/terminology.md (100%) rename docs/{en => }/economics/staking/index.md (100%) rename docs/{en => }/economics/staking/stake-accounts.md (100%) rename docs/{en => }/economics/staking/stake-programming.md (100%) rename docs/{en => }/index.md (100%) rename docs/{en => }/intro/dev.md (100%) rename docs/{en => }/intro/index.md (100%) rename docs/{en => }/intro/installation.md (100%) rename docs/{en => }/intro/quick-start/cross-program-invocation.md (100%) rename docs/{en => }/intro/quick-start/deploying-programs.md (100%) rename docs/{en => }/intro/quick-start/index.md (100%) rename docs/{en => }/intro/quick-start/program-derived-address.md (100%) rename docs/{en => }/intro/quick-start/reading-from-network.md (100%) rename docs/{en => }/intro/quick-start/writing-to-network.md (100%) rename docs/{en => }/intro/wallets.md (100%) rename docs/{ => locales}/uk/advanced/actions.md (100%) rename docs/{ => locales}/uk/advanced/confirmation.md (100%) rename docs/{ => locales}/uk/advanced/index.md (100%) rename docs/{ => locales}/uk/advanced/lookup-tables.md (100%) rename docs/{ => locales}/uk/advanced/retry.md (100%) rename docs/{ => locales}/uk/advanced/state-compression.md (100%) rename docs/{ => locales}/uk/advanced/versions.md (100%) rename docs/{ => locales}/uk/clients/index.md (100%) rename docs/{ => locales}/uk/clients/javascript-reference.md (100%) rename docs/{ => locales}/uk/clients/javascript.md (100%) rename docs/{ => locales}/uk/clients/rust.md (100%) rename docs/{ => locales}/uk/core/accounts.md (100%) rename docs/{ => locales}/uk/core/clusters.md (100%) rename docs/{ => locales}/uk/core/cpi.md (100%) rename docs/{ => locales}/uk/core/fees.md (100%) rename docs/{ => locales}/uk/core/index.md (100%) rename docs/{ => locales}/uk/core/pda.md (100%) rename docs/{ => locales}/uk/core/programs.md (100%) rename docs/{ => locales}/uk/core/tokens.md (100%) rename docs/{ => locales}/uk/core/transactions.md (100%) rename docs/{ => locales}/uk/economics/index.md (100%) rename docs/{ => locales}/uk/economics/inflation/_adjusted_staking_yield.md (100%) rename docs/{ => locales}/uk/economics/inflation/inflation-schedule.md (100%) rename docs/{ => locales}/uk/economics/inflation/terminology.md (100%) rename docs/{ => locales}/uk/economics/staking/index.md (100%) rename docs/{ => locales}/uk/economics/staking/stake-accounts.md (100%) rename docs/{ => locales}/uk/economics/staking/stake-programming.md (100%) rename docs/{ => locales}/uk/index.md (100%) rename docs/{ => locales}/uk/intro/dev.md (100%) rename docs/{ => locales}/uk/intro/index.md (100%) rename docs/{ => locales}/uk/intro/installation.md (100%) rename docs/{ => locales}/uk/intro/quick-start/cross-program-invocation.md (100%) rename docs/{ => locales}/uk/intro/quick-start/deploying-programs.md (100%) rename docs/{ => locales}/uk/intro/quick-start/index.md (100%) rename docs/{ => locales}/uk/intro/quick-start/program-derived-address.md (100%) rename docs/{ => locales}/uk/intro/quick-start/reading-from-network.md (100%) rename docs/{ => locales}/uk/intro/quick-start/writing-to-network.md (100%) rename docs/{ => locales}/uk/intro/wallets.md (100%) rename docs/{ => locales}/uk/more/exchange.md (100%) rename docs/{ => locales}/uk/more/index.md (100%) create mode 100644 docs/locales/uk/programs/anchor/client-typescript.md create mode 100644 docs/locales/uk/programs/anchor/cpi.md create mode 100644 docs/locales/uk/programs/anchor/idl.md create mode 100644 docs/locales/uk/programs/anchor/index.md create mode 100644 docs/locales/uk/programs/anchor/pda.md create mode 100644 docs/locales/uk/programs/anchor/program-structure.md create mode 100644 docs/locales/uk/programs/deploying.md create mode 100644 docs/locales/uk/programs/examples.md create mode 100644 docs/locales/uk/programs/faq.md rename docs/{en => locales/uk}/programs/index.md (100%) create mode 100644 docs/locales/uk/programs/limitations.md create mode 100644 docs/locales/uk/programs/rust/index.md rename docs/{ => locales}/uk/programs/rust/program-structure.md (64%) rename docs/{ => locales}/uk/programs/testing.md (100%) rename docs/{ => locales}/uk/rpc.md (100%) rename docs/{en => locales/uk}/rpc/deprecated/confirmTransaction.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getConfirmedBlock.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getConfirmedBlocks.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getConfirmedBlocksWithLimit.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getConfirmedTransaction.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getFeeCalculatorForBlockhash.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getFeeRateGovernor.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getFees.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getRecentBlockhash.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getSignatureConfirmation.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getSignatureStatus.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getSnapshotSlot.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/getStakeActivation.mdx (100%) rename docs/{en => locales/uk}/rpc/deprecated/index.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getAccountInfo.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getBalance.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getBlock.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getBlockCommitment.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getBlockHeight.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getBlockProduction.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getBlockTime.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getBlocks.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getBlocksWithLimit.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getClusterNodes.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getEpochInfo.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getEpochSchedule.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getFeeForMessage.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getFirstAvailableBlock.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getGenesisHash.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getHealth.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getHighestSnapshotSlot.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getIdentity.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getInflationGovernor.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getInflationRate.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getInflationReward.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getLargestAccounts.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getLatestBlockhash.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getLeaderSchedule.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getMaxRetransmitSlot.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getMaxShredInsertSlot.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getMinimumBalanceForRentExemption.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getMultipleAccounts.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getProgramAccounts.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getRecentPerformanceSamples.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getRecentPrioritizationFees.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getSignatureStatuses.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getSignaturesForAddress.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getSlot.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getSlotLeader.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getSlotLeaders.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getStakeMinimumDelegation.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getSupply.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getTokenAccountBalance.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getTokenAccountsByDelegate.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getTokenAccountsByOwner.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getTokenLargestAccounts.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getTokenSupply.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getTransaction.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getTransactionCount.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getVersion.mdx (100%) rename docs/{en => locales/uk}/rpc/http/getVoteAccounts.mdx (100%) rename docs/{en => locales/uk}/rpc/http/index.mdx (100%) rename docs/{en => locales/uk}/rpc/http/isBlockhashValid.mdx (100%) rename docs/{en => locales/uk}/rpc/http/minimumLedgerSlot.mdx (100%) rename docs/{en => locales/uk}/rpc/http/requestAirdrop.mdx (100%) rename docs/{en => locales/uk}/rpc/http/sendTransaction.mdx (100%) rename docs/{en => locales/uk}/rpc/http/simulateTransaction.mdx (100%) rename docs/{en => locales/uk}/rpc/index.mdx (100%) rename docs/{en => locales/uk}/rpc/json-structures.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/accountSubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/accountUnsubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/blockSubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/blockUnsubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/index.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/logsSubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/logsUnsubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/programSubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/programUnsubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/rootSubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/rootUnsubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/signatureSubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/signatureUnsubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/slotSubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/slotUnsubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/slotsUpdatesSubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/slotsUpdatesUnsubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/voteSubscribe.mdx (100%) rename docs/{en => locales/uk}/rpc/websocket/voteUnsubscribe.mdx (100%) rename docs/{ => locales}/uk/terminology.md (100%) rename docs/{en => }/more/exchange.md (100%) rename docs/{en => }/more/index.md (100%) rename docs/{en => }/programs/anchor/client-typescript.md (100%) rename docs/{en => }/programs/anchor/cpi.md (100%) rename docs/{en => }/programs/anchor/idl.md (100%) rename docs/{en => }/programs/anchor/index.md (100%) rename docs/{en => }/programs/anchor/pda.md (100%) rename docs/{en => }/programs/anchor/program-structure.md (100%) rename docs/{en => }/programs/deploying.md (100%) rename docs/{en => }/programs/examples.md (100%) rename docs/{en => }/programs/faq.md (100%) rename docs/{uk => }/programs/index.md (100%) rename docs/{en => }/programs/limitations.md (100%) rename docs/{en => }/programs/rust/index.md (100%) rename docs/{en => }/programs/rust/program-structure.md (100%) rename docs/{en => }/programs/testing.md (100%) rename docs/{en => }/rpc.md (100%) rename docs/{uk => }/rpc/deprecated/confirmTransaction.mdx (100%) rename docs/{uk => }/rpc/deprecated/getConfirmedBlock.mdx (100%) rename docs/{uk => }/rpc/deprecated/getConfirmedBlocks.mdx (100%) rename docs/{uk => }/rpc/deprecated/getConfirmedBlocksWithLimit.mdx (100%) rename docs/{uk => }/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx (100%) rename docs/{uk => }/rpc/deprecated/getConfirmedTransaction.mdx (100%) rename docs/{uk => }/rpc/deprecated/getFeeCalculatorForBlockhash.mdx (100%) rename docs/{uk => }/rpc/deprecated/getFeeRateGovernor.mdx (100%) rename docs/{uk => }/rpc/deprecated/getFees.mdx (100%) rename docs/{uk => }/rpc/deprecated/getRecentBlockhash.mdx (100%) rename docs/{uk => }/rpc/deprecated/getSignatureConfirmation.mdx (100%) rename docs/{uk => }/rpc/deprecated/getSignatureStatus.mdx (100%) rename docs/{uk => }/rpc/deprecated/getSnapshotSlot.mdx (100%) rename docs/{uk => }/rpc/deprecated/getStakeActivation.mdx (100%) rename docs/{uk => }/rpc/deprecated/index.mdx (100%) rename docs/{uk => }/rpc/http/getAccountInfo.mdx (100%) rename docs/{uk => }/rpc/http/getBalance.mdx (100%) rename docs/{uk => }/rpc/http/getBlock.mdx (100%) rename docs/{uk => }/rpc/http/getBlockCommitment.mdx (100%) rename docs/{uk => }/rpc/http/getBlockHeight.mdx (100%) rename docs/{uk => }/rpc/http/getBlockProduction.mdx (100%) rename docs/{uk => }/rpc/http/getBlockTime.mdx (100%) rename docs/{uk => }/rpc/http/getBlocks.mdx (100%) rename docs/{uk => }/rpc/http/getBlocksWithLimit.mdx (100%) rename docs/{uk => }/rpc/http/getClusterNodes.mdx (100%) rename docs/{uk => }/rpc/http/getEpochInfo.mdx (100%) rename docs/{uk => }/rpc/http/getEpochSchedule.mdx (100%) rename docs/{uk => }/rpc/http/getFeeForMessage.mdx (100%) rename docs/{uk => }/rpc/http/getFirstAvailableBlock.mdx (100%) rename docs/{uk => }/rpc/http/getGenesisHash.mdx (100%) rename docs/{uk => }/rpc/http/getHealth.mdx (100%) rename docs/{uk => }/rpc/http/getHighestSnapshotSlot.mdx (100%) rename docs/{uk => }/rpc/http/getIdentity.mdx (100%) rename docs/{uk => }/rpc/http/getInflationGovernor.mdx (100%) rename docs/{uk => }/rpc/http/getInflationRate.mdx (100%) rename docs/{uk => }/rpc/http/getInflationReward.mdx (100%) rename docs/{uk => }/rpc/http/getLargestAccounts.mdx (100%) rename docs/{uk => }/rpc/http/getLatestBlockhash.mdx (100%) rename docs/{uk => }/rpc/http/getLeaderSchedule.mdx (100%) rename docs/{uk => }/rpc/http/getMaxRetransmitSlot.mdx (100%) rename docs/{uk => }/rpc/http/getMaxShredInsertSlot.mdx (100%) rename docs/{uk => }/rpc/http/getMinimumBalanceForRentExemption.mdx (100%) rename docs/{uk => }/rpc/http/getMultipleAccounts.mdx (100%) rename docs/{uk => }/rpc/http/getProgramAccounts.mdx (100%) rename docs/{uk => }/rpc/http/getRecentPerformanceSamples.mdx (100%) rename docs/{uk => }/rpc/http/getRecentPrioritizationFees.mdx (100%) rename docs/{uk => }/rpc/http/getSignatureStatuses.mdx (100%) rename docs/{uk => }/rpc/http/getSignaturesForAddress.mdx (100%) rename docs/{uk => }/rpc/http/getSlot.mdx (100%) rename docs/{uk => }/rpc/http/getSlotLeader.mdx (100%) rename docs/{uk => }/rpc/http/getSlotLeaders.mdx (100%) rename docs/{uk => }/rpc/http/getStakeMinimumDelegation.mdx (100%) rename docs/{uk => }/rpc/http/getSupply.mdx (100%) rename docs/{uk => }/rpc/http/getTokenAccountBalance.mdx (100%) rename docs/{uk => }/rpc/http/getTokenAccountsByDelegate.mdx (100%) rename docs/{uk => }/rpc/http/getTokenAccountsByOwner.mdx (100%) rename docs/{uk => }/rpc/http/getTokenLargestAccounts.mdx (100%) rename docs/{uk => }/rpc/http/getTokenSupply.mdx (100%) rename docs/{uk => }/rpc/http/getTransaction.mdx (100%) rename docs/{uk => }/rpc/http/getTransactionCount.mdx (100%) rename docs/{uk => }/rpc/http/getVersion.mdx (100%) rename docs/{uk => }/rpc/http/getVoteAccounts.mdx (100%) rename docs/{uk => }/rpc/http/index.mdx (100%) rename docs/{uk => }/rpc/http/isBlockhashValid.mdx (100%) rename docs/{uk => }/rpc/http/minimumLedgerSlot.mdx (100%) rename docs/{uk => }/rpc/http/requestAirdrop.mdx (100%) rename docs/{uk => }/rpc/http/sendTransaction.mdx (100%) rename docs/{uk => }/rpc/http/simulateTransaction.mdx (100%) rename docs/{uk => }/rpc/index.mdx (100%) rename docs/{uk => }/rpc/json-structures.mdx (100%) rename docs/{uk => }/rpc/websocket/accountSubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/accountUnsubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/blockSubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/blockUnsubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/index.mdx (100%) rename docs/{uk => }/rpc/websocket/logsSubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/logsUnsubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/programSubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/programUnsubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/rootSubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/rootUnsubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/signatureSubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/signatureUnsubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/slotSubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/slotUnsubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/slotsUpdatesSubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/slotsUpdatesUnsubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/voteSubscribe.mdx (100%) rename docs/{uk => }/rpc/websocket/voteUnsubscribe.mdx (100%) rename docs/{en => }/terminology.md (100%) delete mode 100644 docs/uk/programs/anchor/client-typescript.md delete mode 100644 docs/uk/programs/anchor/cpi.md delete mode 100644 docs/uk/programs/anchor/idl.md delete mode 100644 docs/uk/programs/anchor/index.md delete mode 100644 docs/uk/programs/anchor/pda.md delete mode 100644 docs/uk/programs/anchor/program-structure.md delete mode 100644 docs/uk/programs/deploying.md delete mode 100644 docs/uk/programs/examples.md delete mode 100644 docs/uk/programs/faq.md delete mode 100644 docs/uk/programs/limitations.md delete mode 100644 docs/uk/programs/rust/index.md diff --git a/docs/en/advanced/actions.md b/docs/advanced/actions.md similarity index 100% rename from docs/en/advanced/actions.md rename to docs/advanced/actions.md diff --git a/docs/en/advanced/confirmation.md b/docs/advanced/confirmation.md similarity index 100% rename from docs/en/advanced/confirmation.md rename to docs/advanced/confirmation.md diff --git a/docs/en/advanced/index.md b/docs/advanced/index.md similarity index 100% rename from docs/en/advanced/index.md rename to docs/advanced/index.md diff --git a/docs/en/advanced/lookup-tables.md b/docs/advanced/lookup-tables.md similarity index 100% rename from docs/en/advanced/lookup-tables.md rename to docs/advanced/lookup-tables.md diff --git a/docs/en/advanced/retry.md b/docs/advanced/retry.md similarity index 100% rename from docs/en/advanced/retry.md rename to docs/advanced/retry.md diff --git a/docs/en/advanced/state-compression.md b/docs/advanced/state-compression.md similarity index 100% rename from docs/en/advanced/state-compression.md rename to docs/advanced/state-compression.md diff --git a/docs/en/advanced/versions.md b/docs/advanced/versions.md similarity index 100% rename from docs/en/advanced/versions.md rename to docs/advanced/versions.md diff --git a/docs/en/clients/index.md b/docs/clients/index.md similarity index 100% rename from docs/en/clients/index.md rename to docs/clients/index.md diff --git a/docs/en/clients/javascript-reference.md b/docs/clients/javascript-reference.md similarity index 100% rename from docs/en/clients/javascript-reference.md rename to docs/clients/javascript-reference.md diff --git a/docs/en/clients/javascript.md b/docs/clients/javascript.md similarity index 100% rename from docs/en/clients/javascript.md rename to docs/clients/javascript.md diff --git a/docs/en/clients/rust.md b/docs/clients/rust.md similarity index 100% rename from docs/en/clients/rust.md rename to docs/clients/rust.md diff --git a/docs/en/core/accounts.md b/docs/core/accounts.md similarity index 100% rename from docs/en/core/accounts.md rename to docs/core/accounts.md diff --git a/docs/en/core/clusters.md b/docs/core/clusters.md similarity index 100% rename from docs/en/core/clusters.md rename to docs/core/clusters.md diff --git a/docs/en/core/cpi.md b/docs/core/cpi.md similarity index 100% rename from docs/en/core/cpi.md rename to docs/core/cpi.md diff --git a/docs/en/core/fees.md b/docs/core/fees.md similarity index 100% rename from docs/en/core/fees.md rename to docs/core/fees.md diff --git a/docs/en/core/index.md b/docs/core/index.md similarity index 100% rename from docs/en/core/index.md rename to docs/core/index.md diff --git a/docs/en/core/pda.md b/docs/core/pda.md similarity index 100% rename from docs/en/core/pda.md rename to docs/core/pda.md diff --git a/docs/en/core/programs.md b/docs/core/programs.md similarity index 100% rename from docs/en/core/programs.md rename to docs/core/programs.md diff --git a/docs/en/core/tokens.md b/docs/core/tokens.md similarity index 100% rename from docs/en/core/tokens.md rename to docs/core/tokens.md diff --git a/docs/en/core/transactions.md b/docs/core/transactions.md similarity index 100% rename from docs/en/core/transactions.md rename to docs/core/transactions.md diff --git a/docs/en/economics/index.md b/docs/economics/index.md similarity index 100% rename from docs/en/economics/index.md rename to docs/economics/index.md diff --git a/docs/en/economics/inflation/_adjusted_staking_yield.md b/docs/economics/inflation/_adjusted_staking_yield.md similarity index 100% rename from docs/en/economics/inflation/_adjusted_staking_yield.md rename to docs/economics/inflation/_adjusted_staking_yield.md diff --git a/docs/en/economics/inflation/inflation-schedule.md b/docs/economics/inflation/inflation-schedule.md similarity index 100% rename from docs/en/economics/inflation/inflation-schedule.md rename to docs/economics/inflation/inflation-schedule.md diff --git a/docs/en/economics/inflation/terminology.md b/docs/economics/inflation/terminology.md similarity index 100% rename from docs/en/economics/inflation/terminology.md rename to docs/economics/inflation/terminology.md diff --git a/docs/en/economics/staking/index.md b/docs/economics/staking/index.md similarity index 100% rename from docs/en/economics/staking/index.md rename to docs/economics/staking/index.md diff --git a/docs/en/economics/staking/stake-accounts.md b/docs/economics/staking/stake-accounts.md similarity index 100% rename from docs/en/economics/staking/stake-accounts.md rename to docs/economics/staking/stake-accounts.md diff --git a/docs/en/economics/staking/stake-programming.md b/docs/economics/staking/stake-programming.md similarity index 100% rename from docs/en/economics/staking/stake-programming.md rename to docs/economics/staking/stake-programming.md diff --git a/docs/en/index.md b/docs/index.md similarity index 100% rename from docs/en/index.md rename to docs/index.md diff --git a/docs/en/intro/dev.md b/docs/intro/dev.md similarity index 100% rename from docs/en/intro/dev.md rename to docs/intro/dev.md diff --git a/docs/en/intro/index.md b/docs/intro/index.md similarity index 100% rename from docs/en/intro/index.md rename to docs/intro/index.md diff --git a/docs/en/intro/installation.md b/docs/intro/installation.md similarity index 100% rename from docs/en/intro/installation.md rename to docs/intro/installation.md diff --git a/docs/en/intro/quick-start/cross-program-invocation.md b/docs/intro/quick-start/cross-program-invocation.md similarity index 100% rename from docs/en/intro/quick-start/cross-program-invocation.md rename to docs/intro/quick-start/cross-program-invocation.md diff --git a/docs/en/intro/quick-start/deploying-programs.md b/docs/intro/quick-start/deploying-programs.md similarity index 100% rename from docs/en/intro/quick-start/deploying-programs.md rename to docs/intro/quick-start/deploying-programs.md diff --git a/docs/en/intro/quick-start/index.md b/docs/intro/quick-start/index.md similarity index 100% rename from docs/en/intro/quick-start/index.md rename to docs/intro/quick-start/index.md diff --git a/docs/en/intro/quick-start/program-derived-address.md b/docs/intro/quick-start/program-derived-address.md similarity index 100% rename from docs/en/intro/quick-start/program-derived-address.md rename to docs/intro/quick-start/program-derived-address.md diff --git a/docs/en/intro/quick-start/reading-from-network.md b/docs/intro/quick-start/reading-from-network.md similarity index 100% rename from docs/en/intro/quick-start/reading-from-network.md rename to docs/intro/quick-start/reading-from-network.md diff --git a/docs/en/intro/quick-start/writing-to-network.md b/docs/intro/quick-start/writing-to-network.md similarity index 100% rename from docs/en/intro/quick-start/writing-to-network.md rename to docs/intro/quick-start/writing-to-network.md diff --git a/docs/en/intro/wallets.md b/docs/intro/wallets.md similarity index 100% rename from docs/en/intro/wallets.md rename to docs/intro/wallets.md diff --git a/docs/uk/advanced/actions.md b/docs/locales/uk/advanced/actions.md similarity index 100% rename from docs/uk/advanced/actions.md rename to docs/locales/uk/advanced/actions.md diff --git a/docs/uk/advanced/confirmation.md b/docs/locales/uk/advanced/confirmation.md similarity index 100% rename from docs/uk/advanced/confirmation.md rename to docs/locales/uk/advanced/confirmation.md diff --git a/docs/uk/advanced/index.md b/docs/locales/uk/advanced/index.md similarity index 100% rename from docs/uk/advanced/index.md rename to docs/locales/uk/advanced/index.md diff --git a/docs/uk/advanced/lookup-tables.md b/docs/locales/uk/advanced/lookup-tables.md similarity index 100% rename from docs/uk/advanced/lookup-tables.md rename to docs/locales/uk/advanced/lookup-tables.md diff --git a/docs/uk/advanced/retry.md b/docs/locales/uk/advanced/retry.md similarity index 100% rename from docs/uk/advanced/retry.md rename to docs/locales/uk/advanced/retry.md diff --git a/docs/uk/advanced/state-compression.md b/docs/locales/uk/advanced/state-compression.md similarity index 100% rename from docs/uk/advanced/state-compression.md rename to docs/locales/uk/advanced/state-compression.md diff --git a/docs/uk/advanced/versions.md b/docs/locales/uk/advanced/versions.md similarity index 100% rename from docs/uk/advanced/versions.md rename to docs/locales/uk/advanced/versions.md diff --git a/docs/uk/clients/index.md b/docs/locales/uk/clients/index.md similarity index 100% rename from docs/uk/clients/index.md rename to docs/locales/uk/clients/index.md diff --git a/docs/uk/clients/javascript-reference.md b/docs/locales/uk/clients/javascript-reference.md similarity index 100% rename from docs/uk/clients/javascript-reference.md rename to docs/locales/uk/clients/javascript-reference.md diff --git a/docs/uk/clients/javascript.md b/docs/locales/uk/clients/javascript.md similarity index 100% rename from docs/uk/clients/javascript.md rename to docs/locales/uk/clients/javascript.md diff --git a/docs/uk/clients/rust.md b/docs/locales/uk/clients/rust.md similarity index 100% rename from docs/uk/clients/rust.md rename to docs/locales/uk/clients/rust.md diff --git a/docs/uk/core/accounts.md b/docs/locales/uk/core/accounts.md similarity index 100% rename from docs/uk/core/accounts.md rename to docs/locales/uk/core/accounts.md diff --git a/docs/uk/core/clusters.md b/docs/locales/uk/core/clusters.md similarity index 100% rename from docs/uk/core/clusters.md rename to docs/locales/uk/core/clusters.md diff --git a/docs/uk/core/cpi.md b/docs/locales/uk/core/cpi.md similarity index 100% rename from docs/uk/core/cpi.md rename to docs/locales/uk/core/cpi.md diff --git a/docs/uk/core/fees.md b/docs/locales/uk/core/fees.md similarity index 100% rename from docs/uk/core/fees.md rename to docs/locales/uk/core/fees.md diff --git a/docs/uk/core/index.md b/docs/locales/uk/core/index.md similarity index 100% rename from docs/uk/core/index.md rename to docs/locales/uk/core/index.md diff --git a/docs/uk/core/pda.md b/docs/locales/uk/core/pda.md similarity index 100% rename from docs/uk/core/pda.md rename to docs/locales/uk/core/pda.md diff --git a/docs/uk/core/programs.md b/docs/locales/uk/core/programs.md similarity index 100% rename from docs/uk/core/programs.md rename to docs/locales/uk/core/programs.md diff --git a/docs/uk/core/tokens.md b/docs/locales/uk/core/tokens.md similarity index 100% rename from docs/uk/core/tokens.md rename to docs/locales/uk/core/tokens.md diff --git a/docs/uk/core/transactions.md b/docs/locales/uk/core/transactions.md similarity index 100% rename from docs/uk/core/transactions.md rename to docs/locales/uk/core/transactions.md diff --git a/docs/uk/economics/index.md b/docs/locales/uk/economics/index.md similarity index 100% rename from docs/uk/economics/index.md rename to docs/locales/uk/economics/index.md diff --git a/docs/uk/economics/inflation/_adjusted_staking_yield.md b/docs/locales/uk/economics/inflation/_adjusted_staking_yield.md similarity index 100% rename from docs/uk/economics/inflation/_adjusted_staking_yield.md rename to docs/locales/uk/economics/inflation/_adjusted_staking_yield.md diff --git a/docs/uk/economics/inflation/inflation-schedule.md b/docs/locales/uk/economics/inflation/inflation-schedule.md similarity index 100% rename from docs/uk/economics/inflation/inflation-schedule.md rename to docs/locales/uk/economics/inflation/inflation-schedule.md diff --git a/docs/uk/economics/inflation/terminology.md b/docs/locales/uk/economics/inflation/terminology.md similarity index 100% rename from docs/uk/economics/inflation/terminology.md rename to docs/locales/uk/economics/inflation/terminology.md diff --git a/docs/uk/economics/staking/index.md b/docs/locales/uk/economics/staking/index.md similarity index 100% rename from docs/uk/economics/staking/index.md rename to docs/locales/uk/economics/staking/index.md diff --git a/docs/uk/economics/staking/stake-accounts.md b/docs/locales/uk/economics/staking/stake-accounts.md similarity index 100% rename from docs/uk/economics/staking/stake-accounts.md rename to docs/locales/uk/economics/staking/stake-accounts.md diff --git a/docs/uk/economics/staking/stake-programming.md b/docs/locales/uk/economics/staking/stake-programming.md similarity index 100% rename from docs/uk/economics/staking/stake-programming.md rename to docs/locales/uk/economics/staking/stake-programming.md diff --git a/docs/uk/index.md b/docs/locales/uk/index.md similarity index 100% rename from docs/uk/index.md rename to docs/locales/uk/index.md diff --git a/docs/uk/intro/dev.md b/docs/locales/uk/intro/dev.md similarity index 100% rename from docs/uk/intro/dev.md rename to docs/locales/uk/intro/dev.md diff --git a/docs/uk/intro/index.md b/docs/locales/uk/intro/index.md similarity index 100% rename from docs/uk/intro/index.md rename to docs/locales/uk/intro/index.md diff --git a/docs/uk/intro/installation.md b/docs/locales/uk/intro/installation.md similarity index 100% rename from docs/uk/intro/installation.md rename to docs/locales/uk/intro/installation.md diff --git a/docs/uk/intro/quick-start/cross-program-invocation.md b/docs/locales/uk/intro/quick-start/cross-program-invocation.md similarity index 100% rename from docs/uk/intro/quick-start/cross-program-invocation.md rename to docs/locales/uk/intro/quick-start/cross-program-invocation.md diff --git a/docs/uk/intro/quick-start/deploying-programs.md b/docs/locales/uk/intro/quick-start/deploying-programs.md similarity index 100% rename from docs/uk/intro/quick-start/deploying-programs.md rename to docs/locales/uk/intro/quick-start/deploying-programs.md diff --git a/docs/uk/intro/quick-start/index.md b/docs/locales/uk/intro/quick-start/index.md similarity index 100% rename from docs/uk/intro/quick-start/index.md rename to docs/locales/uk/intro/quick-start/index.md diff --git a/docs/uk/intro/quick-start/program-derived-address.md b/docs/locales/uk/intro/quick-start/program-derived-address.md similarity index 100% rename from docs/uk/intro/quick-start/program-derived-address.md rename to docs/locales/uk/intro/quick-start/program-derived-address.md diff --git a/docs/uk/intro/quick-start/reading-from-network.md b/docs/locales/uk/intro/quick-start/reading-from-network.md similarity index 100% rename from docs/uk/intro/quick-start/reading-from-network.md rename to docs/locales/uk/intro/quick-start/reading-from-network.md diff --git a/docs/uk/intro/quick-start/writing-to-network.md b/docs/locales/uk/intro/quick-start/writing-to-network.md similarity index 100% rename from docs/uk/intro/quick-start/writing-to-network.md rename to docs/locales/uk/intro/quick-start/writing-to-network.md diff --git a/docs/uk/intro/wallets.md b/docs/locales/uk/intro/wallets.md similarity index 100% rename from docs/uk/intro/wallets.md rename to docs/locales/uk/intro/wallets.md diff --git a/docs/uk/more/exchange.md b/docs/locales/uk/more/exchange.md similarity index 100% rename from docs/uk/more/exchange.md rename to docs/locales/uk/more/exchange.md diff --git a/docs/uk/more/index.md b/docs/locales/uk/more/index.md similarity index 100% rename from docs/uk/more/index.md rename to docs/locales/uk/more/index.md diff --git a/docs/locales/uk/programs/anchor/client-typescript.md b/docs/locales/uk/programs/anchor/client-typescript.md new file mode 100644 index 000000000..42be6e41c --- /dev/null +++ b/docs/locales/uk/programs/anchor/client-typescript.md @@ -0,0 +1,325 @@ +--- +title: JS/TS Client +description: + Дізнайтеся, як використовувати клієнтську бібліотеку TypeScript для взаємодії з Solana +sidebarLabel: JS/TS Client +sidebarSortOrder: 3 +--- + +Anchor надає бібліотеку клієнта TypeScript +([@coral-xyz/anchor](https://github.com/coral-xyz/anchor/tree/v0.30.1/ts/packages/anchor)) +Це спрощує процес взаємодії з програмами Solana від клієнта +у JavaScript або TypeScript. + +## Клієнтська програма + +Для використання клієнтської бібліотеки спочатку створіть екземпляр +[`Program`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/index.ts#L58) +Використання [IDL -файлу] (/DOCS/Програми/Анкер/IDL), створений Anchor. + +Створення екземпляра програми вимагає IDL програми та +[`AnchorProvider`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/provider.ts#L55). +`AnchorProvider` - це абстракція, яка поєднує дві речі: + +- `Підключення ' - з'єднання з [кластером Solana] (/docs/core/clusters.md) +(тобто localhost, devnet, mainnet) +- `Wallet` - (необов’язково) Гаманець за замовчуванням, який використовується для оплати та підписання транзакцій + + + + +При інтеграції з фронтендом за допомогою +[Адаптер гаманця] (https://solana.com/developers/guides/wallets/add-solana-wallet-adapter-to-nextjs), +Вам потрібно буде налаштувати `AnchorProvider` та `Program`. + +```ts {9-10, 12-14} +import { Program, AnchorProvider, setProvider } from "@coral-xyz/anchor"; +import { useAnchorWallet, useConnection } from "@solana/wallet-adapter-react"; +import type { HelloAnchor } from "./idlType"; +import idl from "./idl.json"; + +const { connection } = useConnection(); +const wallet = useAnchorWallet(); + +const provider = new AnchorProvider(connection, wallet, {}); +setProvider(provider); + +export const program = new Program(idl as HelloAnchor, { + connection, +}); +``` + +У фрагменті коду вище: + +- `idl.json` - це файл IDL, створений якір, знайдено на +`/target/idl/ .json` в якорі. +- `idltype.ts` - це тип IDL (для використання з TS), знайдено в +`/target/type/ .ts` в якорі. + +Крім того, ви можете створити екземпляр, використовуючи лише IDL +і підключення до кластеру солани.Це означає, що немає за замовчуванням +`Wallet`, але дозволяє використовувати` Програму 'для отримання облікових записів або побудувати +Інструкції без підключеного гаманця. + +```ts {8-10} +import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js"; +import { Program } from "@coral-xyz/anchor"; +import type { HelloAnchor } from "./idlType"; +import idl from "./idl.json"; + +const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); + +export const program = new Program(idl as HelloAnchor, { + connection, +}); +``` + + + + +Якір автоматично налаштовує екземпляр `Program` у тестовому файлі за замовчуванням +нові проекти.Однак ця установка відрізняється від того, як ви ініціалізуєте програму +Поза робочою областю якоря, наприклад, у програмах React або Node.js. + +```typescript +import * as anchor from "@coral-xyz/anchor"; +import { Program } from "@coral-xyz/anchor"; +import { HelloAnchor } from "../target/types/hello_anchor"; + +describe("hello_anchor", () => { + // Configure the client to use the local cluster. + anchor.setProvider(anchor.AnchorProvider.env()); + + const program = anchor.workspace.HelloAnchor as Program; + + it("Is initialized!", async () => { + // Add your test here. + const tx = await program.methods.initialize().rpc(); + console.log("Your transaction signature", tx); + }); +}); +``` + + + + +## Виклик інструкцій + +Після того як `Program` налаштовано за допомогою програмного IDL, ви можете використовувати якір +[`MethodsBuilder`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L155) +для: +- Створіть окремі інструкції +- Будуйте транзакції +- Будуйте та надсилайте транзакції + +Основний формат виглядає як наступне: + + + + +`program.methods` - Це API Builder для створення інструкційних дзвінків з +IDL програми + +```ts /methods/ {1} +await program.methods + .instructionName(instructionData) + .accounts({}) + .signers([]) + .rpc(); +``` + + + + +У розділі `.methods` вказуйте назву інструкції з IDL програми, передаючи будь-які необхідні аргументи як значення, розділені комами. + +```ts /instructionName/ /instructionData1/ /instructionData2/ {2} +await program.methods + .instructionName(instructionData1, instructionData2) + .accounts({}) + .signers([]) + .rpc(); +``` + + + + +`.accounts` - Вказуйте адресу облікових записів, необхідних для інструкції, як це зазначено в IDL. + +```ts /accounts/ {3} +await program.methods + .instructionName(instructionData) + .accounts({}) + .signers([]) + .rpc(); +``` +Зверніть увагу, що деякі адреси облікових записів не потрібно вказувати явно, оскільки клієнт Anchor може автоматично їх визначити. Це зазвичай стосується: + +- Загальних облікових записів (наприклад, Програма Системи) +- Облікових записів, де адреса є PDA (Програма-Походження Адреси) + + + + +`.signers` - Необов'язково передайте масив ключових пар, які потрібні як додаткові підписанти для інструкції. Це зазвичай використовується при створенні нових облікових записів, де адреса облікового запису є публічним ключем нещодавно згенерованої ключової пари. + +```ts /signers/ {4} +await program.methods + .instructionName(instructionData) + .accounts({}) + .signers([]) + .rpc(); +``` + +Зверніть увагу, що `.signers` слід використовувати тільки при використанні `.rpc()`. Коли ви використовуєте `.transaction()` або `.instruction()`, підписанти повинні бути додані до транзакції перед її відправкою. + + + + +Anchor надає кілька методів для створення інструкцій програми: + + + + + +Метод [`rpc()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L283) +[відправляє підписану транзакцію](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/rpc.ts#L29) +з вказаною інструкцією та повертає `TransactionSignature`. + +При використанні `.rpc` гаманець з `Provider` автоматично додається як підписант. + +```ts {13} +// Generate keypair for the new account +const newAccountKp = new Keypair(); + +const data = new BN(42); +const transactionSignature = await program.methods + .initialize(data) + .accounts({ + newAccount: newAccountKp.publicKey, + signer: wallet.publicKey, + systemProgram: SystemProgram.programId, + }) + .signers([newAccountKp]) + .rpc(); +``` + + + + +Метод [`transaction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L382) +[створює `Transaction`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/transaction.ts#L18-L26) +з вказаною інструкцією без відправки транзакції. + +```ts {12} /transaction()/1,2,4 +// Generate keypair for the new account +const newAccountKp = new Keypair(); + +const data = new BN(42); +const transaction = await program.methods + .initialize(data) + .accounts({ + newAccount: newAccountKp.publicKey, + signer: wallet.publicKey, + systemProgram: SystemProgram.programId, + }) + .transaction(); + +const transactionSignature = await connection.sendTransaction(transaction, [ + wallet.payer, + newAccountKp, +]); +``` + + + + +Метод [`instruction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L348) +[створює `TransactionInstruction`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/instruction.ts#L57-L61) +з вказаною інструкцією. Це корисно, якщо ви хочете вручну додати інструкцію до транзакції та поєднати її з іншими інструкціями. + +```ts {12} /instruction()/ +// Generate keypair for the new account +const newAccountKp = new Keypair(); + +const data = new BN(42); +const instruction = await program.methods + .initialize(data) + .accounts({ + newAccount: newAccountKp.publicKey, + signer: wallet.publicKey, + systemProgram: SystemProgram.programId, + }) + .instruction(); + +const transaction = new Transaction().add(instruction); + +const transactionSignature = await connection.sendTransaction(transaction, [ + wallet.payer, + newAccountKp, +]); +``` + + + + +## Отримання облікових записів + +Клієнт `Program` спрощує процес отримання та десеріалізації облікових записів, створених вашою програмою Anchor. + +Використовуйте `program.account`, за яким слідує назва типу облікового запису, визначеного в IDL. Anchor надає кілька методів для отримання облікових записів. + + + + + +Використовуйте [`all()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L251) +для отримання всіх існуючих облікових записів для конкретного типу облікового запису. + +```ts /all/ +const accounts = await program.account.newAccount.all(); +``` + + + + +Використовуйте `memcmp` (порівняння пам'яті) для фільтрації облікових записів, дані яких відповідають конкретному значенню на вказаному зсуві. Для використання `memcmp` необхідно розуміти байтову структуру поля даних для типу облікового запису, який ви отримуєте. + +При обчисленні зсуву пам'ятайте, що перші 8 байтів у облікових записах, створених програмою Anchor, зарезервовані для дискримінатора облікового запису. + +```ts /memcmp/ +const accounts = await program.account.newAccount.all([ + { + memcmp: { + offset: 8, + bytes: "", + }, + }, +]); +``` + + + + +Використовуйте [`fetch()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L165) +для отримання даних облікового запису для одного облікового запису. + +```ts /fetch/ +const account = await program.account.newAccount.fetch(ACCOUNT_ADDRESS); +``` + + + + +Використовуйте [`fetchMultiple()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L200) +для отримання даних облікових записів для кількох облікових записів, передавши масив адрес облікових записів. + +```ts /fetchMultiple/ +const accounts = await program.account.newAccount.fetchMultiple([ + ACCOUNT_ADDRESS_ONE, + ACCOUNT_ADDRESS_TWO, +]); +``` + + + diff --git a/docs/locales/uk/programs/anchor/cpi.md b/docs/locales/uk/programs/anchor/cpi.md new file mode 100644 index 000000000..4e725d555 --- /dev/null +++ b/docs/locales/uk/programs/anchor/cpi.md @@ -0,0 +1,541 @@ +--- +title: CPIs з Anchor +description: + Дізнайтеся, як реалізувати Cross Program Invocations (CPI) в програмах на Anchor, + що дозволяє взаємодіяти між різними програмами на Solana +sidebarLabel: CPIs з Anchor +sidebarSortOrder: 5 +--- + +[Cross Program Invocations (CPI)](/docs/core/cpi.md) означають процес, коли одна +програма викликає інструкції іншої програми, що дозволяє здійснювати композицію програм на Solana. + +Цей розділ охоплює основи реалізації CPIs в програмі Anchor, +використовуючи інструкцію простого переказу SOL як практичний приклад. Після того, як ви +зрозумієте основи реалізації CPI, ви зможете застосувати ці ж концепції +для будь-якої інструкції. + +## Cross Program Invocations + +Розглянемо програму, яка реалізує CPI для інструкції переказу в System Program. Ось приклад програми на +[Solana Playground](https://beta.solpg.io/66df2751cffcf4b13384d35a). + +Файл `lib.rs` містить одну інструкцію `sol_transfer`. Коли інструкція +`sol_transfer` в програмі Anchor викликається, програма +внутрішньо викликає інструкцію переказу з System Program. + + +```rs filename="lib.rs" /sol_transfer/ /transfer/ {23} +use anchor_lang::prelude::*; +use anchor_lang::system_program::{transfer, Transfer}; + +declare_id!("9AvUNHjxscdkiKQ8tUn12QCMXtcnbR9BVGq3ULNzFMRi"); + +#[program] +pub mod cpi { + use super::*; + + pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.sender.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + let cpi_context = CpiContext::new( + program_id, + Transfer { + from: from_pubkey, + to: to_pubkey, + }, + ); + + transfer(cpi_context, amount)?; + Ok(()) + } +} + +#[derive(Accounts)] +pub struct SolTransfer<'info> { + #[account(mut)] + sender: Signer<'info>, + #[account(mut)] + recipient: SystemAccount<'info>, + system_program: Program<'info, System>, +} +``` + +Файл `cpi.test.ts` показує, як викликати інструкцію `sol_transfer` програми Anchor і реєструє посилання на деталі транзакції на SolanaFM. + + +```ts filename="cpi.test.ts" +it("SOL Transfer Anchor", async () => { + const transactionSignature = await program.methods + .solTransfer(new BN(transferAmount)) + .accounts({ + sender: sender.publicKey, + recipient: recipient.publicKey, + }) + .rpc(); + + console.log( + `\nTransaction Signature:` + + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, + ); +}); +``` + +Ви можете побудувати, розгорнути та запустити тест для цього прикладу на Playground, щоб переглянути +деталі транзакції на [SolanaFM explorer](https://solana.fm/). + +Деталі транзакції покажуть, що спочатку була викликана програма Anchor +(інструкція 1), яка потім викликає System Program (інструкція 1.1), +що призводить до успішного переказу SOL. + +![Деталі транзакції](/assets/docs/core/cpi/transaction-details.png) + +### Пояснення прикладу 1 + +Реалізація CPI слідує такому ж шаблону, як і створення інструкції для додавання в +транзакцію. Коли реалізуємо CPI, потрібно вказати ID програми, +рахунки та дані інструкції для викликаної інструкції. + +Інструкція переказу в System Program вимагає два рахунки: + +- `from`: Рахунок, що надсилає SOL. +- `to`: Рахунок, що отримує SOL. + +У прикладній програмі структура `SolTransfer` вказує рахунки, необхідні +для інструкції переказу. System Program також включена, оскільки CPI +викликає System Program. + +```rust /sender/ /recipient/ /system_program/ +#[derive(Accounts)] +pub struct SolTransfer<'info> { + #[account(mut)] + sender: Signer<'info>, // from account + #[account(mut)] + recipient: SystemAccount<'info>, // to account + system_program: Program<'info, System>, // program ID +} +``` + +Наступні вкладки представляють три підходи до реалізації Cross Program +Invocations (CPI), кожен з яких має різний рівень абстракції. Усі приклади є +функціонально еквівалентними. Основною метою є ілюстрація деталей реалізації +CPI. + + + + + +Інструкція `sol_transfer`, включена в прикладний код, показує типовий +підхід до побудови CPIs за допомогою фреймворку Anchor. + +Цей підхід передбачає створення +[`CpiContext`](https://docs.rs/anchor-lang/latest/anchor_lang/context/struct.CpiContext.html), +який містить `program_id` та рахунки, необхідні для викликаної інструкції, а також допоміжну функцію (`transfer`) для виклику конкретної +інструкції. + +```rust +use anchor_lang::system_program::{transfer, Transfer}; +``` + +```rust /cpi_context/ {14} +pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.sender.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + let cpi_context = CpiContext::new( + program_id, + Transfer { + from: from_pubkey, + to: to_pubkey, + }, + ); + + transfer(cpi_context, amount)?; + Ok(()) +} +``` + +Змінна `cpi_context` вказує ID програми (System Program) та +рахунки (відправник і отримувач), необхідні для інструкції переказу. + +```rust /program_id/ /from_pubkey/ /to_pubkey/ +let cpi_context = CpiContext::new( + program_id, + Transfer { + from: from_pubkey, + to: to_pubkey, + }, +); +``` + +Змінні `cpi_context` та `amount` передаються в функцію `transfer` для +виконання CPI, що викликає інструкцію переказу з System Program. + +```rust +transfer(cpi_context, amount)?; +``` + + + + +Цей приклад показує інший підхід до реалізації CPI за допомогою функції `invoke` та +[`system_instruction::transfer`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L881), +що зазвичай використовується в рідних програмах на Rust. + +Під капотом попередній приклад є абстракцією цієї реалізації. +Нижче наведений приклад є функціонально еквівалентним попередньому. + +```rust +use anchor_lang::solana_program::{program::invoke, system_instruction}; +``` + +```rust /instruction/1,3 {9} +pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.sender.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + let instruction = + &system_instruction::transfer(&from_pubkey.key(), &to_pubkey.key(), amount); + + invoke(instruction, &[from_pubkey, to_pubkey, program_id])?; + Ok(()) +} +``` + + + + +Ви також можете вручну створити інструкцію для передачі в функцію `invoke()`. +Це корисно, коли немає доступної бібліотеки, що допомагає побудувати +інструкцію, яку ви хочете викликати. Цей підхід вимагає вказати `AccountMeta` для інструкції та правильно створити буфер даних інструкції. + +Інструкція `sol_transfer` нижче є вручну реалізованим CPI для інструкції переказу в System Program. + +```rust /instruction/10,13 {28} +pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.sender.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + // Prepare instruction AccountMetas + let account_metas = vec![ + AccountMeta::new(from_pubkey.key(), true), + AccountMeta::new(to_pubkey.key(), false), + ]; + + // SOL transfer instruction discriminator + let instruction_discriminator: u32 = 2; + + // Prepare instruction data + let mut instruction_data = Vec::with_capacity(4 + 8); + instruction_data.extend_from_slice(&instruction_discriminator.to_le_bytes()); + instruction_data.extend_from_slice(&amount.to_le_bytes()); + + // Create instruction + let instruction = Instruction { + program_id: program_id.key(), + accounts: account_metas, + data: instruction_data, + }; + + // Invoke instruction + invoke(&instruction, &[from_pubkey, to_pubkey, program_id])?; + Ok(()) +} +``` + +Інструкція `sol_transfer` вище повторює цей +[приклад](/docs/core/transactions.md#manual-sol-transfer) вручну побудованої інструкції переказу SOL. Вона слідує тому ж шаблону, що і створення +[інструкції](/docs/core/transactions.md#instruction) для додавання в транзакцію. + +При створенні інструкції на Rust використовуйте наступний синтаксис для вказівки +`AccountMeta` для кожного рахунку: + + +```rust +AccountMeta::new(account1_pubkey, true), // writable, signer +AccountMeta::new(account2_pubkey, false), // writable, not signer +AccountMeta::new_readonly(account3_pubkey, false), // not writable, not signer +AccountMeta::new_readonly(account4_pubkey, true), // writable, signer +``` + + + + +Ось програмний приклад на +[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi), +який містить усі 3 приклади. + +## Cross Program Invocations з PDA підписами + +Далі розглянемо програму, яка реалізує CPI для інструкції переказу в System Program, де відправником є Програма Походження Адреси (PDA), для якої програма повинна "підписати" транзакцію. Ось приклад програми на +[Solana Playground](https://beta.solpg.io/66df2bd2cffcf4b13384d35b). + +Файл `lib.rs` містить наступну програму з єдиною інструкцією `sol_transfer`. + + +```rust filename="lib.rs" +use anchor_lang::prelude::*; +use anchor_lang::system_program::{transfer, Transfer}; + +declare_id!("3455LkCS85a4aYmSeNbRrJsduNQfYRY82A7eCD3yQfyR"); + +#[program] +pub mod cpi { + use super::*; + + pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.pda_account.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + let seed = to_pubkey.key(); + let bump_seed = ctx.bumps.pda_account; + let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]]; + + let cpi_context = CpiContext::new( + program_id, + Transfer { + from: from_pubkey, + to: to_pubkey, + }, + ) + .with_signer(signer_seeds); + + transfer(cpi_context, amount)?; + Ok(()) + } +} + +#[derive(Accounts)] +pub struct SolTransfer<'info> { + #[account( + mut, + seeds = [b"pda", recipient.key().as_ref()], + bump, + )] + pda_account: SystemAccount<'info>, + #[account(mut)] + recipient: SystemAccount<'info>, + system_program: Program<'info, System>, +} +``` + +Файл `cpi.test.ts` показує, як викликати інструкцію `sol_transfer` програми Anchor і реєструє посилання на деталі транзакції на SolanaFM. + +Він показує, як отримати PDA за допомогою насіння, вказаного в програмі: + + +```ts /pda/ /wallet.publicKey/ +const [PDA] = PublicKey.findProgramAddressSync( + [Buffer.from("pda"), wallet.publicKey.toBuffer()], + program.programId, +); +``` + +Першим кроком у цьому прикладі є фінансування рахунку PDA за допомогою простого переказу SOL з гаманця Playground. + + +```ts filename="cpi.test.ts" +it("Fund PDA with SOL", async () => { + const transferInstruction = SystemProgram.transfer({ + fromPubkey: wallet.publicKey, + toPubkey: PDA, + lamports: transferAmount, + }); + + const transaction = new Transaction().add(transferInstruction); + + const transactionSignature = await sendAndConfirmTransaction( + connection, + transaction, + [wallet.payer], // signer + ); + + console.log( + `\nTransaction Signature:` + + `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, + ); +}); +``` + +Коли PDA буде фінансовано SOL, викликається інструкція `sol_transfer`. Ця +інструкція переказує SOL з рахунку PDA назад на рахунок `wallet` через +CPI до System Program, що "підписується" програмою. + +```ts +it("SOL Transfer with PDA signer", async () => { + const transactionSignature = await program.methods + .solTransfer(new BN(transferAmount)) + .accounts({ + pdaAccount: PDA, + recipient: wallet.publicKey, + }) + .rpc(); + + console.log( + `\nTransaction Signature: https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, + ); +}); +``` + +Ви можете побудувати, розгорнути та запустити тест, щоб переглянути деталі транзакції на +[SolanaFM explorer](https://solana.fm/). + +Деталі транзакції покажуть, що спочатку була викликана користувацька програма +(інструкція 1), яка потім викликає System Program (інструкція 1.1), +що призводить до успішного переказу SOL. + +![Деталі транзакції](/assets/docs/core/cpi/transaction-details-pda.png) + +### Пояснення прикладу 2 + +У прикладному коді структура `SolTransfer` вказує рахунки, необхідні для +інструкції переказу. + +Відправником є PDA, для якого програма повинна підписати транзакцію. `seeds`, які використовуються для отримання +адреси для `pda_account`, включають зашитий рядок "pda" та адресу +рахунку `recipient`. Це означає, що адреса для `pda_account` є +унікальною для кожного `recipient`. + +```rust /pda_account/ /recipient/2 /system_program/ +#[derive(Accounts)] +pub struct SolTransfer<'info> { + #[account( + mut, + seeds = [b"pda", recipient.key().as_ref()], + bump, + )] + pda_account: SystemAccount<'info>, + #[account(mut)] + recipient: SystemAccount<'info>, + system_program: Program<'info, System>, +} +``` + +Еквівалент на Javascript для отримання PDA включений у тестовий файл. + +```ts /pda/ /wallet.publicKey/ +const [PDA] = PublicKey.findProgramAddressSync( + [Buffer.from("pda"), wallet.publicKey.toBuffer()], + program.programId, +); +``` +Наступні вкладки представляють два підходи до реалізації Cross Program +Invocations (CPI), кожен з яких має різний рівень абстракції. Обидва приклади є +функціонально еквівалентними. Основною метою є ілюстрація деталей реалізації +CPI. + + + + + +Інструкція `sol_transfer`, включена в прикладний код, показує типовий +підхід до побудови CPIs за допомогою фреймворку Anchor. + +Цей підхід передбачає створення +[`CpiContext`](https://docs.rs/anchor-lang/latest/anchor_lang/context/struct.CpiContext.html), +який містить `program_id` та рахунки, необхідні для викликаної інструкції, а також допоміжну функцію (`transfer`) для виклику конкретної +інструкції. + +```rust /cpi_context/ {19} +pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.pda_account.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + let seed = to_pubkey.key(); + let bump_seed = ctx.bumps.pda_account; + let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]]; + + let cpi_context = CpiContext::new( + program_id, + Transfer { + from: from_pubkey, + to: to_pubkey, + }, + ) + .with_signer(signer_seeds); + + transfer(cpi_context, amount)?; + Ok(()) +} +``` + +При підписанні за допомогою PDA, насіння та bump seed включаються в +`cpi_context` як `signer_seeds` за допомогою `with_signer()`. Bump seed для PDA +можна отримати за допомогою `ctx.bumps`, після чого вказується ім'я рахунку PDA. + +```rust /signer_seeds/ /bump_seed/ {3} +let seed = to_pubkey.key(); +let bump_seed = ctx.bumps.pda_account; +let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]]; + +let cpi_context = CpiContext::new( + program_id, + Transfer { + from: from_pubkey, + to: to_pubkey, + }, +) +.with_signer(signer_seeds); +``` + +Змінні `cpi_context` та `amount` передаються в функцію `transfer` для +виконання CPI. + + +```rust +transfer(cpi_context, amount)?; +``` + +Коли обробляється CPI, середовище виконання Solana перевіряє, чи правильно +наведені насіння та ID програми викликача для отримання дійсного PDA. Потім PDA +додається як підписант під час виклику. Цей механізм дозволяє програмам підписувати PDA, +які отримані з їхнього ID програми. + + + + +Під капотом попередній приклад є обгорткою для функції `invoke_signed()`, +яка використовує +[`system_instruction::transfer`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L881) +для побудови інструкції. + +Цей приклад показує, як використовувати функцію `invoke_signed()`, щоб зробити CPI +підписаним PDA. + +```rust +use anchor_lang::solana_program::{program::invoke_signed, system_instruction}; +``` + +```rust /instruction/1,3 {13} +pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { + let from_pubkey = ctx.accounts.pda_account.to_account_info(); + let to_pubkey = ctx.accounts.recipient.to_account_info(); + let program_id = ctx.accounts.system_program.to_account_info(); + + let seed = to_pubkey.key(); + let bump_seed = ctx.bumps.pda_account; + let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]]; + + let instruction = + &system_instruction::transfer(&from_pubkey.key(), &to_pubkey.key(), amount); + + invoke_signed(instruction, &[from_pubkey, to_pubkey, program_id], signer_seeds)?; + Ok(()) +} +``` +Ця реалізація функціонально еквівалентна попередньому прикладу. +`signer_seeds` передаються в функцію `invoke_signed`. + + + + +Ось програмний приклад на +[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi-pda), +який містить обидва приклади. diff --git a/docs/locales/uk/programs/anchor/idl.md b/docs/locales/uk/programs/anchor/idl.md new file mode 100644 index 000000000..1f4024f89 --- /dev/null +++ b/docs/locales/uk/programs/anchor/idl.md @@ -0,0 +1,504 @@ +--- +title: Файл IDL +description: + Дізнайтесь про файл Interface Definition Language (IDL) в Anchor, його + призначення, переваги та те, як він спрощує взаємодію програми з клієнтами +sidebarLabel: Файл IDL +sidebarSortOrder: 2 +--- + +Файл Interface Definition Language (IDL) надає стандартизований JSON-файл, +який описує інструкції та рахунки програми. Цей файл спрощує процес інтеграції +вашої програми на блокчейні з клієнтськими додатками. + +Основні переваги IDL: + +- Стандартизація: Надає послідовний формат для опису інструкцій та рахунків програми +- Генерація клієнта: Використовується для генерації коду клієнта для взаємодії з програмою + +Команда `anchor build` генерує файл IDL, який знаходиться за адресою +`/target/idl/.json`. + +Нижче наведені фрагменти коду, що показують, як програма, IDL та клієнт взаємопов'язані. + +## Інструкції програми + +Масив `instructions` у файлі IDL безпосередньо відповідає інструкціям, +визначеним у вашій програмі. Він вказує на необхідні рахунки та параметри для +кожної інструкції. + + + + + +Наведена програма включає інструкцію `initialize`, що вказує на рахунки +та параметри, які вона потребує. + +```rust {8-12, 15-22} +use anchor_lang::prelude::*; + +declare_id!("BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64, +} +``` + + + + +Згенерований файл IDL включає інструкцію в стандартизованому форматі JSON, +включаючи її ім'я, рахунки, аргументи та дискримінатор. + +```json filename="JSON" {11-12, 14-27, 30-33} +{ + "address": "BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd", + "metadata": { + "name": "hello_anchor", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "initialize", + "discriminator": [175, 175, 109, 31, 13, 152, 155, 237], + "accounts": [ + { + "name": "new_account", + "writable": true, + "signer": true + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "data", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "NewAccount", + "discriminator": [176, 95, 4, 118, 91, 177, 125, 232] + } + ], + "types": [ + { + "name": "NewAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "data", + "type": "u64" + } + ] + } + } + ] +} +``` + + + + +Файл IDL потім використовується для генерації клієнта для взаємодії з програмою, +спрощуючи процес виклику інструкції програми. + +```ts {19-26} +import * as anchor from "@coral-xyz/anchor"; +import { Program, BN } from "@coral-xyz/anchor"; +import { HelloAnchor } from "../target/types/hello_anchor"; +import { Keypair } from "@solana/web3.js"; +import assert from "assert"; + +describe("hello_anchor", () => { + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const wallet = provider.wallet as anchor.Wallet; + const program = anchor.workspace.HelloAnchor as Program; + + it("initialize", async () => { + // Generate keypair for the new account + const newAccountKp = new Keypair(); + + // Send transaction + const data = new BN(42); + const transactionSignature = await program.methods + .initialize(data) + .accounts({ + newAccount: newAccountKp.publicKey, + signer: wallet.publicKey, + }) + .signers([newAccountKp]) + .rpc(); + + // Fetch the created account + const newAccount = await program.account.newAccount.fetch( + newAccountKp.publicKey, + ); + + console.log("Transaction signature: ", transactionSignature); + console.log("On-chain data is:", newAccount.data.toString()); + assert(data.eq(newAccount.data)); + }); +}); +``` + + + + +## Рахунки програми + +Масив `accounts` у файлі IDL відповідає структурам у програмі, +позначеним макросом `#[account]`. Ці структури визначають дані, які зберігаються в +рахунках, створених програмою. + + + + + +Наведена програма визначає структуру `NewAccount` з одним полем `data` +типу `u64`. + + +```rust {24-27} +use anchor_lang::prelude::*; + +declare_id!("BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64, +} +``` + + + + +Згенерований файл IDL включає рахунок у стандартизованому форматі JSON, +включаючи його ім'я, дискримінатор та поля. + + +```json filename="JSON" {39-40, 45-54} +{ + "address": "BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd", + "metadata": { + "name": "hello_anchor", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "initialize", + "discriminator": [175, 175, 109, 31, 13, 152, 155, 237], + "accounts": [ + { + "name": "new_account", + "writable": true, + "signer": true + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "data", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "NewAccount", + "discriminator": [176, 95, 4, 118, 91, 177, 125, 232] + } + ], + "types": [ + { + "name": "NewAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "data", + "type": "u64" + } + ] + } + } + ] +} +``` + + + + +Файл IDL потім використовується для генерації клієнта для взаємодії з програмою, +спрощуючи процес отримання та десеріалізації даних рахунку. + +```ts {29-31} +import * as anchor from "@coral-xyz/anchor"; +import { Program, BN } from "@coral-xyz/anchor"; +import { HelloAnchor } from "../target/types/hello_anchor"; +import { Keypair } from "@solana/web3.js"; +import assert from "assert"; + +describe("hello_anchor", () => { + const provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + const wallet = provider.wallet as anchor.Wallet; + const program = anchor.workspace.HelloAnchor as Program; + + it("initialize", async () => { + // Generate keypair for the new account + const newAccountKp = new Keypair(); + + // Send transaction + const data = new BN(42); + const transactionSignature = await program.methods + .initialize(data) + .accounts({ + newAccount: newAccountKp.publicKey, + signer: wallet.publicKey, + }) + .signers([newAccountKp]) + .rpc(); + + // Fetch the created account + const newAccount = await program.account.newAccount.fetch( + newAccountKp.publicKey, + ); + + console.log("Transaction signature: ", transactionSignature); + console.log("On-chain data is:", newAccount.data.toString()); + assert(data.eq(newAccount.data)); + }); +}); +``` + + + + +## Дискримінатори + +Anchor призначає унікальний 8-байтовий дискримінатор для кожної інструкції та типу рахунку в програмі. Ці дискримінатори служать як ідентифікатори для відрізнення різних інструкцій або типів рахунків. + +Дискримінатор генерується за допомогою перших 8 байтів хешу Sha256 префікса, поєднаного з ім'ям інструкції або рахунку. Починаючи з версії Anchor v0.30, ці дискримінатори включені в файл IDL. + +Зверніть увагу, що при роботі з Anchor, вам зазвичай не потрібно взаємодіяти +безпосередньо з цими дискримінаторами. Цей розділ надає контекст щодо того, +як генерується і використовується дискримінатор. + + + + + +Дискримінатор інструкції використовується програмою для визначення, яку конкретну +інструкцію виконати при виклику. + +Коли інструкція програми Anchor викликається, дискримінатор включається як +перші 8 байтів даних інструкції. Це робиться автоматично клієнтом Anchor. + +```json filename="IDL" {4} + "instructions": [ + { + "name": "initialize", + "discriminator": [175, 175, 109, 31, 13, 152, 155, 237], + ... + } + ] +``` + +Дискримінатор для інструкції — це перші 8 байтів хешу Sha256 префікса `global` плюс ім'я інструкції. + +Наприклад: + +``` +sha256("global:initialize") +``` + +Hexadecimal output: + +``` +af af 6d 1f 0d 98 9b ed d4 6a 95 07 32 81 ad c2 1b b5 e0 e1 d7 73 b2 fb bd 7a b5 04 cd d4 aa 30 +``` + +The first 8 bytes are used as the discriminator for the instruction. + +``` +af = 175 +af = 175 +6d = 109 +1f = 31 +0d = 13 +98 = 152 +9b = 155 +ed = 237 +``` + +Реалізацію генерації дискримінатора ви можете знайти в кодовій базі Anchor +[тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/codegen/program/common.rs#L5-L19), +яка використовується +[тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/codegen/program/instruction.rs#L27). + + + + +Дискримінатор рахунку використовується для ідентифікації конкретного типу рахунку при +десеріалізації даних з ланцюга та встановлюється при створенні рахунку. + +```json filename="IDL" {4} + "accounts": [ + { + "name": "NewAccount", + "discriminator": [176, 95, 4, 118, 91, 177, 125, 232] + } + ] +``` + +Дискримінатор для рахунку — це перші 8 байтів хешу Sha256 префікса `account` плюс ім'я рахунку. + +Наприклад: + + +``` +sha256("account:NewAccount") +``` + +Hexadecimal output: + +``` +b0 5f 04 76 5b b1 7d e8 a1 93 57 2a d3 5e b1 ae e5 f0 69 e2 09 7e 5c d2 64 56 55 2a cb 4a e9 57 +``` + +Перші 8 байтів використовуються як дискримінатор для рахунку. + +``` +b0 = 176 +5f = 95 +04 = 4 +76 = 118 +5b = 91 +b1 = 177 +7d = 125 +e8 = 232 +``` + +Реалізацію генерації дискримінатора ви можете знайти в кодовій базі Anchor +[тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L101-L117). + +Зверніть увагу, що різні програми, які використовують однакові імена рахунків, генеруватимуть той самий дискримінатор. При десеріалізації даних рахунків програми Anchor також перевірятимуть, що рахунок належить очікуваній програмі для заданого типу рахунку. + + + + +Дискримінатор події використовується для ідентифікації конкретного типу події при +десеріалізації даних з ланцюга при емісії події. + +```json filename="IDL" {4} + "events": [ + { + "name": "NewEvent", + "discriminator": [113, 21, 185, 70, 164, 99, 232, 201] + } + ] +``` + +Дискримінатор для події — це перші 8 байтів хешу Sha256 префікса `event` плюс ім'я події. + +Наприклад: + +``` +sha256("event:NewEvent") +``` + +Hexadecimal output: + +``` +71 15 b9 46 a4 63 e8 c9 2a 3c 4d 83 87 16 cd 9b 66 28 cb e2 cb 7c 5d 70 59 f3 42 2b dc 35 03 53 +``` + +Перші 8 байтів використовуються як дискримінатор для рахунку. + +Перетворення з шістнадцяткового в десятковий дає нам: + +``` +71 = 113 +15 = 21 +b9 = 185 +46 = 70 +a4 = 164 +63 = 99 +e8 = 232 +c9 = 201 +``` + +Реалізацію генерації дискримінатора ви можете знайти в кодовій базі Anchor +[тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/event/src/lib.rs#L23-L27). + +Зверніть увагу, що різні програми, які використовують однакові імена подій, генеруватимуть той самий +дискримінатор. При десеріалізації даних подій програми Anchor також перевірятимуть, що +подія належить очікуваній програмі для заданого типу події. + + + \ No newline at end of file diff --git a/docs/locales/uk/programs/anchor/index.md b/docs/locales/uk/programs/anchor/index.md new file mode 100644 index 000000000..35be0c546 --- /dev/null +++ b/docs/locales/uk/programs/anchor/index.md @@ -0,0 +1,361 @@ +--- +title: Початок роботи з Anchor +description: + Дізнайтесь, як будувати програми для Solana за допомогою фреймворку Anchor. Цей + детальний посібник охоплює створення, збірку, тестування та розгортання смарт-контрактів Solana з використанням Anchor. +sidebarLabel: Фреймворк Anchor +sidebarSortOrder: 0 +altRoutes: + - /docs/programs/debugging + - /docs/programs/lang-c + - /docs/programs/overview +--- + +Фреймворк Anchor — це інструмент, який спрощує процес створення програм для Solana. +Неважливо, чи ви новачок у блокчейн-розробці, чи досвідчений програміст, Anchor спрощує процес написання, тестування та розгортання +програм для Solana. + +У цьому розділі ми розглянемо: + +- Створення нового проекту Anchor +- Збірка та тестування вашої програми +- Розгортання на кластерах Solana +- Розуміння структури файлів проекту + +## Попередні вимоги + +Для детальних інструкцій по установці відвідайте сторінку +[встановлення](/docs/intro/installation). + +Перед тим, як почати, переконайтесь, що у вас встановлено наступне: + +- Rust: Мова програмування для створення програм для Solana. +- Solana CLI: Інструмент командного рядка для розробки на Solana. +- Anchor CLI: Інструмент командного рядка для фреймворку Anchor. + +Щоб перевірити встановлення Anchor CLI, відкрийте термінал і виконайте: + + +```shell filename="Terminal" +anchor --version +``` + +Очікуваний результат: + +```shell filename="Terminal" +anchor-cli 0.30.1 +``` + +## Початок роботи + +Цей розділ охоплює основні кроки для створення, зборки та тестування вашої першої локальної програми на Anchor. + + + +### Створення нового проекту + +Щоб почати новий проект, використовуйте команду `anchor init`, після якої вкажіть назву вашого проекту. Ця команда створює нову директорію з вказаним ім'ям і налаштовує стандартну програму та тестовий файл. + +```shell filename="Terminal" +anchor init my-project +``` + +Перейдіть до нової директорії проекту та відкрийте її у вашому редакторі коду. + +```shell filename="Terminal" copy +cd my-project +``` + +Стандартна програма Anchor знаходиться за адресою `programs/my-project/src/lib.rs`. + + + + +Значення в макросі `declare_id!` є ID програми, унікальним ідентифікатором для +вашої програми. + +За замовчуванням це публічний ключ ключової пари, згенерованої в +`/target/deploy/my_project-keypair.json`. + +```rs filename="lib.rs" +use anchor_lang::prelude::*; + +declare_id!("3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg"); + +#[program] +pub mod my_project { + use super::*; + + pub fn initialize(ctx: Context) -> Result<()> { + msg!("Greetings from: {:?}", ctx.program_id); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize {} +``` + + + + +Стандартний тестовий файл TypeScript знаходиться за адресою `/tests/my-project.ts`. + + + + +Цей файл демонструє, як викликати інструкцію `initialize` стандартної програми в TypeScript. + + +```ts filename="my-project.ts" +import * as anchor from "@coral-xyz/anchor"; +import { Program } from "@coral-xyz/anchor"; +import { MyProject } from "../target/types/my_project"; + +describe("my-project", () => { + // Configure the client to use the local cluster. + anchor.setProvider(anchor.AnchorProvider.env()); + + const program = anchor.workspace.MyProject as Program; + + it("Is initialized!", async () => { + // Add your test here. + const tx = await program.methods.initialize().rpc(); + console.log("Your transaction signature", tx); + }); +}); +``` + + + + +Якщо ви віддаєте перевагу Rust для тестування, ініціалізуйте свій проект за допомогою прапорця +`--test-template rust`. + +```shell +anchor init --test-template rust my-project +``` + +Тестовий файл Rust буде знаходитися за адресою `/tests/src/test_initialize.rs`. + + + + +```rust filename="test_initialize.rs" +use std::str::FromStr; + +use anchor_client::{ + solana_sdk::{ + commitment_config::CommitmentConfig, pubkey::Pubkey, signature::read_keypair_file, + }, + Client, Cluster, +}; + +#[test] +fn test_initialize() { + let program_id = "3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg"; + let anchor_wallet = std::env::var("ANCHOR_WALLET").unwrap(); + let payer = read_keypair_file(&anchor_wallet).unwrap(); + + let client = Client::new_with_options(Cluster::Localnet, &payer, CommitmentConfig::confirmed()); + let program_id = Pubkey::from_str(program_id).unwrap(); + let program = client.program(program_id).unwrap(); + + let tx = program + .request() + .accounts(my_program::accounts::Initialize {}) + .args(my_program::instruction::Initialize {}) + .send() + .expect(""); + + println!("Your transaction signature {}", tx); +} +``` + + + + +### Збірка програми + +Зібрати програму можна, виконавши команду `anchor build`. + +```shell filename="Terminal" copy +anchor build +``` + +Зкомпільована програма буде знаходитися за адресою `/target/deploy/my_project.so`. Вміст +цього файлу буде збережено в мережі Solana (як виконуваний акаунт) +під час розгортання вашої програми. + +### Тестування програми + +Для тестування програми виконайте команду `anchor test`. + +```shell filename="Terminal" copy +anchor test +``` + +За замовчуванням конфігураційний файл `Anchor.toml` вказує на кластер `localnet`. При розробці на `localnet`, команда `anchor test` автоматично: + +1. Запускає локальний валідатор Solana +2. Створює та розгортає вашу програму на локальному кластері +3. Виконує тести з папки `tests` +4. Зупиняє локальний валідатор Solana + +Альтернативно, ви можете вручну запустити локальний валідатор Solana та виконувати тести проти нього. Це корисно, якщо ви хочете, щоб валідатор працював, поки ви працюєте над програмою. Це дозволяє вам перевіряти акаунти та журнали транзакцій на [Solana Explorer](https://explorer.solana.com/?cluster=custom) під час розробки локально. + +Відкрийте новий термінал і запустіть локальний валідатор Solana, виконуючи команду +`solana-test-validator`. + +```shell filename="Terminal" copy +solana-test-validator +``` + +У окремому терміналі виконайте тести проти локального кластера. Використовуйте прапорець +`--skip-local-validator`, щоб пропустити запуск локального валідатора, оскільки він уже працює. + +```shell filename="Terminal" copy +anchor test --skip-local-validator +``` + +### Розгортання на Devnet + +За замовчуванням конфігураційний файл `Anchor.toml` у проекті Anchor вказує на кластер localnet. + +```toml filename="Anchor.toml" {14} +[toolchain] + +[features] +resolution = true +skip-lint = false + +[programs.localnet] +my_program = "3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg" + +[registry] +url = "https://api.apr.dev" + +[provider] +cluster = "Localnet" +wallet = "~/.config/solana/id.json" + +[scripts] +test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" +``` + +Щоб розгорнути вашу програму на devnet, змініть значення `cluster` на `Devnet`. Зверніть увагу, що для цього ваш гаманець повинен мати достатньо SOL на Devnet для покриття вартості розгортання. + +```diff +-cluster = "Localnet" ++cluster = "Devnet" +``` + +```toml filename="Anchor.toml" +[provider] +cluster = "Devnet" +wallet = "~/.config/solana/id.json" +``` + +Тепер, коли ви виконаєте команду `anchor deploy`, ваша програма буде розгорнута на кластері devnet. Команда `anchor test` також використовуватиме кластер, вказаний у файлі `Anchor.toml`. + +```shell +anchor deploy +``` + +Щоб розгорнути на mainnet, просто оновіть файл `Anchor.toml`, вказавши кластер mainnet. + +```toml filename="Anchor.toml" +[provider] +cluster = "Mainnet" +wallet = "~/.config/solana/id.json" +``` + +### Оновлення програми + +Програми Solana можна оновити, повторно розгорнувши програму з тим самим ID програми. + +Щоб оновити програму, просто внесіть зміни в код вашої програми і виконайте команду +`anchor build` для генерації оновленого файлу `.so`. + + +```shell +anchor build +``` + +Потім виконайте команду `anchor deploy`, щоб повторно розгорнути оновлену програму. + +```shell +anchor deploy +``` + +### Закриття програми + +Щоб повернути SOL, виділені на акаунт програми, ви можете закрити вашу програму Solana. + +Для закриття програми використовуйте команду `solana program close `. Наприклад: + +```shell +solana program close 3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg --bypass-warning +``` + +Зверніть увагу, що після закриття програми, ID програми не можна буде використовувати для розгортання нової програми. + + + +## Структура файлів проекту + +Нижче наведено огляд стандартної структури файлів у робочому просторі Anchor: + +``` +. +├── .anchor +│ └── program-logs +├── app +├── migrations +├── programs +│ └── [project-name] +│ └── src +│ ├── lib.rs +│ ├── Cargo.toml +│ └── Xargo.toml +├── target +│ ├── deploy +│ │ └── [project-name]-keypair.json +│ ├── idl +│ │ └── [project-name].json +│ └── types +│ └── [project-name].ts +├── tests +│ └── [project-name].ts +├── Anchor.toml +├── Cargo.toml +└── package.json +``` + +### Папка Programs + +Папка `/programs` містить програми Anchor вашого проекту. Один робочий простір може містити кілька програм. + +### Папка Tests + +Папка `/tests` містить тестові файли для вашого проекту. Стандартний тестовий файл створюється автоматично під час створення вашого проекту. + +### Папка Target + +Папка `/target` містить результати збірки. Основні підпапки включають: + +- `/deploy`: Містить ключову пару та бінарний файл програми для ваших програм. +- `/idl`: Містить JSON IDL для ваших програм. +- `/types`: Містить TypeScript тип для IDL. + +### Файл Anchor.toml + +Файл `Anchor.toml` налаштовує параметри робочого простору для вашого проекту. + +### Папка .anchor + +Містить файл `program-logs`, що містить журнали транзакцій з останнього виконання тестових файлів. + +### Папка App + +Папка `/app` є порожньою і може бути опційно використана для вашого фронтенд-коду. \ No newline at end of file diff --git a/docs/locales/uk/programs/anchor/pda.md b/docs/locales/uk/programs/anchor/pda.md new file mode 100644 index 000000000..505698c82 --- /dev/null +++ b/docs/locales/uk/programs/anchor/pda.md @@ -0,0 +1,315 @@ +--- +title: PDAs з Anchor +description: + Дізнайтеся, як використовувати Program Derived Addresses (PDA) в програмах Anchor, використовуючи + обмеження та реалізуючи поширені шаблони PDA +sidebarLabel: PDAs з Anchor +sidebarSortOrder: 4 +--- + +[Program Derived Addresses (PDA)](/docs/core/pda) — це функція розробки на Solana, +яка дозволяє створювати унікальну адресу, що отримується детерміновано +з попередньо визначених вхідних значень (насіння) та ID програми. + +Цей розділ охоплює базові приклади використання PDA в програмі Anchor. + +## Обмеження Anchor для PDA + +При використанні PDA в програмі Anchor, зазвичай використовуються обмеження акаунтів Anchor +для визначення насіння, що використовуються для отримання PDA. Ці обмеження служать +як перевірки безпеки, щоб переконатися, що правильна адреса була отримана. + +Обмеження, які використовуються для визначення насіння PDA, включають: + +- `seeds`: Масив необов'язкових насінь, що використовуються для отримання PDA. Насіння можуть бути + статичними значеннями або динамічними посиланнями на дані акаунтів. +- `bump`: Bump seed, що використовується для отримання PDA. Використовується для забезпечення того, + щоб адреса не потрапляла на криву Ed25519 і була дійсним PDA. +- `seeds::program` - (Необов'язково) ID програми, що використовується для отримання адреси PDA. + Це обмеження використовується лише для отримання PDA, де ID програми не є + поточною програмою. + +Обмеження `seeds` та `bump` повинні використовуватися разом. + +### Приклади використання + +Нижче наведені приклади, що демонструють, як використовувати обмеження PDA в програмі Anchor. + + + + + +Обмеження `seeds` визначає необов'язкові значення, що використовуються для отримання PDA. + +#### Без необов'язкових сідів + +- Використовуйте порожній масив `[]`, щоб визначити PDA без необов'язкових насінь. + + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + #[account( + seeds = [], + bump, + )] + pub pda_account: SystemAccount<'info>, +} +``` + +#### Одне статичне насіння + +- Вкажіть необов'язкові насіння в обмеженні `seeds`. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + #[account( + seeds = [b"hello_world"], + bump, + )] + pub pda_account: SystemAccount<'info>, +} +``` + +#### Кілька насінь та посилань на акаунти + +- Можна вказати кілька насінь в обмеженні `seeds`. Обмеження `seeds` + також може посилатися на інші адреси акаунтів або дані акаунтів. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + pub signer: Signer<'info>, + #[account( + seeds = [b"hello_world", signer.key().as_ref()], + bump, + )] + pub pda_account: SystemAccount<'info>, +} +``` + +Приклад вище використовує як статичне насіння (`b"hello_world"`), так і динамічне насіння +(публічний ключ підписанта). + + + + +Обмеження `bump` визначає bump seed, що використовується для отримання PDA. + +#### Автоматичний розрахунок Bump + +При використанні обмеження `bump` без вказаного значення, bump автоматично +вираховується щоразу, коли викликається інструкція. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + #[account( + seeds = [b"hello_world"], + bump, + )] + pub pda_account: SystemAccount<'info>, +} +``` + +#### Вказати значення Bump + +Ви можете явно вказати значення bump, що корисно для оптимізації використання обчислювальних одиниць. Це передбачає, що акаунт PDA вже був створений і bump seed зберігається як поле в існуючому акаунті. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + #[account( + seeds = [b"hello_world"], + bump = pda_account.bump_seed, + )] + pub pda_account: Account<'info, CustomAccount>, +} + +#[account] +pub struct CustomAccount { + pub bump_seed: u8, +} +``` + +Зберігаючи значення bump у даних акаунту, програма не потребує його повторного обчислення, що дозволяє заощадити обчислювальні одиниці. Збережене значення bump може бути збережено в самому акаунті або в іншому акаунті. + + + + +Обмеження `seeds::program` визначає ID програми, що використовується для отримання PDA. +Це обмеження використовується лише при отриманні PDA з іншої програми. + +Використовуйте це обмеження, коли ваша інструкція повинна взаємодіяти з акаунтами PDA, +створеними іншою програмою. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + #[account( + seeds = [b"hello_world"], + bump, + seeds::program = other_program.key(), + )] + pub pda_account: SystemAccount<'info>, + pub other_program: Program<'info, OtherProgram>, +} +``` + + + + +Обмеження `init` зазвичай використовується разом з `seeds` та `bump` для створення нового +акаунту з адресою, яка є PDA. Під капотом обмеження `init` +викликає System Program для створення акаунту. + +```rs +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + #[account(mut)] + pub signer: Signer<'info>, + #[account( + init, + seeds = [b"hello_world", signer.key().as_ref()], + bump, + payer = signer, + space = 8 + 1, + )] + pub pda_account: Account<'info, CustomAccount>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct CustomAccount { + pub bump_seed: u8, +} +``` + + + + +## Насіння PDA в IDL + +Насіння Program Derived Address (PDA), визначені в обмеженні `seeds`, включені в IDL файл програми. Це дозволяє клієнту Anchor автоматично вирішувати акаунти, використовуючи ці насіння під час побудови інструкцій. + +Наведений нижче приклад показує взаємозв'язок між програмою, IDL та клієнтом. + + + + + +Програма нижче визначає `pda_account`, використовуючи статичне насіння (`b"hello_world"`) +та публічний ключ підписанта як динамічне насіння. + +```rs {18} /signer/ +use anchor_lang::prelude::*; + +declare_id!("BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5"); + +#[program] +mod hello_anchor { + use super::*; + pub fn test_instruction(ctx: Context) -> Result<()> { + msg!("PDA: {}", ctx.accounts.pda_account.key()); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct InstructionAccounts<'info> { + pub signer: Signer<'info>, + #[account( + seeds = [b"hello_world", signer.key().as_ref()], + bump, + )] + pub pda_account: SystemAccount<'info>, +} +``` + + + + +IDL файл програми включає насіння PDA, визначені в обмеженні `seeds`. + +- Статичне насіння `b"hello_world"` перетворюється на байтові значення. +- Динамічне насіння включається як посилання на акаунт підписанта. + +```json {22-29} +{ + "address": "BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5", + "metadata": { + "name": "hello_anchor", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "test_instruction", + "discriminator": [33, 223, 61, 208, 32, 193, 201, 79], + "accounts": [ + { + "name": "signer", + "signer": true + }, + { + "name": "pda_account", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [104, 101, 108, 108, 111, 95, 119, 111, 114, 108, 100] + }, + { + "kind": "account", + "path": "signer" + } + ] + } + } + ], + "args": [] + } + ] +} +``` + + + + +Клієнт Anchor може автоматично визначити адресу PDA, використовуючи IDL файл. + +У наведеному нижче прикладі Anchor автоматично визначає адресу PDA, використовуючи гаманець постачальника як підписанта, а його публічний ключ як динамічне насіння для отримання PDA. Це усуває необхідність явного отримання PDA під час побудови інструкції. + +```ts {13} +import * as anchor from "@coral-xyz/anchor"; +import { Program } from "@coral-xyz/anchor"; +import { HelloAnchor } from "../target/types/hello_anchor"; + +describe("hello_anchor", () => { + // Configure the client to use the local cluster. + anchor.setProvider(anchor.AnchorProvider.env()); + + const program = anchor.workspace.HelloAnchor as Program; + + it("Is initialized!", async () => { + // Add your test here. + const tx = await program.methods.testInstruction().rpc(); + console.log("Your transaction signature", tx); + }); +}); +``` + +Коли інструкція викликається, PDA виводиться в журнали програми, як це визначено в інструкції програми. + +```{3} +Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 invoke [1] +Program log: Instruction: TestInstruction +Program log: PDA: 3Hikt5mpKaSS4UNA5Du1TZJ8tp4o8VC8YWW6X9vtfVnJ +Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 consumed 18505 of 200000 compute units +Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 success +``` + + + diff --git a/docs/locales/uk/programs/anchor/program-structure.md b/docs/locales/uk/programs/anchor/program-structure.md new file mode 100644 index 000000000..3fc534b6c --- /dev/null +++ b/docs/locales/uk/programs/anchor/program-structure.md @@ -0,0 +1,373 @@ +--- +title: Структура програми Anchor +description: + Дізнайтеся про структуру програм Anchor, включаючи основні макроси та їх + роль у спрощенні розробки програм для Solana +sidebarLabel: Структура програми +sidebarSortOrder: 1 +--- + +[Фреймворк Anchor](https://www.anchor-lang.com/) використовує +[макроси Rust](https://doc.rust-lang.org/book/ch19-06-macros.html) для зменшення +обсягу шаблонного коду та спрощення реалізації загальних перевірок безпеки, +необхідних для написання програм для Solana. + +Основні макроси, які використовуються в програмі Anchor, включають: + +- [`declare_id`](#declare-id-macro): Визначає on-chain адресу програми +- [`#[program]`](#program-macro): Визначає модуль, що містить логіку інструкцій програми +- [`#[derive(Accounts)]`](#derive-accounts-macro): Застосовується до структур для + вказівки списку акаунтів, необхідних для інструкції +- [`#[account]`](#account-macro): Застосовується до структур для створення + користувацьких типів акаунтів для програми + +## Приклад програми + +Давайте розглянемо просту програму, яка демонструє використання вищезгаданих макросів, +щоб зрозуміти основну структуру програми Anchor. + +Наведена нижче програма створює новий акаунт (`NewAccount`), який зберігає +значення `u64`, передане в інструкцію `initialize`. + +```rust filename="lib.rs" +use anchor_lang::prelude::*; + +declare_id!("11111111111111111111111111111111"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64, +} +``` + +## Макрос `declare_id!` + +Макрос +[`declare_id`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L430) +вказує on-chain адресу програми, відому як ID програми. + +```rust filename="lib.rs" {3} +use anchor_lang::prelude::*; + +declare_id!("11111111111111111111111111111111"); +``` + +За замовчуванням, ID програми — це публічний ключ ключової пари, згенерованої за адресою +`/target/deploy/your_program_name.json`. + +Щоб оновити значення ID програми в макросі `declare_id` за допомогою публічного +ключа ключової пари з файлу `/target/deploy/your_program_name.json`, виконайте +наступну команду: + +```shell filename="Terminal" +anchor keys sync +``` + +Команда `anchor keys sync` корисна для виконання при клонуванні репозиторію, де +значення ID програми в макросі `declare_id` клонованого репозиторію не буде співпадати +з тим, що генерується при виконанні команди `anchor build` локально. + +## Макрос `#[program]` + +Макрос +[`#[program]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/lib.rs#L12) +визначає модуль, що містить усі обробники інструкцій для вашої програми. Кожна публічна функція +в межах цього модуля відповідає інструкції, яку можна викликати. + +```rust filename="lib.rs" {5, 8-12} +use anchor_lang::prelude::*; + +declare_id!("11111111111111111111111111111111"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64, +} +``` + +### Контекст інструкції + +Обробники інструкцій — це функції, які визначають логіку, що виконується, коли інструкція викликається. Перший параметр кожного обробника має тип `Context`, де `T` — це структура, яка реалізує трейд `Accounts` і вказує на акаунти, які потрібні для інструкції. + +Тип +[`Context`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/context.rs#L24) +надає інструкції доступ до наступних неаргументних входів: + +```rust +pub struct Context<'a, 'b, 'c, 'info, T> { + /// Currently executing program id. + pub program_id: &'a Pubkey, + /// Deserialized accounts. + pub accounts: &'b mut T, + /// Remaining accounts given but not deserialized or validated. + /// Be very careful when using this directly. + pub remaining_accounts: &'c [AccountInfo<'info>], + /// Bump seeds found during constraint validation. This is provided as a + /// convenience so that handlers don't have to recalculate bump seeds or + /// pass them in as arguments. + pub bumps: BTreeMap, +} +``` + +Поля `Context` можна отримати в інструкції за допомогою позначення через крапку: + +- `ctx.accounts`: Акаунти, необхідні для інструкції +- `ctx.program_id`: Публічний ключ програми (адреса) +- `ctx.remaining_accounts`: Додаткові акаунти, які не вказані в структурі `Accounts`. +- `ctx.bumps`: Bump seed для будь-яких акаунтів + [Program Derived Address (PDA)](/docs/core/pda.md), вказаних у структурі + `Accounts` + +Додаткові параметри є необов'язковими та можуть бути включені для вказівки аргументів, які повинні бути надані при виклику інструкції. + +```rust filename="lib.rs" /Context/ /data/1 +pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) +} +``` + +У цьому прикладі структура `Initialize` реалізує трейд `Accounts`, де +кожне поле в структурі представляє акаунт, необхідний для інструкції `initialize`. + +```rust filename="lib.rs" /Initialize/ /Accounts/ +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} +``` + +## Макрос `#[derive(Accounts)]` + +Макрос +[`#[derive(Accounts)]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/derive/accounts/src/lib.rs#L630) +застосовується до структури для вказівки акаунтів, які повинні бути надані під час виклику інструкції. Цей макрос реалізує трейд +[`Accounts`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/lib.rs#L105), +що спрощує перевірку акаунтів, а також серіалізацію та десеріалізацію даних акаунтів. + +```rust /Accounts/ {1} +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} +``` + +Кожне поле в структурі представляє акаунт, необхідний для інструкції. Іменування кожного поля є довільним, але рекомендується використовувати описове ім'я, яке вказує на призначення акаунту. + +```rust /signer/2 /new_account/ /system_program/ +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} +``` + +### Перевірка акаунтів + +Для запобігання вразливостям безпеки важливо перевіряти, що акаунти, надані інструкції, є очікуваними. Акаунти перевіряються в програмах Anchor двома способами, які зазвичай використовуються разом: + +- [Обмеження акаунтів](https://www.anchor-lang.com/docs/account-constraints): + Обмеження визначають додаткові умови, які акаунт повинен задовольняти, щоб вважатися дійсним для інструкції. Обмеження застосовуються за допомогою атрибута `#[account(..)]`, який розміщується над полем у структурі, що реалізує трейд `Accounts`. + + Реалізацію обмежень можна знайти + [тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/parser/accounts/constraints.rs). + + ```rust {3, 5} + #[derive(Accounts)] + pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, + } + ``` + +- [Типи акаунтів](https://www.anchor-lang.com/docs/account-types): Anchor + надає різні типи акаунтів, щоб допомогти гарантувати, що акаунт, наданий клієнтом, відповідає тому, що очікує програма. + + Реалізацію типів акаунтів можна знайти + [тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/accounts). + + ```rust /Account/2 /Signer/ /Program/ + #[derive(Accounts)] + pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, + } + ``` + +Коли інструкція в програмі Anchor викликається, програма спочатку перевіряє +надані акаунти перед виконанням логіки інструкції. Після перевірки ці акаунти можна отримати в інструкції за допомогою синтаксису `ctx.accounts`. + +```rust filename="lib.rs" /ctx.accounts.new_account/ /new_account/ /Initialize/ +use anchor_lang::prelude::*; + +declare_id!("11111111111111111111111111111111"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64, +} +``` + +## Макрос `#[account]` + +Макрос +[`#[account]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L66) +застосовується до структур, які визначають дані, що зберігаються в користувацьких акаунтах, +створених вашою програмою. + +```rust +#[account] +pub struct NewAccount { + data: u64, +} +``` + +Цей макрос реалізує різні трейди +[детальніше тут](https://docs.rs/anchor-lang/latest/anchor_lang/attr.account.html). +Основні функціональні можливості макроса `#[account]` включають: + +- [Призначення власника програми](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L119-L132): + При створенні акаунту власник акаунту автоматично встановлюється на програму, + вказану в `declare_id`. +- [Встановлення дискримінатора](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L101-L117): + Унікальний 8-байтовий дискримінатор, що визначає тип акаунту, додається як + перші 8 байтів даних акаунту під час його ініціалізації. Це допомагає + відрізняти типи акаунтів і використовується для перевірки акаунтів. +- [Серіалізація та десеріалізація даних](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L202-L246): + Дані акаунту автоматично серіалізуються та десеріалізуються відповідно до типу акаунту. + + +```rust filename="lib.rs" /data/2,6 /NewAccount/ {24-27} +use anchor_lang::prelude::*; + +declare_id!("11111111111111111111111111111111"); + +#[program] +mod hello_anchor { + use super::*; + pub fn initialize(ctx: Context, data: u64) -> Result<()> { + ctx.accounts.new_account.data = data; + msg!("Changed data to: {}!", data); + Ok(()) + } +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[account] +pub struct NewAccount { + data: u64, +} +``` + +### Дискримінатор акаунту + +Дискримінатор акаунту в програмі Anchor — це 8-байтовий ідентифікатор, +унікальний для кожного типу акаунту. Він отримується з перших 8 байтів SHA256 +хешу рядка `account:`. Цей дискримінатор зберігається як перші 8 байтів даних акаунту під час його створення. + +При створенні акаунту в програмі Anchor для дискримінатора повинно бути виділено 8 байтів. + +```rust /8/1 +#[account(init, payer = signer, space = 8 + 8)] +pub new_account: Account<'info, NewAccount>, +``` + +Дискримінатор використовується в наступних двох сценаріях: + +- Ініціалізація: Коли акаунт створюється, дискримінатор встановлюється як перші 8 байтів даних акаунту. +- Десеріалізація: Коли дані акаунту десеріалізуються, перші 8 байтів даних акаунту перевіряються на відповідність дискримінатору очікуваного типу акаунту. + +Якщо є невідповідність, це вказує на те, що клієнт надав неочікуваний акаунт. Цей механізм служить перевіркою валідності акаунтів у програмах Anchor. diff --git a/docs/locales/uk/programs/deploying.md b/docs/locales/uk/programs/deploying.md new file mode 100644 index 000000000..7486f9866 --- /dev/null +++ b/docs/locales/uk/programs/deploying.md @@ -0,0 +1,299 @@ +--- +title: "Розгортання програм" +description: + Розгортання програм на ланцюгу можна здійснити за допомогою Solana CLI, використовуючи + Upgradable BPF loader для завантаження скомпільованого байт-коду на блокчейн Solana. +sidebarSortOrder: 2 +--- + +Програми Solana зберігаються в "виконуваних" акаунтах в мережі. Ці +акаунти містять скомпільований байт-код програми, який визначає інструкції, +які користувачі викликають для взаємодії з програмою. + +## Команди CLI + +Цей розділ призначений як довідник для базових команд CLI для створення +та розгортання програм Solana. Для покрокового посібника зі створення вашої першої +програми почніть з [Розробки програм на Rust](/docs/programs/rust). + +### Збірка програми + +Щоб побудувати вашу програму, використовуйте команду `cargo build-sbf`. + +```shell +cargo build-sbf +``` + +Ця команда: + +1. Скомпілює вашу програму +2. Створить директорію `target/deploy` +3. Згенерує файл `.so`, де `` відповідає імені вашої програми у файлі `Cargo.toml` + +Вивантажений файл `.so` містить скомпільований байт-код вашої програми, який буде +збережено в акаунті Solana під час розгортання вашої програми. + +### Розгортання програми + +Щоб розгорнути вашу програму, використовуйте команду `solana program deploy`, вказавши шлях до файлу `.so`, який був створений командою `cargo build-sbf`. + +```shell +solana program deploy ./target/deploy/your_program.so +``` + +Під час періодів завантаження є кілька додаткових прапорців, які можна використовувати для полегшення розгортання програми. + +- `--with-compute-unit-price`: Встановіть ціну за обчислювальні одиниці для транзакції, в increments 0.000001 лампортів (мікро-лампорти) за обчислювальну одиницю. +- `--max-sign-attempts`: Максимальна кількість спроб підписати або повторно підписати транзакції після закінчення терміну дії blockhash. Якщо будь-які транзакції, надіслані під час розгортання програми, залишаються непідтвердженими після закінчення терміну дії початково вибраного останнього blockhash, ці транзакції будуть повторно підписані з новим blockhash і відправлені знову. Використовуйте цей параметр для налаштування максимальної кількості спроб підписання транзакцій. Кожен blockhash є дійсним близько 60 секунд, що означає, що використання значення за замовчуванням 5 призведе до надсилання транзакцій щонайменше 5 хвилин або до тих пір, поки всі транзакції не будуть підтверджені, залежно від того, що відбудеться раніше. [за замовчуванням: 5] +- `--use-rpc`: Надсилайте транзакції запису до налаштованого RPC замість TPU валідатора. Цей прапорець вимагає RPC з урахуванням ставки. + +Ви можете використовувати ці прапорці окремо або поєднувати їх разом. Наприклад: + +```shell +solana program deploy ./target/deploy/your_program.so --with-compute-unit-price 10000 --max-sign-attempts 1000 --use-rpc +``` +- Використовуйте + [Priority Fee API від Helius](https://docs.helius.dev/guides/priority-fee-api) + для отримання оцінки пріоритетної плати, яку потрібно встановити за допомогою + прапорця `--with-compute-unit-price`. + +- Отримайте + [RPC з урахуванням ставки](https://solana.com/developers/guides/advanced/stake-weighted-qos) + від [Helius](https://www.helius.dev/) або + [Triton](https://triton.one/) для використання з прапорцем `--use-rpc`. Прапорець + `--use-rpc` повинен використовуватись тільки з RPC з урахуванням ставки. + +Щоб оновити ваш за умовчанням RPC URL за допомогою власної точки доступу RPC, використовуйте команду +`solana config set`. + +```shell +solana config set --url +``` + +Ви можете переглянути список програм, які ви розгорнули, використовуючи підкоманду `program show`: + +```shell +solana program show --programs +``` + +Example output: + +``` +Program Id | Slot | Authority | Balance +2w3sK6CW7Hy1Ljnz2uqPrQsg4KjNZxD4bDerXDkSX3Q1 | 133132 | 4kh6HxYZiAebF8HWLsUWod2EaQQ6iWHpHYCz8UcmFbM1 | 0.57821592 SOL +``` + +### Оновлення програми + +Авторизація на оновлення програми може змінювати існуючу програму Solana, розгортаючи +новий файл `.so` на той самий ID програми. + +Щоб оновити існуючу програму Solana: + +- Змініть вихідний код вашої програми +- Виконайте команду `cargo build-sbf`, щоб згенерувати оновлений файл `.so` +- Виконайте команду `solana program deploy ./target/deploy/your_program.so`, щоб розгорнути + оновлений файл `.so` + +Авторизацію на оновлення можна змінити за допомогою підкоманди `set-upgrade-authority` +наступним чином: + +```shell +solana program set-upgrade-authority --new-upgrade-authority +``` + +### Незмінна програма + +Програму можна зробити незмінною, видаливши її авторизацію на оновлення. Це незворотна дія. + +```shell +solana program set-upgrade-authority --final +``` + +Ви можете вказати, що програма має бути незмінною при розгортанні, встановивши прапорець +`--final` під час розгортання програми. + +```shell +solana program deploy ./target/deploy/your_program.so --final +``` + +### Закрити програму + +Ви можете закрити свою програму Solana, щоб повернути SOL, виділені для акаунту. +Закриття програми є незворотним, тому це слід робити обережно. Щоб закрити +програму, використовуйте підкоманду `program close`. Наприклад: + +```shell filename="Terminal" +solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz +--bypass-warning +``` + +Example output: + +``` +Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOL +reclaimed +``` + +Зверніть увагу, що після закриття програми її ID програми не можна буде використовувати знову. Спроба розгорнути програму з раніше закритим ID програми призведе до помилки. + +``` +Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, use +a new Program Id +``` + +Якщо вам потрібно повторно розгорнути програму після її закриття, ви повинні згенерувати новий +ID програми. Щоб згенерувати нову ключову пару для програми, виконайте наступну команду: + +```shell filename="Terminal" +solana-keygen new -o ./target/deploy/your_program-keypair.json --force +``` + +Альтернативно, ви можете видалити існуючий файл ключової пари і знову виконати +команду `cargo build-sbf`, що згенерує новий файл ключової пари. + +### Акаунти буфера програми + +Розгортання програми вимагає кількох транзакцій через обмеження в 1232 байти +для транзакцій на Solana. Проміжним кроком процесу розгортання є запис байт-коду програми в тимчасовий "акаунт буфера". + +Цей акаунт буфера автоматично закривається після успішного розгортання програми. +Однак, якщо розгортання не вдалося, акаунт буфера залишається, і ви можете: + +- Продовжити розгортання, використовуючи існуючий акаунт буфера +- Закрити акаунт буфера, щоб повернути виділений SOL (оренду) + +Ви можете перевірити, чи є відкриті акаунти буфера, використовуючи підкоманду `program show`, наступним чином: + +```shell +solana program show --buffers +``` + +Example output: + +``` +Buffer Address | Authority | Balance +5TRm1DxYcXLbSEbbxWcQbEUCce7L4tVgaC6e2V4G82pM | 4kh6HxYZiAebF8HWLsUWod2EaQQ6iWHpHYCz8UcmFbM1 | 0.57821592 SOL +``` + +Ви можете продовжити до розгортання за допомогою підкоманди `program deploy` наступним чином: + +```shell +solana program deploy --buffer 5TRm1DxYcXLbSEbbxWcQbEUCce7L4tVgaC6e2V4G82pM +``` + +Expected output on successful deployment: + +``` +Program Id: 2w3sK6CW7Hy1Ljnz2uqPrQsg4KjNZxD4bDerXDkSX3Q1 + +Signature: 3fsttJFskUmvbdL5F9y8g43rgNea5tYZeVXbimfx2Up5viJnYehWe3yx45rQJc8Kjkr6nY8D4DP4V2eiSPqvWRNL +``` + +To close buffer accounts, use the `program close` subcommand as follows: + +```shell +solana program close --buffers +``` + +### ELF Dump + +Внутрішні дані SBF shared object можна вивести в текстовий файл, щоб отримати більше +інформації про склад програми та те, що вона може виконувати під час виконання. Вивантаження +містить як ELF інформацію, так і список всіх символів та інструкцій, що їх реалізують. Деякі з повідомлень журналу помилок BPF loader +будуть посилатися на конкретні номери інструкцій, де сталася помилка. +Ці посилання можна знайти у вивантаженні ELF, щоб ідентифікувати помилкову інструкцію та її контекст. + +```shell +cargo build-bpf --dump +``` + +Файл буде виведено до `/target/deploy/your_program-dump.txt`. + +## Процес розгортання програми + +Розгортання програми на Solana вимагає кількох транзакцій через максимальний +ліміт розміру транзакцій у 1232 байти. Solana CLI надсилає ці транзакції за допомогою підкоманди `solana program deploy`. Процес можна розділити на наступні 3 фази: + +1. [Ініціалізація буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2113): + Спочатку CLI надсилає транзакцію, яка + [створює акаунт буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1903) + достатнього розміру для байт-коду, що розгортається. Також викликається + [інструкція ініціалізації буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L320), + щоб встановити право власності на буфер і обмежити записи на вибрану адресу розробника. +2. [Запис буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2129): + Після ініціалізації акаунту буфера CLI + [розбиває байт-код програми](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1940) + на шматки розміром близько 1 КБ і + [відправляє транзакції зі швидкістю 100 транзакцій за секунду](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/client/src/tpu_client.rs#L133), + щоб записати кожен шматок за допомогою + [інструкції запису буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L334). + Ці транзакції надсилаються безпосередньо до порту обробки транзакцій (TPU) поточного лідера і обробляються паралельно. Після того, як всі транзакції будуть надіслані, CLI + [опитує RPC API партіями підписів транзакцій](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/client/src/tpu_client.rs#L216), + щоб переконатися, що кожен запис був успішним і підтвердженим. +3. [Фіналізація](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1807): + Після завершення записів CLI + [надсилає фінальну транзакцію](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2150) + для того, щоб + [розгорнути нову програму](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L362) + або + [оновити існуючу програму](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L513). + В будь-якому випадку байт-код, записаний в акаунт буфера, буде скопійовано + в акаунт даних програми і перевірено. + +## Оновлювана програма BPF Loader + +Програма BPF loader є програмою, яка "володіє" всіма виконуваними акаунтами на +Solana. Коли ви розгортаєте програму, власник акаунту програми встановлюється на +програму BPF loader. + +### Акаунти стану + +Оновлювана програма BPF loader підтримує три різні типи акаунтів стану: + +1. [Акаунт програми](https://github.com/solana-labs/solana/blob/master/sdk/program/src/bpf_loader_upgradeable.rs#L34): + Це основний акаунт програми на ланцюгу, і його адреса зазвичай + називається "ID програми". ID програми — це те, на що посилаються інструкції транзакцій + для виклику програми. Акаунти програми незмінні після розгортання, тому ви можете вважати їх проксі-акаунтами для байт-коду та + стану, що зберігаються в інших акаунтах. +2. [Акаунт даних програми](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/bpf_loader_upgradeable.rs#L39): + Цей акаунт зберігає виконуваний байт-код програми на ланцюгу. + Коли програма оновлюється, дані цього акаунту оновлюються новим + байт-кодом. Крім байт-коду, акаунти даних програми також + відповідають за зберігання слоту, коли вони були востаннє змінені, та адреси + єдиного акаунту, авторизованого для зміни акаунту (ця адреса може бути + очищена, щоб зробити програму незмінною). +3. [Акаунти буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/bpf_loader_upgradeable.rs#L27): + Ці акаунти тимчасово зберігають байт-код під час активного + розгортання програми через серію транзакцій. Вони також зберігають адресу + єдиного акаунту, який авторизований для виконання записів. + +### Інструкції + +Акаунти стану, перераховані вище, можуть бути змінені лише за допомогою однієї з наступних +інструкцій, що підтримуються програмою Upgradeable BPF Loader: + +1. [Ініціалізація буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L21): + Створює акаунт буфера і зберігає адресу авторизації, яка дозволена + змінювати буфер. +2. [Запис](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L28): + Записує байт-код на вказаний байтовий офсет в акаунті буфера. Записи + обробляються маленькими шматками через обмеження транзакцій Solana, + максимальний розмір яких складає 1232 байти. +3. [Розгортання](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L77): + Створює акаунт програми та акаунт даних програми. Він заповнює + акаунт даних програми, копіюючи байт-код, що зберігається в акаунті буфера. Якщо + байт-код є дійсним, акаунт програми буде встановлений як виконуваний, + дозволяючи його викликати. Якщо байт-код недійсний, інструкція не вдасться, і всі зміни будуть скасовані. +4. [Оновлення](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L102): + Заповнює існуючий акаунт даних програми, копіюючи виконуваний байт-код з акаунта + буфера. Подібно до інструкції розгортання, вона буде успішною лише в тому випадку, якщо + байт-код є дійсним. +5. [Встановлення авторизації](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L114): + Оновлює авторизацію акаунта даних програми або акаунта буфера, якщо поточний + власник акаунту підписав транзакцію, що обробляється. Якщо авторизація буде видалена без заміни, + її можна буде встановити лише один раз і акаунт більше не можна буде закрити. +6. [Закриття](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L127): + Очищає дані акаунта програми або акаунта буфера та повертає SOL, + використані для депозиту звільнення від оренди. + diff --git a/docs/locales/uk/programs/examples.md b/docs/locales/uk/programs/examples.md new file mode 100644 index 000000000..be25a95dd --- /dev/null +++ b/docs/locales/uk/programs/examples.md @@ -0,0 +1,151 @@ +--- +title: "Приклади програм" +description: + "Список прикладів програм для Solana на різних мовах і фреймворках, + які можуть допомогти вам вивчити та використовувати їх як посилання для ваших власних проектів." +tags: + - quickstart + - program + - anchor + - javascript + - native + - rust + - token22 + - token extensions +keywords: + - rust + - cargo + - toml + - program + - tutorial + - intro to solana development + - blockchain developer + - blockchain tutorial + - web3 developer + - anchor +sidebarSortOrder: 3 +--- + +Репозиторій +[Solana Program Examples](https://github.com/solana-developers/program-examples) +на GitHub пропонує кілька підпапок, кожна з яких містить приклади коду +для різних парадигм програмування Solana та мов, створених, щоб допомогти +розробникам вивчати та експериментувати з розробкою на блокчейні Solana. + +Ви можете знайти приклади в репозиторії `solana-developers/program-examples` +разом з файлами README, що пояснюють, як запускати різні приклади. Більшість +прикладів є самодостатніми та доступні на рідному Rust (тобто без використання +фреймворку) та [Anchor](https://www.anchor-lang.com/docs/installation). Також +є список прикладів, які ми з радістю б +[побачили як внески](https://github.com/solana-developers/program-examples?tab=readme-ov-file#examples-wed-love-to-see). + +У репозиторії ви знайдете наступну підпапку, кожну з яких з різними +прикладами програм: + +- [Основи](#basics) +- [Стиснення](#compression) +- [Оракули](#oracles) +- [Токени](#tokens) +- [Token 2022 (Розширення токенів)](#token-2022-token-extensions) +- [Перерва](#break) + - [Збірка та запуск](#build-and-run) + +## Основи + +Містить серію прикладів, які демонструють основні кроки для +створення програм Solana, використовуючи рідні бібліотеки Rust. Ці приклади +призначені для того, щоб допомогти розробникам зрозуміти основні концепції програмування Solana. + +| Назва прикладу | Опис | Мова | +| ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------ | +| [Дані акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/account-data) | Збереження адреси з ім'ям, номером будинку, вулицею та містом в акаунті. | Native, Anchor | +| [Перевірка акаунтів](https://github.com/solana-developers/program-examples/tree/main/basics/checking-accounts) | Уроки безпеки, що показують, як виконувати перевірки акаунтів | Native, Anchor | +| [Закриття акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/close-account) | Показує, як закривати акаунти, щоб повернути оренду. | Native, Anchor | +| [Лічильник](https://github.com/solana-developers/program-examples/tree/main/basics/counter) | Простий програмний лічильник на всіх різних архітектурах. | Native, Anchor, mpl-stack| +| [Створення акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/create-account) | Як створити системний акаунт в межах програми. | Native, Anchor | +| [Перехресний виклик програми](https://github.com/solana-developers/program-examples/tree/main/basics/cross-program-invocation) | Використовуючи аналогію з рукою та важелем, показує, як викликати іншу програму з програми. | Native, Anchor | +| [Hello Solana](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana) | Приклад "Hello world", який просто виводить hello world у журналах транзакцій. | Native, Anchor | +| [Pda Rent payer](https://github.com/solana-developers/program-examples/tree/main/basics/pda-rent-payer) | Показує, як можна використовувати лампорти з PDA для оплати нового акаунта. | Native, Anchor | +| [Обробка інструкцій](https://github.com/solana-developers/program-examples/tree/main/basics/processing-instructions) | Показує, як обробляти рядкові дані інструкцій та u32. | Native, Anchor | +| [Програма з похідними адресами](https://github.com/solana-developers/program-examples/tree/main/basics/program-derived-addresses) | Показує, як використовувати насіння для посилання на PDA та збереження даних в ньому. | Native, Anchor | +| [Перерозподіл](https://github.com/solana-developers/program-examples/tree/main/basics/realloc) | Показує, як збільшувати та зменшувати розмір існуючого акаунта. | Native, Anchor | +| [Оренда](https://github.com/solana-developers/program-examples/tree/main/basics/rent) | Тут ви дізнаєтесь, як обчислювати вимоги оренди в межах програми. | Native, Anchor | +| [Розташування репозиторію](https://github.com/solana-developers/program-examples/tree/main/basics/repository-layout) | Рекомендації щодо структурування вашого макету програми. | Native, Anchor | +| [Передача SOL](https://github.com/solana-developers/program-examples/tree/main/basics/transfer-sol) | Різні методи передачі SOL для системних акаунтів та PDA. | Native, Anchor, Seahorse | + +## Стиснення + +Містить серію прикладів, які демонструють, як використовувати +[стиснення стану](/docs/advanced/state-compression.md) на Solana. Головним чином +фокусується на стиснених NFT (cNFT). + +| Назва прикладу | Опис | Мова | +| -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------- | +| [cNFT-burn](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-burn) | Для знищення cNFT він може бути спалений. Цей приклад показує, як це зробити в програмі. | Anchor | +| [cNFT-Vault](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-vault/anchor) | Як зберігати cNFT в програмі та відправляти його знову. | Anchor | +| [cutils](https://github.com/solana-developers/program-examples/tree/main/compression/cutils) | Набір утиліт для, наприклад, мінтування та перевірки cNFT в програмі. | Anchor | + +## Оракули + +Оракули дозволяють використовувати дані поза ланцюгом в програмах. + +| Назва прикладу | Опис | Мова | +| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------ | +| [Pyth](https://github.com/solana-developers/program-examples/tree/main/oracles/pyth) | Pyth надає дані про ціни токенів для використання в програмах на ланцюгу. | Anchor | + +## Токени + +Більшість токенів на Solana використовують стандарт токенів Solana Program Library (SPL). Тут +ви знайдете багато прикладів, як створювати, передавати, спалювати токени та навіть як взаємодіяти з ними в програмах. + +| Назва прикладу | Опис | Мова | +| --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------ | +| [Створення токена](https://github.com/solana-developers/program-examples/tree/main/tokens/create-token) | Як створити токен та додати метадані метаплекса до нього. | Anchor, Native | +| [NFT Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/nft-minter) | Мінтування тільки однієї кількості токену, а потім видалення права на мінтинг. | Anchor, Native | +| [PDA Mint Authority](https://github.com/solana-developers/program-examples/tree/main/tokens/pda-mint-authority) | Показує, як змінити право на мінтинг токенів через PDA. | Anchor, Native | +| [SPL Token Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/spl-token-minter) | Пояснює, як використовувати Associated Token Accounts для відслідковування токен акаунтів. | Anchor, Native | +| [Token Swap](https://github.com/solana-developers/program-examples/tree/main/tokens/token-swap) | Розширений приклад, який показує, як побудувати AMM (автоматизований маркет-мейкер) пул для SPL токенів. | Anchor | +| [Передача токенів](https://github.com/solana-developers/program-examples/tree/main/tokens/transfer-tokens) | Показує, як передавати SPL токени за допомогою CPIs у програму токенів. | Anchor, Native | +| [Token-2022](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022) | Див. Token 2022 (Розширення токенів). | Anchor, Native | + +## Token 2022 (Розширення токенів) + +Token 2022 — це новий стандарт для токенів на Solana. Це більш гнучкий стандарт, який +дозволяє додавати до токену 16 різних розширень для додавання більшої функціональності. + +| Назва прикладу | Опис | Мова | +| ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------ | +| [Основи](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/basics/anchor) | Як створити токен, мінтувати та передавати його. | Anchor | +| [Стандартний стан акаунта](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/default-account-state/native) | Це розширення дозволяє створювати акаунти токенів з певним станом, наприклад замороженими. | Native | +| [Право закриття мінта](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/mint-close-authority) | З старою програмою токенів не було можливості закривати мінт. Тепер це можливо. | Native | +| [Багато розширень](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/multiple-extensions) | Показує, як додавати кілька розширень до одного мінта | Native | +| [Вказівник метаданих NFT](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/nft-meta-data-pointer) | Можна використовувати розширення метаданих для створення NFT та додавання динамічних метаданих на ланцюг. | Anchor | +| [Не передаваємий](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/non-transferable/native) | Корисно, наприклад, для досягнень, програм рефералів або будь-яких токенів, які не можна передавати. | Native | +| [Плата за передачу](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-fees) | Кожна передача токенів утримує певну кількість токенів у акаунті токена, яку потім можна забрати. | Native | +| [Transfer Hook](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-hook) | Чотири приклади для додавання додаткової функціональності до вашого токена за допомогою CPI з програми токенів. | Anchor | + +## Break + +[Break](https://break.solana.com/) — це додаток на React, який дає користувачам можливість +відчути, наскільки швидко і ефективно працює мережа Solana. Чи зможете ви _зламати_ блокчейн Solana? Протягом 15 секунд кожне натискання кнопки або клавіші +відправляє нову транзакцію в кластер. Ударте по клавіатурі так швидко, як можете, і дивіться, +як ваші транзакції підтверджуються в реальному часі, поки мережа справляється з усім! + +Break можна грати на наших мережах Devnet, Testnet та Mainnet Beta. Ігри безкоштовні на Devnet і Testnet, +де сесія фінансується мережевим фонтаном. На Mainnet Beta користувачі платять 0,08 SOL за гру. Сесійний акаунт можна +фінансувати через локальний гаманець keystore або скануючи QR-код з Trust Wallet для +переміщення токенів. + +[Клацніть тут, щоб зіграти в Break](https://break.solana.com/) + +### Збірка та запуск + +Спочатку отримайте останню версію прикладів коду: + + +```shell +git clone https://github.com/solana-labs/break.git +cd break +``` +Дотримуйтесь кроків у файлі [README](https://github.com/solana-labs/break/blob/main/README.md) репозиторію. + diff --git a/docs/locales/uk/programs/faq.md b/docs/locales/uk/programs/faq.md new file mode 100644 index 000000000..d11a5f914 --- /dev/null +++ b/docs/locales/uk/programs/faq.md @@ -0,0 +1,186 @@ +--- +title: "Часто задавані питання" +sidebarSortOrder: 7 +--- + +Публікуйте свої питання на +[StackExchange](https://solana.stackexchange.com/questions/ask). + +## Berkeley Packet Filter (BPF) + +Програми Solana на ланцюзі компілюються через +[інфраструктуру компілятора LLVM](https://llvm.org/) в +[Executable and Linkable Format (ELF)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format), +яка містить варіацію +[Berkeley Packet Filter (BPF)](https://en.wikipedia.org/wiki/Berkeley_Packet_Filter) +байткоду. + +Оскільки Solana використовує інфраструктуру компілятора LLVM, програму можна написати +на будь-якій мові програмування, яка підтримує компіляцію в BPF бекенд LLVM. + +BPF надає ефективний +[набір інструкцій](https://github.com/iovisor/bpf-docs/blob/master/eBPF.md), +який можна виконувати в інтерпретованій віртуальній машині або як ефективно згенеровані +нативні інструкції за допомогою just-in-time компіляції. + +## Карта пам'яті + +Віртуальна адресна карта пам'яті, яку використовують програми Solana SBF, є фіксованою +та має наступне розташування: + +- Код програми починається з адреси 0x100000000 +- Дані стека починаються з адреси 0x200000000 +- Дані купи починаються з адреси 0x300000000 +- Вхідні параметри програми починаються з адреси 0x400000000 + +Вищезазначені віртуальні адреси є початковими адресами, але програми отримують доступ до +підмножини карти пам'яті. Програма викликає паніку, якщо вона намагається читати або +записувати в віртуальну адресу, до якої не було надано доступу, і повертається помилка +`AccessViolation`, яка містить адресу та розмір спроби порушення. + +## InvalidAccountData + +Ця помилка програми може статися з багатьох причин. Зазвичай це викликано +передачею акаунта в програму, якого програма не очікує, або через неправильне +положення акаунта в інструкції або акаунт, який не сумісний з виконуваною інструкцією. + +Реалізація програми може також спричинити цю помилку при виконанні +перехресної інструкції між програмами, якщо забули надати акаунт для програми, +яку ви викликаєте. + +## InvalidInstructionData + +Ця помилка програми може статися при спробі десеріалізувати інструкцію, перевірте, +чи структура, передана в інструкцію, точно відповідає вимогам програми. Між полями +може бути деяке додаткове заповнення. Якщо програма реалізує трейти Rust `Pack`, спробуйте +упакувати і розпакувати тип інструкції `T`, щоб визначити точне кодування, +яке програма очікує. + +## MissingRequiredSignature + +Деякі інструкції вимагають, щоб акаунт був підписантом; ця помилка повертається, якщо +очікується підпис акаунта, але він відсутній. + +Реалізація програми може також викликати цю помилку при виконанні +[перехресного виклику програми](/docs/core/cpi.md), який вимагає підписаного адреси програми, +але передані насіння підписувача до `invoke_signed` не збігаються з +насіннями підписувача, що використовуються для створення адреси програми +[`create_program_address`](/docs/core/pda.md#createprogramaddress). + +## Стек + +SBF використовує стекові кадри замість змінного покажчика стеку. Кожен стековий кадр +має розмір 4 КБ. + +Якщо програма порушує розмір цього стекового кадру, компілятор повідомить +про перевищення розміру як попередження. + +Наприклад: + +```text +Error: Function _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E Stack offset of -30728 exceeded max offset of -4096 by 26632 bytes, please minimize large stack variables +``` + +Повідомлення вказує, який символ перевищує розмір свого стекового кадру, але ім'я може бути змінене. + +> Щоб деманглювати символ Rust, використовуйте [rustfilt](https://github.com/luser/rustfilt). + +Вищезазначене попередження походить від програми на Rust, тому демангльоване ім'я символу: + + +```shell +rustfilt _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E +curve25519_dalek::edwards::EdwardsBasepointTable::create +``` +Причина того, що виводиться попередження, а не помилка, полягає в тому, що деякі залежні +пакети можуть містити функціональність, яка порушує обмеження розміру стекового кадру, навіть +якщо програма не використовує цю функціональність. Якщо програма порушить розмір стеку під час виконання, +то буде виведено помилку `AccessViolation`. + +Стекові кадри SBF займають діапазон віртуальних адрес, починаючи з `0x200000000`. + +## Розмір купи + +Програми мають доступ до купи часу виконання через API Rust `alloc`. Для +швидкого виділення пам'яті використовується проста купа на 32 КБ. Куча не підтримує +`free` або `realloc`. + +Програми мають доступ до пам'яті об'ємом 32 КБ, починаючи з віртуальної +адреси 0x300000000, і можуть реалізувати власну купу на основі специфічних потреб програми. + +Програми на Rust реалізують купу безпосередньо, визначаючи власний +[`global_allocator`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/entrypoint.rs#L72) + +## Завантажувачі + +Програми розгортаються і виконуються через завантажувачі часу виконання, наразі підтримуються +два завантажувачі: +- [BPF Loader](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader.rs#L17) +- [BPF loader (deprecated)](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader_deprecated.rs#L14) + +Завантажувачі можуть підтримувати різні інтерфейси бінарних додатків, тому розробники повинні +пишуть свої програми для одного завантажувача і розгортають їх на тому ж завантажувачі. Якщо програма, +написана для одного завантажувача, буде розгорнута на іншому, це зазвичай призведе до +помилки `AccessViolation` через невідповідність десеріалізації вхідних параметрів програми. + +Для практичних цілей програми завжди повинні бути написані для останнього +BPF завантажувача, і останній завантажувач є за умовчанням для інтерфейсу командного рядка +та JavaScript API. + +- [Точки входу програми Rust](/docs/programs/lang-rust.md#program-entrypoint) + +### Розгортання + +Розгортання програми SBF — це процес завантаження спільного об'єкта BPF в +дані акаунта програми та позначення акаунта як виконуваного. Клієнт розбиває +спільний об'єкт SBF на менші частини і надсилає їх як дані інструкцій +[`Write`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/loader_instruction.rs#L13) +до завантажувача, де завантажувач записує ці дані в акаунт програми. +Якщо всі частини отримані, клієнт надсилає +[`Finalize`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/loader_instruction.rs#L30) +інструкцію до завантажувача, завантажувач потім перевіряє, чи є дані SBF дійсними +і позначає акаунт програми як _виконуваний_. Після того, як акаунт програми +буде позначено як виконуваний, подальші транзакції можуть видавати інструкції для цієї +програми для обробки. + +Коли інструкція спрямована до виконуваної програми SBF, завантажувач +конфігурує середовище виконання програми, серіалізує вхідні параметри програми, +викликає точку входу програми і повідомляє про будь-які помилки. + +Додаткову інформацію див. в розділі [розгортання програм](/docs/programs/deploying.md). + +### Серіалізація вхідних параметрів + +Завантажувачі SBF серіалізують вхідні параметри програми в масив байтів, який потім передається +в точку входу програми, де програма відповідає за їх десеріалізацію на ланцюгу. Одна з змін між +депрецованим завантажувачем і поточним полягає в тому, що вхідні параметри серіалізуються так, +що різні параметри потрапляють на вирівняні офсети в межах вирівняного байтового +масиву. Це дозволяє реалізаціям десеріалізації безпосередньо посилатися на +байтовий масив і надавати вирівняні вказівники до програми. + +- [Десеріалізація параметрів програми на Rust](/docs/programs/lang-rust.md#parameter-deserialization) + +Останній завантажувач серіалізує вхідні параметри програми наступним чином (усе +кодування little endian): + +- 8 байт беззнакового числа акаунтів +- Для кожного акаунта: + - 1 байт, що вказує, чи є цей акаунт дублікатом, якщо ні — значення 0xff, + в іншому випадку значення — це індекс акаунта, з яким він є дублікатом. + - Якщо дублікати: 7 байт заповнювальної пам'яті + - Якщо не дублікати: + - 1 байт булевого типу, true, якщо акаунт є підписантом + - 1 байт булевого типу, true, якщо акаунт можна змінювати + - 1 байт булевого типу, true, якщо акаунт є виконуваним + - 4 байти заповнювальної пам'яті + - 32 байти публічного ключа акаунта + - 32 байти публічного ключа власника акаунта + - 8 байт беззнакового числа лампортів, які належать акаунту + - 8 байт беззнакового числа байтів даних акаунта + - x байт даних акаунта + - 10к байт заповнювальної пам'яті, використовується для realloc + - достатньо заповнювальної пам'яті для вирівнювання офсету до 8 байт + - 8 байт епохи оренди +- 8 байт беззнакового числа даних інструкцій +- x байт даних інструкцій +- 32 байти ID програми diff --git a/docs/en/programs/index.md b/docs/locales/uk/programs/index.md similarity index 100% rename from docs/en/programs/index.md rename to docs/locales/uk/programs/index.md diff --git a/docs/locales/uk/programs/limitations.md b/docs/locales/uk/programs/limitations.md new file mode 100644 index 000000000..a2e33411f --- /dev/null +++ b/docs/locales/uk/programs/limitations.md @@ -0,0 +1,79 @@ +--- +title: "Обмеження" +sidebarSortOrder: 6 +--- + +Розробка програм на блокчейні Solana має деякі вроджені обмеження. Нижче наведено список поширених обмежень, з якими ви можете зіткнутися. + +## Бібліотеки Rust + +Оскільки програми Rust на блокчейні повинні бути детермінованими і виконуватись у середовищі з обмеженими ресурсами та одночасною обробкою, вони мають деякі обмеження щодо використання бібліотек. + +Програми Rust на блокчейні підтримують більшість бібліотек Rust, таких як libstd, libcore, liballoc, а також багато сторонніх бібліотек. + +Проте існують певні обмеження через обмежені ресурси середовища та необхідність детермінованості: + +- Немає доступу до: + - `rand` + - `std::fs` + - `std::net` + - `std::future` + - `std::process` + - `std::sync` + - `std::task` + - `std::thread` + - `std::time` +- Обмежений доступ до: + - `std::hash` + - `std::os` +- Використання Bincode є дуже ресурсомістким і його слід уникати. +- Форматування рядків також є ресурсомістким і повинно бути мінімізоване. +- Відсутня підтримка для `println!` та `print!`, замість цього використовуйте макрос + [`msg!`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/log.rs#L33). +- Під час виконання встановлено обмеження на кількість інструкцій, які програма може виконати під час обробки однієї інструкції. Дивіться [бюджет обчислень](/docs/core/fees.md#compute-budget) для більш детальної інформації. + +## Бюджет обчислень + +Для запобігання зловживанню обчислювальними ресурсами блокчейну кожна транзакція отримує [бюджет обчислень](/docs/terminology.md#compute-budget). Перевищення цього бюджету призведе до провалу транзакції. + +Дивіться документацію про [обмеження обчислень](/docs/core/fees.md#compute-budget) для більш детальної інформації. + +## Глибина стеку викликів — помилка `CallDepthExceeded` + +Програми Solana мають обмежену глибину стеку викликів до **64 кадрів**. + +Якщо програма перевищує дозволену глибину стеку викликів, вона отримує помилку `CallDepthExceeded`. + +## Глибина викликів CPI — помилка `CallDepth` + +Перехресні виклики між програмами дозволяють програмам викликати інші програми безпосередньо, але наразі глибина обмежена до `4`. + +Якщо програма перевищує дозволену [глибину викликів між програмами](/docs/core/cpi.md), вона отримує помилку `CallDepth`. + +## Підтримка типів float у Rust + +Програми підтримують обмежений набір операцій із типами float у Rust. Якщо програма намагається використовувати операцію із float, яка не підтримується, виконання викликає помилку про нерозв’язаний символ. + +Операції із float виконуються через програмні бібліотеки (LLVM's float built-ins) і споживають більше обчислювальних одиниць, ніж операції з цілими числами. Загалом рекомендується використовувати фіксовану точку там, де це можливо. + +[Математичні тести Solana Program Library](https://github.com/solana-labs/solana-program-library/tree/master/libraries/math) демонструють продуктивність деяких математичних операцій. Для запуску тесту синхронізуйте репозиторій і виконайте: + +```shell +cargo test-sbf -- --nocapture --test-threads=1 +``` + +Недавні результати показують, що операції із float споживають більше інструкцій порівняно з еквівалентами для цілих чисел. Реалізації з фіксованою точкою також будуть менш ресурсомісткими, ніж float: + +```text + u64 f32 +Multiply 8 176 +Divide 9 219 +``` + +## Статичні змінні, які можна змінювати + +Спільні об’єкти програм не підтримують змінювані спільні дані. Програми спільно використовують один і той самий код та дані лише для читання, що означає, що розробники не повинні включати статичні змінювані або глобальні змінні в програми. У майбутньому може бути додано механізм копіювання при записі для підтримки змінюваних даних. + +## Ділення зі знаком + +Набір інструкцій SBF не підтримує ділення зі знаком. diff --git a/docs/locales/uk/programs/rust/index.md b/docs/locales/uk/programs/rust/index.md new file mode 100644 index 000000000..bfc459af9 --- /dev/null +++ b/docs/locales/uk/programs/rust/index.md @@ -0,0 +1,462 @@ +--- +title: Розробка програм на Rust +description: + Дізнайтеся, як розробляти програми для Solana, використовуючи Rust, включаючи покрокові + інструкції для створення, збірки, тестування та розгортання смарт-контрактів на + блокчейні Solana. +sidebarLabel: Програми на Rust +sidebarSortOrder: 1 +altRoutes: + - /docs/programs/lang-rust +--- + +Програми для Solana в основному розробляються за допомогою мови програмування Rust. +Ця сторінка зосереджена на написанні програм для Solana на Rust без використання фреймворку Anchor, +метод, який часто називають написанням "рідних програм на Rust". + +Розробка рідних програм на Rust дає розробникам повний контроль над їхніми +програмами для Solana. Однак цей підхід вимагає більше ручної налаштування та +шаблонного коду порівняно з використанням фреймворку Anchor. Цей метод рекомендований для розробників, які: + +- Шукають детальний контроль над логікою програми та оптимізаціями +- Хочуть зрозуміти основні концепції, перш ніж переходити до фреймворків вищого рівня + +Для початківців ми рекомендуємо почати з фреймворку Anchor. Для отримання додаткової інформації див. розділ +[Anchor](/docs/programs/anchor). + +## Попередні вимоги + +Для детальних інструкцій по установці відвідайте сторінку +[встановлення](/docs/intro/installation). + +Перед тим, як почати, переконайтесь, що у вас встановлено наступне: + +- Rust: Мова програмування для створення програм для Solana. +- Solana CLI: Інструмент командного рядка для розробки на Solana. + +## Початок роботи + +Наведений приклад охоплює основні кроки для створення вашої першої програми для Solana, +написаної на Rust. Ми створимо мінімальну програму, яка виводить "Hello, world!" в +журнали програми. + + + +### Створення нової програми + +Спочатку створіть новий проект на Rust, використовуючи стандартну команду `cargo init` з +прапорцем `--lib`. + +```shell filename="Terminal" +cargo init hello_world --lib +``` + +Перейдіть до директорії проекту. Ви повинні побачити стандартні файли `src/lib.rs` та +`Cargo.toml`. + +```shell filename="Terminal" +cd hello_world +``` + +Далі додайте залежність `solana-program`. Це мінімальна залежність, +необхідна для побудови програми Solana. + +```shell filename="Terminal" +cargo add solana-program@1.18.26 +``` + +Далі додайте наступний фрагмент до файлу `Cargo.toml`. Якщо ви не включите цю +конфігурацію, директорія `target/deploy` не буде згенерована під час збірки програми. + +```toml filename="Cargo.toml" +[lib] +crate-type = ["cdylib", "lib"] +``` + +Ваш файл `Cargo.toml` повинен виглядати наступним чином: + +```toml filename="Cargo.toml" +[package] +name = "hello_world" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] + +[dependencies] +solana-program = "1.18.26" +``` + +Далі замініть вміст файлу `src/lib.rs` на наступний код. Це мінімальна програма для Solana, яка виводить "Hello, world!" в журнал програми, коли програма викликається. + +Макрос `msg!` використовується в програмах Solana для виведення повідомлення в журнал програми. + +```rs filename="lib.rs" +use solana_program::{ + account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey, +}; + +entrypoint!(process_instruction); + +pub fn process_instruction( + _program_id: &Pubkey, + _accounts: &[AccountInfo], + _instruction_data: &[u8], +) -> ProgramResult { + msg!("Hello, world!"); + Ok(()) +} +``` + +### Збірка програми + +Далі побудуйте програму за допомогою команди `cargo build-sbf`. + +```shell filename="Terminal" +cargo build-sbf +``` + +Ця команда генерує директорію `target/deploy`, що містить два важливі файли: + +1. Файл `.so` (наприклад, `hello_world.so`): Це зкомпільована програма Solana, + яка буде розгорнута в мережі як "смарт-контракт". +2. Файл ключової пари (наприклад, `hello_world-keypair.json`): Публічний ключ цієї + ключової пари використовується як ID програми при розгортанні програми. + +Щоб переглянути ID програми, виконайте наступну команду у вашому терміналі. Ця команда +виводить публічний ключ ключової пари за вказаним шляхом до файлу: + +```shell filename="Terminal" +solana address -k ./target/deploy/hello_world-keypair.json +``` + +Example output: + +``` +4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz +``` + +### Тестування програми + +Далі протестуйте програму за допомогою crate `solana-program-test`. Додайте наступні +залежності до файлу `Cargo.toml`. + +```shell filename="Terminal" +cargo add solana-program-test@1.18.26 --dev +cargo add solana-sdk@1.18.26 --dev +cargo add tokio --dev +``` + +Додайте наступний тест до файлу `src/lib.rs`, під кодом програми. Це тестовий +модуль, який викликає програму hello world. + +```rs filename="lib.rs" +#[cfg(test)] +mod test { + use super::*; + use solana_program_test::*; + use solana_sdk::{signature::Signer, transaction::Transaction}; + + #[tokio::test] + async fn test_hello_world() { + let program_id = Pubkey::new_unique(); + let (mut banks_client, payer, recent_blockhash) = + ProgramTest::new("hello_world", program_id, processor!(process_instruction)) + .start() + .await; + + // Create the instruction to invoke the program + let instruction = + solana_program::instruction::Instruction::new_with_borsh(program_id, &(), vec![]); + + // Add the instruction to a new transaction + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer], recent_blockhash); + + // Process the transaction + let transaction_result = banks_client.process_transaction(transaction).await; + assert!(transaction_result.is_ok()); + } +} +``` + +Запустіть тест за допомогою команди `cargo test-sbf`. У журналі програми буде виведено +"Hello, world!". + +```shell filename="Terminal" +cargo test-sbf +``` + +Example output: + +```shell filename="Terminal" {4} /Program log: Hello, world!/ +running 1 test +[2024-10-18T21:24:54.889570000Z INFO solana_program_test] "hello_world" SBF program from /hello_world/target/deploy/hello_world.so, modified 35 seconds, 828 ms, 268 µs and 398 ns ago +[2024-10-18T21:24:54.974294000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM invoke [1] +[2024-10-18T21:24:54.974814000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, world! +[2024-10-18T21:24:54.976848000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM consumed 140 of 200000 compute units +[2024-10-18T21:24:54.976868000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM success +test test::test_hello_world ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.13s +``` + +### Розгортання програми + +Далі розгорніть програму. Під час локальної розробки ми можемо використовувати +`solana-test-validator`. + +Спочатку налаштуйте Solana CLI для використання локального кластера Solana. + +```shell filename="Terminal" +solana config set -ul +``` + +Example output: + +``` +Config File: /.config/solana/cli/config.yml +RPC URL: http://localhost:8899 +WebSocket URL: ws://localhost:8900/ (computed) +Keypair Path: /.config/solana/id.json +Commitment: confirmed +``` + +Відкрийте новий термінал і виконайте команду `solana-test-validator`, щоб запустити +локальний валідатор. + +```shell filename="Terminal" +solana-test-validator +``` + +Поки тестовий валідатор працює, виконайте команду `solana program deploy` в +окремому терміналі, щоб розгорнути програму на локальному валідаторі. + +```shell filename="Terminal" +solana program deploy ./target/deploy/hello_world.so +``` + +Example output: + +``` +Program Id: 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz +Signature: +5osMiNMiDZGM7L1e2tPHxU8wdB8gwG8fDnXLg5G7SbhwFz4dHshYgAijk4wSQL5cXiu8z1MMou5kLadAQuHp7ybH +``` + +Ви можете перевірити ID програми та підпис транзакції на +[Solana Explorer](https://explorer.solana.com/?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899). +Зверніть увагу, що кластер на Solana Explorer також повинен бути localhost. Опція "Custom RPC +URL" на Solana Explorer за замовчуванням встановлюється на `http://localhost:8899`. + +### Виклик програми + +Далі ми продемонструємо, як викликати програму, використовуючи Rust клієнт. + +Спочатку створіть директорію `examples` та файл `client.rs`. + +```shell filename="Terminal" +mkdir -p examples +touch examples/client.rs +``` + +Додати натсупне до `Cargo.toml`. + +```toml filename="Cargo.toml" +[[example]] +name = "client" +path = "examples/client.rs" +``` + +Додати `solana-client` залежність. + +```shell filename="Terminal" +cargo add solana-client@1.18.26 --dev +``` + +Додайте наступний код до файлу `examples/client.rs`. Це Rust клієнтський скрипт, +який фінансує нову ключову пару для оплати зборів за транзакцію і потім викликає програму hello world. + +```rs filename="example/client.rs" +use solana_client::rpc_client::RpcClient; +use solana_sdk::{ + commitment_config::CommitmentConfig, + instruction::Instruction, + pubkey::Pubkey, + signature::{Keypair, Signer}, + transaction::Transaction, +}; +use std::str::FromStr; + +#[tokio::main] +async fn main() { + // Program ID (replace with your actual program ID) + let program_id = Pubkey::from_str("4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz").unwrap(); + + // Connect to the Solana devnet + let rpc_url = String::from("http://127.0.0.1:8899"); + let client = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed()); + + // Generate a new keypair for the payer + let payer = Keypair::new(); + + // Request airdrop + let airdrop_amount = 1_000_000_000; // 1 SOL + let signature = client + .request_airdrop(&payer.pubkey(), airdrop_amount) + .expect("Failed to request airdrop"); + + // Wait for airdrop confirmation + loop { + let confirmed = client.confirm_transaction(&signature).unwrap(); + if confirmed { + break; + } + } + + // Create the instruction + let instruction = Instruction::new_with_borsh( + program_id, + &(), // Empty instruction data + vec![], // No accounts needed + ); + + // Add the instruction to new transaction + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer], client.get_latest_blockhash().unwrap()); + + // Send and confirm the transaction + match client.send_and_confirm_transaction(&transaction) { + Ok(signature) => println!("Transaction Signature: {}", signature), + Err(err) => eprintln!("Error sending transaction: {}", err), + } +} +``` + +Перед виконанням скрипту замініть ID програми в наведеному коді на той, що відповідає вашій програмі. + +Ви можете отримати свій ID програми, виконавши наступну команду. + +```shell filename="Terminal" +solana address -k ./target/deploy/hello_world-keypair.json +``` + +```diff +#[tokio::main] +async fn main() { +- let program_id = Pubkey::from_str("4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz").unwrap(); ++ let program_id = Pubkey::from_str("YOUR_PROGRAM_ID).unwrap(); + } +} +``` + +Run the client script. + +```shell filename="Terminal" +cargo run --example client +``` + +Example output: + +``` +Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77bAACjKAS9fGnVeEazrXL4SfKrW7xZFYV +``` + +Ви можете перевірити підпис транзакції на +[Solana Explorer](https://explorer.solana.com/?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899) +(локальний кластер), щоб побачити "Hello, world!" в журналі програми. + +### Оновлення програми + +Програми Solana можна оновити, повторно розгорнувши їх на той самий ID програми. Оновіть +програму в `src/lib.rs`, щоб виводити "Hello, Solana!" замість "Hello, world!". + +```diff filename="lib.rs" +pub fn process_instruction( + _program_id: &Pubkey, + _accounts: &[AccountInfo], + _instruction_data: &[u8], +) -> ProgramResult { +- msg!("Hello, world!"); ++ msg!("Hello, Solana!"); + Ok(()) +} +``` + +Протестуйте оновлену програму, виконавши команду `cargo test-sbf`. + +```shell filename="Terminal" +cargo test-sbf +``` + +Ви повинні побачити "Hello, Solana!" в журналі програми. + +```shell filename="Terminal" {4} +running 1 test +[2024-10-23T19:28:28.842639000Z INFO solana_program_test] "hello_world" SBF program from /code/misc/delete/hello_world/target/deploy/hello_world.so, modified 4 minutes, 31 seconds, 435 ms, 566 µs and 766 ns ago +[2024-10-23T19:28:28.934854000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM invoke [1] +[2024-10-23T19:28:28.936735000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, Solana! +[2024-10-23T19:28:28.938774000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM consumed 140 of 200000 compute units +[2024-10-23T19:28:28.938793000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM success +test test::test_hello_world ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.14s +``` + +Виконайте команду `cargo build-sbf`, щоб згенерувати оновлений файл `.so`. + +```shell filename="Terminal" +cargo build-sbf +``` + +Повторно розгорніть програму за допомогою команди `solana program deploy`. + +```shell filename="Terminal" +solana program deploy ./target/deploy/hello_world.so +``` + +Знову виконайте клієнтський код і перевірте підпис транзакції на Solana +Explorer, щоб побачити "Hello, Solana!" в журналі програми. + +```shell filename="Terminal" +cargo run --example client +``` + +### Закриття програми + +Ви можете закрити свою програму Solana, щоб повернути SOL, виділені для акаунту. +Закриття програми є незворотним, тому це слід робити обережно. + +Щоб закрити програму, використовуйте команду `solana program close `. Наприклад: + +```shell filename="Terminal" +solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz +--bypass-warning +``` + +Example output: + +``` +Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOL +reclaimed +``` + +Зверніть увагу, що після закриття програми її ID програми не можна буде використовувати знову. Спроба розгорнути програму з раніше закритим ID програми призведе до помилки. + +``` +Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, use +a new Program Id +``` + +Якщо вам потрібно повторно розгорнути програму з тим самим вихідним кодом після закриття програми, ви повинні згенерувати новий ID програми. Щоб згенерувати нову ключову пару для програми, виконайте наступну команду: + +```shell filename="Terminal" +solana-keygen new -o ./target/deploy/hello_world-keypair.json --force +``` + +Альтернативно, ви можете видалити існуючий файл ключової пари (наприклад, +`./target/deploy/hello_world-keypair.json`) і знову виконати команду `cargo build-sbf`, +що згенерує новий файл ключової пари. + + diff --git a/docs/uk/programs/rust/program-structure.md b/docs/locales/uk/programs/rust/program-structure.md similarity index 64% rename from docs/uk/programs/rust/program-structure.md rename to docs/locales/uk/programs/rust/program-structure.md index 5a46ce82d..96955bdbf 100644 --- a/docs/uk/programs/rust/program-structure.md +++ b/docs/locales/uk/programs/rust/program-structure.md @@ -1,46 +1,44 @@ --- -title: Rust Program Structure -sidebarLabel: Program Structure +title: Структура програми на Rust +sidebarLabel: Структура програми description: - Learn how to structure Solana programs in Rust, including entrypoints, state - management, instruction handling, and testing. + Дізнайтесь, як структуровані програми Solana на Rust, включаючи точки входу, управління станом, + обробку інструкцій та тестування. sidebarSortOrder: 1 --- -Solana programs written in Rust have minimal structural requirements, allowing -for flexibility in how code is organized. The only requirement is that a program -must have an `entrypoint`, which defines where the execution of a program -begins. +Програми Solana, написані на Rust, мають мінімальні вимоги до структури, що дає +гнучкість у тому, як організовувати код. Єдина вимога — програма повинна мати `entrypoint`, +який визначає точку початку виконання програми. -## Program Structure +## Структура програми -While there are no strict rules for file structure, Solana programs typically -follow a common pattern: +Хоча немає строгих правил для структури файлів, програми Solana зазвичай +дотримуються загального шаблону: -- `entrypoint.rs`: Defines the entrypoint that routes incoming instructions. -- `state.rs`: Define program-specific state (account data). -- `instructions.rs`: Defines the instructions that the program can execute. -- `processor.rs`: Defines the instruction handlers (functions) that implement - the business logic for each instruction. -- `error.rs`: Defines custom errors that the program can return. +- `entrypoint.rs`: Визначає точку входу, яка маршрутизує вхідні інструкції. +- `state.rs`: Визначає стан програми (дані акаунтів). +- `instructions.rs`: Визначає інструкції, які програма може виконувати. +- `processor.rs`: Визначає обробники інструкцій (функції), які реалізують + бізнес-логіку для кожної інструкції. +- `error.rs`: Визначає користувацькі помилки, які програма може повернути. -You can find examples in the +Приклади можна знайти в [Solana Program Library](https://github.com/solana-labs/solana-program-library/tree/master/token/program/src). -## Example Program +## Приклад програми -To demonstrate how to build a native Rust program with multiple instructions, -we'll walk through a simple counter program that implements two instructions: +Щоб продемонструвати, як побудувати рідну програму на Rust з кількома інструкціями, +ми розглянемо просту програму лічильника, яка реалізує дві інструкції: -1. `InitializeCounter`: Creates and initializes a new account with an initial - value. -2. `IncrementCounter`: Increments the value stored in an existing account. +1. `InitializeCounter`: Створює і ініціалізує новий акаунт з початковим значенням. +2. `IncrementCounter`: Збільшує значення, що зберігається в існуючому акаунті. -For simplicity, the program will be implemented in a single `lib.rs` file, -though in practice you may want to split larger programs into multiple files. +Для простоти програма буде реалізована в одному файлі `lib.rs`, +хоча на практиці вам, можливо, захочеться розділити більші програми на кілька файлів. - + ```rs filename="lib.rs" use borsh::{BorshDeserialize, BorshSerialize}; @@ -315,39 +313,37 @@ tokio = "1.41.0" -### Create a new Program +### Створення нової програми -First, create a new Rust project using the standard `cargo init` command with -the `--lib` flag. +Спочатку створіть новий проект на Rust, використовуючи стандартну команду `cargo init` з прапорцем `--lib`. ```shell filename="Terminal" cargo init counter_program --lib ``` -Navigate to the project directory. You should see the default `src/lib.rs` and -`Cargo.toml` files +Перейдіть до директорії проекту. Ви повинні побачити стандартні файли `src/lib.rs` та +`Cargo.toml`. ```shell filename="Terminal" cd counter_program ``` -Next, add the `solana-program` dependency. This is the minimum dependency -required to build a Solana program. +Далі додайте залежність `solana-program`. Це мінімальна залежність, +необхідна для побудови програми Solana. ```shell filename="Terminal" cargo add solana-program@1.18.26 ``` -Next, add the following snippet to `Cargo.toml`. If you don't include this -config, the `target/deploy` directory will not be generated when you build the -program. +Далі додайте наступний фрагмент до файлу `Cargo.toml`. Якщо ви не включите цю +конфігурацію, директорія `target/deploy` не буде згенерована під час збірки програми. ```toml filename="Cargo.toml" [lib] crate-type = ["cdylib", "lib"] ``` -Your `Cargo.toml` file should look like the following: +Ваш файл `Cargo.toml` повинен виглядати наступним чином: ```toml filename="Cargo.toml" [package] @@ -362,27 +358,27 @@ crate-type = ["cdylib", "lib"] solana-program = "1.18.26" ``` -### Program Entrypoint +### Точка входу програми -A Solana program entrypoint is the function that gets called when a program is -invoked. The entrypoint has the following raw definition and developers are free -to create their own implementation of the entrypoint function. +Точка входу програми Solana — це функція, яка викликається, коли програма +активується. Точка входу має наступне сире визначення, і розробники можуть створювати власну +реалізацію функції точки входу. -For simplicity, use the +Для простоти використовуйте макрос [`entrypoint!`](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L124-L140) -macro from the `solana_program` crate to define the entrypoint in your program. +з бібліотеки `solana_program` для визначення точки входу у вашій програмі. ```rs #[no_mangle] pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64; ``` -Replace the default code in `lib.rs` with the following code. This snippet: +Замініть стандартний код у файлі `lib.rs` на наступний код. Цей фрагмент: -1. Imports the required dependencies from `solana_program` -2. Defines the program entrypoint using the `entrypoint!` macro -3. Implements the `process_instruction` function that will route instructions to - the appropriate handler functions +1. Імпортує необхідні залежності з `solana_program` +2. Визначає точку входу програми за допомогою макросу `entrypoint!` +3. Реалізує функцію `process_instruction`, яка маршрутизує інструкції до + відповідних функцій обробників ```rs filename="lib.rs" {13} /process_instruction/ use solana_program::{ @@ -409,62 +405,50 @@ pub fn process_instruction( } ``` -The `entrypoint!` macro requires a function with the the following -[type signature](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L28-L29) -as an argument: +Макрос `entrypoint!` вимагає функцію з наступним +[типом підпису](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L28-L29) +як аргумент: ```rs pub type ProcessInstruction = fn(program_id: &Pubkey, accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult; ``` -When a Solana program is invoked, the entrypoint -[deserializes](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L277) -the -[input data](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L129-L131) -(provided as bytes) into three values and passes them to the -[`process_instruction`](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L132) -function: +Коли програма Solana викликається, точка входу +[десеріалізує](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L277) +[вхідні дані](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L129-L131) +(надані як байти) у три значення та передає їх до функції +[`process_instruction`](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L132): -- `program_id`: The public key of the program being invoked (current program) -- `accounts`: The `AccountInfo` for accounts required by the instruction being - invoked -- `instruction_data`: Additional data passed to the program which specifies the - instruction to execute and its required arguments +- `program_id`: Публічний ключ викликаної програми (поточна програма) +- `accounts`: `AccountInfo` для акаунтів, необхідних для викликаної інструкції +- `instruction_data`: Додаткові дані, передані програмі, які вказують інструкцію для виконання та її необхідні аргументи -These three parameters directly correspond to the data that clients must provide -when building an instruction to invoke a program. +Ці три параметри безпосередньо відповідають даним, які клієнти повинні надати +при побудові інструкції для виклику програми. -### Define Program State +### Визначення стану програми -When building a Solana program, you'll typically start by defining your -program's state - the data that will be stored in accounts created and owned by -your program. +При створенні програми Solana зазвичай починають з визначення стану програми — даних, які будуть зберігатися в акаунтах, створених і належних вашій програмі. -Program state is defined using Rust structs that represent the data layout of -your program's accounts. You can define multiple structs to represent different -types of accounts for your program. +Стан програми визначається за допомогою структур Rust, які представляють макет даних акаунтів програми. Ви можете визначити кілька структур для представлення різних типів акаунтів вашої програми. -When working with accounts, you need a way to convert your program's data types -to and from the raw bytes stored in an account's data field: +При роботі з акаунтами вам потрібен спосіб перетворювати типи даних вашої програми в і з сирих байтів, що зберігаються в полі даних акаунту: -- Serialization: Converting your data types into bytes to store in an account's - data field -- Deserialization: Converting the bytes stored in an account back into your data - types +- Серіалізація: Перетворення ваших типів даних у байти для збереження в полі даних акаунту +- Десеріалізація: Перетворення байтів, збережених в акаунті, назад у ваші типи даних -While you can use any serialization format for Solana program development, -[Borsh](https://borsh.io/) is commonly used. To use Borsh in your Solana -program: +Хоча ви можете використовувати будь-який формат серіалізації для розробки програм Solana, +[Borsh](https://borsh.io/) є загальноприйнятим. Щоб використовувати Borsh у вашій програмі Solana: -1. Add the `borsh` crate as a dependency to your `Cargo.toml`: +1. Додайте crate `borsh` як залежність до вашого `Cargo.toml`: ```shell filename="Terminal" cargo add borsh ``` -2. Import the Borsh traits and use the derive macro to implement the traits for - your structs: +2. Імпортуйте трейди Borsh і використовуйте макрос `derive`, щоб реалізувати трейди для + ваших структур: ```rust use borsh::{BorshSerialize, BorshDeserialize}; @@ -476,8 +460,8 @@ pub struct CounterAccount { } ``` -Add the `CounterAccount` struct to `lib.rs` to define the program state. This -struct will be used in both the initialization and increment instructions. +Додайте структуру `CounterAccount` до файлу `lib.rs` для визначення стану програми. Ця +структура буде використовуватися як в інструкції ініціалізації, так і в інструкції збільшення. ```rs filename="lib.rs" {12} {25-29} use solana_program::{ @@ -510,20 +494,18 @@ pub struct CounterAccount { } ``` -### Define Instructions +### Визначення інструкцій -Instructions refer to the different operations that your Solana program can -perform. Think of them as public APIs for your program - they define what -actions users can take when interacting with your program. +Інструкції позначають різні операції, які ваша програма Solana може виконувати. Вважайте їх публічними API вашої програми — вони визначають, які дії користувачі можуть виконувати при взаємодії з вашою програмою. -Instructions are typically defined using a Rust enum where: +Інструкції зазвичай визначаються за допомогою enum на Rust, де: -- Each enum variant represents a different instruction -- The variant's payload represents the instruction's parameters +- Кожен варіант enum представляє різну інструкцію +- Payload варіанту представляє параметри інструкції -Note that Rust enum variants are implicitly numbered starting from 0. +Зверніть увагу, що варіанти enum на Rust автоматично нумеруються, починаючи з 0. -Below is an example of an enum defining two instructions: +Нижче наведено приклад enum, що визначає дві інструкції: ```rust #[derive(BorshSerialize, BorshDeserialize, Debug)] @@ -533,22 +515,18 @@ pub enum CounterInstruction { } ``` -When a client invokes your program, they must provide instruction data (as a -buffer of bytes) where: +Коли клієнт викликає вашу програму, він повинен надати дані інструкції (як буфер байтів), де: -- The first byte identifies which instruction variant to execute (0, 1, etc.) -- The remaining bytes contain the serialized instruction parameters (if - required) +- Перший байт вказує, який варіант інструкції потрібно виконати (0, 1 і т.д.) +- Решта байтів містить серіалізовані параметри інструкції (якщо це необхідно) -To convert the instruction data (bytes) into a variant of the enum, it is common -to implement a helper method. This method: +Для перетворення даних інструкції (байтів) у варіант enum зазвичай реалізують допоміжний метод. Цей метод: -1. Splits the first byte to get the instruction variant -2. Matches on the variant and parses any additional parameters from the - remaining bytes -3. Returns the corresponding enum variant +1. Розділяє перший байт, щоб отримати варіант інструкції +2. Зіставляє варіант і парсить будь-які додаткові параметри з решти байтів +3. Повертає відповідний варіант enum -For example, the `unpack` method for the `CounterInstruction` enum: +Наприклад, метод `unpack` для enum `CounterInstruction`: ```rust impl CounterInstruction { @@ -575,8 +553,7 @@ impl CounterInstruction { } ``` -Add the following code to `lib.rs` to define the instructions for the counter -program. +Додайте наступний код до файлу `lib.rs` для визначення інструкцій для програми лічильника. ```rs filename="lib.rs" {18-46} use borsh::{BorshDeserialize, BorshSerialize}; @@ -626,15 +603,14 @@ impl CounterInstruction { } ``` -### Instruction Handlers +### Обробники інструкцій -Instruction handlers refer to the functions that contain the business logic for -each instruction. It's common to name handler functions as -`process_`, but you're free to choose any naming convention. +Обробники інструкцій — це функції, які містять бізнес-логіку для кожної інструкції. Зазвичай функції обробників називаються як +`process_`, але ви вільні вибрати будь-яку конвенцію найменувань. -Add the following code to `lib.rs`. This code uses the `CounterInstruction` enum -and `unpack` method defined in the previous step to route incoming instructions -to the appropriate handler functions: +Додайте наступний код до файлу `lib.rs`. Цей код використовує enum `CounterInstruction` +та метод `unpack`, визначений на попередньому кроці, для маршрутизації вхідних інструкцій +до відповідних функцій обробників: ```rs filename="lib.rs" {8-17} {20-32} /process_initialize_counter/1 /process_increment_counter/1 entrypoint!(process_instruction); @@ -671,32 +647,32 @@ fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> P } ``` -Next, add the implementation of the `process_initialize_counter` function. This -instruction handler: +Далі додайте реалізацію функції `process_initialize_counter`. Цей +обробник інструкції: -1. Creates and allocates space for a new account to store the counter data -2. Initializing the account data with `initial_value` passed to the instruction +1. Створює і виділяє місце для нового акаунту для збереження даних лічильника +2. Ініціалізує дані акаунту з `initial_value`, переданим в інструкцію - + -The `process_initialize_counter` function requires three accounts: +Функція `process_initialize_counter` вимагає три акаунти: -1. The counter account that will be created and initialized -2. The payer account that will fund the new account creation -3. The System Program that we invoke to create the new account +1. Акаунт лічильника, який буде створено та ініціалізовано +2. Акаунт платника, який профінансує створення нового акаунту +3. System Program, який ми викликаємо для створення нового акаунту -To define the accounts required by the instruction, we create an iterator over -the `accounts` slice and use the `next_account_info` function to get each -account. The number of accounts you define are the accounts required by the -instruction. +Для визначення акаунтів, необхідних для інструкції, ми створюємо ітератор по +масиву `accounts` та використовуємо функцію `next_account_info`, щоб отримати кожен +акаунт. Кількість акаунтів, яку ви визначаєте, є кількістю акаунтів, необхідних для +інструкції. -The order of accounts is important - when building the instruction on the client -side, accounts must be provided in the same order as it is defined in the -program for the instruction to execute successfully. +Порядок акаунтів має значення — при побудові інструкції на стороні клієнта, +акаунти повинні надаватися в тому ж порядку, в якому вони визначені в +програмі, щоб інструкція виконалася успішно. -While the variable names for the accounts have no effect on the program's -functionality, using descriptive names is recommended. +Хоча змінні імена акаунтів не впливають на функціональність програми, +рекомендується використовувати описові імена. ```rs filename="lib.rs" {6-10} fn process_initialize_counter( @@ -714,14 +690,11 @@ fn process_initialize_counter( } ``` -Before creating an account, we need to: +Перед створенням акаунту нам потрібно: -1. Specify the space (in bytes) to allocate to the account's data field. Since - we're storing a u64 value (`count`), we need 8 bytes. +1. Вказати простір (у байтах), який потрібно виділити для поля даних акаунту. Оскільки ми зберігаємо значення типу u64 (`count`), нам потрібно 8 байтів. -2. Calculate the minimum "rent" balance required. On Solana, accounts must - maintain a minimum balance of lamports (rent) based on amount of data stored - on the account. +2. Обчислити мінімальний баланс "ренту", необхідний для акаунту. На Solana акаунти повинні підтримувати мінімальний баланс лампортів (ренту), що залежить від кількості даних, що зберігаються в акаунті. ```rs filename="lib.rs" {12-17} fn process_initialize_counter( @@ -746,26 +719,25 @@ fn process_initialize_counter( } ``` -Once the space is defined and rent is calculated, create the account by invoking -the System Program's `create_account` instruction. +Після того, як простір визначено і рент обчислений, створіть акаунт, викликавши +інструкцію `create_account` з System Program. + +На Solana нові акаунти можуть бути створені тільки через System Program. При створенні +акаунту ми вказуємо кількість байтів для виділення та програму-власника +нового акаунту. System Program: -On Solana, new accounts can only be created by the System Program. When creating -an account, we specify the amount of bytes to allocate and the program owner of -the new account. The System Program: +1. Створює новий акаунт +2. Виділяє вказаний простір для поля даних акаунту +3. Передає право власності на вказану програму -1. Creates the new account -2. Allocates the specified space for the account's data field -3. Transfers ownership to the specified program +Цей перехід права власності важливий, оскільки тільки власник акаунту може змінювати +дані акаунту. У цьому випадку ми встановлюємо нашу програму як власника, що дозволить нам змінювати +дані акаунту для збереження значення лічильника. -This ownership transfer is important because only the program owner of an -account can modify an account's data. In this case, we set our program as the -owner, which will allow us to modify the account's data to store the counter -value. +Щоб викликати System Program з інструкції нашої програми, ми робимо Cross +Program Invocation (CPI) через функцію `invoke`. CPI дозволяє одній програмі +викликати інструкції інших програм — в цьому випадку інструкцію `create_account` з System Program. -To invoke the System Program from our program's instruction, we make a Cross -Program Invocation (CPI) via the `invoke` function. A CPI allows one program to -call instructions on other programs - in this case, the System Program's -`create_account` instruction. ```rs filename="lib.rs" {19-33} fn process_initialize_counter( @@ -806,13 +778,12 @@ fn process_initialize_counter( } ``` -Once the account is created, we initialize the account data by: +Після того, як акаунт створено, ми ініціалізуємо дані акаунту за допомогою: -1. Creating a new `CounterAccount` struct with the `initial_value` provided to - the instruction. -2. Getting a mutable reference to the new account's data field. -3. Serializing the `CounterAccount` struct into the account's data field, - effectively storing the `initial_value` on the account. +1. Створення нової структури `CounterAccount` з переданим значенням `initial_value`. +2. Отримання змінної посилання на поле даних нового акаунту. +3. Серіалізації структури `CounterAccount` в поле даних акаунту, + що ефективно зберігає значення `initial_value` в акаунті. ```rs filename="lib.rs" {35-44} /initial_value/ fn process_initialize_counter( @@ -922,24 +893,22 @@ fn process_initialize_counter( } ``` -Next, add the implementation of the `process_increment_counter` function. This -instruction increments the value of an existing counter account. +Далі додайте реалізацію функції `process_increment_counter`. Ця +інструкція збільшує значення існуючого акаунту лічильника. - + -Just like the `process_initialize_counter` function, we start by creating an -iterator over the accounts. In this case, we are only expecting one account, -which is the account to be updated. +Так само, як і в функції `process_initialize_counter`, ми починаємо з створення ітератора +по акаунтах. У цьому випадку ми очікуємо лише один акаунт, який є акаунтом, що має бути оновлений. -Note that in practice, a developer must implement various security checks to -validate the accounts passed to the program. Since all accounts are provided by -the caller of the instruction, there is no guarantee that the accounts provided -are the ones the program expects. Missing account validation checks are a common -source of program vulnerabilities. +Зверніть увагу, що на практиці розробник повинен реалізувати різні перевірки безпеки для +валідності акаунтів, переданих до програми. Оскільки всі акаунти надаються викликачем інструкції, +немає гарантії, що надані акаунти — це саме ті акаунти, які програма очікує. Відсутність перевірок +валідності акаунтів є поширеним джерелом вразливостей програми. -The example below includes a check to ensure the account we're referring to as -the `counter_account` is owned by the executing program. +Наведений приклад містить перевірку для того, щоб переконатися, що акаунт, на який ми посилаємось як +`counter_account`, належить виконуючій програмі. ```rs filename="lib.rs" {6-9} // Update an existing counter's value @@ -956,12 +925,12 @@ fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> P } ``` -To update the account data, we: +Щоб оновити дані акаунту, ми: -- Mutably borrow the existing account's data field -- Deserialize the raw bytes into our `CounterAccount` struct -- Update the `count` value -- Serialize the modified struct back into the account's data field +- Змінно позичаємо поле даних існуючого акаунту +- Десеріалізуємо сирі байти в нашу структуру `CounterAccount` +- Оновлюємо значення `count` +- Серіалізуємо змінену структуру назад у поле даних акаунту ```rs filename="lib.rs" {11-24} // Update an existing counter's value @@ -1028,10 +997,10 @@ fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> P } ``` -### Instruction Testing +### Тестування інструкцій -To test the program instructions, add the following dependencies to -`Cargo.toml`. +Для тестування інструкцій програми додайте наступні залежності до +файлу `Cargo.toml`. ```shell filename="Terminal" cargo add solana-program-test@1.18.26 --dev @@ -1039,18 +1008,18 @@ cargo add solana-sdk@1.18.26 --dev cargo add tokio --dev ``` -Then add the following test module to `lib.rs` and run `cargo test-sbf` to -execute the tests. Optionally, use the `--nocapture` flag to see the print -statements in the output. +Далі додайте наступний тестовий модуль до файлу `lib.rs` і виконайте команду `cargo test-sbf` для +запуску тестів. За бажанням, використовуйте прапорець `--nocapture`, щоб побачити +виведені дані в результатах. -```shell filename="Terminal" +```shell filename="Термінал" cargo test-sbf -- --nocapture ``` -First, set up the test module and import required dependencies: +Спочатку налаштуйте тестовий модуль і імпортуйте необхідні залежності: ```rs filename="lib.rs" #[cfg(test)] @@ -1071,9 +1040,9 @@ mod test { } ``` -Next, set up the test using `ProgramTest`. Then create a new keypair to use as -the address for the counter account we'll initialize and define an initial value -to set for the counter. +Далі налаштуйте тест за допомогою `ProgramTest`. Потім створіть нову ключову пару, яку будемо використовувати як +адресу для акаунту лічильника, який ми ініціалізуємо, і визначте початкове значення, +яке встановимо для лічильника. ```rs filename="lib.rs" #[cfg(test)] @@ -1105,13 +1074,13 @@ mod test { } ``` -When building an instruction, each account must be provided as an +При побудові інструкції кожен акаунт повинен бути наданий як [`AccountMeta`](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/instruction.rs#L539-L545), -which specifies: +який вказує: -- The account's public key (`Pubkey`) -- `is_writable`: Whether the account data will be modified -- `is_signer`: Whether the account must sign the transaction +- Публічний ключ акаунту (`Pubkey`) +- `is_writable`: Чи будуть змінюватися дані акаунту +- `is_signer`: Чи повинен акаунт підписати транзакцію ```rs AccountMeta::new(account1_pubkey, true), // writable, signer @@ -1120,13 +1089,12 @@ AccountMeta::new_readonly(account3_pubkey, false), // not writable, not signer AccountMeta::new_readonly(account4_pubkey, true), // writable, signer ``` -To test the initialize instruction: +Для тестування інструкції ініціалізації: -- Create instruction data with variant 0 (`InitializeCounter`) and initial value -- Build the instruction with the program ID, instruction data, and required - accounts -- Send a transaction with the initialize instruction -- Check the account was created with the correct initial value +- Створіть дані інструкції з варіантом 0 (`InitializeCounter`) та початковим значенням +- Побудуйте інструкцію з ID програми, даними інструкції та необхідними акаунтами +- Відправте транзакцію з інструкцією ініціалізації +- Перевірте, що акаунт був створений з правильним початковим значенням ```rs filename="lib.rs" {16-53} #[tokio::test] @@ -1185,17 +1153,15 @@ To test the initialize instruction: } ``` -To test the increment instruction: +Для тестування інструкції збільшення: -- Build the instruction with the program ID, instruction data, and required - accounts -- Send a transaction with the increment instruction -- Check the account was incremented to the correct value +- Побудуйте інструкцію з ID програми, даними інструкції та необхідними акаунтами +- Відправте транзакцію з інструкцією збільшення +- Перевірте, що акаунт був збільшений до правильного значення -Note that the instruction data for the increment instruction is `[1]`, which -corresponds to variant 1 (`IncrementCounter`). Since there are no additional -parameters to the increment instruction, the data is simply the instruction -variant. +Зверніть увагу, що дані інструкції для інструкції збільшення — це `[1]`, що +відповідає варіанту 1 (`IncrementCounter`). Оскільки інструкція збільшення не має додаткових +параметрів, дані — це просто варіант інструкції. ```rs filename="lib.rs" {55-82} #[tokio::test] diff --git a/docs/uk/programs/testing.md b/docs/locales/uk/programs/testing.md similarity index 100% rename from docs/uk/programs/testing.md rename to docs/locales/uk/programs/testing.md diff --git a/docs/uk/rpc.md b/docs/locales/uk/rpc.md similarity index 100% rename from docs/uk/rpc.md rename to docs/locales/uk/rpc.md diff --git a/docs/en/rpc/deprecated/confirmTransaction.mdx b/docs/locales/uk/rpc/deprecated/confirmTransaction.mdx similarity index 100% rename from docs/en/rpc/deprecated/confirmTransaction.mdx rename to docs/locales/uk/rpc/deprecated/confirmTransaction.mdx diff --git a/docs/en/rpc/deprecated/getConfirmedBlock.mdx b/docs/locales/uk/rpc/deprecated/getConfirmedBlock.mdx similarity index 100% rename from docs/en/rpc/deprecated/getConfirmedBlock.mdx rename to docs/locales/uk/rpc/deprecated/getConfirmedBlock.mdx diff --git a/docs/en/rpc/deprecated/getConfirmedBlocks.mdx b/docs/locales/uk/rpc/deprecated/getConfirmedBlocks.mdx similarity index 100% rename from docs/en/rpc/deprecated/getConfirmedBlocks.mdx rename to docs/locales/uk/rpc/deprecated/getConfirmedBlocks.mdx diff --git a/docs/en/rpc/deprecated/getConfirmedBlocksWithLimit.mdx b/docs/locales/uk/rpc/deprecated/getConfirmedBlocksWithLimit.mdx similarity index 100% rename from docs/en/rpc/deprecated/getConfirmedBlocksWithLimit.mdx rename to docs/locales/uk/rpc/deprecated/getConfirmedBlocksWithLimit.mdx diff --git a/docs/en/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx b/docs/locales/uk/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx similarity index 100% rename from docs/en/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx rename to docs/locales/uk/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx diff --git a/docs/en/rpc/deprecated/getConfirmedTransaction.mdx b/docs/locales/uk/rpc/deprecated/getConfirmedTransaction.mdx similarity index 100% rename from docs/en/rpc/deprecated/getConfirmedTransaction.mdx rename to docs/locales/uk/rpc/deprecated/getConfirmedTransaction.mdx diff --git a/docs/en/rpc/deprecated/getFeeCalculatorForBlockhash.mdx b/docs/locales/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx similarity index 100% rename from docs/en/rpc/deprecated/getFeeCalculatorForBlockhash.mdx rename to docs/locales/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx diff --git a/docs/en/rpc/deprecated/getFeeRateGovernor.mdx b/docs/locales/uk/rpc/deprecated/getFeeRateGovernor.mdx similarity index 100% rename from docs/en/rpc/deprecated/getFeeRateGovernor.mdx rename to docs/locales/uk/rpc/deprecated/getFeeRateGovernor.mdx diff --git a/docs/en/rpc/deprecated/getFees.mdx b/docs/locales/uk/rpc/deprecated/getFees.mdx similarity index 100% rename from docs/en/rpc/deprecated/getFees.mdx rename to docs/locales/uk/rpc/deprecated/getFees.mdx diff --git a/docs/en/rpc/deprecated/getRecentBlockhash.mdx b/docs/locales/uk/rpc/deprecated/getRecentBlockhash.mdx similarity index 100% rename from docs/en/rpc/deprecated/getRecentBlockhash.mdx rename to docs/locales/uk/rpc/deprecated/getRecentBlockhash.mdx diff --git a/docs/en/rpc/deprecated/getSignatureConfirmation.mdx b/docs/locales/uk/rpc/deprecated/getSignatureConfirmation.mdx similarity index 100% rename from docs/en/rpc/deprecated/getSignatureConfirmation.mdx rename to docs/locales/uk/rpc/deprecated/getSignatureConfirmation.mdx diff --git a/docs/en/rpc/deprecated/getSignatureStatus.mdx b/docs/locales/uk/rpc/deprecated/getSignatureStatus.mdx similarity index 100% rename from docs/en/rpc/deprecated/getSignatureStatus.mdx rename to docs/locales/uk/rpc/deprecated/getSignatureStatus.mdx diff --git a/docs/en/rpc/deprecated/getSnapshotSlot.mdx b/docs/locales/uk/rpc/deprecated/getSnapshotSlot.mdx similarity index 100% rename from docs/en/rpc/deprecated/getSnapshotSlot.mdx rename to docs/locales/uk/rpc/deprecated/getSnapshotSlot.mdx diff --git a/docs/en/rpc/deprecated/getStakeActivation.mdx b/docs/locales/uk/rpc/deprecated/getStakeActivation.mdx similarity index 100% rename from docs/en/rpc/deprecated/getStakeActivation.mdx rename to docs/locales/uk/rpc/deprecated/getStakeActivation.mdx diff --git a/docs/en/rpc/deprecated/index.mdx b/docs/locales/uk/rpc/deprecated/index.mdx similarity index 100% rename from docs/en/rpc/deprecated/index.mdx rename to docs/locales/uk/rpc/deprecated/index.mdx diff --git a/docs/en/rpc/http/getAccountInfo.mdx b/docs/locales/uk/rpc/http/getAccountInfo.mdx similarity index 100% rename from docs/en/rpc/http/getAccountInfo.mdx rename to docs/locales/uk/rpc/http/getAccountInfo.mdx diff --git a/docs/en/rpc/http/getBalance.mdx b/docs/locales/uk/rpc/http/getBalance.mdx similarity index 100% rename from docs/en/rpc/http/getBalance.mdx rename to docs/locales/uk/rpc/http/getBalance.mdx diff --git a/docs/en/rpc/http/getBlock.mdx b/docs/locales/uk/rpc/http/getBlock.mdx similarity index 100% rename from docs/en/rpc/http/getBlock.mdx rename to docs/locales/uk/rpc/http/getBlock.mdx diff --git a/docs/en/rpc/http/getBlockCommitment.mdx b/docs/locales/uk/rpc/http/getBlockCommitment.mdx similarity index 100% rename from docs/en/rpc/http/getBlockCommitment.mdx rename to docs/locales/uk/rpc/http/getBlockCommitment.mdx diff --git a/docs/en/rpc/http/getBlockHeight.mdx b/docs/locales/uk/rpc/http/getBlockHeight.mdx similarity index 100% rename from docs/en/rpc/http/getBlockHeight.mdx rename to docs/locales/uk/rpc/http/getBlockHeight.mdx diff --git a/docs/en/rpc/http/getBlockProduction.mdx b/docs/locales/uk/rpc/http/getBlockProduction.mdx similarity index 100% rename from docs/en/rpc/http/getBlockProduction.mdx rename to docs/locales/uk/rpc/http/getBlockProduction.mdx diff --git a/docs/en/rpc/http/getBlockTime.mdx b/docs/locales/uk/rpc/http/getBlockTime.mdx similarity index 100% rename from docs/en/rpc/http/getBlockTime.mdx rename to docs/locales/uk/rpc/http/getBlockTime.mdx diff --git a/docs/en/rpc/http/getBlocks.mdx b/docs/locales/uk/rpc/http/getBlocks.mdx similarity index 100% rename from docs/en/rpc/http/getBlocks.mdx rename to docs/locales/uk/rpc/http/getBlocks.mdx diff --git a/docs/en/rpc/http/getBlocksWithLimit.mdx b/docs/locales/uk/rpc/http/getBlocksWithLimit.mdx similarity index 100% rename from docs/en/rpc/http/getBlocksWithLimit.mdx rename to docs/locales/uk/rpc/http/getBlocksWithLimit.mdx diff --git a/docs/en/rpc/http/getClusterNodes.mdx b/docs/locales/uk/rpc/http/getClusterNodes.mdx similarity index 100% rename from docs/en/rpc/http/getClusterNodes.mdx rename to docs/locales/uk/rpc/http/getClusterNodes.mdx diff --git a/docs/en/rpc/http/getEpochInfo.mdx b/docs/locales/uk/rpc/http/getEpochInfo.mdx similarity index 100% rename from docs/en/rpc/http/getEpochInfo.mdx rename to docs/locales/uk/rpc/http/getEpochInfo.mdx diff --git a/docs/en/rpc/http/getEpochSchedule.mdx b/docs/locales/uk/rpc/http/getEpochSchedule.mdx similarity index 100% rename from docs/en/rpc/http/getEpochSchedule.mdx rename to docs/locales/uk/rpc/http/getEpochSchedule.mdx diff --git a/docs/en/rpc/http/getFeeForMessage.mdx b/docs/locales/uk/rpc/http/getFeeForMessage.mdx similarity index 100% rename from docs/en/rpc/http/getFeeForMessage.mdx rename to docs/locales/uk/rpc/http/getFeeForMessage.mdx diff --git a/docs/en/rpc/http/getFirstAvailableBlock.mdx b/docs/locales/uk/rpc/http/getFirstAvailableBlock.mdx similarity index 100% rename from docs/en/rpc/http/getFirstAvailableBlock.mdx rename to docs/locales/uk/rpc/http/getFirstAvailableBlock.mdx diff --git a/docs/en/rpc/http/getGenesisHash.mdx b/docs/locales/uk/rpc/http/getGenesisHash.mdx similarity index 100% rename from docs/en/rpc/http/getGenesisHash.mdx rename to docs/locales/uk/rpc/http/getGenesisHash.mdx diff --git a/docs/en/rpc/http/getHealth.mdx b/docs/locales/uk/rpc/http/getHealth.mdx similarity index 100% rename from docs/en/rpc/http/getHealth.mdx rename to docs/locales/uk/rpc/http/getHealth.mdx diff --git a/docs/en/rpc/http/getHighestSnapshotSlot.mdx b/docs/locales/uk/rpc/http/getHighestSnapshotSlot.mdx similarity index 100% rename from docs/en/rpc/http/getHighestSnapshotSlot.mdx rename to docs/locales/uk/rpc/http/getHighestSnapshotSlot.mdx diff --git a/docs/en/rpc/http/getIdentity.mdx b/docs/locales/uk/rpc/http/getIdentity.mdx similarity index 100% rename from docs/en/rpc/http/getIdentity.mdx rename to docs/locales/uk/rpc/http/getIdentity.mdx diff --git a/docs/en/rpc/http/getInflationGovernor.mdx b/docs/locales/uk/rpc/http/getInflationGovernor.mdx similarity index 100% rename from docs/en/rpc/http/getInflationGovernor.mdx rename to docs/locales/uk/rpc/http/getInflationGovernor.mdx diff --git a/docs/en/rpc/http/getInflationRate.mdx b/docs/locales/uk/rpc/http/getInflationRate.mdx similarity index 100% rename from docs/en/rpc/http/getInflationRate.mdx rename to docs/locales/uk/rpc/http/getInflationRate.mdx diff --git a/docs/en/rpc/http/getInflationReward.mdx b/docs/locales/uk/rpc/http/getInflationReward.mdx similarity index 100% rename from docs/en/rpc/http/getInflationReward.mdx rename to docs/locales/uk/rpc/http/getInflationReward.mdx diff --git a/docs/en/rpc/http/getLargestAccounts.mdx b/docs/locales/uk/rpc/http/getLargestAccounts.mdx similarity index 100% rename from docs/en/rpc/http/getLargestAccounts.mdx rename to docs/locales/uk/rpc/http/getLargestAccounts.mdx diff --git a/docs/en/rpc/http/getLatestBlockhash.mdx b/docs/locales/uk/rpc/http/getLatestBlockhash.mdx similarity index 100% rename from docs/en/rpc/http/getLatestBlockhash.mdx rename to docs/locales/uk/rpc/http/getLatestBlockhash.mdx diff --git a/docs/en/rpc/http/getLeaderSchedule.mdx b/docs/locales/uk/rpc/http/getLeaderSchedule.mdx similarity index 100% rename from docs/en/rpc/http/getLeaderSchedule.mdx rename to docs/locales/uk/rpc/http/getLeaderSchedule.mdx diff --git a/docs/en/rpc/http/getMaxRetransmitSlot.mdx b/docs/locales/uk/rpc/http/getMaxRetransmitSlot.mdx similarity index 100% rename from docs/en/rpc/http/getMaxRetransmitSlot.mdx rename to docs/locales/uk/rpc/http/getMaxRetransmitSlot.mdx diff --git a/docs/en/rpc/http/getMaxShredInsertSlot.mdx b/docs/locales/uk/rpc/http/getMaxShredInsertSlot.mdx similarity index 100% rename from docs/en/rpc/http/getMaxShredInsertSlot.mdx rename to docs/locales/uk/rpc/http/getMaxShredInsertSlot.mdx diff --git a/docs/en/rpc/http/getMinimumBalanceForRentExemption.mdx b/docs/locales/uk/rpc/http/getMinimumBalanceForRentExemption.mdx similarity index 100% rename from docs/en/rpc/http/getMinimumBalanceForRentExemption.mdx rename to docs/locales/uk/rpc/http/getMinimumBalanceForRentExemption.mdx diff --git a/docs/en/rpc/http/getMultipleAccounts.mdx b/docs/locales/uk/rpc/http/getMultipleAccounts.mdx similarity index 100% rename from docs/en/rpc/http/getMultipleAccounts.mdx rename to docs/locales/uk/rpc/http/getMultipleAccounts.mdx diff --git a/docs/en/rpc/http/getProgramAccounts.mdx b/docs/locales/uk/rpc/http/getProgramAccounts.mdx similarity index 100% rename from docs/en/rpc/http/getProgramAccounts.mdx rename to docs/locales/uk/rpc/http/getProgramAccounts.mdx diff --git a/docs/en/rpc/http/getRecentPerformanceSamples.mdx b/docs/locales/uk/rpc/http/getRecentPerformanceSamples.mdx similarity index 100% rename from docs/en/rpc/http/getRecentPerformanceSamples.mdx rename to docs/locales/uk/rpc/http/getRecentPerformanceSamples.mdx diff --git a/docs/en/rpc/http/getRecentPrioritizationFees.mdx b/docs/locales/uk/rpc/http/getRecentPrioritizationFees.mdx similarity index 100% rename from docs/en/rpc/http/getRecentPrioritizationFees.mdx rename to docs/locales/uk/rpc/http/getRecentPrioritizationFees.mdx diff --git a/docs/en/rpc/http/getSignatureStatuses.mdx b/docs/locales/uk/rpc/http/getSignatureStatuses.mdx similarity index 100% rename from docs/en/rpc/http/getSignatureStatuses.mdx rename to docs/locales/uk/rpc/http/getSignatureStatuses.mdx diff --git a/docs/en/rpc/http/getSignaturesForAddress.mdx b/docs/locales/uk/rpc/http/getSignaturesForAddress.mdx similarity index 100% rename from docs/en/rpc/http/getSignaturesForAddress.mdx rename to docs/locales/uk/rpc/http/getSignaturesForAddress.mdx diff --git a/docs/en/rpc/http/getSlot.mdx b/docs/locales/uk/rpc/http/getSlot.mdx similarity index 100% rename from docs/en/rpc/http/getSlot.mdx rename to docs/locales/uk/rpc/http/getSlot.mdx diff --git a/docs/en/rpc/http/getSlotLeader.mdx b/docs/locales/uk/rpc/http/getSlotLeader.mdx similarity index 100% rename from docs/en/rpc/http/getSlotLeader.mdx rename to docs/locales/uk/rpc/http/getSlotLeader.mdx diff --git a/docs/en/rpc/http/getSlotLeaders.mdx b/docs/locales/uk/rpc/http/getSlotLeaders.mdx similarity index 100% rename from docs/en/rpc/http/getSlotLeaders.mdx rename to docs/locales/uk/rpc/http/getSlotLeaders.mdx diff --git a/docs/en/rpc/http/getStakeMinimumDelegation.mdx b/docs/locales/uk/rpc/http/getStakeMinimumDelegation.mdx similarity index 100% rename from docs/en/rpc/http/getStakeMinimumDelegation.mdx rename to docs/locales/uk/rpc/http/getStakeMinimumDelegation.mdx diff --git a/docs/en/rpc/http/getSupply.mdx b/docs/locales/uk/rpc/http/getSupply.mdx similarity index 100% rename from docs/en/rpc/http/getSupply.mdx rename to docs/locales/uk/rpc/http/getSupply.mdx diff --git a/docs/en/rpc/http/getTokenAccountBalance.mdx b/docs/locales/uk/rpc/http/getTokenAccountBalance.mdx similarity index 100% rename from docs/en/rpc/http/getTokenAccountBalance.mdx rename to docs/locales/uk/rpc/http/getTokenAccountBalance.mdx diff --git a/docs/en/rpc/http/getTokenAccountsByDelegate.mdx b/docs/locales/uk/rpc/http/getTokenAccountsByDelegate.mdx similarity index 100% rename from docs/en/rpc/http/getTokenAccountsByDelegate.mdx rename to docs/locales/uk/rpc/http/getTokenAccountsByDelegate.mdx diff --git a/docs/en/rpc/http/getTokenAccountsByOwner.mdx b/docs/locales/uk/rpc/http/getTokenAccountsByOwner.mdx similarity index 100% rename from docs/en/rpc/http/getTokenAccountsByOwner.mdx rename to docs/locales/uk/rpc/http/getTokenAccountsByOwner.mdx diff --git a/docs/en/rpc/http/getTokenLargestAccounts.mdx b/docs/locales/uk/rpc/http/getTokenLargestAccounts.mdx similarity index 100% rename from docs/en/rpc/http/getTokenLargestAccounts.mdx rename to docs/locales/uk/rpc/http/getTokenLargestAccounts.mdx diff --git a/docs/en/rpc/http/getTokenSupply.mdx b/docs/locales/uk/rpc/http/getTokenSupply.mdx similarity index 100% rename from docs/en/rpc/http/getTokenSupply.mdx rename to docs/locales/uk/rpc/http/getTokenSupply.mdx diff --git a/docs/en/rpc/http/getTransaction.mdx b/docs/locales/uk/rpc/http/getTransaction.mdx similarity index 100% rename from docs/en/rpc/http/getTransaction.mdx rename to docs/locales/uk/rpc/http/getTransaction.mdx diff --git a/docs/en/rpc/http/getTransactionCount.mdx b/docs/locales/uk/rpc/http/getTransactionCount.mdx similarity index 100% rename from docs/en/rpc/http/getTransactionCount.mdx rename to docs/locales/uk/rpc/http/getTransactionCount.mdx diff --git a/docs/en/rpc/http/getVersion.mdx b/docs/locales/uk/rpc/http/getVersion.mdx similarity index 100% rename from docs/en/rpc/http/getVersion.mdx rename to docs/locales/uk/rpc/http/getVersion.mdx diff --git a/docs/en/rpc/http/getVoteAccounts.mdx b/docs/locales/uk/rpc/http/getVoteAccounts.mdx similarity index 100% rename from docs/en/rpc/http/getVoteAccounts.mdx rename to docs/locales/uk/rpc/http/getVoteAccounts.mdx diff --git a/docs/en/rpc/http/index.mdx b/docs/locales/uk/rpc/http/index.mdx similarity index 100% rename from docs/en/rpc/http/index.mdx rename to docs/locales/uk/rpc/http/index.mdx diff --git a/docs/en/rpc/http/isBlockhashValid.mdx b/docs/locales/uk/rpc/http/isBlockhashValid.mdx similarity index 100% rename from docs/en/rpc/http/isBlockhashValid.mdx rename to docs/locales/uk/rpc/http/isBlockhashValid.mdx diff --git a/docs/en/rpc/http/minimumLedgerSlot.mdx b/docs/locales/uk/rpc/http/minimumLedgerSlot.mdx similarity index 100% rename from docs/en/rpc/http/minimumLedgerSlot.mdx rename to docs/locales/uk/rpc/http/minimumLedgerSlot.mdx diff --git a/docs/en/rpc/http/requestAirdrop.mdx b/docs/locales/uk/rpc/http/requestAirdrop.mdx similarity index 100% rename from docs/en/rpc/http/requestAirdrop.mdx rename to docs/locales/uk/rpc/http/requestAirdrop.mdx diff --git a/docs/en/rpc/http/sendTransaction.mdx b/docs/locales/uk/rpc/http/sendTransaction.mdx similarity index 100% rename from docs/en/rpc/http/sendTransaction.mdx rename to docs/locales/uk/rpc/http/sendTransaction.mdx diff --git a/docs/en/rpc/http/simulateTransaction.mdx b/docs/locales/uk/rpc/http/simulateTransaction.mdx similarity index 100% rename from docs/en/rpc/http/simulateTransaction.mdx rename to docs/locales/uk/rpc/http/simulateTransaction.mdx diff --git a/docs/en/rpc/index.mdx b/docs/locales/uk/rpc/index.mdx similarity index 100% rename from docs/en/rpc/index.mdx rename to docs/locales/uk/rpc/index.mdx diff --git a/docs/en/rpc/json-structures.mdx b/docs/locales/uk/rpc/json-structures.mdx similarity index 100% rename from docs/en/rpc/json-structures.mdx rename to docs/locales/uk/rpc/json-structures.mdx diff --git a/docs/en/rpc/websocket/accountSubscribe.mdx b/docs/locales/uk/rpc/websocket/accountSubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/accountSubscribe.mdx rename to docs/locales/uk/rpc/websocket/accountSubscribe.mdx diff --git a/docs/en/rpc/websocket/accountUnsubscribe.mdx b/docs/locales/uk/rpc/websocket/accountUnsubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/accountUnsubscribe.mdx rename to docs/locales/uk/rpc/websocket/accountUnsubscribe.mdx diff --git a/docs/en/rpc/websocket/blockSubscribe.mdx b/docs/locales/uk/rpc/websocket/blockSubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/blockSubscribe.mdx rename to docs/locales/uk/rpc/websocket/blockSubscribe.mdx diff --git a/docs/en/rpc/websocket/blockUnsubscribe.mdx b/docs/locales/uk/rpc/websocket/blockUnsubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/blockUnsubscribe.mdx rename to docs/locales/uk/rpc/websocket/blockUnsubscribe.mdx diff --git a/docs/en/rpc/websocket/index.mdx b/docs/locales/uk/rpc/websocket/index.mdx similarity index 100% rename from docs/en/rpc/websocket/index.mdx rename to docs/locales/uk/rpc/websocket/index.mdx diff --git a/docs/en/rpc/websocket/logsSubscribe.mdx b/docs/locales/uk/rpc/websocket/logsSubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/logsSubscribe.mdx rename to docs/locales/uk/rpc/websocket/logsSubscribe.mdx diff --git a/docs/en/rpc/websocket/logsUnsubscribe.mdx b/docs/locales/uk/rpc/websocket/logsUnsubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/logsUnsubscribe.mdx rename to docs/locales/uk/rpc/websocket/logsUnsubscribe.mdx diff --git a/docs/en/rpc/websocket/programSubscribe.mdx b/docs/locales/uk/rpc/websocket/programSubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/programSubscribe.mdx rename to docs/locales/uk/rpc/websocket/programSubscribe.mdx diff --git a/docs/en/rpc/websocket/programUnsubscribe.mdx b/docs/locales/uk/rpc/websocket/programUnsubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/programUnsubscribe.mdx rename to docs/locales/uk/rpc/websocket/programUnsubscribe.mdx diff --git a/docs/en/rpc/websocket/rootSubscribe.mdx b/docs/locales/uk/rpc/websocket/rootSubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/rootSubscribe.mdx rename to docs/locales/uk/rpc/websocket/rootSubscribe.mdx diff --git a/docs/en/rpc/websocket/rootUnsubscribe.mdx b/docs/locales/uk/rpc/websocket/rootUnsubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/rootUnsubscribe.mdx rename to docs/locales/uk/rpc/websocket/rootUnsubscribe.mdx diff --git a/docs/en/rpc/websocket/signatureSubscribe.mdx b/docs/locales/uk/rpc/websocket/signatureSubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/signatureSubscribe.mdx rename to docs/locales/uk/rpc/websocket/signatureSubscribe.mdx diff --git a/docs/en/rpc/websocket/signatureUnsubscribe.mdx b/docs/locales/uk/rpc/websocket/signatureUnsubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/signatureUnsubscribe.mdx rename to docs/locales/uk/rpc/websocket/signatureUnsubscribe.mdx diff --git a/docs/en/rpc/websocket/slotSubscribe.mdx b/docs/locales/uk/rpc/websocket/slotSubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/slotSubscribe.mdx rename to docs/locales/uk/rpc/websocket/slotSubscribe.mdx diff --git a/docs/en/rpc/websocket/slotUnsubscribe.mdx b/docs/locales/uk/rpc/websocket/slotUnsubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/slotUnsubscribe.mdx rename to docs/locales/uk/rpc/websocket/slotUnsubscribe.mdx diff --git a/docs/en/rpc/websocket/slotsUpdatesSubscribe.mdx b/docs/locales/uk/rpc/websocket/slotsUpdatesSubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/slotsUpdatesSubscribe.mdx rename to docs/locales/uk/rpc/websocket/slotsUpdatesSubscribe.mdx diff --git a/docs/en/rpc/websocket/slotsUpdatesUnsubscribe.mdx b/docs/locales/uk/rpc/websocket/slotsUpdatesUnsubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/slotsUpdatesUnsubscribe.mdx rename to docs/locales/uk/rpc/websocket/slotsUpdatesUnsubscribe.mdx diff --git a/docs/en/rpc/websocket/voteSubscribe.mdx b/docs/locales/uk/rpc/websocket/voteSubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/voteSubscribe.mdx rename to docs/locales/uk/rpc/websocket/voteSubscribe.mdx diff --git a/docs/en/rpc/websocket/voteUnsubscribe.mdx b/docs/locales/uk/rpc/websocket/voteUnsubscribe.mdx similarity index 100% rename from docs/en/rpc/websocket/voteUnsubscribe.mdx rename to docs/locales/uk/rpc/websocket/voteUnsubscribe.mdx diff --git a/docs/uk/terminology.md b/docs/locales/uk/terminology.md similarity index 100% rename from docs/uk/terminology.md rename to docs/locales/uk/terminology.md diff --git a/docs/en/more/exchange.md b/docs/more/exchange.md similarity index 100% rename from docs/en/more/exchange.md rename to docs/more/exchange.md diff --git a/docs/en/more/index.md b/docs/more/index.md similarity index 100% rename from docs/en/more/index.md rename to docs/more/index.md diff --git a/docs/en/programs/anchor/client-typescript.md b/docs/programs/anchor/client-typescript.md similarity index 100% rename from docs/en/programs/anchor/client-typescript.md rename to docs/programs/anchor/client-typescript.md diff --git a/docs/en/programs/anchor/cpi.md b/docs/programs/anchor/cpi.md similarity index 100% rename from docs/en/programs/anchor/cpi.md rename to docs/programs/anchor/cpi.md diff --git a/docs/en/programs/anchor/idl.md b/docs/programs/anchor/idl.md similarity index 100% rename from docs/en/programs/anchor/idl.md rename to docs/programs/anchor/idl.md diff --git a/docs/en/programs/anchor/index.md b/docs/programs/anchor/index.md similarity index 100% rename from docs/en/programs/anchor/index.md rename to docs/programs/anchor/index.md diff --git a/docs/en/programs/anchor/pda.md b/docs/programs/anchor/pda.md similarity index 100% rename from docs/en/programs/anchor/pda.md rename to docs/programs/anchor/pda.md diff --git a/docs/en/programs/anchor/program-structure.md b/docs/programs/anchor/program-structure.md similarity index 100% rename from docs/en/programs/anchor/program-structure.md rename to docs/programs/anchor/program-structure.md diff --git a/docs/en/programs/deploying.md b/docs/programs/deploying.md similarity index 100% rename from docs/en/programs/deploying.md rename to docs/programs/deploying.md diff --git a/docs/en/programs/examples.md b/docs/programs/examples.md similarity index 100% rename from docs/en/programs/examples.md rename to docs/programs/examples.md diff --git a/docs/en/programs/faq.md b/docs/programs/faq.md similarity index 100% rename from docs/en/programs/faq.md rename to docs/programs/faq.md diff --git a/docs/uk/programs/index.md b/docs/programs/index.md similarity index 100% rename from docs/uk/programs/index.md rename to docs/programs/index.md diff --git a/docs/en/programs/limitations.md b/docs/programs/limitations.md similarity index 100% rename from docs/en/programs/limitations.md rename to docs/programs/limitations.md diff --git a/docs/en/programs/rust/index.md b/docs/programs/rust/index.md similarity index 100% rename from docs/en/programs/rust/index.md rename to docs/programs/rust/index.md diff --git a/docs/en/programs/rust/program-structure.md b/docs/programs/rust/program-structure.md similarity index 100% rename from docs/en/programs/rust/program-structure.md rename to docs/programs/rust/program-structure.md diff --git a/docs/en/programs/testing.md b/docs/programs/testing.md similarity index 100% rename from docs/en/programs/testing.md rename to docs/programs/testing.md diff --git a/docs/en/rpc.md b/docs/rpc.md similarity index 100% rename from docs/en/rpc.md rename to docs/rpc.md diff --git a/docs/uk/rpc/deprecated/confirmTransaction.mdx b/docs/rpc/deprecated/confirmTransaction.mdx similarity index 100% rename from docs/uk/rpc/deprecated/confirmTransaction.mdx rename to docs/rpc/deprecated/confirmTransaction.mdx diff --git a/docs/uk/rpc/deprecated/getConfirmedBlock.mdx b/docs/rpc/deprecated/getConfirmedBlock.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getConfirmedBlock.mdx rename to docs/rpc/deprecated/getConfirmedBlock.mdx diff --git a/docs/uk/rpc/deprecated/getConfirmedBlocks.mdx b/docs/rpc/deprecated/getConfirmedBlocks.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getConfirmedBlocks.mdx rename to docs/rpc/deprecated/getConfirmedBlocks.mdx diff --git a/docs/uk/rpc/deprecated/getConfirmedBlocksWithLimit.mdx b/docs/rpc/deprecated/getConfirmedBlocksWithLimit.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getConfirmedBlocksWithLimit.mdx rename to docs/rpc/deprecated/getConfirmedBlocksWithLimit.mdx diff --git a/docs/uk/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx b/docs/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx rename to docs/rpc/deprecated/getConfirmedSignaturesForAddress2.mdx diff --git a/docs/uk/rpc/deprecated/getConfirmedTransaction.mdx b/docs/rpc/deprecated/getConfirmedTransaction.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getConfirmedTransaction.mdx rename to docs/rpc/deprecated/getConfirmedTransaction.mdx diff --git a/docs/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx b/docs/rpc/deprecated/getFeeCalculatorForBlockhash.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx rename to docs/rpc/deprecated/getFeeCalculatorForBlockhash.mdx diff --git a/docs/uk/rpc/deprecated/getFeeRateGovernor.mdx b/docs/rpc/deprecated/getFeeRateGovernor.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getFeeRateGovernor.mdx rename to docs/rpc/deprecated/getFeeRateGovernor.mdx diff --git a/docs/uk/rpc/deprecated/getFees.mdx b/docs/rpc/deprecated/getFees.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getFees.mdx rename to docs/rpc/deprecated/getFees.mdx diff --git a/docs/uk/rpc/deprecated/getRecentBlockhash.mdx b/docs/rpc/deprecated/getRecentBlockhash.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getRecentBlockhash.mdx rename to docs/rpc/deprecated/getRecentBlockhash.mdx diff --git a/docs/uk/rpc/deprecated/getSignatureConfirmation.mdx b/docs/rpc/deprecated/getSignatureConfirmation.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getSignatureConfirmation.mdx rename to docs/rpc/deprecated/getSignatureConfirmation.mdx diff --git a/docs/uk/rpc/deprecated/getSignatureStatus.mdx b/docs/rpc/deprecated/getSignatureStatus.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getSignatureStatus.mdx rename to docs/rpc/deprecated/getSignatureStatus.mdx diff --git a/docs/uk/rpc/deprecated/getSnapshotSlot.mdx b/docs/rpc/deprecated/getSnapshotSlot.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getSnapshotSlot.mdx rename to docs/rpc/deprecated/getSnapshotSlot.mdx diff --git a/docs/uk/rpc/deprecated/getStakeActivation.mdx b/docs/rpc/deprecated/getStakeActivation.mdx similarity index 100% rename from docs/uk/rpc/deprecated/getStakeActivation.mdx rename to docs/rpc/deprecated/getStakeActivation.mdx diff --git a/docs/uk/rpc/deprecated/index.mdx b/docs/rpc/deprecated/index.mdx similarity index 100% rename from docs/uk/rpc/deprecated/index.mdx rename to docs/rpc/deprecated/index.mdx diff --git a/docs/uk/rpc/http/getAccountInfo.mdx b/docs/rpc/http/getAccountInfo.mdx similarity index 100% rename from docs/uk/rpc/http/getAccountInfo.mdx rename to docs/rpc/http/getAccountInfo.mdx diff --git a/docs/uk/rpc/http/getBalance.mdx b/docs/rpc/http/getBalance.mdx similarity index 100% rename from docs/uk/rpc/http/getBalance.mdx rename to docs/rpc/http/getBalance.mdx diff --git a/docs/uk/rpc/http/getBlock.mdx b/docs/rpc/http/getBlock.mdx similarity index 100% rename from docs/uk/rpc/http/getBlock.mdx rename to docs/rpc/http/getBlock.mdx diff --git a/docs/uk/rpc/http/getBlockCommitment.mdx b/docs/rpc/http/getBlockCommitment.mdx similarity index 100% rename from docs/uk/rpc/http/getBlockCommitment.mdx rename to docs/rpc/http/getBlockCommitment.mdx diff --git a/docs/uk/rpc/http/getBlockHeight.mdx b/docs/rpc/http/getBlockHeight.mdx similarity index 100% rename from docs/uk/rpc/http/getBlockHeight.mdx rename to docs/rpc/http/getBlockHeight.mdx diff --git a/docs/uk/rpc/http/getBlockProduction.mdx b/docs/rpc/http/getBlockProduction.mdx similarity index 100% rename from docs/uk/rpc/http/getBlockProduction.mdx rename to docs/rpc/http/getBlockProduction.mdx diff --git a/docs/uk/rpc/http/getBlockTime.mdx b/docs/rpc/http/getBlockTime.mdx similarity index 100% rename from docs/uk/rpc/http/getBlockTime.mdx rename to docs/rpc/http/getBlockTime.mdx diff --git a/docs/uk/rpc/http/getBlocks.mdx b/docs/rpc/http/getBlocks.mdx similarity index 100% rename from docs/uk/rpc/http/getBlocks.mdx rename to docs/rpc/http/getBlocks.mdx diff --git a/docs/uk/rpc/http/getBlocksWithLimit.mdx b/docs/rpc/http/getBlocksWithLimit.mdx similarity index 100% rename from docs/uk/rpc/http/getBlocksWithLimit.mdx rename to docs/rpc/http/getBlocksWithLimit.mdx diff --git a/docs/uk/rpc/http/getClusterNodes.mdx b/docs/rpc/http/getClusterNodes.mdx similarity index 100% rename from docs/uk/rpc/http/getClusterNodes.mdx rename to docs/rpc/http/getClusterNodes.mdx diff --git a/docs/uk/rpc/http/getEpochInfo.mdx b/docs/rpc/http/getEpochInfo.mdx similarity index 100% rename from docs/uk/rpc/http/getEpochInfo.mdx rename to docs/rpc/http/getEpochInfo.mdx diff --git a/docs/uk/rpc/http/getEpochSchedule.mdx b/docs/rpc/http/getEpochSchedule.mdx similarity index 100% rename from docs/uk/rpc/http/getEpochSchedule.mdx rename to docs/rpc/http/getEpochSchedule.mdx diff --git a/docs/uk/rpc/http/getFeeForMessage.mdx b/docs/rpc/http/getFeeForMessage.mdx similarity index 100% rename from docs/uk/rpc/http/getFeeForMessage.mdx rename to docs/rpc/http/getFeeForMessage.mdx diff --git a/docs/uk/rpc/http/getFirstAvailableBlock.mdx b/docs/rpc/http/getFirstAvailableBlock.mdx similarity index 100% rename from docs/uk/rpc/http/getFirstAvailableBlock.mdx rename to docs/rpc/http/getFirstAvailableBlock.mdx diff --git a/docs/uk/rpc/http/getGenesisHash.mdx b/docs/rpc/http/getGenesisHash.mdx similarity index 100% rename from docs/uk/rpc/http/getGenesisHash.mdx rename to docs/rpc/http/getGenesisHash.mdx diff --git a/docs/uk/rpc/http/getHealth.mdx b/docs/rpc/http/getHealth.mdx similarity index 100% rename from docs/uk/rpc/http/getHealth.mdx rename to docs/rpc/http/getHealth.mdx diff --git a/docs/uk/rpc/http/getHighestSnapshotSlot.mdx b/docs/rpc/http/getHighestSnapshotSlot.mdx similarity index 100% rename from docs/uk/rpc/http/getHighestSnapshotSlot.mdx rename to docs/rpc/http/getHighestSnapshotSlot.mdx diff --git a/docs/uk/rpc/http/getIdentity.mdx b/docs/rpc/http/getIdentity.mdx similarity index 100% rename from docs/uk/rpc/http/getIdentity.mdx rename to docs/rpc/http/getIdentity.mdx diff --git a/docs/uk/rpc/http/getInflationGovernor.mdx b/docs/rpc/http/getInflationGovernor.mdx similarity index 100% rename from docs/uk/rpc/http/getInflationGovernor.mdx rename to docs/rpc/http/getInflationGovernor.mdx diff --git a/docs/uk/rpc/http/getInflationRate.mdx b/docs/rpc/http/getInflationRate.mdx similarity index 100% rename from docs/uk/rpc/http/getInflationRate.mdx rename to docs/rpc/http/getInflationRate.mdx diff --git a/docs/uk/rpc/http/getInflationReward.mdx b/docs/rpc/http/getInflationReward.mdx similarity index 100% rename from docs/uk/rpc/http/getInflationReward.mdx rename to docs/rpc/http/getInflationReward.mdx diff --git a/docs/uk/rpc/http/getLargestAccounts.mdx b/docs/rpc/http/getLargestAccounts.mdx similarity index 100% rename from docs/uk/rpc/http/getLargestAccounts.mdx rename to docs/rpc/http/getLargestAccounts.mdx diff --git a/docs/uk/rpc/http/getLatestBlockhash.mdx b/docs/rpc/http/getLatestBlockhash.mdx similarity index 100% rename from docs/uk/rpc/http/getLatestBlockhash.mdx rename to docs/rpc/http/getLatestBlockhash.mdx diff --git a/docs/uk/rpc/http/getLeaderSchedule.mdx b/docs/rpc/http/getLeaderSchedule.mdx similarity index 100% rename from docs/uk/rpc/http/getLeaderSchedule.mdx rename to docs/rpc/http/getLeaderSchedule.mdx diff --git a/docs/uk/rpc/http/getMaxRetransmitSlot.mdx b/docs/rpc/http/getMaxRetransmitSlot.mdx similarity index 100% rename from docs/uk/rpc/http/getMaxRetransmitSlot.mdx rename to docs/rpc/http/getMaxRetransmitSlot.mdx diff --git a/docs/uk/rpc/http/getMaxShredInsertSlot.mdx b/docs/rpc/http/getMaxShredInsertSlot.mdx similarity index 100% rename from docs/uk/rpc/http/getMaxShredInsertSlot.mdx rename to docs/rpc/http/getMaxShredInsertSlot.mdx diff --git a/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx b/docs/rpc/http/getMinimumBalanceForRentExemption.mdx similarity index 100% rename from docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx rename to docs/rpc/http/getMinimumBalanceForRentExemption.mdx diff --git a/docs/uk/rpc/http/getMultipleAccounts.mdx b/docs/rpc/http/getMultipleAccounts.mdx similarity index 100% rename from docs/uk/rpc/http/getMultipleAccounts.mdx rename to docs/rpc/http/getMultipleAccounts.mdx diff --git a/docs/uk/rpc/http/getProgramAccounts.mdx b/docs/rpc/http/getProgramAccounts.mdx similarity index 100% rename from docs/uk/rpc/http/getProgramAccounts.mdx rename to docs/rpc/http/getProgramAccounts.mdx diff --git a/docs/uk/rpc/http/getRecentPerformanceSamples.mdx b/docs/rpc/http/getRecentPerformanceSamples.mdx similarity index 100% rename from docs/uk/rpc/http/getRecentPerformanceSamples.mdx rename to docs/rpc/http/getRecentPerformanceSamples.mdx diff --git a/docs/uk/rpc/http/getRecentPrioritizationFees.mdx b/docs/rpc/http/getRecentPrioritizationFees.mdx similarity index 100% rename from docs/uk/rpc/http/getRecentPrioritizationFees.mdx rename to docs/rpc/http/getRecentPrioritizationFees.mdx diff --git a/docs/uk/rpc/http/getSignatureStatuses.mdx b/docs/rpc/http/getSignatureStatuses.mdx similarity index 100% rename from docs/uk/rpc/http/getSignatureStatuses.mdx rename to docs/rpc/http/getSignatureStatuses.mdx diff --git a/docs/uk/rpc/http/getSignaturesForAddress.mdx b/docs/rpc/http/getSignaturesForAddress.mdx similarity index 100% rename from docs/uk/rpc/http/getSignaturesForAddress.mdx rename to docs/rpc/http/getSignaturesForAddress.mdx diff --git a/docs/uk/rpc/http/getSlot.mdx b/docs/rpc/http/getSlot.mdx similarity index 100% rename from docs/uk/rpc/http/getSlot.mdx rename to docs/rpc/http/getSlot.mdx diff --git a/docs/uk/rpc/http/getSlotLeader.mdx b/docs/rpc/http/getSlotLeader.mdx similarity index 100% rename from docs/uk/rpc/http/getSlotLeader.mdx rename to docs/rpc/http/getSlotLeader.mdx diff --git a/docs/uk/rpc/http/getSlotLeaders.mdx b/docs/rpc/http/getSlotLeaders.mdx similarity index 100% rename from docs/uk/rpc/http/getSlotLeaders.mdx rename to docs/rpc/http/getSlotLeaders.mdx diff --git a/docs/uk/rpc/http/getStakeMinimumDelegation.mdx b/docs/rpc/http/getStakeMinimumDelegation.mdx similarity index 100% rename from docs/uk/rpc/http/getStakeMinimumDelegation.mdx rename to docs/rpc/http/getStakeMinimumDelegation.mdx diff --git a/docs/uk/rpc/http/getSupply.mdx b/docs/rpc/http/getSupply.mdx similarity index 100% rename from docs/uk/rpc/http/getSupply.mdx rename to docs/rpc/http/getSupply.mdx diff --git a/docs/uk/rpc/http/getTokenAccountBalance.mdx b/docs/rpc/http/getTokenAccountBalance.mdx similarity index 100% rename from docs/uk/rpc/http/getTokenAccountBalance.mdx rename to docs/rpc/http/getTokenAccountBalance.mdx diff --git a/docs/uk/rpc/http/getTokenAccountsByDelegate.mdx b/docs/rpc/http/getTokenAccountsByDelegate.mdx similarity index 100% rename from docs/uk/rpc/http/getTokenAccountsByDelegate.mdx rename to docs/rpc/http/getTokenAccountsByDelegate.mdx diff --git a/docs/uk/rpc/http/getTokenAccountsByOwner.mdx b/docs/rpc/http/getTokenAccountsByOwner.mdx similarity index 100% rename from docs/uk/rpc/http/getTokenAccountsByOwner.mdx rename to docs/rpc/http/getTokenAccountsByOwner.mdx diff --git a/docs/uk/rpc/http/getTokenLargestAccounts.mdx b/docs/rpc/http/getTokenLargestAccounts.mdx similarity index 100% rename from docs/uk/rpc/http/getTokenLargestAccounts.mdx rename to docs/rpc/http/getTokenLargestAccounts.mdx diff --git a/docs/uk/rpc/http/getTokenSupply.mdx b/docs/rpc/http/getTokenSupply.mdx similarity index 100% rename from docs/uk/rpc/http/getTokenSupply.mdx rename to docs/rpc/http/getTokenSupply.mdx diff --git a/docs/uk/rpc/http/getTransaction.mdx b/docs/rpc/http/getTransaction.mdx similarity index 100% rename from docs/uk/rpc/http/getTransaction.mdx rename to docs/rpc/http/getTransaction.mdx diff --git a/docs/uk/rpc/http/getTransactionCount.mdx b/docs/rpc/http/getTransactionCount.mdx similarity index 100% rename from docs/uk/rpc/http/getTransactionCount.mdx rename to docs/rpc/http/getTransactionCount.mdx diff --git a/docs/uk/rpc/http/getVersion.mdx b/docs/rpc/http/getVersion.mdx similarity index 100% rename from docs/uk/rpc/http/getVersion.mdx rename to docs/rpc/http/getVersion.mdx diff --git a/docs/uk/rpc/http/getVoteAccounts.mdx b/docs/rpc/http/getVoteAccounts.mdx similarity index 100% rename from docs/uk/rpc/http/getVoteAccounts.mdx rename to docs/rpc/http/getVoteAccounts.mdx diff --git a/docs/uk/rpc/http/index.mdx b/docs/rpc/http/index.mdx similarity index 100% rename from docs/uk/rpc/http/index.mdx rename to docs/rpc/http/index.mdx diff --git a/docs/uk/rpc/http/isBlockhashValid.mdx b/docs/rpc/http/isBlockhashValid.mdx similarity index 100% rename from docs/uk/rpc/http/isBlockhashValid.mdx rename to docs/rpc/http/isBlockhashValid.mdx diff --git a/docs/uk/rpc/http/minimumLedgerSlot.mdx b/docs/rpc/http/minimumLedgerSlot.mdx similarity index 100% rename from docs/uk/rpc/http/minimumLedgerSlot.mdx rename to docs/rpc/http/minimumLedgerSlot.mdx diff --git a/docs/uk/rpc/http/requestAirdrop.mdx b/docs/rpc/http/requestAirdrop.mdx similarity index 100% rename from docs/uk/rpc/http/requestAirdrop.mdx rename to docs/rpc/http/requestAirdrop.mdx diff --git a/docs/uk/rpc/http/sendTransaction.mdx b/docs/rpc/http/sendTransaction.mdx similarity index 100% rename from docs/uk/rpc/http/sendTransaction.mdx rename to docs/rpc/http/sendTransaction.mdx diff --git a/docs/uk/rpc/http/simulateTransaction.mdx b/docs/rpc/http/simulateTransaction.mdx similarity index 100% rename from docs/uk/rpc/http/simulateTransaction.mdx rename to docs/rpc/http/simulateTransaction.mdx diff --git a/docs/uk/rpc/index.mdx b/docs/rpc/index.mdx similarity index 100% rename from docs/uk/rpc/index.mdx rename to docs/rpc/index.mdx diff --git a/docs/uk/rpc/json-structures.mdx b/docs/rpc/json-structures.mdx similarity index 100% rename from docs/uk/rpc/json-structures.mdx rename to docs/rpc/json-structures.mdx diff --git a/docs/uk/rpc/websocket/accountSubscribe.mdx b/docs/rpc/websocket/accountSubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/accountSubscribe.mdx rename to docs/rpc/websocket/accountSubscribe.mdx diff --git a/docs/uk/rpc/websocket/accountUnsubscribe.mdx b/docs/rpc/websocket/accountUnsubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/accountUnsubscribe.mdx rename to docs/rpc/websocket/accountUnsubscribe.mdx diff --git a/docs/uk/rpc/websocket/blockSubscribe.mdx b/docs/rpc/websocket/blockSubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/blockSubscribe.mdx rename to docs/rpc/websocket/blockSubscribe.mdx diff --git a/docs/uk/rpc/websocket/blockUnsubscribe.mdx b/docs/rpc/websocket/blockUnsubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/blockUnsubscribe.mdx rename to docs/rpc/websocket/blockUnsubscribe.mdx diff --git a/docs/uk/rpc/websocket/index.mdx b/docs/rpc/websocket/index.mdx similarity index 100% rename from docs/uk/rpc/websocket/index.mdx rename to docs/rpc/websocket/index.mdx diff --git a/docs/uk/rpc/websocket/logsSubscribe.mdx b/docs/rpc/websocket/logsSubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/logsSubscribe.mdx rename to docs/rpc/websocket/logsSubscribe.mdx diff --git a/docs/uk/rpc/websocket/logsUnsubscribe.mdx b/docs/rpc/websocket/logsUnsubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/logsUnsubscribe.mdx rename to docs/rpc/websocket/logsUnsubscribe.mdx diff --git a/docs/uk/rpc/websocket/programSubscribe.mdx b/docs/rpc/websocket/programSubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/programSubscribe.mdx rename to docs/rpc/websocket/programSubscribe.mdx diff --git a/docs/uk/rpc/websocket/programUnsubscribe.mdx b/docs/rpc/websocket/programUnsubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/programUnsubscribe.mdx rename to docs/rpc/websocket/programUnsubscribe.mdx diff --git a/docs/uk/rpc/websocket/rootSubscribe.mdx b/docs/rpc/websocket/rootSubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/rootSubscribe.mdx rename to docs/rpc/websocket/rootSubscribe.mdx diff --git a/docs/uk/rpc/websocket/rootUnsubscribe.mdx b/docs/rpc/websocket/rootUnsubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/rootUnsubscribe.mdx rename to docs/rpc/websocket/rootUnsubscribe.mdx diff --git a/docs/uk/rpc/websocket/signatureSubscribe.mdx b/docs/rpc/websocket/signatureSubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/signatureSubscribe.mdx rename to docs/rpc/websocket/signatureSubscribe.mdx diff --git a/docs/uk/rpc/websocket/signatureUnsubscribe.mdx b/docs/rpc/websocket/signatureUnsubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/signatureUnsubscribe.mdx rename to docs/rpc/websocket/signatureUnsubscribe.mdx diff --git a/docs/uk/rpc/websocket/slotSubscribe.mdx b/docs/rpc/websocket/slotSubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/slotSubscribe.mdx rename to docs/rpc/websocket/slotSubscribe.mdx diff --git a/docs/uk/rpc/websocket/slotUnsubscribe.mdx b/docs/rpc/websocket/slotUnsubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/slotUnsubscribe.mdx rename to docs/rpc/websocket/slotUnsubscribe.mdx diff --git a/docs/uk/rpc/websocket/slotsUpdatesSubscribe.mdx b/docs/rpc/websocket/slotsUpdatesSubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/slotsUpdatesSubscribe.mdx rename to docs/rpc/websocket/slotsUpdatesSubscribe.mdx diff --git a/docs/uk/rpc/websocket/slotsUpdatesUnsubscribe.mdx b/docs/rpc/websocket/slotsUpdatesUnsubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/slotsUpdatesUnsubscribe.mdx rename to docs/rpc/websocket/slotsUpdatesUnsubscribe.mdx diff --git a/docs/uk/rpc/websocket/voteSubscribe.mdx b/docs/rpc/websocket/voteSubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/voteSubscribe.mdx rename to docs/rpc/websocket/voteSubscribe.mdx diff --git a/docs/uk/rpc/websocket/voteUnsubscribe.mdx b/docs/rpc/websocket/voteUnsubscribe.mdx similarity index 100% rename from docs/uk/rpc/websocket/voteUnsubscribe.mdx rename to docs/rpc/websocket/voteUnsubscribe.mdx diff --git a/docs/en/terminology.md b/docs/terminology.md similarity index 100% rename from docs/en/terminology.md rename to docs/terminology.md diff --git a/docs/uk/programs/anchor/client-typescript.md b/docs/uk/programs/anchor/client-typescript.md deleted file mode 100644 index f3d72118d..000000000 --- a/docs/uk/programs/anchor/client-typescript.md +++ /dev/null @@ -1,354 +0,0 @@ ---- -title: JS/TS Client -description: - Learn how to use Anchor's TypeScript client library to interact with Solana - program -sidebarLabel: JS/TS Client -sidebarSortOrder: 3 ---- - -Anchor provides a Typescript client library -([@coral-xyz/anchor](https://github.com/coral-xyz/anchor/tree/v0.30.1/ts/packages/anchor)) -that simplifies the process of interacting with Solana programs from the client -in JavaScript or TypeScript. - -## Client Program - -To use the client library, first create an instance of a -[`Program`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/index.ts#L58) -using the [IDL file](/docs/programs/anchor/idl) generated by Anchor. - -Creating an instance of the `Program` requires the program's IDL and an -[`AnchorProvider`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/provider.ts#L55). -An `AnchorProvider` is an abstraction that combines two things: - -- `Connection` - the connection to a [Solana cluster](/docs/core/clusters.md) - (i.e. localhost, devnet, mainnet) -- `Wallet` - (optional) a default wallet used to pay and sign transactions - - - - - -When integrating with a frontend using the -[wallet adapter](https://solana.com/developers/guides/wallets/add-solana-wallet-adapter-to-nextjs), -you'll need to set up the `AnchorProvider` and `Program`. - -```ts {9-10, 12-14} -import { Program, AnchorProvider, setProvider } from "@coral-xyz/anchor"; -import { useAnchorWallet, useConnection } from "@solana/wallet-adapter-react"; -import type { HelloAnchor } from "./idlType"; -import idl from "./idl.json"; - -const { connection } = useConnection(); -const wallet = useAnchorWallet(); - -const provider = new AnchorProvider(connection, wallet, {}); -setProvider(provider); - -export const program = new Program(idl as HelloAnchor, { - connection, -}); -``` - -In the code snippet above: - -- `idl.json` is the IDL file generated by Anchor, found at - `/target/idl/.json` in an Anchor project. -- `idlType.ts` is the IDL type (for use with TS), found at - `/target/types/.ts` in an Anchor project. - -Alternatively, you can create an instance of the `Program` using only the IDL -and the `Connection` to a Solana cluster. This means there is no default -`Wallet`, but allows you to use the `Program` to fetch accounts or build -instructions without a connected wallet. - -```ts {8-10} -import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js"; -import { Program } from "@coral-xyz/anchor"; -import type { HelloAnchor } from "./idlType"; -import idl from "./idl.json"; - -const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); - -export const program = new Program(idl as HelloAnchor, { - connection, -}); -``` - - - - -Anchor automatically sets up a `Program` instance in the default test file of -new projects. However, this setup differs from how you'd initialize a `Program` -outside the Anchor workspace, such as in React or Node.js applications. - -```typescript -import * as anchor from "@coral-xyz/anchor"; -import { Program } from "@coral-xyz/anchor"; -import { HelloAnchor } from "../target/types/hello_anchor"; - -describe("hello_anchor", () => { - // Configure the client to use the local cluster. - anchor.setProvider(anchor.AnchorProvider.env()); - - const program = anchor.workspace.HelloAnchor as Program; - - it("Is initialized!", async () => { - // Add your test here. - const tx = await program.methods.initialize().rpc(); - console.log("Your transaction signature", tx); - }); -}); -``` - - - - -## Invoke Instructions - -Once the `Program` is set up using a program IDL, you can use the Anchor -[`MethodsBuilder`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L155) -to: - -- Build individual instructions -- Build transactions -- Build and send transactions - -The basic format looks like the following: - - - - - -`program.methods` - This is the builder API for creating instruction calls from -the program's IDL - -```ts /methods/ {1} -await program.methods - .instructionName(instructionData) - .accounts({}) - .signers([]) - .rpc(); -``` - - - - -Following `.methods`, specify the name of an instruction from the program IDL, -passing in any required arguments as comma-separated values. - -```ts /instructionName/ /instructionData1/ /instructionData2/ {2} -await program.methods - .instructionName(instructionData1, instructionData2) - .accounts({}) - .signers([]) - .rpc(); -``` - - - - -`.accounts` - Pass in the address of the accounts required by the instruction as -specified in the IDL - -```ts /accounts/ {3} -await program.methods - .instructionName(instructionData) - .accounts({}) - .signers([]) - .rpc(); -``` - -Note that certain account addresses don't need to be explicitly provided, as the -Anchor client can automatically resolve them. These typically include: - -- Common accounts (ex. the System Program) -- Accounts where the address is a PDA (Program Derived Address) - - - - -`.signers` - Optionally pass in an array of keypairs required as additional -signers by the instruction. This is commonly used when creating new accounts -where the account address is the public key of a newly generated keypair. - -```ts /signers/ {4} -await program.methods - .instructionName(instructionData) - .accounts({}) - .signers([]) - .rpc(); -``` - -Note that `.signers` should only be used when also using `.rpc()`. When using -`.transaction()` or `.instruction()`, signers should be added to the transaction -before sending. - - - - -Anchor provides multiple methods for building program instructions: - - - - - -The -[`rpc()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L283) -method -[sends a signed transaction](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/rpc.ts#L29) -with the specified instruction and returns a `TransactionSignature`. - -When using `.rpc`, the `Wallet` from the `Provider` is automatically included as -a signer. - -```ts {13} -// Generate keypair for the new account -const newAccountKp = new Keypair(); - -const data = new BN(42); -const transactionSignature = await program.methods - .initialize(data) - .accounts({ - newAccount: newAccountKp.publicKey, - signer: wallet.publicKey, - systemProgram: SystemProgram.programId, - }) - .signers([newAccountKp]) - .rpc(); -``` - - - - -The -[`transaction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L382) -method -[builds a `Transaction`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/transaction.ts#L18-L26) -with the specified instruction without sending the transaction. - -```ts {12} /transaction()/1,2,4 -// Generate keypair for the new account -const newAccountKp = new Keypair(); - -const data = new BN(42); -const transaction = await program.methods - .initialize(data) - .accounts({ - newAccount: newAccountKp.publicKey, - signer: wallet.publicKey, - systemProgram: SystemProgram.programId, - }) - .transaction(); - -const transactionSignature = await connection.sendTransaction(transaction, [ - wallet.payer, - newAccountKp, -]); -``` - - - - -The -[`instruction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L348) -method -[builds a `TransactionInstruction`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/instruction.ts#L57-L61) -using the specified instruction. This is useful if you want to manually add the -instruction to a transaction and combine it with other instructions. - -```ts {12} /instruction()/ -// Generate keypair for the new account -const newAccountKp = new Keypair(); - -const data = new BN(42); -const instruction = await program.methods - .initialize(data) - .accounts({ - newAccount: newAccountKp.publicKey, - signer: wallet.publicKey, - systemProgram: SystemProgram.programId, - }) - .instruction(); - -const transaction = new Transaction().add(instruction); - -const transactionSignature = await connection.sendTransaction(transaction, [ - wallet.payer, - newAccountKp, -]); -``` - - - - -## Fetch Accounts - -The `Program` client simplifies the process of fetching and deserializing -accounts created by your Anchor program. - -Use `program.account` followed by the name of the account type defined in the -IDL. Anchor provides multiple methods for fetching accounts. - - - - - -Use -[`all()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L251) -to fetch all existing accounts for a specific account type. - -```ts /all/ -const accounts = await program.account.newAccount.all(); -``` - - - - -Use `memcmp` (memory compare) to filter for account data that matches a specific -value at a specific offset. Using `memcmp` requires you to understand the byte -layout of the data field for the account type you are fetching. - -When calculating the offset, remember that the first 8 bytes in accounts created -by an Anchor program are reserved for the account discriminator. - -```ts /memcmp/ -const accounts = await program.account.newAccount.all([ - { - memcmp: { - offset: 8, - bytes: "", - }, - }, -]); -``` - - - - -Use -[`fetch()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L165) -to fetch the account data for a single account - -```ts /fetch/ -const account = await program.account.newAccount.fetch(ACCOUNT_ADDRESS); -``` - - - - -Use -[`fetchMultiple()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L200) -to fetch the account data for multiple accounts by passing in an array of -account addresses - -```ts /fetchMultiple/ -const accounts = await program.account.newAccount.fetchMultiple([ - ACCOUNT_ADDRESS_ONE, - ACCOUNT_ADDRESS_TWO, -]); -``` - - - diff --git a/docs/uk/programs/anchor/cpi.md b/docs/uk/programs/anchor/cpi.md deleted file mode 100644 index bb1d0d583..000000000 --- a/docs/uk/programs/anchor/cpi.md +++ /dev/null @@ -1,551 +0,0 @@ ---- -title: CPIs with Anchor -description: - Learn how to implement Cross Program Invocations (CPIs) in Anchor programs, - enabling interaction between different programs on Solana -sidebarLabel: CPIs with Anchor -sidebarSortOrder: 5 ---- - -[Cross Program Invocations (CPI)](/docs/core/cpi.md) refer to the process of one -program invoking instructions of another program, which enables the -composability of programs on Solana. - -This section will cover the basics of implementing CPIs in an Anchor program, -using a simple SOL transfer instruction as a practical example. Once you -understand the basics of how to implement a CPI, you can apply the same concepts -for any instruction. - -## Cross Program Invocations - -Let's examine a program that implements a CPI to the System Program's transfer -instruction. Here is the example program on -[Solana Playground](https://beta.solpg.io/66df2751cffcf4b13384d35a). - -The `lib.rs` file includes a single `sol_transfer` instruction. When the -`sol_transfer` instruction on the Anchor program is invoked, the program -internally invokes the transfer instruction of the System Program. - -```rs filename="lib.rs" /sol_transfer/ /transfer/ {23} -use anchor_lang::prelude::*; -use anchor_lang::system_program::{transfer, Transfer}; - -declare_id!("9AvUNHjxscdkiKQ8tUn12QCMXtcnbR9BVGq3ULNzFMRi"); - -#[program] -pub mod cpi { - use super::*; - - pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { - let from_pubkey = ctx.accounts.sender.to_account_info(); - let to_pubkey = ctx.accounts.recipient.to_account_info(); - let program_id = ctx.accounts.system_program.to_account_info(); - - let cpi_context = CpiContext::new( - program_id, - Transfer { - from: from_pubkey, - to: to_pubkey, - }, - ); - - transfer(cpi_context, amount)?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct SolTransfer<'info> { - #[account(mut)] - sender: Signer<'info>, - #[account(mut)] - recipient: SystemAccount<'info>, - system_program: Program<'info, System>, -} -``` - -The `cpi.test.ts` file shows how to invoke the Anchor program's `sol_transfer` -instruction and logs a link to the transaction details on SolanaFM. - -```ts filename="cpi.test.ts" -it("SOL Transfer Anchor", async () => { - const transactionSignature = await program.methods - .solTransfer(new BN(transferAmount)) - .accounts({ - sender: sender.publicKey, - recipient: recipient.publicKey, - }) - .rpc(); - - console.log( - `\nTransaction Signature:` + - `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, - ); -}); -``` - -You can build, deploy, and run the test for this example on Playground to view -the transaction details on the [SolanaFM explorer](https://solana.fm/). - -The transaction details will show that the Anchor program was first invoked -(instruction 1), which then invokes the System Program (instruction 1.1), -resulting in a successful SOL transfer. - -![Transaction Details](/assets/docs/core/cpi/transaction-details.png) - -### Example 1 Explanation - -Implementing a CPI follows the same pattern as building an instruction to add to -a transaction. When implementing a CPI, we must specify the program ID, -accounts, and instruction data for the instruction being called. - -The System Program's transfer instruction requires two accounts: - -- `from`: The account sending SOL. -- `to`: The account receiving SOL. - -In the example program, the `SolTransfer` struct specifies the accounts required -by the transfer instruction. The System Program is also included because the CPI -invokes the System Program. - -```rust /sender/ /recipient/ /system_program/ -#[derive(Accounts)] -pub struct SolTransfer<'info> { - #[account(mut)] - sender: Signer<'info>, // from account - #[account(mut)] - recipient: SystemAccount<'info>, // to account - system_program: Program<'info, System>, // program ID -} -``` - -The following tabs present three approaches to implementing Cross Program -Invocations (CPIs), each at a different level of abstraction. All examples are -functionally equivalent. The main purpose is to illustrate the implementation -details of the CPI. - - - - - -The `sol_transfer` instruction included in the example code shows a typical -approach for constructing CPIs using the Anchor framework. - -This approach involves creating a -[`CpiContext`](https://docs.rs/anchor-lang/latest/anchor_lang/context/struct.CpiContext.html), -which includes the `program_id` and accounts required for the instruction being -called, followed by a helper function (`transfer`) to invoke a specific -instruction. - -```rust -use anchor_lang::system_program::{transfer, Transfer}; -``` - -```rust /cpi_context/ {14} -pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { - let from_pubkey = ctx.accounts.sender.to_account_info(); - let to_pubkey = ctx.accounts.recipient.to_account_info(); - let program_id = ctx.accounts.system_program.to_account_info(); - - let cpi_context = CpiContext::new( - program_id, - Transfer { - from: from_pubkey, - to: to_pubkey, - }, - ); - - transfer(cpi_context, amount)?; - Ok(()) -} -``` - -The `cpi_context` variable specifies the program ID (System Program) and -accounts (sender and recipient) required by the transfer instruction. - -```rust /program_id/ /from_pubkey/ /to_pubkey/ -let cpi_context = CpiContext::new( - program_id, - Transfer { - from: from_pubkey, - to: to_pubkey, - }, -); -``` - -The `cpi_context` and `amount` are then passed into the `transfer` function to -execute the CPI invoking the transfer instruction of the System Program. - -```rust -transfer(cpi_context, amount)?; -``` - - - - -This example shows a different approach to implementing a CPI using the `invoke` -function and -[`system_instruction::transfer`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L881), -which is generally seen in native Rust programs. - -Under the hood, the previous example is an abstraction of this implementation. -The example below is functionally equivalent to the previous example. - -```rust -use anchor_lang::solana_program::{program::invoke, system_instruction}; -``` - -```rust /instruction/1,3 {9} -pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { - let from_pubkey = ctx.accounts.sender.to_account_info(); - let to_pubkey = ctx.accounts.recipient.to_account_info(); - let program_id = ctx.accounts.system_program.to_account_info(); - - let instruction = - &system_instruction::transfer(&from_pubkey.key(), &to_pubkey.key(), amount); - - invoke(instruction, &[from_pubkey, to_pubkey, program_id])?; - Ok(()) -} -``` - - - - -You can also manually build the instruction to pass into the `invoke()` -function. This is useful when there is no crate available to help build the -instruction you want to invoke. This approach requires you to specify the -`AccountMeta`s for the instruction and correctly create the instruction data -buffer. - -The `sol_transfer` instruction below is a manual implementation of a CPI to the -System Program's transfer instruction. - -```rust /instruction/10,13 {28} -pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { - let from_pubkey = ctx.accounts.sender.to_account_info(); - let to_pubkey = ctx.accounts.recipient.to_account_info(); - let program_id = ctx.accounts.system_program.to_account_info(); - - // Prepare instruction AccountMetas - let account_metas = vec![ - AccountMeta::new(from_pubkey.key(), true), - AccountMeta::new(to_pubkey.key(), false), - ]; - - // SOL transfer instruction discriminator - let instruction_discriminator: u32 = 2; - - // Prepare instruction data - let mut instruction_data = Vec::with_capacity(4 + 8); - instruction_data.extend_from_slice(&instruction_discriminator.to_le_bytes()); - instruction_data.extend_from_slice(&amount.to_le_bytes()); - - // Create instruction - let instruction = Instruction { - program_id: program_id.key(), - accounts: account_metas, - data: instruction_data, - }; - - // Invoke instruction - invoke(&instruction, &[from_pubkey, to_pubkey, program_id])?; - Ok(()) -} -``` - -The `sol_transfer` instruction above replicates this -[example](/docs/core/transactions.md#manual-sol-transfer) of manually building a -SOL transfer instruction. It follows the same pattern as building an -[instruction](/docs/core/transactions.md#instruction) to add to a transaction. - -When building an instruction in Rust, use the following syntax to specify the -`AccountMeta` for each account: - -```rust -AccountMeta::new(account1_pubkey, true), // writable, signer -AccountMeta::new(account2_pubkey, false), // writable, not signer -AccountMeta::new_readonly(account3_pubkey, false), // not writable, not signer -AccountMeta::new_readonly(account4_pubkey, true), // writable, signer -``` - - - - -Here is a reference program on -[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi) -which includes all 3 examples. - -## Cross Program Invocations with PDA Signers - -Next, let's examine a program that implements a CPI to the System Program's -transfer instruction where the sender is a Program Derived Address (PDA) that -must be "signed" for by the program. Here is the example program on -[Solana Playground](https://beta.solpg.io/66df2bd2cffcf4b13384d35b). - -The `lib.rs` file includes the following program with a single `sol_transfer` -instruction. - -```rust filename="lib.rs" -use anchor_lang::prelude::*; -use anchor_lang::system_program::{transfer, Transfer}; - -declare_id!("3455LkCS85a4aYmSeNbRrJsduNQfYRY82A7eCD3yQfyR"); - -#[program] -pub mod cpi { - use super::*; - - pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { - let from_pubkey = ctx.accounts.pda_account.to_account_info(); - let to_pubkey = ctx.accounts.recipient.to_account_info(); - let program_id = ctx.accounts.system_program.to_account_info(); - - let seed = to_pubkey.key(); - let bump_seed = ctx.bumps.pda_account; - let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]]; - - let cpi_context = CpiContext::new( - program_id, - Transfer { - from: from_pubkey, - to: to_pubkey, - }, - ) - .with_signer(signer_seeds); - - transfer(cpi_context, amount)?; - Ok(()) - } -} - -#[derive(Accounts)] -pub struct SolTransfer<'info> { - #[account( - mut, - seeds = [b"pda", recipient.key().as_ref()], - bump, - )] - pda_account: SystemAccount<'info>, - #[account(mut)] - recipient: SystemAccount<'info>, - system_program: Program<'info, System>, -} -``` - -The `cpi.test.ts` file shows how to invoke the Anchor program's `sol_transfer` -instruction and logs a link to the transaction details on SolanaFM. - -It shows how to derive the PDA using the seeds specified in the program: - -```ts /pda/ /wallet.publicKey/ -const [PDA] = PublicKey.findProgramAddressSync( - [Buffer.from("pda"), wallet.publicKey.toBuffer()], - program.programId, -); -``` - -The first step in this example is to fund the PDA account with a basic SOL -transfer from the Playground wallet. - -```ts filename="cpi.test.ts" -it("Fund PDA with SOL", async () => { - const transferInstruction = SystemProgram.transfer({ - fromPubkey: wallet.publicKey, - toPubkey: PDA, - lamports: transferAmount, - }); - - const transaction = new Transaction().add(transferInstruction); - - const transactionSignature = await sendAndConfirmTransaction( - connection, - transaction, - [wallet.payer], // signer - ); - - console.log( - `\nTransaction Signature:` + - `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, - ); -}); -``` - -Once the PDA is funded with SOL, invoke the `sol_transfer` instruction. This -instruction transfers SOL from the PDA account back to the `wallet` account via -a CPI to the System Program, which is "signed" for by the program. - -```ts -it("SOL Transfer with PDA signer", async () => { - const transactionSignature = await program.methods - .solTransfer(new BN(transferAmount)) - .accounts({ - pdaAccount: PDA, - recipient: wallet.publicKey, - }) - .rpc(); - - console.log( - `\nTransaction Signature: https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`, - ); -}); -``` - -You can build, deploy, and run the test to view the transaction details on the -[SolanaFM explorer](https://solana.fm/). - -The transaction details will show that the custom program was first invoked -(instruction 1), which then invokes the System Program (instruction 1.1), -resulting in a successful SOL transfer. - -![Transaction Details](/assets/docs/core/cpi/transaction-details-pda.png) - -### Example 2 Explanation - -In the example code, the `SolTransfer` struct specifies the accounts required by -the transfer instruction. - -The sender is a PDA that the program must sign for. The `seeds` to derive the -address for the `pda_account` include the hardcoded string "pda" and the address -of the `recipient` account. This means the address for the `pda_account` is -unique for each `recipient`. - -```rust /pda_account/ /recipient/2 /system_program/ -#[derive(Accounts)] -pub struct SolTransfer<'info> { - #[account( - mut, - seeds = [b"pda", recipient.key().as_ref()], - bump, - )] - pda_account: SystemAccount<'info>, - #[account(mut)] - recipient: SystemAccount<'info>, - system_program: Program<'info, System>, -} -``` - -The Javascript equivalent to derive the PDA is included in the test file. - -```ts /pda/ /wallet.publicKey/ -const [PDA] = PublicKey.findProgramAddressSync( - [Buffer.from("pda"), wallet.publicKey.toBuffer()], - program.programId, -); -``` - -The following tabs present two approaches to implementing Cross Program -Invocations (CPIs), each at a different level of abstraction. Both examples are -functionally equivalent. The main purpose is to illustrate the implementation -details of the CPI. - - - - - -The `sol_transfer` instruction included in the example code shows a typical -approach for constructing CPIs using the Anchor framework. - -This approach involves creating a -[`CpiContext`](https://docs.rs/anchor-lang/latest/anchor_lang/context/struct.CpiContext.html), -which includes the `program_id` and accounts required for the instruction being -called, followed by a helper function (`transfer`) to invoke a specific -instruction. - -```rust /cpi_context/ {19} -pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { - let from_pubkey = ctx.accounts.pda_account.to_account_info(); - let to_pubkey = ctx.accounts.recipient.to_account_info(); - let program_id = ctx.accounts.system_program.to_account_info(); - - let seed = to_pubkey.key(); - let bump_seed = ctx.bumps.pda_account; - let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]]; - - let cpi_context = CpiContext::new( - program_id, - Transfer { - from: from_pubkey, - to: to_pubkey, - }, - ) - .with_signer(signer_seeds); - - transfer(cpi_context, amount)?; - Ok(()) -} -``` - -When signing with PDAs, the seeds and bump seed are included in the -`cpi_context` as `signer_seeds` using `with_signer()`. The bump seed for a PDA -can be accessed using `ctx.bumps` followed by the name of the PDA account. - -```rust /signer_seeds/ /bump_seed/ {3} -let seed = to_pubkey.key(); -let bump_seed = ctx.bumps.pda_account; -let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]]; - -let cpi_context = CpiContext::new( - program_id, - Transfer { - from: from_pubkey, - to: to_pubkey, - }, -) -.with_signer(signer_seeds); -``` - -The `cpi_context` and `amount` are then passed into the `transfer` function to -execute the CPI. - -```rust -transfer(cpi_context, amount)?; -``` - -When the CPI is processed, the Solana runtime will validate that the provided -seeds and caller program ID derive a valid PDA. The PDA is then added as a -signer on the invocation. This mechanism allows for programs to sign for PDAs -that are derived from their program ID. - - - - -Under the hood, the previous example is a wrapper around the `invoke_signed()` -function which uses -[`system_instruction::transfer`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L881) -to build the instruction. - -This example shows how to use the `invoke_signed()` function to make a CPI -signed for by a PDA. - -```rust -use anchor_lang::solana_program::{program::invoke_signed, system_instruction}; -``` - -```rust /instruction/1,3 {13} -pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { - let from_pubkey = ctx.accounts.pda_account.to_account_info(); - let to_pubkey = ctx.accounts.recipient.to_account_info(); - let program_id = ctx.accounts.system_program.to_account_info(); - - let seed = to_pubkey.key(); - let bump_seed = ctx.bumps.pda_account; - let signer_seeds: &[&[&[u8]]] = &[&[b"pda", seed.as_ref(), &[bump_seed]]]; - - let instruction = - &system_instruction::transfer(&from_pubkey.key(), &to_pubkey.key(), amount); - - invoke_signed(instruction, &[from_pubkey, to_pubkey, program_id], signer_seeds)?; - Ok(()) -} -``` - -This implementation is functionally equivalent to the previous example. The -`signer_seeds` are passed into the `invoke_signed` function. - - - - -Here is a reference program on -[Solana Playground](https://beta.solpg.io/github.com/ZYJLiu/doc-examples/tree/main/cpi-pda) -which includes both examples. diff --git a/docs/uk/programs/anchor/idl.md b/docs/uk/programs/anchor/idl.md deleted file mode 100644 index 79e42c8f7..000000000 --- a/docs/uk/programs/anchor/idl.md +++ /dev/null @@ -1,516 +0,0 @@ ---- -title: IDL File -description: - Learn about the Interface Definition Language (IDL) file in Anchor, its - purpose, benefits, and how it simplifies program-client interactions -sidebarLabel: IDL File -sidebarSortOrder: 2 ---- - -An Interface Definition Language (IDL) file provides a standardized JSON file -describing the program's instructions and accounts. This file simplifies the -process of integrating your on-chain program with client applications. - -Key Benefits of the IDL: - -- Standardization: Provides a consistent format for describing the program's - instructions and accounts -- Client Generation: Used to generate client code to interact with the program - -The `anchor build` command generates an IDL file located at -`/target/idl/.json`. - -The code snippets below highlights how the program, IDL, and client relate to -each other. - -## Program Instructions - -The `instructions` array in the IDL corresponds directly to the instructions -defined in your program. It specifies the required accounts and parameters for -each instruction. - - - - - -The program below includes an `initialize` instruction, specifying the accounts -and parameters it requires. - -```rust {8-12, 15-22} -use anchor_lang::prelude::*; - -declare_id!("BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd"); - -#[program] -mod hello_anchor { - use super::*; - pub fn initialize(ctx: Context, data: u64) -> Result<()> { - ctx.accounts.new_account.data = data; - msg!("Changed data to: {}!", data); - Ok(()) - } -} - -#[derive(Accounts)] -pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, -} - -#[account] -pub struct NewAccount { - data: u64, -} -``` - - - - -The generated IDL file includes the instruction in a standardized JSON format, -including its name, accounts, arguments, and discriminator. - -```json filename="JSON" {11-12, 14-27, 30-33} -{ - "address": "BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd", - "metadata": { - "name": "hello_anchor", - "version": "0.1.0", - "spec": "0.1.0", - "description": "Created with Anchor" - }, - "instructions": [ - { - "name": "initialize", - "discriminator": [175, 175, 109, 31, 13, 152, 155, 237], - "accounts": [ - { - "name": "new_account", - "writable": true, - "signer": true - }, - { - "name": "signer", - "writable": true, - "signer": true - }, - { - "name": "system_program", - "address": "11111111111111111111111111111111" - } - ], - "args": [ - { - "name": "data", - "type": "u64" - } - ] - } - ], - "accounts": [ - { - "name": "NewAccount", - "discriminator": [176, 95, 4, 118, 91, 177, 125, 232] - } - ], - "types": [ - { - "name": "NewAccount", - "type": { - "kind": "struct", - "fields": [ - { - "name": "data", - "type": "u64" - } - ] - } - } - ] -} -``` - - - - -The IDL file is then used to generate a client for interacting with the program, -simplifying the process of invoking the program instruction. - -```ts {19-26} -import * as anchor from "@coral-xyz/anchor"; -import { Program, BN } from "@coral-xyz/anchor"; -import { HelloAnchor } from "../target/types/hello_anchor"; -import { Keypair } from "@solana/web3.js"; -import assert from "assert"; - -describe("hello_anchor", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const wallet = provider.wallet as anchor.Wallet; - const program = anchor.workspace.HelloAnchor as Program; - - it("initialize", async () => { - // Generate keypair for the new account - const newAccountKp = new Keypair(); - - // Send transaction - const data = new BN(42); - const transactionSignature = await program.methods - .initialize(data) - .accounts({ - newAccount: newAccountKp.publicKey, - signer: wallet.publicKey, - }) - .signers([newAccountKp]) - .rpc(); - - // Fetch the created account - const newAccount = await program.account.newAccount.fetch( - newAccountKp.publicKey, - ); - - console.log("Transaction signature: ", transactionSignature); - console.log("On-chain data is:", newAccount.data.toString()); - assert(data.eq(newAccount.data)); - }); -}); -``` - - - - -## Program Accounts - -The `accounts` array in the IDL corresponds to the structs in a program -annotated with the `#[account]` macro. These structs define the data stored in -accounts created by the program. - - - - - -The program below defines a `NewAccount` struct with a single `data` field of -type `u64`. - -```rust {24-27} -use anchor_lang::prelude::*; - -declare_id!("BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd"); - -#[program] -mod hello_anchor { - use super::*; - pub fn initialize(ctx: Context, data: u64) -> Result<()> { - ctx.accounts.new_account.data = data; - msg!("Changed data to: {}!", data); - Ok(()) - } -} - -#[derive(Accounts)] -pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, -} - -#[account] -pub struct NewAccount { - data: u64, -} -``` - - - - -The generated IDL file includes the account in a standardized JSON format, -including its name, discriminator, and fields. - -```json filename="JSON" {39-40, 45-54} -{ - "address": "BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd", - "metadata": { - "name": "hello_anchor", - "version": "0.1.0", - "spec": "0.1.0", - "description": "Created with Anchor" - }, - "instructions": [ - { - "name": "initialize", - "discriminator": [175, 175, 109, 31, 13, 152, 155, 237], - "accounts": [ - { - "name": "new_account", - "writable": true, - "signer": true - }, - { - "name": "signer", - "writable": true, - "signer": true - }, - { - "name": "system_program", - "address": "11111111111111111111111111111111" - } - ], - "args": [ - { - "name": "data", - "type": "u64" - } - ] - } - ], - "accounts": [ - { - "name": "NewAccount", - "discriminator": [176, 95, 4, 118, 91, 177, 125, 232] - } - ], - "types": [ - { - "name": "NewAccount", - "type": { - "kind": "struct", - "fields": [ - { - "name": "data", - "type": "u64" - } - ] - } - } - ] -} -``` - - - - -The IDL file is then used to generate a client for interacting with the program, -simplifying the process of fetching and deserializing account data. - -```ts {29-31} -import * as anchor from "@coral-xyz/anchor"; -import { Program, BN } from "@coral-xyz/anchor"; -import { HelloAnchor } from "../target/types/hello_anchor"; -import { Keypair } from "@solana/web3.js"; -import assert from "assert"; - -describe("hello_anchor", () => { - const provider = anchor.AnchorProvider.env(); - anchor.setProvider(provider); - const wallet = provider.wallet as anchor.Wallet; - const program = anchor.workspace.HelloAnchor as Program; - - it("initialize", async () => { - // Generate keypair for the new account - const newAccountKp = new Keypair(); - - // Send transaction - const data = new BN(42); - const transactionSignature = await program.methods - .initialize(data) - .accounts({ - newAccount: newAccountKp.publicKey, - signer: wallet.publicKey, - }) - .signers([newAccountKp]) - .rpc(); - - // Fetch the created account - const newAccount = await program.account.newAccount.fetch( - newAccountKp.publicKey, - ); - - console.log("Transaction signature: ", transactionSignature); - console.log("On-chain data is:", newAccount.data.toString()); - assert(data.eq(newAccount.data)); - }); -}); -``` - - - - -## Discriminators - -Anchor assigns a unique 8 byte discriminator to each instruction and account -type in a program. These discriminators serve as identifiers to distinguish -between different instructions or account types. - -The discriminator is generated using the first 8 bytes of the Sha256 hash of a -prefix combined with the instruction or account name. As of Anchor v0.30, these -discriminators are included in the IDL file. - -Note that when working with Anchor, you typically won't need to interact -directly with these discriminators. This section is primarily to provide context -on how the discriminator is generated and used. - - - - - -The instruction discriminator is used by the program to determine which specific -instruction to execute when called. - -When an Anchor program instruction is invoked, the discriminator is included as -the first 8 bytes of the instruction data. This is done automatically by the -Anchor client. - -```json filename="IDL" {4} - "instructions": [ - { - "name": "initialize", - "discriminator": [175, 175, 109, 31, 13, 152, 155, 237], - ... - } - ] -``` - -The discriminator for an instruction is the first 8 bytes of the Sha256 hash of -the prefix `global` plus the instruction name. - -For example: - -``` -sha256("global:initialize") -``` - -Hexadecimal output: - -``` -af af 6d 1f 0d 98 9b ed d4 6a 95 07 32 81 ad c2 1b b5 e0 e1 d7 73 b2 fb bd 7a b5 04 cd d4 aa 30 -``` - -The first 8 bytes are used as the discriminator for the instruction. - -``` -af = 175 -af = 175 -6d = 109 -1f = 31 -0d = 13 -98 = 152 -9b = 155 -ed = 237 -``` - -You can find the implementation of the discriminator generation in the Anchor -codebase -[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/codegen/program/common.rs#L5-L19), -which is used -[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/codegen/program/instruction.rs#L27). - - - - -The account discriminator is used to identify the specific account type when -deserializing on-chain data and is set when the account is created. - -```json filename="IDL" {4} - "accounts": [ - { - "name": "NewAccount", - "discriminator": [176, 95, 4, 118, 91, 177, 125, 232] - } - ] -``` - -The discriminator for an account is the first 8 bytes of the Sha256 hash of the -prefix `account` plus the account name. - -For example: - -``` -sha256("account:NewAccount") -``` - -Hexadecimal output: - -``` -b0 5f 04 76 5b b1 7d e8 a1 93 57 2a d3 5e b1 ae e5 f0 69 e2 09 7e 5c d2 64 56 55 2a cb 4a e9 57 -``` - -The first 8 bytes are used as the discriminator for the account. - -``` -b0 = 176 -5f = 95 -04 = 4 -76 = 118 -5b = 91 -b1 = 177 -7d = 125 -e8 = 232 -``` - -You can find the implementation of the discriminator generation in the Anchor -codebase -[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L101-L117). - -Note that different programs using identical account names will generate the -same discriminator. When deserializing account data, Anchor programs will also -check an account is owned by the expected program for a specified account type. - - - - -The event discriminator is used to identify the specific event type when -deserializing on-chain data on event emission. - -```json filename="IDL" {4} - "events": [ - { - "name": "NewEvent", - "discriminator": [113, 21, 185, 70, 164, 99, 232, 201] - } - ] -``` - -The discriminator for an event is the first 8 bytes of the Sha256 hash of the -prefix `event` plus the event name. - -For example: - -``` -sha256("event:NewEvent") -``` - -Hexadecimal output: - -``` -71 15 b9 46 a4 63 e8 c9 2a 3c 4d 83 87 16 cd 9b 66 28 cb e2 cb 7c 5d 70 59 f3 42 2b dc 35 03 53 -``` - -The first 8 bytes are used as the discriminator for the account. - -Hex to decimal gives us: - -``` -71 = 113 -15 = 21 -b9 = 185 -46 = 70 -a4 = 164 -63 = 99 -e8 = 232 -c9 = 201 -``` - -You can find the implementation of the discriminator generation in the Anchor -codebase -[here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/event/src/lib.rs#L23-L27). - -Note that different programs using identical event names will generate the same -discriminator. When deserializing event data, Anchor programs will also check an -event is owned by the expected program for a specified event type. - - - diff --git a/docs/uk/programs/anchor/index.md b/docs/uk/programs/anchor/index.md deleted file mode 100644 index 8b998aed3..000000000 --- a/docs/uk/programs/anchor/index.md +++ /dev/null @@ -1,384 +0,0 @@ ---- -title: Getting Started with Anchor -description: - Learn how to build Solana programs using the Anchor framework. This - comprehensive guide covers creating, building, testing, and deploying Solana - smart contracts with Anchor. -sidebarLabel: Anchor Framework -sidebarSortOrder: 0 -altRoutes: - - /docs/programs/debugging - - /docs/programs/lang-c - - /docs/programs/overview ---- - -The Anchor framework is a tool that simplifies the process of building Solana -programs. Whether you're new to blockchain development or an experienced -programmer, Anchor simplifies the process of writing, testing, and deploying -Solana programs. - -In this section, we'll walk through: - -- Creating a new Anchor project -- Building and testing your program -- Deploying to Solana clusters -- Understanding the project file structure - -## Prerequisites - -For detailed installation instructions, visit the -[installation](/docs/intro/installation) page. - -Before you begin, ensure you have the following installed: - -- Rust: The programming language for building Solana programs. -- Solana CLI: Command-line tool for Solana development. -- Anchor CLI: Command-line tool for the Anchor framework. - -To verify Anchor CLI installation, open your terminal and run: - -```shell filename="Terminal" -anchor --version -``` - -Expected output: - -```shell filename="Terminal" -anchor-cli 0.30.1 -``` - -## Getting Started - -This section covers the basic steps to create, build, and test your first local -Anchor program. - - - -### Create a new Project - -To start a new project, use the `anchor init` command followed by your project's -name. This command creates a new directory with the specified name and sets up a -default program and test file. - -```shell filename="Terminal" -anchor init my-project -``` - -Navigate to the new project directory and open it in your code editor. - -```shell filename="Terminal" copy -cd my-project -``` - -The default Anchor program is located at `programs/my-project/src/lib.rs`. - - - - -The value in the `declare_id!` macro is the program ID, a unique identifier for -your program. - -By default, it is the public key of the keypair generated in -`/target/deploy/my_project-keypair.json`. - -```rs filename="lib.rs" -use anchor_lang::prelude::*; - -declare_id!("3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg"); - -#[program] -pub mod my_project { - use super::*; - - pub fn initialize(ctx: Context) -> Result<()> { - msg!("Greetings from: {:?}", ctx.program_id); - Ok(()) - } -} - -#[derive(Accounts)] -pub struct Initialize {} -``` - - - - -The default Typescript test file is located at `/tests/my-project.ts`. - - - - -This file demonstrates how to invoke the default program's `initialize` -instruction in Typescript. - -```ts filename="my-project.ts" -import * as anchor from "@coral-xyz/anchor"; -import { Program } from "@coral-xyz/anchor"; -import { MyProject } from "../target/types/my_project"; - -describe("my-project", () => { - // Configure the client to use the local cluster. - anchor.setProvider(anchor.AnchorProvider.env()); - - const program = anchor.workspace.MyProject as Program; - - it("Is initialized!", async () => { - // Add your test here. - const tx = await program.methods.initialize().rpc(); - console.log("Your transaction signature", tx); - }); -}); -``` - - - - -If you prefer Rust for testing, initialize your project with the -`--test-template rust` flag. - -```shell -anchor init --test-template rust my-project -``` - -The Rust test file will be at `/tests/src/test_initialize.rs`. - - - - -```rust filename="test_initialize.rs" -use std::str::FromStr; - -use anchor_client::{ - solana_sdk::{ - commitment_config::CommitmentConfig, pubkey::Pubkey, signature::read_keypair_file, - }, - Client, Cluster, -}; - -#[test] -fn test_initialize() { - let program_id = "3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg"; - let anchor_wallet = std::env::var("ANCHOR_WALLET").unwrap(); - let payer = read_keypair_file(&anchor_wallet).unwrap(); - - let client = Client::new_with_options(Cluster::Localnet, &payer, CommitmentConfig::confirmed()); - let program_id = Pubkey::from_str(program_id).unwrap(); - let program = client.program(program_id).unwrap(); - - let tx = program - .request() - .accounts(my_program::accounts::Initialize {}) - .args(my_program::instruction::Initialize {}) - .send() - .expect(""); - - println!("Your transaction signature {}", tx); -} -``` - - - - -### Build the Program - -Build the program by running `anchor build`. - -```shell filename="Terminal" copy -anchor build -``` - -The compiled program will be at `/target/deploy/my_project.so`. The content of -this file is what gets stored on the Solana network (as an executable account) -when you deploy your program. - -### Test the Program - -To test the program, run `anchor test`. - -```shell filename="Terminal" copy -anchor test -``` - -By default, the `Anchor.toml` config file specifies the `localnet` cluster. When -developing on `localnet`, `anchor test` will automatically: - -1. Start a local Solana validator -2. Build and deploy your program to the local cluster -3. Run the tests in the `tests` folder -4. Stop the local Solana validator - -Alternatively, you can manually start a local Solana validator and run tests -against it. This is useful if you want to keep the validator running while you -iterate on your program. It allows you to inspect accounts and transaction logs -on the [Solana Explorer](https://explorer.solana.com/?cluster=custom) while -developing locally. - -Open a new terminal and start a local Solana validator by running the -`solana-test-validator` command. - -```shell filename="Terminal" copy -solana-test-validator -``` - -In a separate terminal, run the tests against the local cluster. Use the -`--skip-local-validator` flag to skip starting the local validator since it's -already running. - -```shell filename="Terminal" copy -anchor test --skip-local-validator -``` - -### Deploy to Devnet - -By default, the `Anchor.toml` config file in an Anchor project specifies the -localnet cluster. - -```toml filename="Anchor.toml" {14} -[toolchain] - -[features] -resolution = true -skip-lint = false - -[programs.localnet] -my_program = "3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg" - -[registry] -url = "https://api.apr.dev" - -[provider] -cluster = "Localnet" -wallet = "~/.config/solana/id.json" - -[scripts] -test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" -``` - -To deploy your program to devnet, change the `cluster` value to `Devnet`. Note -that this requires your wallet to have enough SOL on Devnet to cover deployment -cost. - -```diff --cluster = "Localnet" -+cluster = "Devnet" -``` - -```toml filename="Anchor.toml" -[provider] -cluster = "Devnet" -wallet = "~/.config/solana/id.json" -``` - -Now when you run `anchor deploy`, your program will be deployed to the devnet -cluster. The `anchor test` command will also use the cluster specified in the -`Anchor.toml` file. - -```shell -anchor deploy -``` - -To deploy to mainnet, simply update the `Anchor.toml` file to specify the -mainnet cluster. - -```toml filename="Anchor.toml" -[provider] -cluster = "Mainnet" -wallet = "~/.config/solana/id.json" -``` - -### Update the Program - -Solana programs can be updated by redeploying the program to the same program -ID. - -To update a program, simply make changes to your program's code and run the -`anchor build` command to generated an updated `.so` file. - -```shell -anchor build -``` - -Then run the `anchor deploy` command to redeploy the updated program. - -```shell -anchor deploy -``` - -### Close the Program - -To reclaim the SOL allocated to a program account, you can close your Solana -program. - -To close a program, use the `solana program close ` command. For -example: - -```shell -solana program close 3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg --bypass-warning -``` - -Note that once a program is closed, the program ID cannot be reused to deploy a -new program. - - - -## Project File Structure - -Below is an overview of default file structure in an Anchor workspace: - -``` -. -├── .anchor -│ └── program-logs -├── app -├── migrations -├── programs -│ └── [project-name] -│ └── src -│ ├── lib.rs -│ ├── Cargo.toml -│ └── Xargo.toml -├── target -│ ├── deploy -│ │ └── [project-name]-keypair.json -│ ├── idl -│ │ └── [project-name].json -│ └── types -│ └── [project-name].ts -├── tests -│ └── [project-name].ts -├── Anchor.toml -├── Cargo.toml -└── package.json -``` - -### Programs Folder - -The `/programs` folder contains your project's Anchor programs. A single -workspace can contain multiple programs. - -### Tests Folder - -The `/tests` folder contains test files for your project. A default test file is -created for you when you create your project. - -### Target Folder - -The `/target` folder contains build outputs. The main subfolders include: - -- `/deploy`: Contains the keypair and program binary for your programs. -- `/idl`: Contains the JSON IDL for your programs. -- `/types`: Contains the TypeScript type for the IDL. - -### Anchor.toml File - -The `Anchor.toml` file configures workspace settings for your project. - -### .anchor Folder - -Includes a `program-logs` file that contains transaction logs from the last run -of test files. - -### App Folder - -The `/app` folder is an empty folder that can be optionally used for your -frontend code. diff --git a/docs/uk/programs/anchor/pda.md b/docs/uk/programs/anchor/pda.md deleted file mode 100644 index bec281733..000000000 --- a/docs/uk/programs/anchor/pda.md +++ /dev/null @@ -1,325 +0,0 @@ ---- -title: PDAs with Anchor -description: - Learn how to use Program Derived Addresses (PDAs) in Anchor programs, using - constraints, and implementing common PDA patterns -sidebarLabel: PDAs with Anchor -sidebarSortOrder: 4 ---- - -[Program Derived Addresses (PDA)](/docs/core/pda) refer to a feature of Solana -development that allows you to create a unique address derived deterministically -from pre-defined inputs (seeds) and a program ID. - -This section will cover basic examples of how to use PDAs in an Anchor program. - -## Anchor PDA Constraints - -When using PDAs in an Anchor program, you generally use Anchor's account -constraints to define the seeds used to derive the PDA. These constraints serve -as security checks to ensure that the correct address is derived. - -The constraints used to define the PDA seeds include: - -- `seeds`: An array of optional seeds used to derive the PDA. Seeds can be - static values or dynamic references to account data. -- `bump`: The bump seed used to derive the PDA. Used to ensure the address falls - off the Ed25519 curve and is a valid PDA. -- `seeds::program` - (Optional) The program ID used to derive the PDA address. - This constraint is only used to derive a PDA where the program ID is not the - current program. - -The `seeds` and `bump` constraints are required to be used together. - -### Usage Examples - -Below are examples demonstrating how to use PDA constraints in an Anchor -program. - - - - - -The `seeds` constraint specifies the optional values used to derive the PDA. - -#### No Optional Seeds - -- Use an empty array `[]` to define a PDA without optional seeds. - -```rs -#[derive(Accounts)] -pub struct InstructionAccounts<'info> { - #[account( - seeds = [], - bump, - )] - pub pda_account: SystemAccount<'info>, -} -``` - -#### Single Static Seed - -- Specify optional seeds in the `seeds` constraint. - -```rs -#[derive(Accounts)] -pub struct InstructionAccounts<'info> { - #[account( - seeds = [b"hello_world"], - bump, - )] - pub pda_account: SystemAccount<'info>, -} -``` - -#### Multiple Seeds and Account References - -- Multiple seeds can be specified in the `seeds` constraint. The `seeds` - constraint can also reference other account addresses or account data. - -```rs -#[derive(Accounts)] -pub struct InstructionAccounts<'info> { - pub signer: Signer<'info>, - #[account( - seeds = [b"hello_world", signer.key().as_ref()], - bump, - )] - pub pda_account: SystemAccount<'info>, -} -``` - -The example above uses both a static seed (`b"hello_world"`) and a dynamic seed -(the signer's public key). - - - - -The `bump` constraint specifies the bump seed used to derive the PDA. - -#### Automatic Bump Calculation - -When using the `bump` constraint without a value, the bump is automatically -calculated each time the instruction is invoked. - -```rs -#[derive(Accounts)] -pub struct InstructionAccounts<'info> { - #[account( - seeds = [b"hello_world"], - bump, - )] - pub pda_account: SystemAccount<'info>, -} -``` - -#### Specify Bump Value - -You can explicitly provide the bump value, which is useful for optimizing -compute unit usage. This assumes that the PDA account has been created and the -bump seed is stored as a field on an existing account. - -```rs -#[derive(Accounts)] -pub struct InstructionAccounts<'info> { - #[account( - seeds = [b"hello_world"], - bump = pda_account.bump_seed, - )] - pub pda_account: Account<'info, CustomAccount>, -} - -#[account] -pub struct CustomAccount { - pub bump_seed: u8, -} -``` - -By storing the bump value in the account's data, the program doesn't need to -recalculate it, saving compute units. The saved bump value can be stored on the -account itself or another account. - - - - -The `seeds::program` constraint specifies the program ID used to derive the PDA. -This constraint is only used when deriving a PDA from a different program. - -Use this constraint when your instruction needs to interact with PDA accounts -created by another program. - -```rs -#[derive(Accounts)] -pub struct InstructionAccounts<'info> { - #[account( - seeds = [b"hello_world"], - bump, - seeds::program = other_program.key(), - )] - pub pda_account: SystemAccount<'info>, - pub other_program: Program<'info, OtherProgram>, -} -``` - - - - -The `init` constraint is commonly used with `seeds` and `bump` to create a new -account with an address that is a PDA. Under the hood, the `init` constraint -invokes the System Program to create the account. - -```rs -#[derive(Accounts)] -pub struct InstructionAccounts<'info> { - #[account(mut)] - pub signer: Signer<'info>, - #[account( - init, - seeds = [b"hello_world", signer.key().as_ref()], - bump, - payer = signer, - space = 8 + 1, - )] - pub pda_account: Account<'info, CustomAccount>, - pub system_program: Program<'info, System>, -} - -#[account] -pub struct CustomAccount { - pub bump_seed: u8, -} -``` - - - - -## PDA seeds in the IDL - -Program Derived Address (PDA) seeds defined in the `seeds` constraint are -included in the program's IDL file. This allows the Anchor client to -automatically resolve accounts using these seeds when constructing instructions. - -This example below shows the relationship between the program, IDL, and client. - - - - - -The program below defines a `pda_account` using a static seed (`b"hello_world"`) -and the signer's public key as a dynamic seed. - -```rs {18} /signer/ -use anchor_lang::prelude::*; - -declare_id!("BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5"); - -#[program] -mod hello_anchor { - use super::*; - pub fn test_instruction(ctx: Context) -> Result<()> { - msg!("PDA: {}", ctx.accounts.pda_account.key()); - Ok(()) - } -} - -#[derive(Accounts)] -pub struct InstructionAccounts<'info> { - pub signer: Signer<'info>, - #[account( - seeds = [b"hello_world", signer.key().as_ref()], - bump, - )] - pub pda_account: SystemAccount<'info>, -} -``` - - - - -The program's IDL file includes the PDA seeds defined in the `seeds` constraint. - -- The static seed `b"hello_world"` is converted to byte values. -- The dynamic seed is included as reference to the signer account. - -```json {22-29} -{ - "address": "BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5", - "metadata": { - "name": "hello_anchor", - "version": "0.1.0", - "spec": "0.1.0", - "description": "Created with Anchor" - }, - "instructions": [ - { - "name": "test_instruction", - "discriminator": [33, 223, 61, 208, 32, 193, 201, 79], - "accounts": [ - { - "name": "signer", - "signer": true - }, - { - "name": "pda_account", - "pda": { - "seeds": [ - { - "kind": "const", - "value": [104, 101, 108, 108, 111, 95, 119, 111, 114, 108, 100] - }, - { - "kind": "account", - "path": "signer" - } - ] - } - } - ], - "args": [] - } - ] -} -``` - - - - -The Anchor client can automatically resolve the PDA address using the IDL file. - -In the example below, Anchor automatically resolves the PDA address using the -provider wallet as the signer, and its public key as the dynamic seed for PDA -derivation. This removes the need to explicitly derive the PDA when building the -instruction. - -```ts {13} -import * as anchor from "@coral-xyz/anchor"; -import { Program } from "@coral-xyz/anchor"; -import { HelloAnchor } from "../target/types/hello_anchor"; - -describe("hello_anchor", () => { - // Configure the client to use the local cluster. - anchor.setProvider(anchor.AnchorProvider.env()); - - const program = anchor.workspace.HelloAnchor as Program; - - it("Is initialized!", async () => { - // Add your test here. - const tx = await program.methods.testInstruction().rpc(); - console.log("Your transaction signature", tx); - }); -}); -``` - -When the instruction is invoked, the PDA is printed to program logs as defined -in the program instruction. - -```{3} -Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 invoke [1] -Program log: Instruction: TestInstruction -Program log: PDA: 3Hikt5mpKaSS4UNA5Du1TZJ8tp4o8VC8YWW6X9vtfVnJ -Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 consumed 18505 of 200000 compute units -Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 success -``` - - - diff --git a/docs/uk/programs/anchor/program-structure.md b/docs/uk/programs/anchor/program-structure.md deleted file mode 100644 index a7d5fc07c..000000000 --- a/docs/uk/programs/anchor/program-structure.md +++ /dev/null @@ -1,399 +0,0 @@ ---- -title: Anchor Program Structure -description: - Learn about the structure of Anchor programs, including key macros and their - roles in simplifying Solana program development -sidebarLabel: Program Structure -sidebarSortOrder: 1 ---- - -The [Anchor framework](https://www.anchor-lang.com/) uses -[Rust macros](https://doc.rust-lang.org/book/ch19-06-macros.html) to reduce -boilerplate code and simplify the implementation of common security checks -required for writing Solana programs. - -The main macros found in an Anchor program include: - -- [`declare_id`](#declare-id-macro): Specifies the program's on-chain address -- [`#[program]`](#program-macro): Specifies the module containing the program’s - instruction logic -- [`#[derive(Accounts)]`](#derive-accounts-macro): Applied to structs to - indicate a list of accounts required by an instruction -- [`#[account]`](#account-macro): Applied to structs to create custom account - types for the program - -## Example Program - -Let's examine a simple program that demonstrates the usage of the macros -mentioned above to understand the basic structure of an Anchor program. - -The example program below creates a new account (`NewAccount`) that stores a -`u64` value passed to the `initialize` instruction. - -```rust filename="lib.rs" -use anchor_lang::prelude::*; - -declare_id!("11111111111111111111111111111111"); - -#[program] -mod hello_anchor { - use super::*; - pub fn initialize(ctx: Context, data: u64) -> Result<()> { - ctx.accounts.new_account.data = data; - msg!("Changed data to: {}!", data); - Ok(()) - } -} - -#[derive(Accounts)] -pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, -} - -#[account] -pub struct NewAccount { - data: u64, -} -``` - -## declare_id! macro - -The -[`declare_id`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L430) -macro specifies the on-chain address of the program, known as the program ID. - -```rust filename="lib.rs" {3} -use anchor_lang::prelude::*; - -declare_id!("11111111111111111111111111111111"); -``` - -By default, the program ID is the public key of the keypair generated at -`/target/deploy/your_program_name.json`. - -To update the value of the program ID in the `declare_id` macro with the public -key of the keypair in the `/target/deploy/your_program_name.json` file, run the -following command: - -```shell filename="Terminal" -anchor keys sync -``` - -The `anchor keys sync` command is useful to run when cloning a repository where -the value of the program ID in a cloned repo's `declare_id` macro won't match -the one generated when you run `anchor build` locally. - -## #[program] macro - -The -[`#[program]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/lib.rs#L12) -macro defines the module that contains all the instruction handlers for your -program. Each public function within this module corresponds to an instruction -that can be invoked. - -```rust filename="lib.rs" {5, 8-12} -use anchor_lang::prelude::*; - -declare_id!("11111111111111111111111111111111"); - -#[program] -mod hello_anchor { - use super::*; - pub fn initialize(ctx: Context, data: u64) -> Result<()> { - ctx.accounts.new_account.data = data; - msg!("Changed data to: {}!", data); - Ok(()) - } -} - -#[derive(Accounts)] -pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, -} - -#[account] -pub struct NewAccount { - data: u64, -} -``` - -### Instruction Context - -Instruction handlers are functions that define the logic executed when an -instruction is invoked. The first parameter of each handler is a `Context` -type, where `T` is a struct implementing the `Accounts` trait and specifies the -accounts the instruction requires. - -The -[`Context`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/context.rs#L24) -type provides the instruction with access to the following non-argument inputs: - -```rust -pub struct Context<'a, 'b, 'c, 'info, T> { - /// Currently executing program id. - pub program_id: &'a Pubkey, - /// Deserialized accounts. - pub accounts: &'b mut T, - /// Remaining accounts given but not deserialized or validated. - /// Be very careful when using this directly. - pub remaining_accounts: &'c [AccountInfo<'info>], - /// Bump seeds found during constraint validation. This is provided as a - /// convenience so that handlers don't have to recalculate bump seeds or - /// pass them in as arguments. - pub bumps: BTreeMap, -} -``` - -The `Context` fields can be accessed in an instruction using dot notation: - -- `ctx.accounts`: The accounts required for the instruction -- `ctx.program_id`: The program's public key (address) -- `ctx.remaining_accounts`: Additional accounts not specified in the `Accounts` - struct. -- `ctx.bumps`: Bump seeds for any - [Program Derived Address (PDA)](/docs/core/pda.md) accounts specified in the - `Accounts` struct - -Additional parameters are optional and can be included to specify arguments that -must be provided when the instruction is invoked. - -```rust filename="lib.rs" /Context/ /data/1 -pub fn initialize(ctx: Context, data: u64) -> Result<()> { - ctx.accounts.new_account.data = data; - msg!("Changed data to: {}!", data); - Ok(()) -} -``` - -In this example, the `Initialize` struct implements the `Accounts` trait where -each field in the struct represents an account required by the `initialize` -instruction. - -```rust filename="lib.rs" /Initialize/ /Accounts/ -#[program] -mod hello_anchor { - use super::*; - pub fn initialize(ctx: Context, data: u64) -> Result<()> { - ctx.accounts.new_account.data = data; - msg!("Changed data to: {}!", data); - Ok(()) - } -} - -#[derive(Accounts)] -pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, -} -``` - -## #[derive(Accounts)] macro - -The -[`#[derive(Accounts)]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/derive/accounts/src/lib.rs#L630) -macro is applied to a struct to specify the accounts that must be provided when -an instruction is invoked. This macro implements the -[`Accounts`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/lib.rs#L105) -trait, which simplifies account validation and serialization and deserialization -of account data. - -```rust /Accounts/ {1} -#[derive(Accounts)] -pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, -} -``` - -Each field in the struct represents an account required by an instruction. The -naming of each field is arbitrary, but it is recommended to use a descriptive -name that indicates the purpose of the account. - -```rust /signer/2 /new_account/ /system_program/ -#[derive(Accounts)] -pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, -} -``` - -### Account Validation - -To prevent security vulnerabilities, it's important to verify that accounts -provided to an instruction are the expected accounts. Accounts are validated in -Anchor programs in two ways that are generally used together: - -- [Account Constraints](https://www.anchor-lang.com/docs/account-constraints): - Constraints define additional conditions that an account must satisfy to be - considered valid for the instruction. Constraints are applied using the - `#[account(..)]` attribute, which is placed above a field in a struct that - implements the `Accounts` trait. - - You can find the implementation of the constraints - [here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/parser/accounts/constraints.rs). - - ```rust {3, 5} - #[derive(Accounts)] - pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, - } - ``` - -- [Account Types](https://www.anchor-lang.com/docs/account-types): Anchor - provides various account types to help ensure that the account provided by the - client matches what the program expects. - - You can find the implementation of the account types - [here](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/accounts). - - ```rust /Account/2 /Signer/ /Program/ - #[derive(Accounts)] - pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, - } - ``` - -When an instruction in an Anchor program is invoked, the program first validates -the accounts provided before executing the instruction's logic. After -validation, these accounts can be accessed within the instruction using the -`ctx.accounts` syntax. - -```rust filename="lib.rs" /ctx.accounts.new_account/ /new_account/ /Initialize/ -use anchor_lang::prelude::*; - -declare_id!("11111111111111111111111111111111"); - -#[program] -mod hello_anchor { - use super::*; - pub fn initialize(ctx: Context, data: u64) -> Result<()> { - ctx.accounts.new_account.data = data; - msg!("Changed data to: {}!", data); - Ok(()) - } -} - -#[derive(Accounts)] -pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, -} - -#[account] -pub struct NewAccount { - data: u64, -} -``` - -## #[account] macro - -The -[`#[account]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L66) -macro is applied to structs that define the data stored in custom accounts -created by your program. - -```rust -#[account] -pub struct NewAccount { - data: u64, -} -``` - -This macro implements various traits -[detailed here](https://docs.rs/anchor-lang/latest/anchor_lang/attr.account.html). -The key functionalities of the `#[account]` macro include: - -- [Assign Program Owner](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L119-L132): - When creating an account, the program owner of the account is automatically - set to the program specified in `declare_id`. -- [Set Discriminator](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L101-L117): - A unique 8 byte discriminator, specific to the account type, is added as the - first 8 bytes of account data during its initialization. This helps in - differentiating account types and is used for account validation. -- [Data Serialization and Deserialization](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L202-L246): - Account data is automatically serialized and deserialized as the account type. - -```rust filename="lib.rs" /data/2,6 /NewAccount/ {24-27} -use anchor_lang::prelude::*; - -declare_id!("11111111111111111111111111111111"); - -#[program] -mod hello_anchor { - use super::*; - pub fn initialize(ctx: Context, data: u64) -> Result<()> { - ctx.accounts.new_account.data = data; - msg!("Changed data to: {}!", data); - Ok(()) - } -} - -#[derive(Accounts)] -pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, -} - -#[account] -pub struct NewAccount { - data: u64, -} -``` - -### Account Discriminator - -An account discriminator in an Anchor program refers to an 8 byte identifier -unique to each account type. It's derived from the first 8 bytes of the SHA256 -hash of the string `account:`. This discriminator is stored as the -first 8 bytes of account data when an account is created. - -When creating an account in an Anchor program, 8 bytes must be allocated for the -discriminator. - -```rust /8/1 -#[account(init, payer = signer, space = 8 + 8)] -pub new_account: Account<'info, NewAccount>, -``` - -The discriminator is used during the following two scenarios: - -- Initialization: When an account is created, the discriminator is set as the - first 8 bytes of the account's data. -- Deserialization: When account data is deserialized, the first 8 bytes of - account data is checked against the discriminator of the expected account - type. - -If there's a mismatch, it indicates that the client has provided an unexpected -account. This mechanism serves as an account validation check in Anchor -programs. diff --git a/docs/uk/programs/deploying.md b/docs/uk/programs/deploying.md deleted file mode 100644 index 94d79556c..000000000 --- a/docs/uk/programs/deploying.md +++ /dev/null @@ -1,331 +0,0 @@ ---- -title: "Deploying Programs" -description: - Deploying onchain programs can be done using the Solana CLI using the - Upgradable BPF loader to upload the compiled byte-code to the Solana - blockchain. -sidebarSortOrder: 2 ---- - -Solana programs are stored in "executable" accounts on the network. These -accounts contain the program's compiled bytecode that define the instructions -users invoke to interact with the program. - -## CLI Commands - -The section is intended as a reference for the basic CLI commands for building -and deploying Solana programs. For a step-by-step guide on creating your first -program, start with [Developing Programs in Rust](/docs/programs/rust). - -### Build Program - -To build your program, use the `cargo build-sbf` command. - -```shell -cargo build-sbf -``` - -This command will: - -1. Compile your program -2. Create a `target/deploy` directory -3. Generate a `.so` file, where `` matches your - program's name in `Cargo.toml` - -The output `.so` file contains your program's compiled bytecode that will be -stored in a Solana account when you deploy your program. - -### Deploy Program - -To deploy your program, use the `solana program deploy` command followed by the -path to the `.so` file created by the `cargo build-sbf` command. - -```shell -solana program deploy ./target/deploy/your_program.so -``` - -During times of congestion, there are a few additional flags you can use to help -with program deployment. - -- `--with-compute-unit-price`: Set compute unit price for transaction, in - increments of 0.000001 lamports (micro-lamports) per compute unit. -- `--max-sign-attempts`: Maximum number of attempts to sign or resign - transactions after blockhash expiration. If any transactions sent during the - program deploy are still unconfirmed after the initially chosen recent - blockhash expires, those transactions will be resigned with a new recent - blockhash and resent. Use this setting to adjust the maximum number of - transaction signing iterations. Each blockhash is valid for about 60 seconds, - which means using the default value of 5 will lead to sending transactions for - at least 5 minutes or until all transactions are confirmed,whichever comes - first. [default: 5] -- `--use-rpc`: Send write transactions to the configured RPC instead of - validator TPUs. This flag requires a stake-weighted RPC connection. - -You can use the flags individually or combine them together. For example: - -```shell -solana program deploy ./target/deploy/your_program.so --with-compute-unit-price 10000 --max-sign-attempts 1000 --use-rpc -``` - -- Use the - [Priority Fee API by Helius](https://docs.helius.dev/guides/priority-fee-api) - to get an estimate of the priority fee to set with the - `--with-compute-unit-price` flag. - -- Get a - [stake-weighted](https://solana.com/developers/guides/advanced/stake-weighted-qos) - RPC connection from [Helius](https://www.helius.dev/) or - [Triton](https://triton.one/) to use with the `--use-rpc` flag. The - `--use-rpc` flag should only be used with a stake-weighted RPC connection. - -To update your default RPC URL with a custom RPC endpoint, use the -`solana config set` command. - -```shell -solana config set --url -``` - -You can view the list of programs you've deployed using the `program show` -subcommand: - -```shell -solana program show --programs -``` - -Example output: - -``` -Program Id | Slot | Authority | Balance -2w3sK6CW7Hy1Ljnz2uqPrQsg4KjNZxD4bDerXDkSX3Q1 | 133132 | 4kh6HxYZiAebF8HWLsUWod2EaQQ6iWHpHYCz8UcmFbM1 | 0.57821592 SOL -``` - -### Update Program - -A program's update authority can modify an existing Solana program by deploying -a new `.so` file to the same program ID. - -To update an existing Solana program: - -- Make changes to your program source code -- Run `cargo build-sbf` to generate an updated `.so` file -- Run `solana program deploy ./target/deploy/your_program.so` to deploy the - updated `.so` file - -The update authority can be changed using the `set-upgrade-authority` subcommand -as follows: - -```shell -solana program set-upgrade-authority --new-upgrade-authority -``` - -### Immutable Program - -A program can be made immutable by removing its update authority. This is an -irreversible action. - -```shell -solana program set-upgrade-authority --final -``` - -You can specify that program should be immutable on deployment by setting the -`--final` flag when deploying the program. - -```shell -solana program deploy ./target/deploy/your_program.so --final -``` - -### Close Program - -You can close your Solana program to reclaim the SOL allocated to the account. -Closing a program is irreversible, so it should be done with caution. To close a -program, use the `program close` subcommand. For example: - -```shell filename="Terminal" -solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz ---bypass-warning -``` - -Example output: - -``` -Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOL -reclaimed -``` - -Note that once a program is closed, its program ID cannot be reused. Attempting -to deploy a program with a previously closed program ID will result in an error. - -``` -Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, use -a new Program Id -``` - -If you need to redeploy a program after closing it, you must generate a new -program ID. To generate a new keypair for the program, run the following -command: - -```shell filename="Terminal" -solana-keygen new -o ./target/deploy/your_program-keypair.json --force -``` - -Alternatively, you can delete the existing keypair file and run -`cargo build-sbf` again, which will generate a new keypair file. - -### Program Buffer Accounts - -Deploying a program requires multiple transactions due to the 1232 byte limit -for transactions on Solana. An intermediate step of the deploy process involves -writing the program's byte-code to temporary "buffer account". - -This buffer account is automatically closed after successful program deployment. -However, if the deployment fails, the buffer account remains and you can either: - -- Continue the deployment using the existing buffer account -- Close the buffer account to reclaim the allocated SOL (rent) - -You can check if you have any open buffer accounts by using the `program show` -subcommand as follows: - -```shell -solana program show --buffers -``` - -Example output: - -``` -Buffer Address | Authority | Balance -5TRm1DxYcXLbSEbbxWcQbEUCce7L4tVgaC6e2V4G82pM | 4kh6HxYZiAebF8HWLsUWod2EaQQ6iWHpHYCz8UcmFbM1 | 0.57821592 SOL -``` - -You can continue to the deployment using the `program deploy` subcommand as -follows: - -```shell -solana program deploy --buffer 5TRm1DxYcXLbSEbbxWcQbEUCce7L4tVgaC6e2V4G82pM -``` - -Expected output on successful deployment: - -``` -Program Id: 2w3sK6CW7Hy1Ljnz2uqPrQsg4KjNZxD4bDerXDkSX3Q1 - -Signature: 3fsttJFskUmvbdL5F9y8g43rgNea5tYZeVXbimfx2Up5viJnYehWe3yx45rQJc8Kjkr6nY8D4DP4V2eiSPqvWRNL -``` - -To close buffer accounts, use the `program close` subcommand as follows: - -```shell -solana program close --buffers -``` - -### ELF Dump - -The SBF shared object internals can be dumped to a text file to gain more -insight into a program's composition and what it may be doing at runtime. The -dump will contain both the ELF information as well as a list of all the symbols -and the instructions that implement them. Some of the BPF loader's error log -messages will reference specific instruction numbers where the error occurred. -These references can be looked up in the ELF dump to identify the offending -instruction and its context. - -```shell -cargo build-bpf --dump -``` - -The file will be output to `/target/deploy/your_program-dump.txt`. - -## Program Deployment Process - -Deploying a program on Solana requires multiple transactions, due to the max -size limit of 1232 bytes for Solana transactions. The Solana CLI sends these -transactions with the `solana program deploy` subcommand. The process can be -broken down into the following 3 phases: - -1. [Buffer initialization](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2113): - First, the CLI sends a transaction which - [creates a buffer account](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1903) - large enough for the byte-code being deployed. It also invokes the - [initialize buffer instruction](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L320) - to set the buffer authority to restrict writes to the deployer's chosen - address. -2. [Buffer writes](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2129): - Once the buffer account is initialized, the CLI - [breaks up the program byte-code](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1940) - into ~1KB chunks and - [sends transactions at a rate of 100 transactions per second](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/client/src/tpu_client.rs#L133) - to write each chunk with - [the write buffer instruction](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L334). - These transactions are sent directly to the current leader's transaction - processing (TPU) port and are processed in parallel with each other. Once all - transactions have been sent, the CLI - [polls the RPC API with batches of transaction signatures](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/client/src/tpu_client.rs#L216) - to ensure that every write was successful and confirmed. -3. [Finalization](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1807): - Once writes are completed, the CLI - [sends a final transaction](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2150) - to either - [deploy a new program](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L362) - or - [upgrade an existing program](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L513). - In either case, the byte-code written to the buffer account will be copied - into a program data account and verified. - -## Upgradeable BPF Loader Program - -The BPF loader program is the program that "owns" all executable accounts on -Solana. When you deploy a program, the owner of the program account is set to -the the BPF loader program. - -### State accounts - -The Upgradeable BPF loader program supports three different types of state -accounts: - -1. [Program account](https://github.com/solana-labs/solana/blob/master/sdk/program/src/bpf_loader_upgradeable.rs#L34): - This is the main account of an on-chain program and its address is commonly - referred to as a "program id." Program id's are what transaction instructions - reference in order to invoke a program. Program accounts are immutable once - deployed, so you can think of them as a proxy account to the byte-code and - state stored in other accounts. -2. [Program data account](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/bpf_loader_upgradeable.rs#L39): - This account is what stores the executable byte-code of an on-chain program. - When a program is upgraded, this account's data is updated with new - byte-code. In addition to byte-code, program data accounts are also - responsible for storing the slot when it was last modified and the address of - the sole account authorized to modify the account (this address can be - cleared to make a program immutable). -3. [Buffer accounts](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/bpf_loader_upgradeable.rs#L27): - These accounts temporarily store byte-code while a program is being actively - deployed through a series of transactions. They also each store the address - of the sole account which is authorized to do writes. - -### Instructions - -The state accounts listed above can only be modified with one of the following -instructions supported by the Upgradeable BPF Loader program: - -1. [Initialize buffer](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L21): - Creates a buffer account and stores an authority address which is allowed to - modify the buffer. -2. [Write](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L28): - Writes byte-code at a specified byte offset inside a buffer account. Writes - are processed in small chunks due to a limitation of Solana transactions - having a maximum serialized size of 1232 bytes. -3. [Deploy](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L77): - Creates both a program account and a program data account. It fills the - program data account by copying the byte-code stored in a buffer account. If - the byte-code is valid, the program account will be set as executable, - allowing it to be invoked. If the byte-code is invalid, the instruction will - fail and all changes are reverted. -4. [Upgrade](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L102): - Fills an existing program data account by copying executable byte-code from a - buffer account. Similar to the deploy instruction, it will only succeed if - the byte-code is valid. -5. [Set authority](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L114): - Updates the authority of a program data or buffer account if the account's - current authority has signed the transaction being processed. If the - authority is deleted without replacement, it can never be set to a new - address and the account can never be closed. -6. [Close](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L127): - Clears the data of a program data account or buffer account and reclaims the - SOL used for the rent exemption deposit. diff --git a/docs/uk/programs/examples.md b/docs/uk/programs/examples.md deleted file mode 100644 index d16eaf27a..000000000 --- a/docs/uk/programs/examples.md +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: "Program Examples" -description: - "A list of Solana program examples in different languages and frameworks, - which can help you learn and use as reference for your own projects." -tags: - - quickstart - - program - - anchor - - javascript - - native - - rust - - token22 - - token extensions -keywords: - - rust - - cargo - - toml - - program - - tutorial - - intro to solana development - - blockchain developer - - blockchain tutorial - - web3 developer - - anchor -sidebarSortOrder: 3 ---- - -The -[Solana Program Examples](https://github.com/solana-developers/program-examples) -repository on GitHub offers several subfolders, each containing code examples -for different Solana programming paradigms and languages, designed to help -developers learn and experiment with Solana blockchain development. - -You can find the examples in the `solana-developers/program-examples` together -with README files that explain you how to run the different examples. Most -examples are self-contained and are available in native Rust (ie, with no -framework) and [Anchor](https://www.anchor-lang.com/docs/installation). It also -contains a list of examples that we would love to -[see as contributions](https://github.com/solana-developers/program-examples?tab=readme-ov-file#examples-wed-love-to-see). - -Within the repo you will find the following subfolder, each with assorted -example programs within them: - -- [Basics](#basics) -- [Compression](#compression) -- [Oracles](#oracles) -- [Tokens](#tokens) -- [Token 2022 (Token Extensions)](#token-2022-token-extensions) -- [Break](#break) - - [Build and Run](#build-and-run) - -## Basics - -Contains a series of examples that demonstrate the foundational steps for -building Solana programs using native Rust libraries. These examples are -designed to help developers understand the core concepts of Solana programming. - -| Example Name | Description | Language | -| ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------- | -| [Account Data](https://github.com/solana-developers/program-examples/tree/main/basics/account-data) | Saving an address with name, house number, street and city in an account. | Native, Anchor | -| [Checking Accounts](https://github.com/solana-developers/program-examples/tree/main/basics/checking-accounts) | Security lessons that shows how to do account checks | Native, Anchor | -| [Close Account](https://github.com/solana-developers/program-examples/tree/main/basics/close-account) | Show you how to close accounts to get its rent back. | Native, Anchor | -| [Counter](https://github.com/solana-developers/program-examples/tree/main/basics/counter) | A simple counter program in all the different architectures. | Native, Anchor, mpl-stack | -| [Create Account](https://github.com/solana-developers/program-examples/tree/main/basics/create-account) | How to create a system account within a program. | Native, Anchor | -| [Cross Program Invocation](https://github.com/solana-developers/program-examples/tree/main/basics/cross-program-invocation) | Using a hand and lever analogy this shows you how to call another program from within a program. | Native, Anchor | -| [hello solana](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana) | Hello world example which just prints hello world in the transaction logs. | Native, Anchor | -| [Pda Rent payer](https://github.com/solana-developers/program-examples/tree/main/basics/pda-rent-payer) | Shows you how you can use the lamports from a PDA to pay for a new account. | Native, Anchor | -| [Processing Instructions](https://github.com/solana-developers/program-examples/tree/main/basics/processing-instructions) | Shows you how to handle instruction data string and u32. | Native, Anchor | -| [Program Derived Addresses](https://github.com/solana-developers/program-examples/tree/main/basics/program-derived-addresses) | Shows how to use seeds to refer to a PDA and save data in it. | Native, Anchor | -| [Realloc](https://github.com/solana-developers/program-examples/tree/main/basics/realloc) | Shows you how to increase and decrease the size of an existing account. | Native, Anchor | -| [Rent](https://github.com/solana-developers/program-examples/tree/main/basics/rent) | Here you will learn how to calculate rent requirements within a program. | Native, Anchor | -| [Repository Layout](https://github.com/solana-developers/program-examples/tree/main/basics/repository-layout) | Recommendations on how to structure your program layout. | Native, Anchor | -| [Transfer SOL](https://github.com/solana-developers/program-examples/tree/main/basics/transfer-sol) | Different methods of transferring SOL for system accounts and PDAs. | Native, Anchor, Seahorse | - -## Compression - -Contains a series of examples that demonstrate how to use -[state compression](/docs/advanced/state-compression.md) on Solana. Mainly -focused on compressed NFTs (cNFTs). - -| Example Name | Description | Language | -| ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | -------- | -| [cNFT-burn](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-burn) | To destroy a cNFT it can be burnt. This examples shows how to do that in a program. | Anchor | -| [cNFT-Vault](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-vault/anchor) | How to custody a cNFT in a program and send it out again. | Anchor | -| [cutils](https://github.com/solana-developers/program-examples/tree/main/compression/cutils) | A suite utils to for example mint and verify cNFTs in a program. | Anchor | - -## Oracles - -Oracles allow to use off chain data in programs. - -| Example Name | Description | Language | -| ------------------------------------------------------------------------------------ | --------------------------------------------------------------- | -------- | -| [Pyth](https://github.com/solana-developers/program-examples/tree/main/oracles/pyth) | Pyth makes price data of tokens available in on chain programs. | Anchor | - -## Tokens - -Most tokens on Solana use the Solana Program Library (SPL) token standard. Here -you can find many examples on how to mint, transfer, burn tokens and even how to -interact with them in programs. - -| Example Name | Description | Language | -| --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------------- | -| [Create Token](https://github.com/solana-developers/program-examples/tree/main/tokens/create-token) | How to create a token and add metaplex metadata to it. | Anchor, Native | -| [NFT Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/nft-minter) | Minting only one amount of a token and then removing the mint authority. | Anchor, Native | -| [PDA Mint Authority](https://github.com/solana-developers/program-examples/tree/main/tokens/pda-mint-authority) | Shows you how to change the mint authority of a mint, to mint tokens from within a program. | Anchor, Native | -| [SPL Token Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/spl-token-minter) | Explains how to use Associated Token Accounts to be able to keep track of token accounts. | Anchor, Native | -| [Token Swap](https://github.com/solana-developers/program-examples/tree/main/tokens/token-swap) | Extensive example that shows you how to build a AMM (automated market maker) pool for SPL tokens. | Anchor | -| [Transfer Tokens](https://github.com/solana-developers/program-examples/tree/main/tokens/transfer-tokens) | Shows how to transfer SPL token using CPIs into the token program. | Anchor, Native | -| [Token-2022](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022) | See Token 2022 (Token extensions). | Anchor, Native | - -## Token 2022 (Token Extensions) - -Token 2022 is a new standard for tokens on Solana. It is a more flexible and -lets you add 16 different extensions to a token mint to add more functionality -to it. A full list of the extensions can be found in the -[Getting Started Guide](https://solana.com/developers/guides/token-extensions/getting-started) - -| Example Name | Description | Language | -| --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -------- | -| [Basics](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/basics/anchor) | How to create a token, mint and transfer it. | Anchor | -| [Default account state](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/default-account-state/native) | This extension lets you create token accounts with a certain state, for example frozen. | Native | -| [Mint Close Authority](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/mint-close-authority) | With the old token program it was not possible to close a mint. Now it is. | Native | -| [Multiple Extensions](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/multiple-extensions) | Shows you how you can add multiple extensions to a single mint | Native | -| [NFT Metadata pointer](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/nft-meta-data-pointer) | It is possible to use the metadata extension to create NFTs and add dynamic on chain metadata. | Anchor | -| [Not Transferable](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/non-transferable/native) | Useful for example for achievements, referral programs or any soul bound tokens. | Native | -| [Transfer fee](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-fees) | Every transfer of the tokens hold some tokens back in the token account which can then be collected. | Native | -| [Transfer Hook](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-hook) | Four examples to add additional functionality to your token using a CPI from the token program into your program. | Anchor | - -## Break - -[Break](https://break.solana.com/) is a React app that gives users a visceral -feeling for just how fast and high-performance the Solana network really is. Can -you _break_ the Solana blockchain? During a 15 second play-through, each click -of a button or keystroke sends a new transaction to the cluster. Smash the -keyboard as fast as you can and watch your transactions get finalized in -real-time while the network takes it all in stride! - -Break can be played on our Devnet, Testnet and Mainnet Beta networks. Plays are -free on Devnet and Testnet, where the session is funded by a network faucet. On -Mainnet Beta, users pay to play 0.08 SOL per game. The session account can be -funded by a local keystore wallet or by scanning a QR code from Trust Wallet to -transfer the tokens. - -[Click here to play Break](https://break.solana.com/) - -### Build and Run - -First fetch the latest version of the example code: - -```shell -git clone https://github.com/solana-labs/break.git -cd break -``` - -Next, follow the steps in the git repository's -[README](https://github.com/solana-labs/break/blob/main/README.md). diff --git a/docs/uk/programs/faq.md b/docs/uk/programs/faq.md deleted file mode 100644 index c478fa37d..000000000 --- a/docs/uk/programs/faq.md +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: "FAQ" -sidebarSortOrder: 7 ---- - -Post your questions on -[StackExchange](https://solana.stackexchange.com/questions/ask). - -## Berkeley Packet Filter (BPF) - -Solana onchain programs are compiled via the -[LLVM compiler infrastructure](https://llvm.org/) to an -[Executable and Linkable Format (ELF)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) -containing a variation of the -[Berkeley Packet Filter (BPF)](https://en.wikipedia.org/wiki/Berkeley_Packet_Filter) -bytecode. - -Because Solana uses the LLVM compiler infrastructure, a program may be written -in any programming language that can target the LLVM's BPF backend. - -BPF provides an efficient -[instruction set](https://github.com/iovisor/bpf-docs/blob/master/eBPF.md) that -can be executed in an interpreted virtual machine or as efficient just-in-time -compiled native instructions. - -## Memory map - -The virtual address memory map used by Solana SBF programs is fixed and laid out -as follows - -- Program code starts at 0x100000000 -- Stack data starts at 0x200000000 -- Heap data starts at 0x300000000 -- Program input parameters start at 0x400000000 - -The above virtual addresses are start addresses but programs are given access to -a subset of the memory map. The program will panic if it attempts to read or -write to a virtual address that it was not granted access to, and an -`AccessViolation` error will be returned that contains the address and size of -the attempted violation. - -## InvalidAccountData - -This program error can happen for a lot of reasons. Usually, it's caused by -passing an account to the program that the program is not expecting, either in -the wrong position in the instruction or an account not compatible with the -instruction being executed. - -An implementation of a program might also cause this error when performing a -cross-program instruction and forgetting to provide the account for the program -that you are calling. - -## InvalidInstructionData - -This program error can occur while trying to deserialize the instruction, check -that the structure passed in matches exactly the instruction. There may be some -padding between fields. If the program implements the Rust `Pack` trait then try -packing and unpacking the instruction type `T` to determine the exact encoding -the program expects. - -## MissingRequiredSignature - -Some instructions require the account to be a signer; this error is returned if -an account is expected to be signed but is not. - -An implementation of a program might also cause this error when performing a -[cross-program invocation](/docs/core/cpi.md) that requires a signed program -address, but the passed signer seeds passed to `invoke_signed` don't match the -signer seeds used to create the program address -[`create_program_address`](/docs/core/pda.md#createprogramaddress). - -## Stack - -SBF uses stack frames instead of a variable stack pointer. Each stack frame is -4KB in size. - -If a program violates that stack frame size, the compiler will report the -overrun as a warning. - -For example: - -```text -Error: Function _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E Stack offset of -30728 exceeded max offset of -4096 by 26632 bytes, please minimize large stack variables -``` - -The message identifies which symbol is exceeding its stack frame, but the name -might be mangled. - -> To demangle a Rust symbol use [rustfilt](https://github.com/luser/rustfilt). - -The above warning came from a Rust program, so the demangled symbol name is: - -```shell -rustfilt _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E -curve25519_dalek::edwards::EdwardsBasepointTable::create -``` - -The reason a warning is reported rather than an error is because some dependent -crates may include functionality that violates the stack frame restrictions even -if the program doesn't use that functionality. If the program violates the stack -size at runtime, an `AccessViolation` error will be reported. - -SBF stack frames occupy a virtual address range starting at `0x200000000`. - -## Heap size - -Programs have access to a runtime heap via the Rust `alloc` APIs. To facilitate -fast allocations, a simple 32KB bump heap is utilized. The heap does not support -`free` or `realloc`. - -Internally, programs have access to the 32KB memory region starting at virtual -address 0x300000000 and may implement a custom heap based on the program's -specific needs. - -Rust programs implement the heap directly by defining a custom -[`global_allocator`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/entrypoint.rs#L72) - -## Loaders - -Programs are deployed with and executed by runtime loaders, currently there are -two supported loaders -[BPF Loader](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader.rs#L17) -and -[BPF loader deprecated](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader_deprecated.rs#L14) - -Loaders may support different application binary interfaces so developers must -write their programs for and deploy them to the same loader. If a program -written for one loader is deployed to a different one the result is usually a -`AccessViolation` error due to mismatched deserialization of the program's input -parameters. - -For all practical purposes program should always be written to target the latest -BPF loader and the latest loader is the default for the command-line interface -and the javascript APIs. - -- [Rust program entrypoints](/docs/programs/lang-rust.md#program-entrypoint) - -### Deployment - -SBF program deployment is the process of uploading a BPF shared object into a -program account's data and marking the account executable. A client breaks the -SBF shared object into smaller pieces and sends them as the instruction data of -[`Write`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/loader_instruction.rs#L13) -instructions to the loader where loader writes that data into the program's -account data. Once all the pieces are received the client sends a -[`Finalize`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/loader_instruction.rs#L30) -instruction to the loader, the loader then validates that the SBF data is valid -and marks the program account as _executable_. Once the program account is -marked executable, subsequent transactions may issue instructions for that -program to process. - -When an instruction is directed at an executable SBF program the loader -configures the program's execution environment, serializes the program's input -parameters, calls the program's entrypoint, and reports any errors encountered. - -For further information, see [deploying programs](/docs/programs/deploying.md). - -### Input Parameter Serialization - -SBF loaders serialize the program input parameters into a byte array that is -then passed to the program's entrypoint, where the program is responsible for -deserializing it on-chain. One of the changes between the deprecated loader and -the current loader is that the input parameters are serialized in a way that -results in various parameters falling on aligned offsets within the aligned byte -array. This allows deserialization implementations to directly reference the -byte array and provide aligned pointers to the program. - -- [Rust program parameter deserialization](/docs/programs/lang-rust.md#parameter-deserialization) - -The latest loader serializes the program input parameters as follows (all -encoding is little endian): - -- 8 bytes unsigned number of accounts -- For each account - - 1 byte indicating if this is a duplicate account, if not a duplicate then - the value is 0xff, otherwise the value is the index of the account it is a - duplicate of. - - If duplicate: 7 bytes of padding - - If not duplicate: - - 1 byte boolean, true if account is a signer - - 1 byte boolean, true if account is writable - - 1 byte boolean, true if account is executable - - 4 bytes of padding - - 32 bytes of the account public key - - 32 bytes of the account's owner public key - - 8 bytes unsigned number of lamports owned by the account - - 8 bytes unsigned number of bytes of account data - - x bytes of account data - - 10k bytes of padding, used for realloc - - enough padding to align the offset to 8 bytes. - - 8 bytes rent epoch -- 8 bytes of unsigned number of instruction data -- x bytes of instruction data -- 32 bytes of the program id diff --git a/docs/uk/programs/limitations.md b/docs/uk/programs/limitations.md deleted file mode 100644 index 1ec59ccc3..000000000 --- a/docs/uk/programs/limitations.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: "Limitations" -sidebarSortOrder: 6 ---- - -Developing programs on the Solana blockchain have some inherent limitation -associated with them. Below is a list of common limitation that you may run -into. - -## Rust libraries - -Since Rust based onchain programs must run be deterministic while running in a -resource-constrained, single-threaded environment, they have some limitations on -various libraries. - -On-chain Rust programs support most of Rust's libstd, libcore, and liballoc, as -well as many 3rd party crates. - -There are some limitations since these programs run in a resource-constrained, -single-threaded environment, as well as being deterministic: - -- No access to - - `rand` - - `std::fs` - - `std::net` - - `std::future` - - `std::process` - - `std::sync` - - `std::task` - - `std::thread` - - `std::time` -- Limited access to: - - `std::hash` - - `std::os` -- Bincode is extremely computationally expensive in both cycles and call depth - and should be avoided -- String formatting should be avoided since it is also computationally - expensive. -- No support for `println!`, `print!`, use the - [`msg!`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/log.rs#L33) - macro instead. -- The runtime enforces a limit on the number of instructions a program can - execute during the processing of one instruction. See - [computation budget](/docs/core/fees.md#compute-budget) for more information. - -## Compute budget - -To prevent abuse of the blockchain's computational resources, each transaction -is allocated a [compute budget](/docs/terminology.md#compute-budget). Exceeding -this compute budget will result in the transaction failing. - -See the [computational constraints](/docs/core/fees.md#compute-budget) -documentation for more specific details. - -## Call stack depth - `CallDepthExceeded` error - -Solana programs are constrained to run quickly, and to facilitate this, the -program's call stack is limited to a max depth of **64 frames**. - -When a program exceeds the allowed call stack depth limit, it will receive the -`CallDepthExceeded` error. - -## CPI call depth - `CallDepth` error - -Cross-program invocations allow programs to invoke other programs directly, but -the depth is constrained currently to `4`. - -When a program exceeds the allowed -[cross-program invocation call depth](/docs/core/cpi.md), it will receive a -`CallDepth` error - -## Float Rust types support - -Programs support a limited subset of Rust's float operations. If a program -attempts to use a float operation that is not supported, the runtime will report -an unresolved symbol error. - -Float operations are performed via software libraries, specifically LLVM's float -built-ins. Due to the software emulated, they consume more compute units than -integer operations. In general, fixed point operations are recommended where -possible. - -The -[Solana Program Library math](https://github.com/solana-labs/solana-program-library/tree/master/libraries/math) -tests will report the performance of some math operations. To run the test, sync -the repo and run: - -```shell -cargo test-sbf -- --nocapture --test-threads=1 -``` - -Recent results show the float operations take more instructions compared to -integers equivalents. Fixed point implementations may vary but will also be less -than the float equivalents: - -```text - u64 f32 -Multiply 8 176 -Divide 9 219 -``` - -## Static writable data - -Program shared objects do not support writable shared data. Programs are shared -between multiple parallel executions using the same shared read-only code and -data. This means that developers should not include any static writable or -global variables in programs. In the future a copy-on-write mechanism could be -added to support writable data. - -## Signed division - -The SBF instruction set does not support signed division. diff --git a/docs/uk/programs/rust/index.md b/docs/uk/programs/rust/index.md deleted file mode 100644 index 7fe456337..000000000 --- a/docs/uk/programs/rust/index.md +++ /dev/null @@ -1,474 +0,0 @@ ---- -title: Developing Programs in Rust -description: - Learn how to develop Solana programs using Rust, including step-by-step - instructions for creating, building, testing, and deploying smart contracts on - the Solana blockchain. -sidebarLabel: Rust Programs -sidebarSortOrder: 1 -altRoutes: - - /docs/programs/lang-rust ---- - -Solana programs are primarily developed using the Rust programming language. -This page focuses on writing Solana programs in Rust without using the Anchor -framework, an approach often referred to as writing "native Rust" programs. - -Native Rust development provides developers with direct control over their -Solana programs. However, this approach requires more manual setup and -boilerplate code compared to using the Anchor framework. This method is -recommended for developers who: - -- Seek granular control over program logic and optimizations -- Want to learn the underlying concepts before moving to higher-level frameworks - -For beginners, we recommend starting with the Anchor framework. See the -[Anchor](/docs/programs/anchor) section for more information. - -## Prerequisites - -For detailed installation instructions, visit the -[installation](/docs/intro/installation) page. - -Before you begin, ensure you have the following installed: - -- Rust: The programming language for building Solana programs. -- Solana CLI: Command-line tool for Solana development. - -## Getting Started - -The example below covers the basic steps to create your first Solana program -written in Rust. We'll create a minimal program that prints "Hello, world!" to -the program log. - - - -### Create a new Program - -First, create a new Rust project using the standard `cargo init` command with -the `--lib` flag. - -```shell filename="Terminal" -cargo init hello_world --lib -``` - -Navigate to the project directory. You should see the default `src/lib.rs` and -`Cargo.toml` files - -```shell filename="Terminal" -cd hello_world -``` - -Next, add the `solana-program` dependency. This is the minimum dependency -required to build a Solana program. - -```shell filename="Terminal" -cargo add solana-program@1.18.26 -``` - -Next, add the following snippet to `Cargo.toml`. If you don't include this -config, the `target/deploy` directory will not be generated when you build the -program. - -```toml filename="Cargo.toml" -[lib] -crate-type = ["cdylib", "lib"] -``` - -Your `Cargo.toml` file should look like the following: - -```toml filename="Cargo.toml" -[package] -name = "hello_world" -version = "0.1.0" -edition = "2021" - -[lib] -crate-type = ["cdylib", "lib"] - -[dependencies] -solana-program = "1.18.26" -``` - -Next, replace the contents of `src/lib.rs` with the following code. This is a -minimal Solana program that prints "Hello, world!" to the program log when the -program is invoked. - -The `msg!` macro is used in Solana programs to print a message to the program -log. - -```rs filename="lib.rs" -use solana_program::{ - account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey, -}; - -entrypoint!(process_instruction); - -pub fn process_instruction( - _program_id: &Pubkey, - _accounts: &[AccountInfo], - _instruction_data: &[u8], -) -> ProgramResult { - msg!("Hello, world!"); - Ok(()) -} -``` - -### Build the Program - -Next, build the program using the `cargo build-sbf` command. - -```shell filename="Terminal" -cargo build-sbf -``` - -This command generates a `target/deploy` directory containing two important -files: - -1. A `.so` file (e.g., `hello_world.so`): This is the compiled Solana program - that will be deployed to the network as a "smart contract". -2. A keypair file (e.g., `hello_world-keypair.json`): The public key of this - keypair is used as the program ID when deploying the program. - -To view the program ID, run the following command in your terminal. This command -prints the public key of the keypair at the specified file path: - -```shell filename="Terminal" -solana address -k ./target/deploy/hello_world-keypair.json -``` - -Example output: - -``` -4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz -``` - -### Test the Program - -Next, test the program using the `solana-program-test` crate. Add the following -dependencies to `Cargo.toml`. - -```shell filename="Terminal" -cargo add solana-program-test@1.18.26 --dev -cargo add solana-sdk@1.18.26 --dev -cargo add tokio --dev -``` - -Add the following test to `src/lib.rs`, below the program code. This is a test -module that invokes the hello world program. - -```rs filename="lib.rs" -#[cfg(test)] -mod test { - use super::*; - use solana_program_test::*; - use solana_sdk::{signature::Signer, transaction::Transaction}; - - #[tokio::test] - async fn test_hello_world() { - let program_id = Pubkey::new_unique(); - let (mut banks_client, payer, recent_blockhash) = - ProgramTest::new("hello_world", program_id, processor!(process_instruction)) - .start() - .await; - - // Create the instruction to invoke the program - let instruction = - solana_program::instruction::Instruction::new_with_borsh(program_id, &(), vec![]); - - // Add the instruction to a new transaction - let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); - transaction.sign(&[&payer], recent_blockhash); - - // Process the transaction - let transaction_result = banks_client.process_transaction(transaction).await; - assert!(transaction_result.is_ok()); - } -} -``` - -Run the test using the `cargo test-sbf` command. The program log will display -"Hello, world!". - -```shell filename="Terminal" -cargo test-sbf -``` - -Example output: - -```shell filename="Terminal" {4} /Program log: Hello, world!/ -running 1 test -[2024-10-18T21:24:54.889570000Z INFO solana_program_test] "hello_world" SBF program from /hello_world/target/deploy/hello_world.so, modified 35 seconds, 828 ms, 268 µs and 398 ns ago -[2024-10-18T21:24:54.974294000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM invoke [1] -[2024-10-18T21:24:54.974814000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, world! -[2024-10-18T21:24:54.976848000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM consumed 140 of 200000 compute units -[2024-10-18T21:24:54.976868000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM success -test test::test_hello_world ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.13s -``` - -### Deploy the Program - -Next, deploy the program. When developing locally, we can use the -`solana-test-validator`. - -First, configure the Solana CLI to use the local Solana cluster. - -```shell filename="Terminal" -solana config set -ul -``` - -Example output: - -``` -Config File: /.config/solana/cli/config.yml -RPC URL: http://localhost:8899 -WebSocket URL: ws://localhost:8900/ (computed) -Keypair Path: /.config/solana/id.json -Commitment: confirmed -``` - -Open a new terminal and run the `solana-test-validators` command to start the -local validator. - -```shell filename="Terminal" -solana-test-validator -``` - -While the test validator is running, run the `solana program deploy` command in -a separate terminal to deploy the program to the local validator. - -```shell filename="Terminal" -solana program deploy ./target/deploy/hello_world.so -``` - -Example output: - -``` -Program Id: 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz -Signature: -5osMiNMiDZGM7L1e2tPHxU8wdB8gwG8fDnXLg5G7SbhwFz4dHshYgAijk4wSQL5cXiu8z1MMou5kLadAQuHp7ybH -``` - -You can inspect the program ID and transaction signature on -[Solana Explorer](https://explorer.solana.com/?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899). -Note that the cluster on Solana Explorer must also be localhost. The "Custom RPC -URL" option on Solana Explorer defaults to `http://localhost:8899`. - -### Invoke the Program - -Next, we'll demonstrate how to invoke the program using a Rust client. - -First create an `examples` directory and a `client.rs` file. - -```shell filename="Terminal" -mkdir -p examples -touch examples/client.rs -``` - -Add the following to `Cargo.toml`. - -```toml filename="Cargo.toml" -[[example]] -name = "client" -path = "examples/client.rs" -``` - -Add the `solana-client` dependency. - -```shell filename="Terminal" -cargo add solana-client@1.18.26 --dev -``` - -Add the following code to `examples/client.rs`. This is a Rust client script -that funds a new keypair to pay for transaction fees and then invokes the hello -world program. - -```rs filename="example/client.rs" -use solana_client::rpc_client::RpcClient; -use solana_sdk::{ - commitment_config::CommitmentConfig, - instruction::Instruction, - pubkey::Pubkey, - signature::{Keypair, Signer}, - transaction::Transaction, -}; -use std::str::FromStr; - -#[tokio::main] -async fn main() { - // Program ID (replace with your actual program ID) - let program_id = Pubkey::from_str("4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz").unwrap(); - - // Connect to the Solana devnet - let rpc_url = String::from("http://127.0.0.1:8899"); - let client = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed()); - - // Generate a new keypair for the payer - let payer = Keypair::new(); - - // Request airdrop - let airdrop_amount = 1_000_000_000; // 1 SOL - let signature = client - .request_airdrop(&payer.pubkey(), airdrop_amount) - .expect("Failed to request airdrop"); - - // Wait for airdrop confirmation - loop { - let confirmed = client.confirm_transaction(&signature).unwrap(); - if confirmed { - break; - } - } - - // Create the instruction - let instruction = Instruction::new_with_borsh( - program_id, - &(), // Empty instruction data - vec![], // No accounts needed - ); - - // Add the instruction to new transaction - let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); - transaction.sign(&[&payer], client.get_latest_blockhash().unwrap()); - - // Send and confirm the transaction - match client.send_and_confirm_transaction(&transaction) { - Ok(signature) => println!("Transaction Signature: {}", signature), - Err(err) => eprintln!("Error sending transaction: {}", err), - } -} -``` - -Before running the script, replace the program ID in the code snippet above with -the one for your program. - -You can get your program ID by running the following command. - -```shell filename="Terminal" -solana address -k ./target/deploy/hello_world-keypair.json -``` - -```diff -#[tokio::main] -async fn main() { -- let program_id = Pubkey::from_str("4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz").unwrap(); -+ let program_id = Pubkey::from_str("YOUR_PROGRAM_ID).unwrap(); - } -} -``` - -Run the client script with the following command. - -```shell filename="Terminal" -cargo run --example client -``` - -Example output: - -``` -Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77bAACjKAS9fGnVeEazrXL4SfKrW7xZFYV -``` - -You can inspect the transaction signature on -[Solana Explorer](https://explorer.solana.com/?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899) -(local cluster) to see "Hello, world!" in the program log. - -### Update the Program - -Solana programs can be updated by redeploying to the same program ID. Update the -program in `src/lib.rs` to print "Hello, Solana!" instead of "Hello, world!". - -```diff filename="lib.rs" -pub fn process_instruction( - _program_id: &Pubkey, - _accounts: &[AccountInfo], - _instruction_data: &[u8], -) -> ProgramResult { -- msg!("Hello, world!"); -+ msg!("Hello, Solana!"); - Ok(()) -} -``` - -Test the updated program by running the `cargo test-sbf` command. - -```shell filename="Terminal" -cargo test-sbf -``` - -You should see "Hello, Solana!" in the program log. - -```shell filename="Terminal" {4} -running 1 test -[2024-10-23T19:28:28.842639000Z INFO solana_program_test] "hello_world" SBF program from /code/misc/delete/hello_world/target/deploy/hello_world.so, modified 4 minutes, 31 seconds, 435 ms, 566 µs and 766 ns ago -[2024-10-23T19:28:28.934854000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM invoke [1] -[2024-10-23T19:28:28.936735000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, Solana! -[2024-10-23T19:28:28.938774000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM consumed 140 of 200000 compute units -[2024-10-23T19:28:28.938793000Z DEBUG solana_runtime::message_processor::stable_log] Program 1111111QLbz7JHiBTspS962RLKV8GndWFwiEaqKM success -test test::test_hello_world ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.14s -``` - -Run the `cargo build-sbf` command to generate an updated `.so` file. - -```shell filename="Terminal" -cargo build-sbf -``` - -Redeploy the program using the `solana program deploy` command. - -```shell filename="Terminal" -solana program deploy ./target/deploy/hello_world.so -``` - -Run the client code again and inspect the transaction signature on Solana -Explorer to see "Hello, Solana!" in the program log. - -```shell filename="Terminal" -cargo run --example client -``` - -### Close the Program - -You can close your Solana program to reclaim the SOL allocated to the account. -Closing a program is irreversible, so it should be done with caution. - -To close a program, use the `solana program close ` command. For -example: - -```shell filename="Terminal" -solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz ---bypass-warning -``` - -Example output: - -``` -Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOL -reclaimed -``` - -Note that once a program is closed, its program ID cannot be reused. Attempting -to deploy a program with a previously closed program ID will result in an error. - -``` -Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, use -a new Program Id -``` - -If you need to redeploy a program with the same source code after closing a -program, you must generate a new program ID. To generate a new keypair for the -program, run the following command: - -```shell filename="Terminal" -solana-keygen new -o ./target/deploy/hello_world-keypair.json --force -``` - -Alternatively, you can delete the existing keypair file (e.g. -`./target/deploy/hello_world-keypair.json`) and run `cargo build-sbf` again, -which will generate a new keypair file. - - From b285aa21bc800fa2c5942a94eb4e4f05ffda6dfc Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Tue, 14 Jan 2025 22:37:58 +0200 Subject: [PATCH 11/14] added required field for testing.md. Build fix --- docs/locales/uk/programs/testing.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/locales/uk/programs/testing.md b/docs/locales/uk/programs/testing.md index dbd7711fa..663653121 100644 --- a/docs/locales/uk/programs/testing.md +++ b/docs/locales/uk/programs/testing.md @@ -1,3 +1,9 @@ +--- +title: "Тестування з NodeJS" +description: "Тестування нативних solana programs написаних Rust використовуючи NodeJS" +sidebarSortOrder: 5 +--- + ## Тестування з NodeJS Коли ви розробляєте програми на Solana, важливо забезпечити їхню правильність і надійність. До цього часу розробники використовували `solana-test-validator` для тестування. Цей документ описує тестування вашої програми Solana за допомогою Node.js і бібліотеки `solana-bankrun`. From bad31928e6dc93a5bdb1dda54120a663433b950e Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Tue, 14 Jan 2025 22:44:15 +0200 Subject: [PATCH 12/14] Prettier issues fix --- docs/locales/uk/advanced/actions.md | 626 ++++++++++++------ docs/locales/uk/advanced/confirmation.md | 337 +++++++--- docs/locales/uk/advanced/lookup-tables.md | 91 ++- docs/locales/uk/advanced/retry.md | 115 +++- docs/locales/uk/advanced/state-compression.md | 166 +++-- docs/locales/uk/advanced/versions.md | 54 +- .../uk/clients/javascript-reference.md | 130 +++- docs/locales/uk/clients/javascript.md | 117 +++- docs/locales/uk/clients/rust.md | 24 +- docs/locales/uk/core/accounts.md | 160 +++-- docs/locales/uk/core/clusters.md | 45 +- docs/locales/uk/core/cpi.md | 39 +- docs/locales/uk/core/fees.md | 411 +++++++++--- docs/locales/uk/core/index.md | 84 ++- docs/locales/uk/core/pda.md | 125 ++-- docs/locales/uk/core/programs.md | 104 +-- docs/locales/uk/core/tokens.md | 308 +++++---- docs/locales/uk/core/transactions.md | 193 ++++-- docs/locales/uk/economics/index.md | 43 +- .../inflation/_adjusted_staking_yield.md | 45 +- .../economics/inflation/inflation-schedule.md | 69 +- .../uk/economics/inflation/terminology.md | 76 ++- docs/locales/uk/economics/staking/index.md | 103 +-- .../uk/economics/staking/stake-accounts.md | 57 +- .../uk/economics/staking/stake-programming.md | 24 +- docs/locales/uk/index.md | 88 ++- docs/locales/uk/intro/dev.md | 150 +++-- docs/locales/uk/intro/installation.md | 201 ++++-- .../quick-start/cross-program-invocation.md | 153 +++-- .../intro/quick-start/deploying-programs.md | 115 ++-- docs/locales/uk/intro/quick-start/index.md | 61 +- .../quick-start/program-derived-address.md | 227 ++++--- .../intro/quick-start/reading-from-network.md | 153 +++-- .../intro/quick-start/writing-to-network.md | 59 +- docs/locales/uk/intro/wallets.md | 53 +- docs/locales/uk/more/exchange.md | 586 ++++++++++++---- .../uk/programs/anchor/client-typescript.md | 112 ++-- docs/locales/uk/programs/anchor/cpi.md | 149 +++-- docs/locales/uk/programs/anchor/idl.md | 82 ++- docs/locales/uk/programs/anchor/index.md | 104 +-- docs/locales/uk/programs/anchor/pda.md | 88 ++- .../uk/programs/anchor/program-structure.md | 94 ++- docs/locales/uk/programs/deploying.md | 188 +++--- docs/locales/uk/programs/examples.md | 146 ++-- docs/locales/uk/programs/faq.md | 157 +++-- docs/locales/uk/programs/limitations.md | 62 +- docs/locales/uk/programs/rust/index.md | 102 +-- .../uk/programs/rust/program-structure.md | 186 +++--- docs/locales/uk/programs/testing.md | 90 ++- docs/locales/uk/rpc.md | 6 +- docs/locales/uk/terminology.md | 291 +++++--- 51 files changed, 4875 insertions(+), 2374 deletions(-) diff --git a/docs/locales/uk/advanced/actions.md b/docs/locales/uk/advanced/actions.md index 0debc4c69..22a93fa1f 100644 --- a/docs/locales/uk/advanced/actions.md +++ b/docs/locales/uk/advanced/actions.md @@ -4,8 +4,8 @@ title: "Дії та Блінки" seoTitle: "Дії та Блінки" description: "Дії Solana — це API, які повертають транзакції для попереднього перегляду і - підпису користувачами. Посилання на блокчейн — або блінки — перетворюють дії - в зручні, багаті на метадані посилання для спільного використання." + підпису користувачами. Посилання на блокчейн — або блінки — перетворюють дії в + зручні, багаті на метадані посилання для спільного використання." altRoutes: - /docs/actions - /docs/blinks @@ -16,16 +16,16 @@ altRoutes: транзакції в блокчейні Solana для попереднього перегляду, підпису та відправки. Вони можуть використовуватися в різних контекстах, таких як QR-коди, кнопки, віджети та вебсайти. Дії дозволяють розробникам легко інтегрувати функціонал -екосистеми Solana у свій додаток, дозволяючи виконувати блокчейн-транзакції -без необхідності переходу на інші сторінки або додатки. +екосистеми Solana у свій додаток, дозволяючи виконувати блокчейн-транзакції без +необхідності переходу на інші сторінки або додатки. [Посилання на блокчейн](#blinks) — або блінки — перетворюють будь-яку дію Solana в зручне посилання, багате метаданими. Блінки дозволяють клієнтам, які підтримують їх, (таким як гаманці або боти) відображати додаткові функціональні можливості. Наприклад, на вебсайті блінк може негайно відкрити попередній перегляд транзакції у гаманці, а в Discord бот може перетворити блінк на -інтерактивні кнопки. Це забезпечує взаємодію з блокчейном на будь-якій платформі, -що підтримує URL. +інтерактивні кнопки. Це забезпечує взаємодію з блокчейном на будь-якій +платформі, що підтримує URL. ## Початок роботи @@ -35,15 +35,16 @@ altRoutes: npm install @solana/actions ``` -- встановіть [Solana Actions SDK](https://www.npmjs.com/package/@solana/actions) у вашому додатку +- встановіть [Solana Actions SDK](https://www.npmjs.com/package/@solana/actions) + у вашому додатку - створіть API-ендпойнт для [GET-запиту](#get-request), який повертає метадані про вашу дію - створіть API-ендпойнт для [POST-запиту](#post-request), який повертає транзакцію для підпису користувачем > Перегляньте цей відеоурок про -> [створення дії Solana](https://www.youtube.com/watch?v=kCht01Ycif0) за допомогою -> `@solana/actions` SDK. +> [створення дії Solana](https://www.youtube.com/watch?v=kCht01Ycif0) за +> допомогою `@solana/actions` SDK. > > Ви також можете знайти > [вихідний код дії](https://github.com/solana-developers/solana-actions/blob/main/examples/next-js/src/app/api/actions/transfer-sol/route.ts), @@ -68,22 +69,21 @@ npm install @solana/actions ## Дії Специфікація дій Solana використовує набір стандартних API для передачі -транзакцій (та, зрештою, повідомлень) для підпису безпосередньо користувачам. -Ці API доступні за публічними URL, які можуть взаємодіяти з будь-якими клієнтами. +транзакцій (та, зрештою, повідомлень) для підпису безпосередньо користувачам. Ці +API доступні за публічними URL, які можуть взаємодіяти з будь-якими клієнтами. -> Дії можна уявити як API-ендпойнт, який повертає метадані та об'єкт для -> підпису користувачем (транзакцію або повідомлення для аутентифікації) за -> допомогою їх блокчейн-гаманця. +> Дії можна уявити як API-ендпойнт, який повертає метадані та об'єкт для підпису +> користувачем (транзакцію або повідомлення для аутентифікації) за допомогою їх +> блокчейн-гаманця. API дій складається з простих `GET` і `POST` запитів до URL-ендпойнтів дій та обробки відповідей, які відповідають інтерфейсу дій. -1. [GET-запит](#get-request) повертає метадані, які надають клієнту - інформацію про доступні дії за цим URL, а також список пов’язаних дій (за - бажанням). -2. [POST-запит](#post-request) повертає транзакцію або повідомлення для - підпису, які клієнт відображає в гаманці користувача для підпису та виконання - у блокчейні або іншому офчейн-сервісі. +1. [GET-запит](#get-request) повертає метадані, які надають клієнту інформацію + про доступні дії за цим URL, а також список пов’язаних дій (за бажанням). +2. [POST-запит](#post-request) повертає транзакцію або повідомлення для підпису, + які клієнт відображає в гаманці користувача для підпису та виконання у + блокчейні або іншому офчейн-сервісі. ### Виконання дії та життєвий цикл @@ -116,16 +116,16 @@ API дій складається з простих `GET` і `POST` запиті ## Блінки -Блінки (посилання на блокчейн) — це клієнтські програми, які аналізують API -дій і створюють інтерфейси користувача для взаємодії з діями та їх виконання. +Блінки (посилання на блокчейн) — це клієнтські програми, які аналізують API дій +і створюють інтерфейси користувача для взаємодії з діями та їх виконання. Клієнтські програми, що підтримують блінки, виявляють URL, сумісні з діями, аналізують їх і дозволяють користувачам взаємодіяти з ними у стандартизованих інтерфейсах. > Будь-яка клієнтська програма, яка повністю аналізує API дій для створення -> повноцінного інтерфейсу, є _блінком_. Отже, не всі клієнти, які -> використовують API дій, є блінками. +> повноцінного інтерфейсу, є _блінком_. Отже, не всі клієнти, які використовують +> API дій, є блінками. ### Специфікація URL блінків @@ -141,7 +141,8 @@ https://example.domain/?action= - URL блінка повинен містити параметр запиту `action`, значення якого має бути [URL-кодованим](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) - [URL дії](#url-scheme). Це значення має бути закодоване, щоб уникнути конфліктів з іншими параметрами протоколу. + [URL дії](#url-scheme). Це значення має бути закодоване, щоб уникнути + конфліктів з іншими параметрами протоколу. - Клієнтська програма повинна [декодувати URL](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent) @@ -149,8 +150,9 @@ https://example.domain/?action= [Схему URL дії](#url-scheme)). - Клієнт повинен відобразити багатий інтерфейс користувача, який дозволяє - завершити повний [життєвий цикл виконання дії](#action-execution-and-lifecycle), - включаючи підписання у гаманці. + завершити повний + [життєвий цикл виконання дії](#action-execution-and-lifecycle), включаючи + підписання у гаманці. > Не всі клієнтські програми-блінки (наприклад, вебсайти або децентралізовані > додатки) підтримуватимуть усі дії. Розробники додатків можуть обирати, які дії @@ -167,8 +169,7 @@ https://example.domain/?action=solana-action%3Ahttps%3A%2F%2Factions.alice.com%2 Блінки можуть бути пов’язані з діями щонайменше трьома способами: -1. Поширення явного URL дії: - `solana-action:https://actions.alice.com/donate` +1. Поширення явного URL дії: `solana-action:https://actions.alice.com/donate` У цьому випадку лише клієнти, які підтримують блінки, можуть відобразити блінк. Не буде доступного попереднього перегляду посилання або сайту, який @@ -178,9 +179,9 @@ https://example.domain/?action=solana-action%3Ahttps%3A%2F%2Factions.alice.com%2 [`actions.json`](#actionsjson) у кореневій директорії домену вебсайту. Наприклад, `https://alice.com/actions.json` зіставляє - `https://alice.com/donate`, URL вебсайту, на якому користувачі можуть - зробити пожертву для Alice, з API URL `https://actions.alice.com/donate`, на - якому хостяться дії для пожертвування Alice. + `https://alice.com/donate`, URL вебсайту, на якому користувачі можуть зробити + пожертву для Alice, з API URL `https://actions.alice.com/donate`, на якому + хостяться дії для пожертвування Alice. 3. Вбудовування URL дії у "перехідний" URL сайту, який розуміє, як аналізувати дії. @@ -211,8 +212,8 @@ https://example.domain/?action=solana-action%3Ahttps%3A%2F%2Factions.alice.com%2 > всі введення для кожної з ваших пов'язаних дій. Кожен клієнтський додаток або гаманець може мати різні вимоги щодо того, які -ендпойнти дій будуть автоматично розгортатися й негайно відображатися користувачам -на платформах соціальних мереж. +ендпойнти дій будуть автоматично розгортатися й негайно відображатися +користувачам на платформах соціальних мереж. Наприклад, деякі клієнти можуть працювати за підходом "список дозволених" і вимагати верифікації перед розгортанням дії для користувачів, як це робить @@ -223,16 +224,16 @@ https://example.domain/?action=solana-action%3Ahttps%3A%2F%2Factions.alice.com%2 ### Реєстр дій Dialect -Як загальне благо для екосистеми Solana, [Dialect](https://dialect.to) -підтримує публічний реєстр — разом із допомогою Solana Foundation та інших -членів спільноти — для посилань на блокчейн, які попередньо перевірені й -походять із відомих джерел. На момент запуску лише дії, зареєстровані в реєстрі -Dialect, будуть автоматично розгортатися у Twitter, коли їх публікують. +Як загальне благо для екосистеми Solana, [Dialect](https://dialect.to) підтримує +публічний реєстр — разом із допомогою Solana Foundation та інших членів +спільноти — для посилань на блокчейн, які попередньо перевірені й походять із +відомих джерел. На момент запуску лише дії, зареєстровані в реєстрі Dialect, +будуть автоматично розгортатися у Twitter, коли їх публікують. Клієнтські програми та гаманці можуть вільно використовувати цей публічний -реєстр або інші рішення, щоб забезпечити безпеку користувачів. Якщо посилання -на блокчейн не верифіковане через реєстр Dialect, воно не оброблятиметься -клієнтом блінків і буде відображатися як звичайне URL. +реєстр або інші рішення, щоб забезпечити безпеку користувачів. Якщо посилання на +блокчейн не верифіковане через реєстр Dialect, воно не оброблятиметься клієнтом +блінків і буде відображатися як звичайне URL. Розробники можуть подати заявку на верифікацію у Dialect тут: [dial.to/register](https://dial.to/register) @@ -243,16 +244,17 @@ Dialect, будуть автоматично розгортатися у Twitter процесу взаємодії запит/відповідь: - Схема URL [Solana Action](#url-scheme), яка надає URL дії -- [OPTIONS-відповідь](#options-response) на URL дії для відповідності вимогам CORS +- [OPTIONS-відповідь](#options-response) на URL дії для відповідності вимогам + CORS - [GET-запит](#get-request) до URL дії - [GET-відповідь](#get-response) із сервера - [POST-запит](#post-request) до URL дії - [POST-відповідь](#post-response) із сервера -Кожен із цих запитів надсилається _клієнтом дій_ (наприклад, гаманець, розширення -для браузера, децентралізований додаток, вебсайт тощо) для збору специфічних -метаданих для багатого інтерфейсу користувача та забезпечення вводу користувачем -до API дій. +Кожен із цих запитів надсилається _клієнтом дій_ (наприклад, гаманець, +розширення для браузера, децентралізований додаток, вебсайт тощо) для збору +специфічних метаданих для багатого інтерфейсу користувача та забезпечення вводу +користувачем до API дій. Кожна з відповідей створюється додатком (наприклад, вебсайтом, серверним додатком тощо) і повертається _клієнту дій_. Зрештою, це забезпечує транзакцію @@ -263,7 +265,8 @@ Dialect, будуть автоматично розгортатися у Twitter > полегшення читання. > > Для кращої безпеки типів і покращеного досвіду розробників пакет -> `@solana/actions-spec` містить більш складні визначення типів. Ви можете знайти +> `@solana/actions-spec` містить більш складні визначення типів. Ви можете +> знайти > [вихідний код тут](https://github.com/solana-developers/solana-actions/blob/main/packages/actions-spec/index.d.ts). ### Схема URL @@ -299,8 +302,8 @@ solana-action: ### OPTIONS-відповідь Для забезпечення крос-доменного доступу (CORS) у клієнтах дій (включаючи -блінки), усі ендпойнти дій повинні відповідати на HTTP-запити методу `OPTIONS` -з дійсними заголовками, які дозволять клієнтам проходити CORS-перевірки для всіх +блінки), усі ендпойнти дій повинні відповідати на HTTP-запити методу `OPTIONS` з +дійсними заголовками, які дозволять клієнтам проходити CORS-перевірки для всіх подальших запитів із їхнього домену. Клієнт дій може виконувати @@ -347,7 +350,8 @@ HTTP `GET` JSON-запит до URL-ендпойнта дії. ### GET-відповідь URL-ендпойнт дії (наприклад, додаток або серверний бекенд) повинен відповідати -HTTP `OK` JSON-відповіддю (з дійсним вмістом у тілі) або відповідною помилкою HTTP. +HTTP `OK` JSON-відповіддю (з дійсним вмістом у тілі) або відповідною помилкою +HTTP. - Клієнт повинен обробляти HTTP [помилки клієнта](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses), @@ -401,28 +405,56 @@ export interface Action { } ``` -- `type` - Тип дії, що надається користувачеві. За замовчуванням встановлено значення `action`. Початковий `ActionGetResponse` повинен мати тип `action`. - - - `action` - Стандартна дія, яка дозволяє користувачеві взаємодіяти з будь-якими `LinkedActions`. - - `completed` - Використовується для позначення стану "завершено" у ланцюжку дій. - -- `icon` - Значення має бути абсолютним HTTP або HTTPS URL іконки. Файл повинен бути формату SVG, PNG або WebP, інакше клієнт/гаманець повинен відхилити його як **пошкоджений**. - -- `title` - Значення має бути рядком UTF-8, що представляє джерело запиту дії. Наприклад, це може бути назва бренду, магазину, програми або особи, яка робить запит. - -- `description` - Значення має бути рядком UTF-8, що надає інформацію про дію. Опис повинен бути відображений користувачеві. - -- `label` - Значення має бути рядком UTF-8, який буде відображено на кнопці для натискання користувачем. Усі мітки не повинні перевищувати 5 слів і повинні починатися з дієслова, щоб закріпити дію, яку ви хочете, щоб користувач виконав. Наприклад, "Mint NFT", "Vote Yes" або "Stake 1 SOL". - -- `disabled` - Значення має бути логічним (boolean), щоб представляти стан вимкнення кнопки (яка відображає рядок `label`). Якщо значення не надано, `disabled` має за замовчуванням бути `false` (тобто увімкнено). Наприклад, якщо кінцева точка дії використовується для голосування, яке вже закрите, встановіть `disabled=true`, а мітка може бути "Vote Closed". - -- `error` - Необов'язковий індикатор помилки для нефатальних помилок. Якщо присутній, клієнт повинен відобразити це користувачеві. Якщо встановлено, це не повинно заважати клієнту інтерпретувати дію або відображати її користувачеві (див. [Помилки дій](#action-errors)). Наприклад, помилка може використовуватися разом із `disabled`, щоб показати причину, як-от бізнес-обмеження, авторизація, стан або помилка зовнішнього ресурсу. - -- `links.actions` - Необов'язковий масив пов'язаних дій для кінцевої точки. Користувачам повинен бути відображений інтерфейс для кожної зі вказаних дій, і очікується, що вони виконають лише одну. Наприклад, кінцева точка дії для голосування в управлінні DAO може повернути три варіанти для користувача: "Vote Yes", "Vote No" і "Abstain from Vote". - - - Якщо `links.actions` не надано, клієнт повинен відобразити одну кнопку, використовуючи кореневий рядок `label`, і виконати POST-запит до тієї самої кінцевої точки URL дії, що й початковий GET-запит. - - - Якщо будь-які `links.actions` надані, клієнт повинен відображати лише кнопки та поля введення на основі елементів, перелічених у полі `links.actions`. Клієнт не повинен відображати кнопку для вмісту кореневого `label`. +- `type` - Тип дії, що надається користувачеві. За замовчуванням встановлено + значення `action`. Початковий `ActionGetResponse` повинен мати тип `action`. + + - `action` - Стандартна дія, яка дозволяє користувачеві взаємодіяти з + будь-якими `LinkedActions`. + - `completed` - Використовується для позначення стану "завершено" у ланцюжку + дій. + +- `icon` - Значення має бути абсолютним HTTP або HTTPS URL іконки. Файл повинен + бути формату SVG, PNG або WebP, інакше клієнт/гаманець повинен відхилити його + як **пошкоджений**. + +- `title` - Значення має бути рядком UTF-8, що представляє джерело запиту дії. + Наприклад, це може бути назва бренду, магазину, програми або особи, яка робить + запит. + +- `description` - Значення має бути рядком UTF-8, що надає інформацію про дію. + Опис повинен бути відображений користувачеві. + +- `label` - Значення має бути рядком UTF-8, який буде відображено на кнопці для + натискання користувачем. Усі мітки не повинні перевищувати 5 слів і повинні + починатися з дієслова, щоб закріпити дію, яку ви хочете, щоб користувач + виконав. Наприклад, "Mint NFT", "Vote Yes" або "Stake 1 SOL". + +- `disabled` - Значення має бути логічним (boolean), щоб представляти стан + вимкнення кнопки (яка відображає рядок `label`). Якщо значення не надано, + `disabled` має за замовчуванням бути `false` (тобто увімкнено). Наприклад, + якщо кінцева точка дії використовується для голосування, яке вже закрите, + встановіть `disabled=true`, а мітка може бути "Vote Closed". + +- `error` - Необов'язковий індикатор помилки для нефатальних помилок. Якщо + присутній, клієнт повинен відобразити це користувачеві. Якщо встановлено, це + не повинно заважати клієнту інтерпретувати дію або відображати її + користувачеві (див. [Помилки дій](#action-errors)). Наприклад, помилка може + використовуватися разом із `disabled`, щоб показати причину, як-от + бізнес-обмеження, авторизація, стан або помилка зовнішнього ресурсу. + +- `links.actions` - Необов'язковий масив пов'язаних дій для кінцевої точки. + Користувачам повинен бути відображений інтерфейс для кожної зі вказаних дій, і + очікується, що вони виконають лише одну. Наприклад, кінцева точка дії для + голосування в управлінні DAO може повернути три варіанти для користувача: + "Vote Yes", "Vote No" і "Abstain from Vote". + + - Якщо `links.actions` не надано, клієнт повинен відобразити одну кнопку, + використовуючи кореневий рядок `label`, і виконати POST-запит до тієї самої + кінцевої точки URL дії, що й початковий GET-запит. + + - Якщо будь-які `links.actions` надані, клієнт повинен відображати лише кнопки + та поля введення на основі елементів, перелічених у полі `links.actions`. + Клієнт не повинен відображати кнопку для вмісту кореневого `label`. ```ts filename="LinkedAction" export interface LinkedAction { @@ -439,7 +471,8 @@ export interface LinkedAction { } ``` -`ActionParameter` дозволяє визначити, яке саме введення API дій запитує у користувача: +`ActionParameter` дозволяє визначити, яке саме введення API дій запитує у +користувача: ```ts filename="ActionParameter" /** @@ -466,15 +499,30 @@ export interface ActionParameter { } ``` -`pattern` повинен бути рядком, еквівалентним дійсному регулярному виразу. Цей регулярний вираз має використовуватися клієнтами-блінками для перевірки введення користувача перед виконанням POST-запиту. Якщо `pattern` не є дійсним регулярним виразом, клієнт повинен його ігнорувати. - -`patternDescription` — це опис, зрозумілий для людини, який пояснює очікуване введення користувача. Якщо надано `pattern`, то `patternDescription` також обов’язково має бути надано. - -Значення `min` та `max` дозволяють встановити нижню та/або верхню межу введення, запитуваного у користувача (наприклад, мінімальне/максимальне число або мінімальну/максимальну довжину рядка). Вони повинні використовуватися для клієнтської валідації. Для типів введення `date` або `datetime-local` ці значення мають бути рядками, що представляють дати. Для інших типів введення на основі рядків значення повинні бути числами, що представляють їх мінімальну/максимальну довжину символів. - -Якщо введене значення користувача не відповідає `pattern`, користувач має отримати повідомлення про помилку на стороні клієнта, що вказує на недійсність поля введення, і відображати рядок `patternDescription`. - -Поле `type` дозволяє API дій визначати більш конкретні поля введення користувача, забезпечуючи кращу валідацію на стороні клієнта та покращуючи користувацький досвід. У багатьох випадках цей тип буде подібний до стандартного +`pattern` повинен бути рядком, еквівалентним дійсному регулярному виразу. Цей +регулярний вираз має використовуватися клієнтами-блінками для перевірки введення +користувача перед виконанням POST-запиту. Якщо `pattern` не є дійсним регулярним +виразом, клієнт повинен його ігнорувати. + +`patternDescription` — це опис, зрозумілий для людини, який пояснює очікуване +введення користувача. Якщо надано `pattern`, то `patternDescription` також +обов’язково має бути надано. + +Значення `min` та `max` дозволяють встановити нижню та/або верхню межу введення, +запитуваного у користувача (наприклад, мінімальне/максимальне число або +мінімальну/максимальну довжину рядка). Вони повинні використовуватися для +клієнтської валідації. Для типів введення `date` або `datetime-local` ці +значення мають бути рядками, що представляють дати. Для інших типів введення на +основі рядків значення повинні бути числами, що представляють їх +мінімальну/максимальну довжину символів. + +Якщо введене значення користувача не відповідає `pattern`, користувач має +отримати повідомлення про помилку на стороні клієнта, що вказує на недійсність +поля введення, і відображати рядок `patternDescription`. + +Поле `type` дозволяє API дій визначати більш конкретні поля введення +користувача, забезпечуючи кращу валідацію на стороні клієнта та покращуючи +користувацький досвід. У багатьох випадках цей тип буде подібний до стандартного [елемента введення HTML](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). Тип `ActionParameterType` можна спростити до такого формату: @@ -497,7 +545,10 @@ export type ActionParameterType = | "select"; ``` -Кожне зі значень `type` зазвичай має відповідати полю введення користувача, яке нагадує стандартний HTML-елемент `input` відповідного типу (наприклад, ``), щоб забезпечити кращу валідацію на стороні клієнта та покращити користувацький досвід: +Кожне зі значень `type` зазвичай має відповідати полю введення користувача, яке +нагадує стандартний HTML-елемент `input` відповідного типу (наприклад, +``), щоб забезпечити кращу валідацію на стороні клієнта та +покращити користувацький досвід: - `text` - еквівалент HTML [елемента введення типу "text"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/text) @@ -513,22 +564,31 @@ export type ActionParameterType = [елемента введення типу "datetime-local"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local) - `checkbox` - еквівалент групи стандартних HTML [елементів введення типу "checkbox"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox). - API дій має повертати `options`, як описано нижче. Користувач повинен мати змогу вибрати кілька запропонованих варіантів. + API дій має повертати `options`, як описано нижче. Користувач повинен мати + змогу вибрати кілька запропонованих варіантів. - `radio` - еквівалент групи стандартних HTML [елементів введення типу "radio"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio). - API дій має повертати `options`, як описано нижче. Користувач повинен мати змогу вибрати лише один із запропонованих варіантів. -- Інші еквіваленти HTML-типів введення, не зазначені вище (`hidden`, `button`, `submit`, `file` тощо), наразі не підтримуються. + API дій має повертати `options`, як описано нижче. Користувач повинен мати + змогу вибрати лише один із запропонованих варіантів. +- Інші еквіваленти HTML-типів введення, не зазначені вище (`hidden`, `button`, + `submit`, `file` тощо), наразі не підтримуються. -Окрім елементів, схожих на HTML-типи введення, також підтримуються наступні елементи введення користувача: +Окрім елементів, схожих на HTML-типи введення, також підтримуються наступні +елементи введення користувача: - `textarea` - еквівалент HTML [елемента "textarea"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea), що дозволяє користувачеві вводити багаторядковий текст. - `select` - еквівалент HTML [елемента "select"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select), - що надає користувачеві досвід вибору з випадаючого списку. API дій має повертати `options`, як описано нижче. + що надає користувачеві досвід вибору з випадаючого списку. API дій має + повертати `options`, як описано нижче. -Коли `type` встановлено як `select`, `checkbox` або `radio`, API дій має включати масив `options`, кожен із яких надає `label` та `value` принаймні. Кожна опція також може мати значення `selected`, яке інформує клієнт-блінк, яка опція має бути обрана за замовчуванням для користувача (див. відмінності для `checkbox` і `radio`). +Коли `type` встановлено як `select`, `checkbox` або `radio`, API дій має +включати масив `options`, кожен із яких надає `label` та `value` принаймні. +Кожна опція також може мати значення `selected`, яке інформує клієнт-блінк, яка +опція має бути обрана за замовчуванням для користувача (див. відмінності для +`checkbox` і `radio`). Цей `ActionParameterSelectable` можна спростити до такого визначення типу: @@ -548,15 +608,23 @@ interface ActionParameterSelectable extends ActionParameter { } ``` -Якщо `type` не встановлено або задано невідоме/непідтримуване значення, клієнти-блінки мають за замовчуванням використовувати `text` і відображати просте текстове поле введення. +Якщо `type` не встановлено або задано невідоме/непідтримуване значення, +клієнти-блінки мають за замовчуванням використовувати `text` і відображати +просте текстове поле введення. -API дій все одно відповідає за валідацію та санітизацію всіх даних, отриманих від параметрів введення користувача, забезпечуючи виконання всіх обов’язкових ("required") полів введення за необхідності. +API дій все одно відповідає за валідацію та санітизацію всіх даних, отриманих +від параметрів введення користувача, забезпечуючи виконання всіх обов’язкових +("required") полів введення за необхідності. -Для платформ, які не базуються на HTML/веб (наприклад, для нативних мобільних додатків), слід використовувати еквівалентні нативні компоненти введення, щоб забезпечити аналогічний досвід та валідацію на стороні клієнта, як описано для HTML/веб. +Для платформ, які не базуються на HTML/веб (наприклад, для нативних мобільних +додатків), слід використовувати еквівалентні нативні компоненти введення, щоб +забезпечити аналогічний досвід та валідацію на стороні клієнта, як описано для +HTML/веб. #### Приклад відповіді на GET-запит -Наступний приклад відповіді забезпечує єдину "кореневу" дію, яка очікує, що користувачеві буде представлена одна кнопка з міткою "Отримати токен доступу": +Наступний приклад відповіді забезпечує єдину "кореневу" дію, яка очікує, що +користувачеві буде представлена одна кнопка з міткою "Отримати токен доступу": ```json { @@ -567,7 +635,9 @@ API дій все одно відповідає за валідацію та с } ``` -Наступний приклад відповіді забезпечує 3 пов’язані посилання на дії, що дозволяють користувачеві натиснути одну з трьох кнопок для голосування за пропозицію DAO: +Наступний приклад відповіді забезпечує 3 пов’язані посилання на дії, що +дозволяють користувачеві натиснути одну з трьох кнопок для голосування за +пропозицію DAO: ```json { @@ -596,9 +666,14 @@ API дій все одно відповідає за валідацію та с #### Приклад відповіді на GET-запит з параметрами -Наступні приклади відповіді демонструють, як приймати текстове введення від користувача (через `parameters`) і включати це введення у кінцеву кінцеву точку запиту `POST` (через поле `href` у `LinkedAction`): +Наступні приклади відповіді демонструють, як приймати текстове введення від +користувача (через `parameters`) і включати це введення у кінцеву кінцеву точку +запиту `POST` (через поле `href` у `LinkedAction`): -Наступний приклад відповіді забезпечує користувачеві 3 пов’язані дії для стейкінгу SOL: кнопку з міткою "Stake 1 SOL", іншу кнопку з міткою "Stake 5 SOL" та текстове поле введення, яке дозволяє користувачеві ввести конкретне значення "amount", що буде надіслано до API дій: +Наступний приклад відповіді забезпечує користувачеві 3 пов’язані дії для +стейкінгу SOL: кнопку з міткою "Stake 1 SOL", іншу кнопку з міткою "Stake 5 SOL" +та текстове поле введення, яке дозволяє користувачеві ввести конкретне значення +"amount", що буде надіслано до API дій: ```json { @@ -633,7 +708,9 @@ API дій все одно відповідає за валідацію та с } ``` -Наступний приклад відповіді забезпечує одне поле введення для користувача, щоб ввести `amount`, яке буде надіслано з запитом `POST` (може бути використано як параметр запиту або як підшлях): +Наступний приклад відповіді забезпечує одне поле введення для користувача, щоб +ввести `amount`, яке буде надіслано з запитом `POST` (може бути використано як +параметр запиту або як підшлях): ```json { @@ -661,7 +738,9 @@ API дій все одно відповідає за валідацію та с ### POST Запит -Наступний приклад відповіді забезпечує одне поле введення для користувача, щоб ввести `amount`, яке буде надіслано з запитом `POST` (може бути використано як параметр запиту або як підшлях): +Наступний приклад відповіді забезпечує одне поле введення для користувача, щоб +ввести `amount`, яке буде надіслано з запитом `POST` (може бути використано як +параметр запиту або як підшлях): ```json { @@ -669,35 +748,42 @@ API дій все одно відповідає за валідацію та с } ``` -- `account` - Значення повинно бути відкритим ключем облікового запису у форматі base58, який може підписувати транзакцію. +- `account` - Значення повинно бути відкритим ключем облікового запису у форматі + base58, який може підписувати транзакцію. -Клієнт має виконати запит із заголовком -[Accept-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding), -а застосунок може відповісти заголовком -[Content-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding) +Клієнт має виконати запит із заголовком +[Accept-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding), +а застосунок може відповісти заголовком +[Content-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding) для HTTP-компресії. -Клієнт повинен відобразити домен URL дії під час виконання запиту. Якщо був виконаний `GET`-запит, клієнт також повинен відобразити `title` та відрендерити зображення `icon` з відповіді GET. +Клієнт повинен відобразити домен URL дії під час виконання запиту. Якщо був +виконаний `GET`-запит, клієнт також повинен відобразити `title` та відрендерити +зображення `icon` з відповіді GET. ### Відповідь на POST-запит -Кінцева точка `POST` для дії повинна відповідати HTTP-відповіддю `OK` у форматі JSON (з дійсним тілом відповіді) або відповідною HTTP-помилкою. +Кінцева точка `POST` для дії повинна відповідати HTTP-відповіддю `OK` у форматі +JSON (з дійсним тілом відповіді) або відповідною HTTP-помилкою. -- Клієнт повинен обробляти +- Клієнт повинен обробляти [помилки клієнта](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses), - [помилки сервера](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses), - та + [помилки сервера](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses), + та [відповіді-перенаправлення](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). -- Кінцева точка повинна відповідати з - заголовком [`Content-Type`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) +- Кінцева точка повинна відповідати з заголовком + [`Content-Type`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) значенням `application/json`. -Помилкові відповіді (тобто HTTP-коди стану 4xx і 5xx) повинні повертати JSON-відповідь, що відповідає структурі `ActionError`, для відображення корисного повідомлення про помилку користувачам. Див. [Помилки дій](#action-errors). +Помилкові відповіді (тобто HTTP-коди стану 4xx і 5xx) повинні повертати +JSON-відповідь, що відповідає структурі `ActionError`, для відображення +корисного повідомлення про помилку користувачам. Див. +[Помилки дій](#action-errors). #### Тіло відповіді на POST-запит -Відповідь `POST` з HTTP-відповіддю `OK` у форматі JSON повинна включати тіло відповіді наступного вигляду: - +Відповідь `POST` з HTTP-відповіддю `OK` у форматі JSON повинна включати тіло +відповіді наступного вигляду: ```ts filename="ActionPostResponse" /** @@ -717,23 +803,25 @@ export interface ActionPostResponse { }; } ``` -- `transaction` - Значення повинно бути серіалізованою транзакцією, закодованою в base64 + +- `transaction` - Значення повинно бути серіалізованою транзакцією, закодованою + в base64 ([документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#serialize)). Клієнт повинен декодувати транзакцію з base64 і [десеріалізувати її](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#from). -- `message` - Значення повинно бути рядком у форматі UTF-8, який описує суть транзакції, - включеної у відповідь. Клієнт повинен відобразити це значення користувачу. - Наприклад, це може бути назва товару, який купується, застосована знижка, - або подяка. +- `message` - Значення повинно бути рядком у форматі UTF-8, який описує суть + транзакції, включеної у відповідь. Клієнт повинен відобразити це значення + користувачу. Наприклад, це може бути назва товару, який купується, застосована + знижка, або подяка. -- `links.next` - Необов'язкове значення, яке використовується для "зчеплення" кількох дій - у послідовності. Після підтвердження включеної `transaction` у блокчейні - клієнт може отримати та відобразити наступну дію. Дивіться +- `links.next` - Необов'язкове значення, яке використовується для "зчеплення" + кількох дій у послідовності. Після підтвердження включеної `transaction` у + блокчейні клієнт може отримати та відобразити наступну дію. Дивіться [Зчеплення дій](#action-chaining) для отримання додаткової інформації. -- Клієнт та застосунок повинні дозволяти додаткові поля у тілі запиту - та відповіді, які можуть бути додані у майбутніх оновленнях специфікацій. +- Клієнт та застосунок повинні дозволяти додаткові поля у тілі запиту та + відповіді, які можуть бути додані у майбутніх оновленнях специфікацій. > Застосунок може відповідати частково або повністю підписаною транзакцією. > Клієнт та гаманець повинні перевіряти транзакцію як **ненадійну**. @@ -751,8 +839,9 @@ export interface ActionPostResponse { [`recentBlockhash`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#recentBlockhash) у транзакції та встановити `recentBlockhash` на [останній blockhash](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getLatestBlockhash). -- Клієнт повинен серіалізувати та десеріалізувати транзакцію перед її підписанням. - Це забезпечує послідовний порядок ключів облікових записів як рішення для +- Клієнт повинен серіалізувати та десеріалізувати транзакцію перед її + підписанням. Це забезпечує послідовний порядок ключів облікових записів як + рішення для [цієї проблеми](https://github.com/solana-labs/solana/issues/21722). Якщо транзакція вже частково підписана: @@ -765,18 +854,17 @@ export interface ActionPostResponse { - Клієнт повинен перевірити існуючі підписи, і якщо будь-який з них недійсний, клієнт повинен відхилити транзакцію як **пошкоджену**. -Клієнт повинен підписати транзакцію лише за допомогою `account`, зазначеного у запиті, -і зробити це лише у випадку, якщо очікується підпис для цього `account`. +Клієнт повинен підписати транзакцію лише за допомогою `account`, зазначеного у +запиті, і зробити це лише у випадку, якщо очікується підпис для цього `account`. -Якщо очікується будь-який підпис, окрім підпису для `account` у запиті, -клієнт повинен відхилити транзакцію як **шкідливу**. +Якщо очікується будь-який підпис, окрім підпису для `account` у запиті, клієнт +повинен відхилити транзакцію як **шкідливу**. ### Помилки дій API для дій повинні повертати помилки у форматі `ActionError`, щоб надати -корисні повідомлення про помилки для користувачів. Залежно від контексту, ця помилка -може бути фатальною або нефатальною. - +корисні повідомлення про помилки для користувачів. Залежно від контексту, ця +помилка може бути фатальною або нефатальною. ```ts filename="ActionError" export interface ActionError { @@ -784,26 +872,43 @@ export interface ActionError { message: string; } ``` -Коли API для дій відповідає HTTP-кодом помилки (тобто 4xx і 5xx), тіло відповіді має бути JSON-навантаженням, яке відповідає формату `ActionError`. Помилка вважається фатальною, і повідомлення, яке міститься в ній, має бути представлене користувачеві. -Для відповідей API, які підтримують необов'язковий атрибут `error` (наприклад, [`ActionGetResponse`](#get-response)), помилка вважається нефатальною, і повідомлення, яке міститься в ній, також має бути представлене користувачеві. +Коли API для дій відповідає HTTP-кодом помилки (тобто 4xx і 5xx), тіло відповіді +має бути JSON-навантаженням, яке відповідає формату `ActionError`. Помилка +вважається фатальною, і повідомлення, яке міститься в ній, має бути представлене +користувачеві. + +Для відповідей API, які підтримують необов'язковий атрибут `error` (наприклад, +[`ActionGetResponse`](#get-response)), помилка вважається нефатальною, і +повідомлення, яке міститься в ній, також має бути представлене користувачеві. ## Зчеплення дій -Дії Solana можуть бути "зчеплені" разом у послідовну серію. Після підтвердження транзакції дії у блокчейні можна отримати наступну дію та представити її користувачеві. +Дії Solana можуть бути "зчеплені" разом у послідовну серію. Після підтвердження +транзакції дії у блокчейні можна отримати наступну дію та представити її +користувачеві. -Зчеплення дій дозволяє розробникам створювати більш складний і динамічний досвід у рамках blinks, включаючи: +Зчеплення дій дозволяє розробникам створювати більш складний і динамічний досвід +у рамках blinks, включаючи: -- надання декількох транзакцій (і в майбутньому повідомлень для підпису) користувачу; +- надання декількох транзакцій (і в майбутньому повідомлень для підпису) + користувачу; - налаштування метаданих дії залежно від адреси гаманця користувача; - оновлення метаданих blink після успішної транзакції; -- отримання API-зворотного виклику з підписом транзакції для додаткової перевірки та логіки на сервері API для дій; -- налаштовані повідомлення про успіх, шляхом оновлення відображуваних метаданих (наприклад, нове зображення або опис). +- отримання API-зворотного виклику з підписом транзакції для додаткової + перевірки та логіки на сервері API для дій; +- налаштовані повідомлення про успіх, шляхом оновлення відображуваних метаданих + (наприклад, нове зображення або опис). -Для зчеплення кількох дій разом, у будь-якому `ActionPostResponse` включіть `links.next` одного з наступних типів: +Для зчеплення кількох дій разом, у будь-якому `ActionPostResponse` включіть +`links.next` одного з наступних типів: -- `PostNextActionLink` — Посилання POST-запиту з URL зворотного виклику того самого походження для отримання `signature` і `account` користувача у тілі. Цей URL зворотного виклику повинен відповідати `NextAction`. -- `InlineNextActionLink` — Вбудовані метадані для наступної дії, які мають бути представлені користувачеві негайно після підтвердження транзакції. Ніякий зворотний виклик не буде виконано. +- `PostNextActionLink` — Посилання POST-запиту з URL зворотного виклику того + самого походження для отримання `signature` і `account` користувача у тілі. + Цей URL зворотного виклику повинен відповідати `NextAction`. +- `InlineNextActionLink` — Вбудовані метадані для наступної дії, які мають бути + представлені користувачеві негайно після підтвердження транзакції. Ніякий + зворотний виклик не буде виконано. ```ts export type NextActionLink = PostNextActionLink | InlineNextActionLink; @@ -826,15 +931,20 @@ export interface InlineNextActionLink { action: NextAction; } ``` -### NextAction -Після того як транзакція, включена в `ActionPostResponse`, підписана користувачем і підтверджена у блокчейні, blink-клієнт повинен або: +### NextAction -- виконати запит зворотного виклику, щоб отримати і відобразити `NextAction`, або -- якщо `NextAction` вже надана через `links.next`, blink-клієнт повинен оновити відображувані метадані і не робити запит зворотного виклику. +Після того як транзакція, включена в `ActionPostResponse`, підписана +користувачем і підтверджена у блокчейні, blink-клієнт повинен або: -Якщо URL зворотного виклику не має того ж походження, що і початковий POST-запит, запит зворотного виклику не повинен виконуватися. Blink-клієнти повинні відобразити помилку, що повідомляє користувача. +- виконати запит зворотного виклику, щоб отримати і відобразити `NextAction`, + або +- якщо `NextAction` вже надана через `links.next`, blink-клієнт повинен оновити + відображувані метадані і не робити запит зворотного виклику. +Якщо URL зворотного виклику не має того ж походження, що і початковий +POST-запит, запит зворотного виклику не повинен виконуватися. Blink-клієнти +повинні відобразити помилку, що повідомляє користувача. ```ts filename="NextAction" /** The next action to be performed */ @@ -846,31 +956,47 @@ export type CompletedAction = Omit, "links">; ### Відповідно до `type`, наступна дія повинна бути представлена користувачеві через blink-клієнти одним із наступних способів: -- `action` - (за замовчуванням) Стандартна дія, яка дозволяє користувачеві переглядати включені метадані Action, взаємодіяти з наданими `LinkedActions` і продовжувати виконувати будь-які наступні дії в ланцюжку. +- `action` - (за замовчуванням) Стандартна дія, яка дозволяє користувачеві + переглядати включені метадані Action, взаємодіяти з наданими `LinkedActions` і + продовжувати виконувати будь-які наступні дії в ланцюжку. -- `completed` - Завершальний стан ланцюжка дій, який може оновлювати інтерфейс blink із включеними метаданими Action, але не дозволяє користувачеві виконувати подальші дії. +- `completed` - Завершальний стан ланцюжка дій, який може оновлювати інтерфейс + blink із включеними метаданими Action, але не дозволяє користувачеві + виконувати подальші дії. -Якщо `links.next` не надано, blink-клієнти повинні припустити, що поточна дія є фінальною у ланцюжку, і представити свій інтерфейс "завершеної" дії після підтвердження транзакції. +Якщо `links.next` не надано, blink-клієнти повинні припустити, що поточна дія є +фінальною у ланцюжку, і представити свій інтерфейс "завершеної" дії після +підтвердження транзакції. ## actions.json -Файл [`actions.json`](#actionsjson) використовується для того, щоб додаток міг інструктувати клієнтів про те, які URL-адреси вебсайту підтримують Solana Actions, і надавати мапінг, який може бути використаний для виконання [GET запитів](#get-request) до серверу API дій. +Файл [`actions.json`](#actionsjson) використовується для того, щоб додаток міг +інструктувати клієнтів про те, які URL-адреси вебсайту підтримують Solana +Actions, і надавати мапінг, який може бути використаний для виконання +[GET запитів](#get-request) до серверу API дій. -Відповідь файлу `actions.json` також повинна повертати дійсні заголовки Cross-Origin для запитів `GET` і `OPTIONS`, зокрема заголовок `Access-Control-Allow-Origin` із значенням `*`. +Відповідь файлу `actions.json` також повинна повертати дійсні заголовки +Cross-Origin для запитів `GET` і `OPTIONS`, зокрема заголовок +`Access-Control-Allow-Origin` із значенням `*`. Детальніше див. у розділі [OPTIONS response](#options-response) вище. -Файл `actions.json` повинен бути збережений і загальнодоступний у кореневій директорії домену. +Файл `actions.json` повинен бути збережений і загальнодоступний у кореневій +директорії домену. -Наприклад, якщо ваш вебдодаток розгорнуто на `my-site.com`, тоді файл `actions.json` має бути доступний за адресою `https://my-site.com/actions.json`. Цей файл також має бути доступний через будь-який браузер за допомогою заголовка `Access-Control-Allow-Origin` із значенням `*`. +Наприклад, якщо ваш вебдодаток розгорнуто на `my-site.com`, тоді файл +`actions.json` має бути доступний за адресою `https://my-site.com/actions.json`. +Цей файл також має бути доступний через будь-який браузер за допомогою заголовка +`Access-Control-Allow-Origin` із значенням `*`. ### Правила -Поле `rules` дозволяє додатку мапувати набір відносних маршрутів вебсайту на інші шляхи. +Поле `rules` дозволяє додатку мапувати набір відносних маршрутів вебсайту на +інші шляхи. **Тип:** `Array` з `ActionRuleObject`. @@ -882,28 +1008,39 @@ interface ActionRuleObject { apiPath: string; } ``` -- [`pathPattern`](#rules-pathpattern) - Шаблон, який відповідає кожному вхідному шляху. -- [`apiPath`](#rules-apipath) - Місце призначення, визначене як абсолютний шлях або зовнішній URL. +- [`pathPattern`](#rules-pathpattern) - Шаблон, який відповідає кожному вхідному + шляху. + +- [`apiPath`](#rules-apipath) - Місце призначення, визначене як абсолютний шлях + або зовнішній URL. #### Правила - pathPattern -Шаблон, який відповідає кожному вхідному шляху. Це може бути абсолютний або відносний шлях, який підтримує наступні формати: +Шаблон, який відповідає кожному вхідному шляху. Це може бути абсолютний або +відносний шлях, який підтримує наступні формати: - **Точне співпадіння**: Відповідає точному URL-шляху. - Приклад: `/exact-path` - Приклад: `https://website.com/exact-path` -- **Співпадіння з використанням шаблону**: Використовує символи підстановки для відповідності будь-якій послідовності символів у шляху URL. Це може відповідати одному (за допомогою `*`) або кільком сегментам (за допомогою `**`). (Див. [Path Matching](#rules-path-matching) нижче). +- **Співпадіння з використанням шаблону**: Використовує символи підстановки для + відповідності будь-якій послідовності символів у шляху URL. Це може + відповідати одному (за допомогою `*`) або кільком сегментам (за допомогою + `**`). (Див. [Path Matching](#rules-path-matching) нижче). - - Приклад: `/trade/*` відповідатиме `/trade/123` і `/trade/abc`, захоплюючи лише перший сегмент після `/trade/`. - - Приклад: `/category/*/item/**` відповідатиме `/category/123/item/456` і `/category/abc/item/def`. - - Приклад: `/api/actions/trade/*/confirm` відповідатиме `/api/actions/trade/123/confirm`. + - Приклад: `/trade/*` відповідатиме `/trade/123` і `/trade/abc`, захоплюючи + лише перший сегмент після `/trade/`. + - Приклад: `/category/*/item/**` відповідатиме `/category/123/item/456` і + `/category/abc/item/def`. + - Приклад: `/api/actions/trade/*/confirm` відповідатиме + `/api/actions/trade/123/confirm`. #### Правила - apiPath -Шлях призначення для запиту дії. Він може бути визначений як абсолютний шлях або зовнішній URL. +Шлях призначення для запиту дії. Він може бути визначений як абсолютний шлях або +зовнішній URL. - Приклад: `/api/exact-path` - Приклад: `https://api.example.com/v1/donate/*` @@ -912,21 +1049,24 @@ interface ActionRuleObject { #### Правила - Query Parameters -Параметри запиту з оригінального URL завжди зберігаються та додаються до мапованого URL. +Параметри запиту з оригінального URL завжди зберігаються та додаються до +мапованого URL. #### Правила - Path Matching Наступна таблиця описує синтаксис для шаблонів відповідності шляхів: -| Оператор | Відповідає | -| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `*` | Один сегмент шляху, що не включає оточуючі символи розділювача шляху `/`. | +| Оператор | Відповідає | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `*` | Один сегмент шляху, що не включає оточуючі символи розділювача шляху `/`. | | `**` | Відповідає нулю або більшій кількості символів, включаючи будь-які символи розділювача шляху `/` між декількома сегментами шляху. Якщо включені інші оператори, оператор `**` повинен бути останнім. | -| `?` | Непідтримуваний шаблон. | +| `?` | Непідтримуваний шаблон. | ### Приклади Правил -Наступний приклад демонструє правило точного співпадіння для мапування запитів до `/buy` з кореня вашого сайту на точний шлях `/api/buy`, відносно кореня вашого сайту: +Наступний приклад демонструє правило точного співпадіння для мапування запитів +до `/buy` з кореня вашого сайту на точний шлях `/api/buy`, відносно кореня +вашого сайту: ```json filename="actions.json" { @@ -939,7 +1079,10 @@ interface ActionRuleObject { } ``` -Наступний приклад використовує шаблонне співставлення шляху для відображення запитів до будь-якого шляху (за винятком підкаталогів) під `/actions/` від кореня вашого сайту до відповідного шляху під `/api/actions/`, відносно кореня вашого сайту: +Наступний приклад використовує шаблонне співставлення шляху для відображення +запитів до будь-якого шляху (за винятком підкаталогів) під `/actions/` від +кореня вашого сайту до відповідного шляху під `/api/actions/`, відносно кореня +вашого сайту: ```json filename="actions.json" { @@ -952,7 +1095,10 @@ interface ActionRuleObject { } ``` -Наступний приклад використовує зіставлення шляхів із використанням символів підстановки для перенаправлення запитів до будь-якого шляху (за винятком підкаталогів) під `/donate/` у кореневій директорії вашого сайту до відповідного абсолютного шляху `https://api.dialect.com/api/v1/donate/` на зовнішньому сайті: +Наступний приклад використовує зіставлення шляхів із використанням символів +підстановки для перенаправлення запитів до будь-якого шляху (за винятком +підкаталогів) під `/donate/` у кореневій директорії вашого сайту до відповідного +абсолютного шляху `https://api.dialect.com/api/v1/donate/` на зовнішньому сайті: ```json filename="actions.json" { @@ -965,9 +1111,13 @@ interface ActionRuleObject { } ``` -Наступний приклад використовує зіставлення шляхів із використанням символів підстановки для ідемпотентного правила, щоб перенаправляти запити до будь-якого шляху (включаючи підкаталоги) під `/api/actions/` у кореневій директорії вашого сайту до самого себе: +Наступний приклад використовує зіставлення шляхів із використанням символів +підстановки для ідемпотентного правила, щоб перенаправляти запити до будь-якого +шляху (включаючи підкаталоги) під `/api/actions/` у кореневій директорії вашого +сайту до самого себе: -> Ідемпотентні правила дозволяють клієнтам blink легше визначати, чи підтримує даний шлях запити API дій, без необхідності: +> Ідемпотентні правила дозволяють клієнтам blink легше визначати, чи підтримує +> даний шлях запити API дій, без необхідності: > > - додавання префіксу `solana-action:` URI, > - виконання додаткового тестування відповіді, @@ -986,53 +1136,107 @@ interface ActionRuleObject { ## Ідентифікація Дії (Action Identity) -Кінцеві точки дій (Action endpoints) можуть включати _Ідентифікацію Дії_ у транзакціях, які повертаються у [POST-відповіді](#post-response) для підпису користувачем. Це дозволяє індексаторам та аналітичним платформам легко та достовірно приписувати активність у блокчейні конкретному провайдеру дій (тобто сервісу). - -[Ідентифікація Дії](#action-identity) — це пара ключів (keypair), яка використовується для підпису спеціально форматованого повідомлення, що включається до транзакції за допомогою інструкції Memo. Це _Повідомлення Ідентифікатора_ (_Identifier Message_) може бути достовірно приписане до конкретної Ідентифікації Дії, а отже, до конкретного провайдера дій. - -Пара ключів не вимагається для підписання самої транзакції. Це дозволяє гаманцям та додаткам покращити доставку транзакції, якщо у транзакції, поверненій користувачу, немає інших підписів (див. [POST-відповідь транзакції](#post-response-transaction)). - -Якщо сценарій використання провайдера дій вимагає, щоб їх бекенд-сервіси попередньо підписували транзакцію перед тим, як це зробить користувач, вони мають використовувати цю пару ключів як Ідентифікацію Дії. Це дозволить зменшити кількість облікових записів у транзакції, скоротивши її загальний розмір на 32 байти. +Кінцеві точки дій (Action endpoints) можуть включати _Ідентифікацію Дії_ у +транзакціях, які повертаються у [POST-відповіді](#post-response) для підпису +користувачем. Це дозволяє індексаторам та аналітичним платформам легко та +достовірно приписувати активність у блокчейні конкретному провайдеру дій (тобто +сервісу). + +[Ідентифікація Дії](#action-identity) — це пара ключів (keypair), яка +використовується для підпису спеціально форматованого повідомлення, що +включається до транзакції за допомогою інструкції Memo. Це _Повідомлення +Ідентифікатора_ (_Identifier Message_) може бути достовірно приписане до +конкретної Ідентифікації Дії, а отже, до конкретного провайдера дій. + +Пара ключів не вимагається для підписання самої транзакції. Це дозволяє гаманцям +та додаткам покращити доставку транзакції, якщо у транзакції, поверненій +користувачу, немає інших підписів (див. +[POST-відповідь транзакції](#post-response-transaction)). + +Якщо сценарій використання провайдера дій вимагає, щоб їх бекенд-сервіси +попередньо підписували транзакцію перед тим, як це зробить користувач, вони +мають використовувати цю пару ключів як Ідентифікацію Дії. Це дозволить зменшити +кількість облікових записів у транзакції, скоротивши її загальний розмір на 32 +байти. ### Повідомлення Ідентифікатора Дії (Action Identifier Message) -Повідомлення Ідентифікатора Дії — це UTF-8 рядок, розділений двокрапками, який включається до транзакції за допомогою однієї [інструкції SPL Memo](https://spl.solana.com/memo). +Повідомлення Ідентифікатора Дії — це UTF-8 рядок, розділений двокрапками, який +включається до транзакції за допомогою однієї +[інструкції SPL Memo](https://spl.solana.com/memo). ```shell protocol:identity:reference:signature ``` -- `protocol` - Значення протоколу, який використовується (встановлено як `solana-action` відповідно до [URL-схеми](#url-scheme) вище). -- `identity` - Значення має бути публічним ключем у форматі base58, який відповідає парі ключів Ідентифікації Дії. -- `reference` - Значення має бути масивом байтів довжиною 32 у форматі base58. Це можуть бути як публічні ключі, так і інші дані, які можуть або не можуть відповідати обліковим записам у Solana. -- `signature` - Підпис у форматі base58, створений парою ключів Ідентифікації Дії, що підписує лише значення `reference`. - -Значення `reference` має використовуватися тільки один раз і в одній транзакції. Для приписування транзакцій провайдеру дій, лише перше використання значення `reference` вважається дійсним. -Транзакції можуть містити кілька інструкцій Memo. Під час виконання [`getSignaturesForAddress`](https://solana.com/docs/rpc/http/getsignaturesforaddress) поле `memo` у результатах повертає повідомлення кожної інструкції Memo як єдиний рядок, розділений крапкою з комою. - -Жодні інші дані не повинні включатися до інструкції Memo Повідомлення Ідентифікатора. - -Облікові записи `identity` та `reference` повинні бути включені як доступні тільки для читання, але без можливості підпису ([ключі](https://solana-labs.github.io/solana-web3.js/v1.x/classes/TransactionInstruction.html#keys)) у транзакції в інструкції, яка не є Інструкцією Memo Повідомлення Ідентифікатора. - -Інструкція Memo Повідомлення Ідентифікатора не повинна містити жодних облікових записів. Якщо облікові записи надаються, програма Memo вимагає, щоб ці облікові записи були дійсними підписувачами. Це обмежує гнучкість і може погіршити досвід користувача, тому це вважається антипатерном і має бути уникнуто. +- `protocol` - Значення протоколу, який використовується (встановлено як + `solana-action` відповідно до [URL-схеми](#url-scheme) вище). +- `identity` - Значення має бути публічним ключем у форматі base58, який + відповідає парі ключів Ідентифікації Дії. +- `reference` - Значення має бути масивом байтів довжиною 32 у форматі base58. + Це можуть бути як публічні ключі, так і інші дані, які можуть або не можуть + відповідати обліковим записам у Solana. +- `signature` - Підпис у форматі base58, створений парою ключів Ідентифікації + Дії, що підписує лише значення `reference`. + +Значення `reference` має використовуватися тільки один раз і в одній транзакції. +Для приписування транзакцій провайдеру дій, лише перше використання значення +`reference` вважається дійсним. + +Транзакції можуть містити кілька інструкцій Memo. Під час виконання +[`getSignaturesForAddress`](https://solana.com/docs/rpc/http/getsignaturesforaddress) +поле `memo` у результатах повертає повідомлення кожної інструкції Memo як єдиний +рядок, розділений крапкою з комою. + +Жодні інші дані не повинні включатися до інструкції Memo Повідомлення +Ідентифікатора. + +Облікові записи `identity` та `reference` повинні бути включені як доступні +тільки для читання, але без можливості підпису +([ключі](https://solana-labs.github.io/solana-web3.js/v1.x/classes/TransactionInstruction.html#keys)) +у транзакції в інструкції, яка не є Інструкцією Memo Повідомлення +Ідентифікатора. + +Інструкція Memo Повідомлення Ідентифікатора не повинна містити жодних облікових +записів. Якщо облікові записи надаються, програма Memo вимагає, щоб ці облікові +записи були дійсними підписувачами. Це обмежує гнучкість і може погіршити досвід +користувача, тому це вважається антипатерном і має бути уникнуто. ### Перевірка Ідентифікації Дії (Action Identity Verification) -Будь-яка транзакція, що включає обліковий запис `identity`, може бути достовірно пов'язана з провайдером дій за допомогою багатоступінчастого процесу: +Будь-яка транзакція, що включає обліковий запис `identity`, може бути достовірно +пов'язана з провайдером дій за допомогою багатоступінчастого процесу: 1. Отримайте всі транзакції для заданого `identity`. -2. Розберіть і перевірте рядок memo кожної транзакції, переконавшись, що підпис `signature` дійсний для збереженого значення `reference`. -3. Перевірте, чи є ця транзакція першим випадком використання `reference` у блокчейні: - - Якщо ця транзакція є першим випадком, вона вважається підтвердженою і може бути достовірно приписана провайдеру дій. - - Якщо ця транзакція НЕ є першим випадком, вона вважається недійсною і, відповідно, не може бути приписана провайдеру дій. - -Оскільки валідатори Solana індексують транзакції за обліковими записами, метод RPC [`getSignaturesForAddress`](https://solana.com/docs/rpc/http/getsignaturesforaddress) може бути використаний для визначення всіх транзакцій, що включають обліковий запис `identity`. - -Відповідь цього методу RPC включає всі дані Memo у полі `memo`. Якщо в транзакції було використано кілька інструкцій Memo, кожне повідомлення Memo буде включено в це поле `memo` і має бути відповідним чином розібране перевіряючою стороною для отримання _Повідомлення Ідентифікації_. - -Ці транзакції спочатку мають вважатися **НЕПЕРЕВІРЕНИМИ**. Це пов'язано з тим, що `identity` не вимагається для підписання транзакції, що дозволяє будь-якій транзакції включати цей обліковий запис як не-підписувач. Це потенційно може штучно збільшити статистику приписування та використання. - -Повідомлення Ідентифікації має бути перевірене для забезпечення того, що `signature` було створено `identity`, підписуючи `reference`. Якщо ця перевірка підпису не вдається, транзакція вважається недійсною. - -Якщо перевірка підпису успішна, перевіряюча сторона має забезпечити, що ця транзакція є першим випадком використання `reference`. Якщо це не так, транзакція вважається недійсною. - +2. Розберіть і перевірте рядок memo кожної транзакції, переконавшись, що підпис + `signature` дійсний для збереженого значення `reference`. +3. Перевірте, чи є ця транзакція першим випадком використання `reference` у + блокчейні: + - Якщо ця транзакція є першим випадком, вона вважається підтвердженою і може + бути достовірно приписана провайдеру дій. + - Якщо ця транзакція НЕ є першим випадком, вона вважається недійсною і, + відповідно, не може бути приписана провайдеру дій. + +Оскільки валідатори Solana індексують транзакції за обліковими записами, метод +RPC +[`getSignaturesForAddress`](https://solana.com/docs/rpc/http/getsignaturesforaddress) +може бути використаний для визначення всіх транзакцій, що включають обліковий +запис `identity`. + +Відповідь цього методу RPC включає всі дані Memo у полі `memo`. Якщо в +транзакції було використано кілька інструкцій Memo, кожне повідомлення Memo буде +включено в це поле `memo` і має бути відповідним чином розібране перевіряючою +стороною для отримання _Повідомлення Ідентифікації_. + +Ці транзакції спочатку мають вважатися **НЕПЕРЕВІРЕНИМИ**. Це пов'язано з тим, +що `identity` не вимагається для підписання транзакції, що дозволяє будь-якій +транзакції включати цей обліковий запис як не-підписувач. Це потенційно може +штучно збільшити статистику приписування та використання. + +Повідомлення Ідентифікації має бути перевірене для забезпечення того, що +`signature` було створено `identity`, підписуючи `reference`. Якщо ця перевірка +підпису не вдається, транзакція вважається недійсною. + +Якщо перевірка підпису успішна, перевіряюча сторона має забезпечити, що ця +транзакція є першим випадком використання `reference`. Якщо це не так, +транзакція вважається недійсною. diff --git a/docs/locales/uk/advanced/confirmation.md b/docs/locales/uk/advanced/confirmation.md index 7134d5313..08621dfb1 100644 --- a/docs/locales/uk/advanced/confirmation.md +++ b/docs/locales/uk/advanced/confirmation.md @@ -4,96 +4,126 @@ sidebarLabel: "Підтвердження та закінчення строку title: "Підтвердження транзакції та закінчення строку дії" seoTitle: "Підтвердження транзакції та закінчення строку дії" description: - "Дізнайтеся, як працює підтвердження транзакцій у Solana і коли транзакція завершує дію - (включаючи перевірку останніх blockhash)." + "Дізнайтеся, як працює підтвердження транзакцій у Solana і коли транзакція + завершує дію (включаючи перевірку останніх blockhash)." altRoutes: - /docs/uk/advanced - /docs/uk/core/transactions/confirmation --- -Проблеми, пов'язані з -[підтвердженням транзакції](/docs/uk/terminology.md#transaction-confirmations), -є поширеними серед нових розробників під час створення застосунків. Ця стаття має на меті підвищити загальне розуміння механізму підтвердження, який використовується в блокчейні Solana, включаючи деякі рекомендовані найкращі практики. +Проблеми, пов'язані з +[підтвердженням транзакції](/docs/uk/terminology.md#transaction-confirmations), +є поширеними серед нових розробників під час створення застосунків. Ця стаття +має на меті підвищити загальне розуміння механізму підтвердження, який +використовується в блокчейні Solana, включаючи деякі рекомендовані найкращі +практики. ## Короткий вступ до транзакцій -Перед тим як розглянути, як працює підтвердження та закінчення строку дії транзакцій у Solana, давайте коротко розглянемо кілька основ: +Перед тим як розглянути, як працює підтвердження та закінчення строку дії +транзакцій у Solana, давайте коротко розглянемо кілька основ: - що таке транзакція, - життєвий цикл транзакції, - що таке blockhash, -- і коротке ознайомлення з Proof of History (PoH) і тим, як це стосується blockhash. +- і коротке ознайомлення з Proof of History (PoH) і тим, як це стосується + blockhash. ### Що таке транзакція? -Транзакції складаються з двох компонентів: -[повідомлення](/docs/uk/terminology.md#message) -і -[списку підписів](/docs/uk/terminology.md#signature). -Повідомлення транзакції містить основну інформацію та складається з чотирьох компонентів: +Транзакції складаються з двох компонентів: +[повідомлення](/docs/uk/terminology.md#message) і +[списку підписів](/docs/uk/terminology.md#signature). Повідомлення транзакції +містить основну інформацію та складається з чотирьох компонентів: - **заголовок** з метаданими про транзакцію, - **список інструкцій** для виконання, - **список акаунтів**, які потрібно завантажити, - та **“недавній blockhash”**. -У цій статті ми зосередимося на -[недавньому blockhash](/docs/uk/terminology.md#blockhash), -оскільки він відіграє важливу роль у підтвердженні транзакції. +У цій статті ми зосередимося на +[недавньому blockhash](/docs/uk/terminology.md#blockhash), оскільки він відіграє +важливу роль у підтвердженні транзакції. ### Життєвий цикл транзакції -Нижче наведено основні етапи життєвого циклу транзакції. У цій статті розглядаються всі етапи, крім 1 і 4. +Нижче наведено основні етапи життєвого циклу транзакції. У цій статті +розглядаються всі етапи, крім 1 і 4. -1. Створення заголовка та списку інструкцій разом із переліком акаунтів, які потрібно прочитати або записати. -2. Отримання недавнього blockhash та його використання для підготовки повідомлення транзакції. +1. Створення заголовка та списку інструкцій разом із переліком акаунтів, які + потрібно прочитати або записати. +2. Отримання недавнього blockhash та його використання для підготовки + повідомлення транзакції. 3. Симуляція транзакції, щоб переконатися, що вона поводиться очікувано. -4. Запит користувача на підписання підготовленого повідомлення транзакції за допомогою його приватного ключа. -5. Відправка транзакції до RPC-вузла, який намагається передати її поточному виробнику блоків. +4. Запит користувача на підписання підготовленого повідомлення транзакції за + допомогою його приватного ключа. +5. Відправка транзакції до RPC-вузла, який намагається передати її поточному + виробнику блоків. 6. Очікування, що виробник блоку перевірить і додасть транзакцію до свого блоку. -7. Підтвердження того, що транзакція або була включена в блок, або закінчився її термін дії. +7. Підтвердження того, що транзакція або була включена в блок, або закінчився її + термін дії. ### Що таке Blockhash? -[“Blockhash”](/docs/uk/terminology.md#blockhash) -означає останній Proof of History (PoH) хеш для -[“слота”](/docs/uk/terminology.md#slot) -(опис нижче). Оскільки Solana використовує PoH як довірений годинник, недавній blockhash транзакції можна розглядати як **мітку часу**. +[“Blockhash”](/docs/uk/terminology.md#blockhash) означає останній Proof of +History (PoH) хеш для [“слота”](/docs/uk/terminology.md#slot) (опис нижче). +Оскільки Solana використовує PoH як довірений годинник, недавній blockhash +транзакції можна розглядати як **мітку часу**. ### Коротке нагадування про Proof of History -Механізм Proof of History у Solana використовує довгий ланцюг рекурсивних хешів SHA-256 для створення довіреного годинника. Назва “історія” походить від того, що виробники блоків додають хеш ідентифікаторів транзакцій у потік, щоб зафіксувати, які транзакції були оброблені в їхньому блоці. +Механізм Proof of History у Solana використовує довгий ланцюг рекурсивних хешів +SHA-256 для створення довіреного годинника. Назва “історія” походить від того, +що виробники блоків додають хеш ідентифікаторів транзакцій у потік, щоб +зафіксувати, які транзакції були оброблені в їхньому блоці. -[Обчислення PoH-хешу](https://github.com/anza-xyz/agave/blob/aa0922d6845e119ba466f88497e8209d1c82febc/entry/src/poh.rs#L79): +[Обчислення PoH-хешу](https://github.com/anza-xyz/agave/blob/aa0922d6845e119ba466f88497e8209d1c82febc/entry/src/poh.rs#L79): `next_hash = hash(prev_hash, hash(transaction_ids))`. -PoH може використовуватися як довірений годинник, оскільки кожен хеш має бути створений послідовно. Кожен згенерований блок містить blockhash і список контрольних точок хешів, званих “ticks,” які дозволяють валідаторам перевіряти весь ланцюг хешів паралельно та доводити, що певний час дійсно минув. +PoH може використовуватися як довірений годинник, оскільки кожен хеш має бути +створений послідовно. Кожен згенерований блок містить blockhash і список +контрольних точок хешів, званих “ticks,” які дозволяють валідаторам перевіряти +весь ланцюг хешів паралельно та доводити, що певний час дійсно минув. ## Закінчення строку дії транзакції -За замовчуванням усі транзакції Solana закінчують строк дії, якщо їх не включено в блок протягом певного періоду часу. **Переважна більшість** проблем із підтвердженням транзакцій пов'язана з тим, як RPC-вузли та валідатори виявляють і обробляють **прострочені** транзакції. Чітке розуміння механізму закінчення строку дії транзакції допоможе вам діагностувати більшість проблем із підтвердженням транзакцій. +За замовчуванням усі транзакції Solana закінчують строк дії, якщо їх не включено +в блок протягом певного періоду часу. **Переважна більшість** проблем із +підтвердженням транзакцій пов'язана з тим, як RPC-вузли та валідатори виявляють +і обробляють **прострочені** транзакції. Чітке розуміння механізму закінчення +строку дії транзакції допоможе вам діагностувати більшість проблем із +підтвердженням транзакцій. ### Як працює закінчення строку дії транзакції? -Кожна транзакція містить “недавній blockhash,” який використовується як часовий штамп PoH і закінчується, коли цей blockhash більше не вважається “достатньо недавнім.” - -Коли кожен блок завершується (тобто досягається максимальна висота тиків, -[визначена](https://github.com/anza-xyz/agave/blob/0588ecc6121ba026c65600d117066dbdfaf63444/runtime/src/bank.rs#L3269-L3271), -до "кордону блоку"), фінальний хеш блоку додається до `BlockhashQueue`, яка зберігає максимум -[300 найновіших blockhash](https://github.com/anza-xyz/agave/blob/e0b0bcc80380da34bb63364cc393801af1e1057f/sdk/program/src/clock.rs#L123-L126). -Під час обробки транзакцій валідатори Solana перевіряють, чи зберігається недавній blockhash транзакції серед останніх 151 записаних хешів (так званий "максимальний вік обробки"). Якщо недавній blockhash транзакції -[старший за цей вік](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/runtime/src/bank.rs#L3570-L3571), +Кожна транзакція містить “недавній blockhash,” який використовується як часовий +штамп PoH і закінчується, коли цей blockhash більше не вважається “достатньо +недавнім.” + +Коли кожен блок завершується (тобто досягається максимальна висота тиків, +[визначена](https://github.com/anza-xyz/agave/blob/0588ecc6121ba026c65600d117066dbdfaf63444/runtime/src/bank.rs#L3269-L3271), +до "кордону блоку"), фінальний хеш блоку додається до `BlockhashQueue`, яка +зберігає максимум +[300 найновіших blockhash](https://github.com/anza-xyz/agave/blob/e0b0bcc80380da34bb63364cc393801af1e1057f/sdk/program/src/clock.rs#L123-L126). +Під час обробки транзакцій валідатори Solana перевіряють, чи зберігається +недавній blockhash транзакції серед останніх 151 записаних хешів (так званий +"максимальний вік обробки"). Якщо недавній blockhash транзакції +[старший за цей вік](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/runtime/src/bank.rs#L3570-L3571), транзакція не обробляється. -> Завдяки поточному -> [максимальному віку обробки, що становить 150](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L129-L131) -> і тому, що "вік" blockhash у черзі є -> [нульовим індексом](https://github.com/anza-xyz/agave/blob/992a398fe8ea29ec4f04d081ceef7664960206f4/accounts-db/src/blockhash_queue.rs#L248-L274), -> фактично є 151 blockhash, які вважаються "достатньо недавніми" і дійсними для обробки. +> Завдяки поточному +> [максимальному віку обробки, що становить 150](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L129-L131) +> і тому, що "вік" blockhash у черзі є +> [нульовим індексом](https://github.com/anza-xyz/agave/blob/992a398fe8ea29ec4f04d081ceef7664960206f4/accounts-db/src/blockhash_queue.rs#L248-L274), +> фактично є 151 blockhash, які вважаються "достатньо недавніми" і дійсними для +> обробки. -Оскільки [слоти](/docs/uk/terminology.md#slot) (тобто періоди часу, протягом яких валідатор може створити блок) налаштовані на тривалість близько -[400 мс](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L107-L109), -але можуть коливатися між 400 мс і 600 мс, певний blockhash можна використовувати в транзакціях приблизно протягом 60–90 секунд, перш ніж він вважатиметься простроченим у середовищі виконання. +Оскільки [слоти](/docs/uk/terminology.md#slot) (тобто періоди часу, протягом +яких валідатор може створити блок) налаштовані на тривалість близько +[400 мс](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L107-L109), +але можуть коливатися між 400 мс і 600 мс, певний blockhash можна +використовувати в транзакціях приблизно протягом 60–90 секунд, перш ніж він +вважатиметься простроченим у середовищі виконання. ### Приклад закінчення строку дії транзакції @@ -101,16 +131,26 @@ PoH може використовуватися як довірений годи 1. Валідатор активно створює новий блок для поточного слота. 2. Валідатор отримує транзакцію від користувача з недавнім blockhash `abcd...`. -3. Валідатор перевіряє цей blockhash `abcd...` у списку недавніх blockhash у `BlockhashQueue` і виявляє, що він був створений 151 блок тому. -4. Оскільки йому рівно 151 блок, транзакція ще не прострочена та може бути оброблена. -5. Але зачекайте: перед обробкою транзакції валідатор завершує створення наступного блоку та додає його до `BlockhashQueue`. Потім валідатор починає створювати блок для наступного слота (валідатори можуть створювати блоки протягом 4 послідовних слотів). -6. Валідатор перевіряє ту ж транзакцію ще раз і виявляє, що їй тепер 152 блоки. Вона відхиляється, оскільки занадто стара. :( +3. Валідатор перевіряє цей blockhash `abcd...` у списку недавніх blockhash у + `BlockhashQueue` і виявляє, що він був створений 151 блок тому. +4. Оскільки йому рівно 151 блок, транзакція ще не прострочена та може бути + оброблена. +5. Але зачекайте: перед обробкою транзакції валідатор завершує створення + наступного блоку та додає його до `BlockhashQueue`. Потім валідатор починає + створювати блок для наступного слота (валідатори можуть створювати блоки + протягом 4 послідовних слотів). +6. Валідатор перевіряє ту ж транзакцію ще раз і виявляє, що їй тепер 152 блоки. + Вона відхиляється, оскільки занадто стара. :( ## Чому транзакції закінчують строк дії? -Це робиться для того, щоб валідатори могли уникнути повторної обробки тієї ж транзакції. +Це робиться для того, щоб валідатори могли уникнути повторної обробки тієї ж +транзакції. -Наївний підхід для запобігання повторній обробці полягав би в перевірці кожної нової транзакції з усією історією транзакцій блокчейна. Але завдяки тому, що транзакції закінчують строк дії за короткий період часу, валідаторам потрібно перевіряти лише відносно невеликий набір **недавніх** транзакцій. +Наївний підхід для запобігання повторній обробці полягав би в перевірці кожної +нової транзакції з усією історією транзакцій блокчейна. Але завдяки тому, що +транзакції закінчують строк дії за короткий період часу, валідаторам потрібно +перевіряти лише відносно невеликий набір **недавніх** транзакцій. ### Other blockchains @@ -126,124 +166,229 @@ processing. ### Інші блокчейни -Підхід Solana до запобігання повторній обробці транзакцій значно відрізняється від інших блокчейнів. Наприклад, Ethereum використовує лічильник (nonce) для кожного відправника транзакцій і обробляє лише транзакції, які використовують наступний дійсний nonce. +Підхід Solana до запобігання повторній обробці транзакцій значно відрізняється +від інших блокчейнів. Наприклад, Ethereum використовує лічильник (nonce) для +кожного відправника транзакцій і обробляє лише транзакції, які використовують +наступний дійсний nonce. -Підхід Ethereum є простим для реалізації валідаторами, але може викликати проблеми для користувачів. Багато хто стикався із ситуаціями, коли їхні транзакції Ethereum залишалися в стані **очікування** протягом тривалого часу, а всі подальші транзакції з більшими значеннями nonce блокувалися. +Підхід Ethereum є простим для реалізації валідаторами, але може викликати +проблеми для користувачів. Багато хто стикався із ситуаціями, коли їхні +транзакції Ethereum залишалися в стані **очікування** протягом тривалого часу, а +всі подальші транзакції з більшими значеннями nonce блокувалися. ### Переваги на Solana Solana має кілька переваг у цьому підході: -1. Один платник комісії може надсилати кілька транзакцій одночасно, які можуть оброблятися в будь-якому порядку. Це може статися, якщо ви використовуєте кілька додатків одночасно. -2. Якщо транзакція не була додана до блоку та закінчила строк дії, користувачі можуть спробувати знову, знаючи, що їхня попередня транзакція **ніколи** не буде оброблена. +1. Один платник комісії може надсилати кілька транзакцій одночасно, які можуть + оброблятися в будь-якому порядку. Це може статися, якщо ви використовуєте + кілька додатків одночасно. +2. Якщо транзакція не була додана до блоку та закінчила строк дії, користувачі + можуть спробувати знову, знаючи, що їхня попередня транзакція **ніколи** не + буде оброблена. -Відсутність використання лічильників робить досвід роботи з Solana більш зрозумілим для користувачів, оскільки вони швидше отримують результат — успіх, невдачу або закінчення строку дії — та уникають тривалого стану очікування. +Відсутність використання лічильників робить досвід роботи з Solana більш +зрозумілим для користувачів, оскільки вони швидше отримують результат — успіх, +невдачу або закінчення строку дії — та уникають тривалого стану очікування. ### Недоліки на Solana Звісно, є й недоліки: -1. Валідатори повинні активно відстежувати набір усіх оброблених ідентифікаторів транзакцій, щоб запобігти їх повторній обробці. -2. Якщо час закінчення строку дії надто короткий, користувачі можуть не встигнути надіслати свої транзакції до того, як вони стануть недійсними. +1. Валідатори повинні активно відстежувати набір усіх оброблених ідентифікаторів + транзакцій, щоб запобігти їх повторній обробці. +2. Якщо час закінчення строку дії надто короткий, користувачі можуть не + встигнути надіслати свої транзакції до того, як вони стануть недійсними. -Ці недоліки показують компроміс у тому, як налаштовано строк дії транзакцій. Якщо збільшити час закінчення строку дії, валідаторам доведеться використовувати більше пам’яті для відстеження транзакцій. Якщо ж скоротити строк дії, користувачам буде важче встигнути надіслати свої транзакції. +Ці недоліки показують компроміс у тому, як налаштовано строк дії транзакцій. +Якщо збільшити час закінчення строку дії, валідаторам доведеться використовувати +більше пам’яті для відстеження транзакцій. Якщо ж скоротити строк дії, +користувачам буде важче встигнути надіслати свої транзакції. -Наразі кластери Solana вимагають, щоб транзакції використовували blockhash, який не старший за 151 блок. +Наразі кластери Solana вимагають, щоб транзакції використовували blockhash, який +не старший за 151 блок. -> У цьому [питанні GitHub](https://github.com/solana-labs/solana/issues/23582) надані розрахунки, які оцінюють, що валідаторам mainnet-beta потрібно близько 150 МБ пам’яті для відстеження транзакцій. У майбутньому це можна оптимізувати, не скорочуючи строк дії транзакцій, як зазначено в цьому обговоренні. +> У цьому [питанні GitHub](https://github.com/solana-labs/solana/issues/23582) +> надані розрахунки, які оцінюють, що валідаторам mainnet-beta потрібно близько +> 150 МБ пам’яті для відстеження транзакцій. У майбутньому це можна +> оптимізувати, не скорочуючи строк дії транзакцій, як зазначено в цьому +> обговоренні. ## Поради щодо підтвердження транзакцій -Як зазначалося раніше, blockhash закінчують строк дії через період, який може тривати всього **одну хвилину**, коли слоти обробляються з цільовим часом 400 мс. +Як зазначалося раніше, blockhash закінчують строк дії через період, який може +тривати всього **одну хвилину**, коли слоти обробляються з цільовим часом 400 +мс. -Одна хвилина — це не багато, враховуючи, що клієнту потрібно отримати недавній blockhash, дочекатися підписання транзакції користувачем, а потім сподіватися, що надіслана транзакція досягне лідера, який погодиться її обробити. Розглянемо кілька порад, які допоможуть уникнути невдач підтвердження через закінчення строку дії транзакцій. +Одна хвилина — це не багато, враховуючи, що клієнту потрібно отримати недавній +blockhash, дочекатися підписання транзакції користувачем, а потім сподіватися, +що надіслана транзакція досягне лідера, який погодиться її обробити. Розглянемо +кілька порад, які допоможуть уникнути невдач підтвердження через закінчення +строку дії транзакцій. ### Отримуйте blockhash із відповідним рівнем підтвердження -З огляду на короткий період закінчення строку дії, клієнти та додатки повинні допомагати користувачам створювати транзакції з blockhash, який є максимально недавнім. +З огляду на короткий період закінчення строку дії, клієнти та додатки повинні +допомагати користувачам створювати транзакції з blockhash, який є максимально +недавнім. -Коли ви отримуєте blockhash, рекомендованим RPC API є [`getLatestBlockhash`](/docs/uk/rpc/http/getLatestBlockhash.mdx). За замовчуванням цей API використовує рівень підтвердження `finalized`, щоб повернути blockhash останнього фіналізованого блоку. Проте ви можете змінити цю поведінку, встановивши параметр `commitment` на інший рівень підтвердження. +Коли ви отримуєте blockhash, рекомендованим RPC API є +[`getLatestBlockhash`](/docs/uk/rpc/http/getLatestBlockhash.mdx). За +замовчуванням цей API використовує рівень підтвердження `finalized`, щоб +повернути blockhash останнього фіналізованого блоку. Проте ви можете змінити цю +поведінку, встановивши параметр `commitment` на інший рівень підтвердження. **Рекомендація** -Рівень підтвердження `confirmed` майже завжди слід використовувати для запитів RPC, оскільки він зазвичай лише на кілька слотів відстає від рівня `processed` і має дуже низьку ймовірність належати до відхиленого [форку](https://docs.anza.xyz/consensus/fork-generation). +Рівень підтвердження `confirmed` майже завжди слід використовувати для запитів +RPC, оскільки він зазвичай лише на кілька слотів відстає від рівня `processed` і +має дуже низьку ймовірність належати до відхиленого +[форку](https://docs.anza.xyz/consensus/fork-generation). Але ви також можете розглянути інші варіанти: -- Вибір `processed` дозволяє отримати найбільш недавній blockhash порівняно з іншими рівнями підтвердження, що дає більше часу на підготовку і обробку транзакції. Однак через поширеність форків у блокчейні Solana близько 5% блоків не потрапляють у фіналізований кластер, що створює ризик того, що ваша транзакція використовує blockhash, що належить до відкинутого форку. Транзакції з такими blockhash ніколи не будуть вважатися недавніми у фіналізованому блокчейні. -- Використання [рівня підтвердження за замовчуванням](/docs/uk/rpc#default-commitment) `finalized` виключає ризик того, що вибраний blockhash належатиме до відкинутого форку. Однак це має компроміс: зазвичай є щонайменше 32 слоти різниці між найбільш недавнім підтвердженим блоком і найбільш недавнім фіналізованим блоком. Це значно зменшує строк дії ваших транзакцій приблизно на 13 секунд, що може бути ще більш суттєвим за нестабільних умов кластеру. +- Вибір `processed` дозволяє отримати найбільш недавній blockhash порівняно з + іншими рівнями підтвердження, що дає більше часу на підготовку і обробку + транзакції. Однак через поширеність форків у блокчейні Solana близько 5% + блоків не потрапляють у фіналізований кластер, що створює ризик того, що ваша + транзакція використовує blockhash, що належить до відкинутого форку. + Транзакції з такими blockhash ніколи не будуть вважатися недавніми у + фіналізованому блокчейні. +- Використання + [рівня підтвердження за замовчуванням](/docs/uk/rpc#default-commitment) + `finalized` виключає ризик того, що вибраний blockhash належатиме до + відкинутого форку. Однак це має компроміс: зазвичай є щонайменше 32 слоти + різниці між найбільш недавнім підтвердженим блоком і найбільш недавнім + фіналізованим блоком. Це значно зменшує строк дії ваших транзакцій приблизно + на 13 секунд, що може бути ще більш суттєвим за нестабільних умов кластеру. ### Використовуйте відповідний рівень підтвердження для preflight -Якщо ваша транзакція використовує blockhash, отриманий з одного RPC-вузла, але надсилається або симулюється на іншому, можуть виникнути проблеми через затримку одного з вузлів. +Якщо ваша транзакція використовує blockhash, отриманий з одного RPC-вузла, але +надсилається або симулюється на іншому, можуть виникнути проблеми через затримку +одного з вузлів. -Коли RPC-вузли отримують запит `sendTransaction`, вони намагаються визначити строк дії транзакції, використовуючи найбільш недавній фіналізований блок або блок, вибраний параметром `preflightCommitment`. **Дуже поширена проблема** виникає, якщо blockhash транзакції створений після блоку, який використовується для обчислення строку дії. У такому випадку RPC-вузол лише один раз пересилає транзакцію, а потім **видаляє** її. +Коли RPC-вузли отримують запит `sendTransaction`, вони намагаються визначити +строк дії транзакції, використовуючи найбільш недавній фіналізований блок або +блок, вибраний параметром `preflightCommitment`. **Дуже поширена проблема** +виникає, якщо blockhash транзакції створений після блоку, який використовується +для обчислення строку дії. У такому випадку RPC-вузол лише один раз пересилає +транзакцію, а потім **видаляє** її. -Аналогічно, при отриманні запиту `simulateTransaction` RPC-вузли симулюють транзакцію, використовуючи найбільш недавній фіналізований блок або блок, вибраний параметром `preflightCommitment`. Якщо вибраний блок для симуляції старіший за blockhash транзакції, симуляція завершиться помилкою “blockhash not found”. +Аналогічно, при отриманні запиту `simulateTransaction` RPC-вузли симулюють +транзакцію, використовуючи найбільш недавній фіналізований блок або блок, +вибраний параметром `preflightCommitment`. Якщо вибраний блок для симуляції +старіший за blockhash транзакції, симуляція завершиться помилкою “blockhash not +found”. **Рекомендація** -Навіть якщо ви використовуєте `skipPreflight`, **завжди** встановлюйте параметр `preflightCommitment` на той самий рівень підтвердження, який використовувався для отримання blockhash транзакції, як для запитів `sendTransaction`, так і `simulateTransaction`. +Навіть якщо ви використовуєте `skipPreflight`, **завжди** встановлюйте параметр +`preflightCommitment` на той самий рівень підтвердження, який використовувався +для отримання blockhash транзакції, як для запитів `sendTransaction`, так і +`simulateTransaction`. ### Уникайте відставання RPC-вузлів під час надсилання транзакцій -Якщо ваш додаток використовує сервіс пулу RPC або якщо кінцева точка RPC відрізняється між створенням транзакції та її надсиланням, будьте обережні зі сценаріями, коли один RPC-вузол відстає від іншого. Наприклад, якщо blockhash транзакції отримано з одного RPC-вузла, а транзакція надсилається на інший для обробки або симуляції, другий RPC-вузол може відставати. +Якщо ваш додаток використовує сервіс пулу RPC або якщо кінцева точка RPC +відрізняється між створенням транзакції та її надсиланням, будьте обережні зі +сценаріями, коли один RPC-вузол відстає від іншого. Наприклад, якщо blockhash +транзакції отримано з одного RPC-вузла, а транзакція надсилається на інший для +обробки або симуляції, другий RPC-вузол може відставати. **Рекомендація** -Для запитів `sendTransaction` клієнти повинні повторно надсилати транзакцію до RPC-вузла на частих інтервалах, щоб у випадку, якщо RPC-вузол трохи відстає від кластеру, він врешті-решт виявив транзакцію та її строк дії. +Для запитів `sendTransaction` клієнти повинні повторно надсилати транзакцію до +RPC-вузла на частих інтервалах, щоб у випадку, якщо RPC-вузол трохи відстає від +кластеру, він врешті-решт виявив транзакцію та її строк дії. -Для запитів `simulateTransaction` клієнти повинні використовувати параметр -[`replaceRecentBlockhash`](/docs/uk/rpc/http/simulateTransaction.mdx), щоб інструктувати RPC-вузол замінювати blockhash симульованої транзакції на blockhash, який завжди буде дійсним для симуляції. +Для запитів `simulateTransaction` клієнти повинні використовувати параметр +[`replaceRecentBlockhash`](/docs/uk/rpc/http/simulateTransaction.mdx), щоб +інструктувати RPC-вузол замінювати blockhash симульованої транзакції на +blockhash, який завжди буде дійсним для симуляції. ### Уникайте повторного використання застарілих blockhash -Навіть якщо ваш додаток отримав дуже недавній blockhash, переконайтеся, що ви не використовуєте його надто довго. Ідеальний сценарій — отримати свіжий blockhash безпосередньо перед підписанням транзакції. +Навіть якщо ваш додаток отримав дуже недавній blockhash, переконайтеся, що ви не +використовуєте його надто довго. Ідеальний сценарій — отримати свіжий blockhash +безпосередньо перед підписанням транзакції. **Рекомендація для додатків** -Часто запитуйте нові blockhash, щоб забезпечити готовність вашого додатка до створення транзакції, коли користувач виконує дію. +Часто запитуйте нові blockhash, щоб забезпечити готовність вашого додатка до +створення транзакції, коли користувач виконує дію. **Рекомендація для гаманців** -Часто запитуйте нові blockhash та оновлюйте blockhash транзакції перед підписанням, щоб забезпечити її актуальність. +Часто запитуйте нові blockhash та оновлюйте blockhash транзакції перед +підписанням, щоб забезпечити її актуальність. ### Використовуйте надійні RPC-вузли для отримання blockhash -RPC-вузли можуть відставати від кластеру через навантаження або інші причини, повертаючи blockhash, який майже вичерпав строк дії. +RPC-вузли можуть відставати від кластеру через навантаження або інші причини, +повертаючи blockhash, який майже вичерпав строк дії. **Рекомендація** Моніторте стан RPC-вузлів, використовуючи такі методи: -1. Викликайте API - [`getSlot`](/docs/uk/rpc/http/getSlot.mdx) з рівнем підтвердження `processed` для отримання останнього обробленого слота вузла та порівняйте його з - [`getMaxShredInsertSlot`](/docs/uk/rpc/http/getMaxShredInsertSlot.mdx), щоб оцінити відставання вузла. -2. Використовуйте RPC API `getLatestBlockhash` з рівнем підтвердження `confirmed` на кількох різних RPC-вузлах та обирайте blockhash від вузла, який повертає найвищий слот для свого [контекстного слоту](/docs/uk/rpc/index.mdx#rpcresponse-structure). +1. Викликайте API [`getSlot`](/docs/uk/rpc/http/getSlot.mdx) з рівнем + підтвердження `processed` для отримання останнього обробленого слота вузла та + порівняйте його з + [`getMaxShredInsertSlot`](/docs/uk/rpc/http/getMaxShredInsertSlot.mdx), щоб + оцінити відставання вузла. +2. Використовуйте RPC API `getLatestBlockhash` з рівнем підтвердження + `confirmed` на кількох різних RPC-вузлах та обирайте blockhash від вузла, + який повертає найвищий слот для свого + [контекстного слоту](/docs/uk/rpc/index.mdx#rpcresponse-structure). ### Зачекайте достатньо довго перед закінченням терміну дії **Рекомендація** -При виклику RPC API [`getLatestBlockhash`](/docs/uk/rpc/http/getLatestBlockhash.mdx) для отримання останнього blockhash вашої транзакції зверніть увагу на `lastValidBlockHeight` у відповіді. +При виклику RPC API +[`getLatestBlockhash`](/docs/uk/rpc/http/getLatestBlockhash.mdx) для отримання +останнього blockhash вашої транзакції зверніть увагу на `lastValidBlockHeight` у +відповіді. -Потім викликайте RPC API [`getBlockHeight`](/docs/uk/rpc/http/getBlockHeight.mdx) з рівнем підтвердження `confirmed`, поки він не поверне висоту блоку, більшу за попередньо отриманий `lastValidBlockHeight`. +Потім викликайте RPC API +[`getBlockHeight`](/docs/uk/rpc/http/getBlockHeight.mdx) з рівнем підтвердження +`confirmed`, поки він не поверне висоту блоку, більшу за попередньо отриманий +`lastValidBlockHeight`. ### Розгляньте використання "довготривалих" транзакцій -Іноді уникнути проблем із закінченням терміну дії транзакції дуже важко (наприклад, при офлайн-підписанні або нестабільності кластера). Якщо попередні поради не підходять для вашого випадку використання, ви можете перейти на використання довготривалих транзакцій (вони вимагають трохи налаштувань). +Іноді уникнути проблем із закінченням терміну дії транзакції дуже важко +(наприклад, при офлайн-підписанні або нестабільності кластера). Якщо попередні +поради не підходять для вашого випадку використання, ви можете перейти на +використання довготривалих транзакцій (вони вимагають трохи налаштувань). -Щоб почати використовувати довготривалі транзакції, користувач спочатку повинен подати транзакцію, яка -[викликає інструкції для створення спеціального "nonce" облікового запису на блокчейні](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.create_nonce_account.html) і зберігає в ньому "довготривалий blockhash". У будь-який момент у майбутньому (доки nonce-аккаунт ще не використаний) користувач може створити довготривалу транзакцію, дотримуючись двох правил: +Щоб почати використовувати довготривалі транзакції, користувач спочатку повинен +подати транзакцію, яка +[викликає інструкції для створення спеціального "nonce" облікового запису на блокчейні](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.create_nonce_account.html) +і зберігає в ньому "довготривалий blockhash". У будь-який момент у майбутньому +(доки nonce-аккаунт ще не використаний) користувач може створити довготривалу +транзакцію, дотримуючись двох правил: -1. Список інструкцій повинен починатися з [системної інструкції "advance nonce"](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.advance_nonce_account.html), яка завантажує їх nonce-аккаунт. -2. Blockhash транзакції повинен дорівнювати довготривалому blockhash, збереженому nonce-аккаунтом на блокчейні. +1. Список інструкцій повинен починатися з + [системної інструкції "advance nonce"](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.advance_nonce_account.html), + яка завантажує їх nonce-аккаунт. +2. Blockhash транзакції повинен дорівнювати довготривалому blockhash, + збереженому nonce-аккаунтом на блокчейні. Ось як Solana обробляє ці довготривалі транзакції: -1. Якщо blockhash транзакції більше не є "недавнім", система перевіряє, чи починається список інструкцій транзакції з інструкції "advance nonce". +1. Якщо blockhash транзакції більше не є "недавнім", система перевіряє, чи + починається список інструкцій транзакції з інструкції "advance nonce". 2. Якщо так, система завантажує nonce-аккаунт, вказаний у цій інструкції. -3. Потім перевіряє, чи збережений довготривалий blockhash відповідає blockhash транзакції. -4. Нарешті, система оновлює blockhash nonce-аккаунту до останнього недавнього blockhash, щоб гарантувати, що ця ж транзакція не може бути оброблена повторно. - -Детальніше про роботу цих довготривалих транзакцій ви можете дізнатися з [оригінальної пропозиції](https://docs.anza.xyz/implemented-proposals/durable-tx-nonces) та [ознайомитися з прикладом](/content/guides/advanced/introduction-to-durable-nonces.md) у документації Solana. +3. Потім перевіряє, чи збережений довготривалий blockhash відповідає blockhash + транзакції. +4. Нарешті, система оновлює blockhash nonce-аккаунту до останнього недавнього + blockhash, щоб гарантувати, що ця ж транзакція не може бути оброблена + повторно. + +Детальніше про роботу цих довготривалих транзакцій ви можете дізнатися з +[оригінальної пропозиції](https://docs.anza.xyz/implemented-proposals/durable-tx-nonces) +та +[ознайомитися з прикладом](/content/guides/advanced/introduction-to-durable-nonces.md) +у документації Solana. diff --git a/docs/locales/uk/advanced/lookup-tables.md b/docs/locales/uk/advanced/lookup-tables.md index 360f13a6a..3bedf440d 100644 --- a/docs/locales/uk/advanced/lookup-tables.md +++ b/docs/locales/uk/advanced/lookup-tables.md @@ -2,28 +2,45 @@ sidebarSortOrder: 4 title: Таблиці пошуку адрес description: - Дізнайтеся, як використовувати таблиці пошуку адрес Solana (ALTs) для ефективної обробки до 64 адрес у кожній транзакції. Створюйте, розширюйте та використовуйте таблиці пошуку за допомогою web3.js. + Дізнайтеся, як використовувати таблиці пошуку адрес Solana (ALTs) для + ефективної обробки до 64 адрес у кожній транзакції. Створюйте, розширюйте та + використовуйте таблиці пошуку за допомогою web3.js. --- -Таблиці пошуку адрес, зазвичай відомі як "_lookup tables_" або скорочено "_ALTs_", дозволяють розробникам створювати колекції пов’язаних адрес для ефективного завантаження більшої кількості адрес в одній транзакції. +Таблиці пошуку адрес, зазвичай відомі як "_lookup tables_" або скорочено +"_ALTs_", дозволяють розробникам створювати колекції пов’язаних адрес для +ефективного завантаження більшої кількості адрес в одній транзакції. -Оскільки кожна транзакція в блокчейні Solana вимагає переліку всіх адрес, з якими вона взаємодіє, цей перелік фактично обмежується 32 адресами на транзакцію. Завдяки [Таблицям пошуку адрес](/docs/uk/advanced/lookup-tables.md) це обмеження можна збільшити до 64 адрес у кожній транзакції. +Оскільки кожна транзакція в блокчейні Solana вимагає переліку всіх адрес, з +якими вона взаємодіє, цей перелік фактично обмежується 32 адресами на +транзакцію. Завдяки [Таблицям пошуку адрес](/docs/uk/advanced/lookup-tables.md) +це обмеження можна збільшити до 64 адрес у кожній транзакції. ## Стиснення адрес на блокчейні -Після того, як усі необхідні адреси були збережені на блокчейні у Таблиці пошуку адрес, кожну адресу можна посилатися в транзакції за її 1-байтовим індексом у таблиці (замість повної 32-байтової адреси). Цей метод пошуку ефективно "_стискає_" 32-байтову адресу до 1-байтового значення індексу. +Після того, як усі необхідні адреси були збережені на блокчейні у Таблиці пошуку +адрес, кожну адресу можна посилатися в транзакції за її 1-байтовим індексом у +таблиці (замість повної 32-байтової адреси). Цей метод пошуку ефективно +"_стискає_" 32-байтову адресу до 1-байтового значення індексу. -Таке "_стиснення_" дозволяє зберігати до 256 адрес у одній таблиці пошуку для використання у будь-якій транзакції. +Таке "_стиснення_" дозволяє зберігати до 256 адрес у одній таблиці пошуку для +використання у будь-якій транзакції. ## Версійні транзакції -Щоб використовувати Таблицю пошуку адрес у транзакції, розробники повинні застосовувати транзакції версії v0, які були запроваджені з новим форматом [Версійних транзакцій](/docs/uk/advanced/versions.md). +Щоб використовувати Таблицю пошуку адрес у транзакції, розробники повинні +застосовувати транзакції версії v0, які були запроваджені з новим форматом +[Версійних транзакцій](/docs/uk/advanced/versions.md). ## Як створити таблицю пошуку адрес -Створення нової таблиці пошуку за допомогою бібліотеки `@solana/web3.js` подібне до старішого формату `legacy` транзакцій, але має певні відмінності. +Створення нової таблиці пошуку за допомогою бібліотеки `@solana/web3.js` подібне +до старішого формату `legacy` транзакцій, але має певні відмінності. -Використовуючи бібліотеку `@solana/web3.js`, ви можете скористатися функцією [`createLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#createLookupTable) для створення інструкції, необхідної для створення нової таблиці пошуку, а також для визначення її адреси. +Використовуючи бібліотеку `@solana/web3.js`, ви можете скористатися функцією +[`createLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#createLookupTable) +для створення інструкції, необхідної для створення нової таблиці пошуку, а також +для визначення її адреси. ```js const web3 = require("@solana/web3.js"); @@ -48,11 +65,18 @@ console.log("lookup table address:", lookupTableAddress.toBase58()); // send the `lookupTableInst` instruction in a transaction ``` -> ПРИМІТКА: Таблиці пошуку адрес можуть бути **створені** за допомогою як транзакцій `v0`, так і `legacy`. Але виконуюче середовище Solana може отримувати та обробляти додаткові адреси в таблиці пошуку лише під час використання [Версійних транзакцій v0](/docs/uk/advanced/versions.md#current-transaction-versions). +> ПРИМІТКА: Таблиці пошуку адрес можуть бути **створені** за допомогою як +> транзакцій `v0`, так і `legacy`. Але виконуюче середовище Solana може +> отримувати та обробляти додаткові адреси в таблиці пошуку лише під час +> використання +> [Версійних транзакцій v0](/docs/uk/advanced/versions.md#current-transaction-versions). ## Додавання адрес до таблиці пошуку -Додавання адрес до таблиці пошуку відоме як "_розширення_" ("_extending_"). Використовуючи бібліотеку `@solana/web3.js`, ви можете створити нову інструкцію для _розширення_ за допомогою методу [`extendLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#extendLookupTable): +Додавання адрес до таблиці пошуку відоме як "_розширення_" ("_extending_"). +Використовуючи бібліотеку `@solana/web3.js`, ви можете створити нову інструкцію +для _розширення_ за допомогою методу +[`extendLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#extendLookupTable): ```js // add addresses to the `lookupTableAddress` table via an `extend` instruction @@ -71,13 +95,22 @@ const extendInstruction = web3.AddressLookupTableProgram.extendLookupTable({ // to insert the listing of `addresses` into your lookup table with address `lookupTableAddress` ``` -> ПРИМІТКА: Через ті самі обмеження пам'яті транзакцій `legacy`, будь-яка транзакція, яка використовується для _розширення_ таблиці пошуку адрес, також обмежена в кількості адрес, які можна додати одночасно. Через це вам потрібно буде використовувати кілька транзакцій, щоб _розширити_ будь-яку таблицю більшою кількістю адрес (приблизно 20), ніж це дозволяють обмеження пам'яті однієї транзакції. +> ПРИМІТКА: Через ті самі обмеження пам'яті транзакцій `legacy`, будь-яка +> транзакція, яка використовується для _розширення_ таблиці пошуку адрес, також +> обмежена в кількості адрес, які можна додати одночасно. Через це вам потрібно +> буде використовувати кілька транзакцій, щоб _розширити_ будь-яку таблицю +> більшою кількістю адрес (приблизно 20), ніж це дозволяють обмеження пам'яті +> однієї транзакції. -Після того як ці адреси були вставлені в таблицю та збережені в блокчейні, ви зможете використовувати таблицю пошуку адрес у майбутніх транзакціях. Це дозволяє включити до 64 адрес у цих транзакціях. +Після того як ці адреси були вставлені в таблицю та збережені в блокчейні, ви +зможете використовувати таблицю пошуку адрес у майбутніх транзакціях. Це +дозволяє включити до 64 адрес у цих транзакціях. ## Отримання таблиці пошуку адрес -Аналогічно запиту іншого облікового запису (або PDA) з кластера, ви можете отримати повну таблицю пошуку адрес за допомогою методу [`getAddressLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getAddressLookupTable): +Аналогічно запиту іншого облікового запису (або PDA) з кластера, ви можете +отримати повну таблицю пошуку адрес за допомогою методу +[`getAddressLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getAddressLookupTable): ```js // define the `PublicKey` of the lookup table to fetch @@ -93,7 +126,9 @@ const lookupTableAccount = ( console.log("Table address from cluster:", lookupTableAccount.key.toBase58()); ``` -Змінна `lookupTableAccount` тепер буде об'єктом типу `AddressLookupTableAccount`, який можна проаналізувати для читання списку всіх адрес, збережених у таблиці пошуку в блокчейні: +Змінна `lookupTableAccount` тепер буде об'єктом типу +`AddressLookupTableAccount`, який можна проаналізувати для читання списку всіх +адрес, збережених у таблиці пошуку в блокчейні: ```js // loop through and parse all the addresses stored in the table @@ -102,16 +137,23 @@ for (let i = 0; i < lookupTableAccount.state.addresses.length; i++) { console.log(i, address.toBase58()); } ``` + ## Як використовувати таблицю пошуку адрес у транзакції -Після того як ви створили таблицю пошуку і зберегли необхідні адреси в блокчейні (через розширення таблиці пошуку), ви можете створити транзакцію `v0`, щоб скористатися можливостями пошуку адрес в блокчейні. +Після того як ви створили таблицю пошуку і зберегли необхідні адреси в блокчейні +(через розширення таблиці пошуку), ви можете створити транзакцію `v0`, щоб +скористатися можливостями пошуку адрес в блокчейні. -Так само, як і для старих транзакцій `legacy`, ви можете створити всі -[інструкції](/docs/uk/terminology.md#instruction), які ваша транзакція виконуватиме в блокчейні. Потім ви можете передати масив цих інструкцій у -[Message](/docs/uk/terminology.md#message), що використовується в транзакції `v0`. +Так само, як і для старих транзакцій `legacy`, ви можете створити всі +[інструкції](/docs/uk/terminology.md#instruction), які ваша транзакція +виконуватиме в блокчейні. Потім ви можете передати масив цих інструкцій у +[Message](/docs/uk/terminology.md#message), що використовується в транзакції +`v0`. -> **Примітка:** Інструкції, що використовуються в транзакції `v0`, можна створювати за допомогою тих самих методів і функцій, які використовувалися раніше для створення інструкцій. -> Немає необхідності змінювати інструкції, пов'язані з використанням таблиці пошуку адрес. +> **Примітка:** Інструкції, що використовуються в транзакції `v0`, можна +> створювати за допомогою тих самих методів і функцій, які використовувалися +> раніше для створення інструкцій. Немає необхідності змінювати інструкції, +> пов'язані з використанням таблиці пошуку адрес. ```js // Assumptions: @@ -140,10 +182,13 @@ console.log( ); ``` -> **Примітка:** Під час відправлення `VersionedTransaction` до кластеру, вона має бути підписана **ДО** виклику методу `sendAndConfirmTransaction`. Якщо передати масив `Signer` (як у транзакціях `legacy`), метод викличе помилку! +> **Примітка:** Під час відправлення `VersionedTransaction` до кластеру, вона +> має бути підписана **ДО** виклику методу `sendAndConfirmTransaction`. Якщо +> передати масив `Signer` (як у транзакціях `legacy`), метод викличе помилку! ## Додаткові ресурси -- Ознайомтеся з [пропозицією](https://docs.anza.xyz/proposals/versioned-transactions) щодо таблиць пошуку адрес і версійованих транзакцій +- Ознайомтеся з + [пропозицією](https://docs.anza.xyz/proposals/versioned-transactions) щодо + таблиць пошуку адрес і версійованих транзакцій - [Приклад програми на Rust, яка використовує таблиці пошуку адрес](https://github.com/TeamRaccoons/address-lookup-table-multi-swap) - diff --git a/docs/locales/uk/advanced/retry.md b/docs/locales/uk/advanced/retry.md index 42d1ee4c8..9a5af666f 100644 --- a/docs/locales/uk/advanced/retry.md +++ b/docs/locales/uk/advanced/retry.md @@ -5,55 +5,90 @@ altRoutes: - /docs/core/transactions/retry description: Дізнайтеся, як обробляти втрачені транзакції та впроваджувати користувацьку - логіку повторної відправки у Solana. Цей посібник охоплює повторне - передавання транзакцій, перевірки перед виконанням (preflight) і найкращі - практики для забезпечення надійної обробки транзакцій у блокчейні Solana. + логіку повторної відправки у Solana. Цей посібник охоплює повторне передавання + транзакцій, перевірки перед виконанням (preflight) і найкращі практики для + забезпечення надійної обробки транзакцій у блокчейні Solana. --- # Повторна відправка транзакцій -Іноді здається, що дійсна транзакція може бути втрачена до її включення в блок. Це зазвичай трапляється під час завантаженості мережі, коли RPC-вузол не може повторно передати транзакцію до [лідера](/docs/uk/terminology.md#leader). Для кінцевого користувача це може виглядати так, ніби транзакція повністю зникає. Хоча RPC-вузли мають універсальний алгоритм повторного передавання, розробники додатків також можуть створювати власну логіку повторної передачі. +Іноді здається, що дійсна транзакція може бути втрачена до її включення в блок. +Це зазвичай трапляється під час завантаженості мережі, коли RPC-вузол не може +повторно передати транзакцію до [лідера](/docs/uk/terminology.md#leader). Для +кінцевого користувача це може виглядати так, ніби транзакція повністю зникає. +Хоча RPC-вузли мають універсальний алгоритм повторного передавання, розробники +додатків також можуть створювати власну логіку повторної передачі. ## Коротко: -- RPC-вузли намагатимуться повторно передати транзакції за допомогою універсального алгоритму. +- RPC-вузли намагатимуться повторно передати транзакції за допомогою + універсального алгоритму. - Розробники додатків можуть впроваджувати власну логіку повторного передавання. -- Розробникам слід використовувати параметр `maxRetries` у методі JSON-RPC `sendTransaction`. -- Розробникам слід вмикати перевірки перед виконанням (preflight), щоб виявляти помилки до відправки транзакцій. -- Перед повторним підписанням будь-якої транзакції важливо переконатися, що термін дії blockhash вихідної транзакції минув. +- Розробникам слід використовувати параметр `maxRetries` у методі JSON-RPC + `sendTransaction`. +- Розробникам слід вмикати перевірки перед виконанням (preflight), щоб виявляти + помилки до відправки транзакцій. +- Перед повторним підписанням будь-якої транзакції важливо переконатися, що + термін дії blockhash вихідної транзакції минув. ## Шлях транзакції ### Як клієнти відправляють транзакції -У Solana немає концепції мемпулу. Усі транзакції, незалежно від того, чи ініційовані вони програмно або користувачем, ефективно маршрутизуються до лідерів для обробки в блоках. Є два основні способи надсилання транзакцій до лідерів: +У Solana немає концепції мемпулу. Усі транзакції, незалежно від того, чи +ініційовані вони програмно або користувачем, ефективно маршрутизуються до +лідерів для обробки в блоках. Є два основні способи надсилання транзакцій до +лідерів: -1. Через RPC-сервер за допомогою методу JSON-RPC [sendTransaction](/docs/uk/rpc/http/sendTransaction.mdx). -2. Безпосередньо до лідерів через [TPU Client](https://docs.rs/solana-client/latest/solana_client/tpu_client/index.html). +1. Через RPC-сервер за допомогою методу JSON-RPC + [sendTransaction](/docs/uk/rpc/http/sendTransaction.mdx). +2. Безпосередньо до лідерів через + [TPU Client](https://docs.rs/solana-client/latest/solana_client/tpu_client/index.html). -Більшість користувачів відправляють транзакції через RPC-сервер. Коли клієнт надсилає транзакцію, RPC-вузол намагається передати її поточному та наступному лідерам. Поки транзакція не буде оброблена лідером, вона існує лише у вигляді запису в клієнта або проміжних RPC-вузлів. У випадку використання TPU клієнтом, передавання та маршрутизація обробляються програмним забезпеченням клієнта. +Більшість користувачів відправляють транзакції через RPC-сервер. Коли клієнт +надсилає транзакцію, RPC-вузол намагається передати її поточному та наступному +лідерам. Поки транзакція не буде оброблена лідером, вона існує лише у вигляді +запису в клієнта або проміжних RPC-вузлів. У випадку використання TPU клієнтом, +передавання та маршрутизація обробляються програмним забезпеченням клієнта. ![Огляд шляху транзакції, від клієнта до лідера](/assets/docs/rt-tx-journey.png) ### Як RPC-вузли передають транзакції -Після отримання транзакції через `sendTransaction`, RPC-вузол перетворює транзакцію в [UDP](https://uk.wikipedia.org/wiki/UDP) пакет і передає його відповідним лідерам. UDP дозволяє вузлам швидко обмінюватися даними, але не гарантує доставки пакетів. +Після отримання транзакції через `sendTransaction`, RPC-вузол перетворює +транзакцію в [UDP](https://uk.wikipedia.org/wiki/UDP) пакет і передає його +відповідним лідерам. UDP дозволяє вузлам швидко обмінюватися даними, але не +гарантує доставки пакетів. -Оскільки розклад лідерів Solana відомий заздалегідь для кожного [епоха](/docs/uk/terminology.md#epoch) (~2 дні), RPC-вузол передає транзакції безпосередньо до поточного та наступного лідерів. За замовчуванням RPC-вузли намагаються повторно передавати транзакції кожні дві секунди, доки транзакція не буде завершена або доки термін дії її blockhash не закінчиться (~1 хвилина 19 секунд). Якщо черга для повторної передачі перевищує [10,000 транзакцій](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/send-transaction-service/src/send_transaction_service.rs#L20), нові транзакції скидаються. +Оскільки розклад лідерів Solana відомий заздалегідь для кожного +[епоха](/docs/uk/terminology.md#epoch) (~2 дні), RPC-вузол передає транзакції +безпосередньо до поточного та наступного лідерів. За замовчуванням RPC-вузли +намагаються повторно передавати транзакції кожні дві секунди, доки транзакція не +буде завершена або доки термін дії її blockhash не закінчиться (~1 хвилина 19 +секунд). Якщо черга для повторної передачі перевищує +[10,000 транзакцій](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/send-transaction-service/src/send_transaction_service.rs#L20), +нові транзакції скидаються. ![Процес обробки транзакцій TPU](/assets/docs/rt-tpu-jito-labs.png) ## Як транзакції скидаються -Транзакції можуть бути скинуті через кілька причин, таких як перевантаження мережі, втрати пакетів UDP або конфлікти через різні статуси вузлів у пулі RPC. +Транзакції можуть бути скинуті через кілька причин, таких як перевантаження +мережі, втрати пакетів UDP або конфлікти через різні статуси вузлів у пулі RPC. ## Обробка скинутих транзакцій -Розробники можуть використовувати параметр `maxRetries` методу `sendTransaction` для створення власної логіки повторного передавання, зокрема перевірки `lastValidBlockHeight` і опитування стану мережі. +Розробники можуть використовувати параметр `maxRetries` методу `sendTransaction` +для створення власної логіки повторного передавання, зокрема перевірки +`lastValidBlockHeight` і опитування стану мережі. ## Налаштування власної логіки -Впровадження алгоритмів, таких як [експоненціальне збільшення інтервалів](https://uk.wikipedia.org/wiki/Експоненційне_зростання), або постійне повторне передавання, як у [Mango](https://github.com/blockworks-foundation/mango-ui/blob/b6abfc6c13b71fc17ebbe766f50b8215fa1ec54f/src/utils/send.tsx#L713), може допомогти впоратися із завантаженістю мережі. +Впровадження алгоритмів, таких як +[експоненціальне збільшення інтервалів](https://uk.wikipedia.org/wiki/Експоненційне_зростання), +або постійне повторне передавання, як у +[Mango](https://github.com/blockworks-foundation/mango-ui/blob/b6abfc6c13b71fc17ebbe766f50b8215fa1ec54f/src/utils/send.tsx#L713), +може допомогти впоратися із завантаженістю мережі. ```ts import { @@ -112,26 +147,48 @@ const sleep = async (ms: number) => { })(); ``` -При опитуванні через `getLatestBlockhash` додатки повинні вказувати бажаний рівень [зобов'язань (commitment)](/docs/uk/rpc/index.mdx#configuring-state-commitment). Встановлюючи зобов'язання на рівень `confirmed` (підтверджений) або `finalized` (~30 блоків після `confirmed`), додаток може уникнути опитування blockhash із меншості вузлів. - -Якщо додаток має доступ до RPC-вузлів за балансувальником навантаження, він також може розподіляти своє навантаження між конкретними вузлами. RPC-вузли, які обслуговують ресурсоємні запити, такі як -[getProgramAccounts](/content/guides/javascript/get-program-accounts.md), можуть відставати і бути менш ефективними для пересилання транзакцій. Для додатків, що обробляють транзакції в реальному часі, може бути розумним використовувати спеціалізовані вузли, які обслуговують лише `sendTransaction`. +При опитуванні через `getLatestBlockhash` додатки повинні вказувати бажаний +рівень +[зобов'язань (commitment)](/docs/uk/rpc/index.mdx#configuring-state-commitment). +Встановлюючи зобов'язання на рівень `confirmed` (підтверджений) або `finalized` +(~30 блоків після `confirmed`), додаток може уникнути опитування blockhash із +меншості вузлів. + +Якщо додаток має доступ до RPC-вузлів за балансувальником навантаження, він +також може розподіляти своє навантаження між конкретними вузлами. RPC-вузли, які +обслуговують ресурсоємні запити, такі як +[getProgramAccounts](/content/guides/javascript/get-program-accounts.md), можуть +відставати і бути менш ефективними для пересилання транзакцій. Для додатків, що +обробляють транзакції в реальному часі, може бути розумним використовувати +спеціалізовані вузли, які обслуговують лише `sendTransaction`. ### Вартість пропуску перевірки перед виконанням -За замовчуванням `sendTransaction` виконує три перевірки перед відправкою транзакції. Зокрема, `sendTransaction`: +За замовчуванням `sendTransaction` виконує три перевірки перед відправкою +транзакції. Зокрема, `sendTransaction`: - Перевіряє, що всі підписи є дійсними. - Перевіряє, що вказаний blockhash знаходиться в межах останніх 150 блоків. - Симулює транзакцію на основі слоту банку, зазначеного у `preflightCommitment`. -У разі, якщо одна з цих перевірок не пройде, `sendTransaction` видасть помилку до відправки транзакції. Перевірки перед виконанням можуть стати вирішальним фактором між втратою транзакції та можливістю клієнта обробити помилку. Щоб гарантувати врахування цих поширених помилок, рекомендується залишати `skipPreflight` встановленим у значення `false`. +У разі, якщо одна з цих перевірок не пройде, `sendTransaction` видасть помилку +до відправки транзакції. Перевірки перед виконанням можуть стати вирішальним +фактором між втратою транзакції та можливістю клієнта обробити помилку. Щоб +гарантувати врахування цих поширених помилок, рекомендується залишати +`skipPreflight` встановленим у значення `false`. ### Коли потрібно повторно підписувати транзакції -Попри всі спроби повторного передавання, іноді клієнт може бути змушений повторно підписати транзакцію. Перед повторним підписанням будь-якої транзакції **дуже важливо** переконатися, що термін дії blockhash вихідної транзакції закінчився. Якщо початковий blockhash все ще дійсний, обидві транзакції можуть бути прийняті мережею. Для кінцевого користувача це виглядатиме як ненавмисне повторне відправлення однієї і тієї ж транзакції. - -У Solana втрачену транзакцію можна безпечно відхилити, якщо blockhash, на який вона посилається, старший за `lastValidBlockHeight`, отриманий із -`getLatestBlockhash`. Розробникам слід відстежувати цей `lastValidBlockHeight`, опитуючи -[`getEpochInfo`](/docs/uk/rpc/http/getEpochInfo.mdx) і порівнюючи з `blockHeight` у відповіді. Після того, як blockhash стане недійсним, клієнти можуть повторно підписати транзакцію з новозапитаним blockhash. - +Попри всі спроби повторного передавання, іноді клієнт може бути змушений +повторно підписати транзакцію. Перед повторним підписанням будь-якої транзакції +**дуже важливо** переконатися, що термін дії blockhash вихідної транзакції +закінчився. Якщо початковий blockhash все ще дійсний, обидві транзакції можуть +бути прийняті мережею. Для кінцевого користувача це виглядатиме як ненавмисне +повторне відправлення однієї і тієї ж транзакції. + +У Solana втрачену транзакцію можна безпечно відхилити, якщо blockhash, на який +вона посилається, старший за `lastValidBlockHeight`, отриманий із +`getLatestBlockhash`. Розробникам слід відстежувати цей `lastValidBlockHeight`, +опитуючи [`getEpochInfo`](/docs/uk/rpc/http/getEpochInfo.mdx) і порівнюючи з +`blockHeight` у відповіді. Після того, як blockhash стане недійсним, клієнти +можуть повторно підписати транзакцію з новозапитаним blockhash. diff --git a/docs/locales/uk/advanced/state-compression.md b/docs/locales/uk/advanced/state-compression.md index c094491db..b2df0fdc9 100644 --- a/docs/locales/uk/advanced/state-compression.md +++ b/docs/locales/uk/advanced/state-compression.md @@ -2,20 +2,31 @@ sidebarSortOrder: 4 title: Стиснення стану (State Compression) description: - 'Стиснення стану - це метод дешевого та безпечного збереження - "відбитків" даних поза мережею в реєстрі Solana замість дорогих облікових записів.' + 'Стиснення стану - це метод дешевого та безпечного збереження "відбитків" + даних поза мережею в реєстрі Solana замість дорогих облікових записів.' --- -У Solana [стиснення стану](/docs/uk/advanced/state-compression.md) є методом створення "відбитку" (або гешу) даних поза мережею та збереження цього відбитку в мережі для безпечної перевірки. Цей процес використовує безпеку реєстру Solana для гарантування цілісності даних поза мережею, забезпечуючи їх незмінність. +У Solana [стиснення стану](/docs/uk/advanced/state-compression.md) є методом +створення "відбитку" (або гешу) даних поза мережею та збереження цього відбитку +в мережі для безпечної перевірки. Цей процес використовує безпеку реєстру Solana +для гарантування цілісності даних поза мережею, забезпечуючи їх незмінність. -Цей метод "стиснення" дозволяє програмам та децентралізованим додаткам (dApps) використовувати дешевий простір у [реєстрі](/docs/uk/terminology.md#ledger) блокчейну, замість більш дорогого простору [облікових записів](/docs/uk/terminology.md#account), для безпечного зберігання даних. +Цей метод "стиснення" дозволяє програмам та децентралізованим додаткам (dApps) +використовувати дешевий простір у [реєстрі](/docs/uk/terminology.md#ledger) +блокчейну, замість більш дорогого простору +[облікових записів](/docs/uk/terminology.md#account), для безпечного зберігання +даних. -Це досягається за допомогою спеціальної структури двійкового дерева, відомого як -[конкурентне мерклеве дерево](#what-is-a-concurrent-merkle-tree), яке створює геш кожного фрагмента даних (названого `листком`), об'єднує ці геші і зберігає тільки фінальний геш у мережі. +Це досягається за допомогою спеціальної структури двійкового дерева, відомого як +[конкурентне мерклеве дерево](#what-is-a-concurrent-merkle-tree), яке створює +геш кожного фрагмента даних (названого `листком`), об'єднує ці геші і зберігає +тільки фінальний геш у мережі. ## Що таке стиснення стану? -Простіше кажучи, стиснення стану використовує структури "**_дерев_**" для криптографічного хешування даних поза мережею детермінованим способом, щоб обчислити один кінцевий геш, який зберігається у мережі. +Простіше кажучи, стиснення стану використовує структури "**_дерев_**" для +криптографічного хешування даних поза мережею детермінованим способом, щоб +обчислити один кінцевий геш, який зберігається у мережі. Ці _дерева_ створюються таким "_детермінованим_" процесом: @@ -26,35 +37,63 @@ description: - Кожна `гілка` також хешується разом. - Процес повторюється, поки не буде обчислено фінальний `кореневий геш`. -Цей `кореневий геш` зберігається в мережі як верифіковане **_підтвердження_** для всіх даних у кожному листку. Це дозволяє криптографічно перевіряти всі дані поза мережею, використовуючи мінімальну кількість даних у мережі. Таким чином, значно знижуються витрати на зберігання/перевірку великих обсягів даних завдяки "стисненню стану". +Цей `кореневий геш` зберігається в мережі як верифіковане **_підтвердження_** +для всіх даних у кожному листку. Це дозволяє криптографічно перевіряти всі дані +поза мережею, використовуючи мінімальну кількість даних у мережі. Таким чином, +значно знижуються витрати на зберігання/перевірку великих обсягів даних завдяки +"стисненню стану". ## Мерклеві дерева та конкурентні мерклеві дерева -Стиснення стану у Solana використовує спеціальний тип -[мерклевого дерева](#what-is-a-merkle-tree), який дозволяє виконувати кілька змін у дереві, зберігаючи його цілісність і валідність. +Стиснення стану у Solana використовує спеціальний тип +[мерклевого дерева](#what-is-a-merkle-tree), який дозволяє виконувати кілька +змін у дереві, зберігаючи його цілісність і валідність. -Це спеціальне дерево, відоме як -"[конкурентне мерклеве дерево](#what-is-a-concurrent-merkle-tree)", зберігає "журнал змін" дерева в мережі. Це дозволяє виконувати кілька змін до дерева (наприклад, у межах одного блоку), не порушуючи підтвердження. +Це спеціальне дерево, відоме як +"[конкурентне мерклеве дерево](#what-is-a-concurrent-merkle-tree)", зберігає +"журнал змін" дерева в мережі. Це дозволяє виконувати кілька змін до дерева +(наприклад, у межах одного блоку), не порушуючи підтвердження. ### Що таке мерклеве дерево? -[Мерклеве дерево](https://uk.wikipedia.org/wiki/Мерклеве_дерево), або "дерево гешів", — це двійкова структура, у якій кожен `листок` є криптографічним гешем даних. Всі вузли, які **не** є листками, називаються `гілками` і є гешами їхніх дочірніх листків. +[Мерклеве дерево](https://uk.wikipedia.org/wiki/Мерклеве_дерево), або "дерево +гешів", — це двійкова структура, у якій кожен `листок` є криптографічним гешем +даних. Всі вузли, які **не** є листками, називаються `гілками` і є гешами їхніх +дочірніх листків. -Кожна гілка також хешується разом, поступово піднімаючись вгору, поки не залишиться один геш. Цей фінальний геш, званий `кореневим гешем`, можна використовувати разом із "шляхом підтвердження" для перевірки будь-яких даних, збережених у листковому вузлі. +Кожна гілка також хешується разом, поступово піднімаючись вгору, поки не +залишиться один геш. Цей фінальний геш, званий `кореневим гешем`, можна +використовувати разом із "шляхом підтвердження" для перевірки будь-яких даних, +збережених у листковому вузлі. ### Що таке Конкурентне Мерклеве дерево? -У високопродуктивних застосунках, таких як [середовище виконання Solana](/docs/uk/core/fees.md), запити на зміну ончейн _традиційного мерклевого дерева_ можуть надходити до валідаторів досить швидко (наприклад, у межах одного слота). У таких випадках кожна зміна даних у листках повинна виконуватися послідовно. Це призводить до невдачі наступних запитів на зміну, оскільки кореневий геш і підтвердження стають недійсними після попередньої зміни в слоті. +У високопродуктивних застосунках, таких як +[середовище виконання Solana](/docs/uk/core/fees.md), запити на зміну ончейн +_традиційного мерклевого дерева_ можуть надходити до валідаторів досить швидко +(наприклад, у межах одного слота). У таких випадках кожна зміна даних у листках +повинна виконуватися послідовно. Це призводить до невдачі наступних запитів на +зміну, оскільки кореневий геш і підтвердження стають недійсними після +попередньої зміни в слоті. Рішенням цієї проблеми є Конкурентні Мерклеві дерева. -**Конкурентне Мерклеве дерево** зберігає **захищений журнал змін**, який містить останні зміни, їх кореневий геш і підтвердження для його обчислення. Цей буфер змін ("changelog buffer") зберігається ончейн у спеціальному акаунті для кожного дерева, з обмеженням на максимальну кількість записів у журналі змін (`maxBufferSize`). +**Конкурентне Мерклеве дерево** зберігає **захищений журнал змін**, який містить +останні зміни, їх кореневий геш і підтвердження для його обчислення. Цей буфер +змін ("changelog buffer") зберігається ончейн у спеціальному акаунті для кожного +дерева, з обмеженням на максимальну кількість записів у журналі змін +(`maxBufferSize`). -Коли валідатори отримують кілька запитів на зміну даних у листках у межах одного слота, ончейн _конкурентне мерклеве дерево_ може використовувати цей буфер змін як джерело правдивої інформації для більш прийнятних підтверджень. Це дозволяє виконувати до `maxBufferSize` змін для одного дерева в межах одного слота, що значно підвищує пропускну здатність. +Коли валідатори отримують кілька запитів на зміну даних у листках у межах одного +слота, ончейн _конкурентне мерклеве дерево_ може використовувати цей буфер змін +як джерело правдивої інформації для більш прийнятних підтверджень. Це дозволяє +виконувати до `maxBufferSize` змін для одного дерева в межах одного слота, що +значно підвищує пропускну здатність. ## Розмір Конкурентного Мерклевого дерева -При створенні такого ончейн дерева існує 3 параметри, які визначають розмір дерева, вартість його створення і кількість одночасних змін: +При створенні такого ончейн дерева існує 3 параметри, які визначають розмір +дерева, вартість його створення і кількість одночасних змін: 1. Максимальна глибина (max depth) 2. Розмір буфера змін (max buffer size) @@ -62,20 +101,29 @@ description: ### Максимальна глибина -"Максимальна глибина" дерева — це **максимальна кількість** переходів від будь-якого `листка` даних до `кореня` дерева. +"Максимальна глибина" дерева — це **максимальна кількість** переходів від +будь-якого `листка` даних до `кореня` дерева. -Оскільки мерклеві дерева є двійковими, кожен листок з'єднаний лише з **одним** іншим листком; вони утворюють `пару листків`. +Оскільки мерклеві дерева є двійковими, кожен листок з'єднаний лише з **одним** +іншим листком; вони утворюють `пару листків`. -Таким чином, `maxDepth` дерева використовується для визначення максимальної кількості вузлів (тобто елементів даних або `листків`), які можна зберігати у дереві, за допомогою простої формули: +Таким чином, `maxDepth` дерева використовується для визначення максимальної +кількості вузлів (тобто елементів даних або `листків`), які можна зберігати у +дереві, за допомогою простої формули: ```text nodes_count = 2 ^ maxDepth ``` -Оскільки глибину дерева потрібно встановити під час його створення, ви повинні визначити, скільки елементів даних ви хочете зберігати у своєму дереві. Потім, використовуючи просту формулу вище, ви можете визначити найменше значення `maxDepth`, яке дозволить зберігати ваші дані. + +Оскільки глибину дерева потрібно встановити під час його створення, ви повинні +визначити, скільки елементів даних ви хочете зберігати у своєму дереві. Потім, +використовуючи просту формулу вище, ви можете визначити найменше значення +`maxDepth`, яке дозволить зберігати ваші дані. #### Приклад 1: Мінтинг 100 NFT -Якщо ви хочете створити дерево для зберігання 100 стиснутих NFT, вам знадобиться щонайменше "100 листків" або "100 вузлів". +Якщо ви хочете створити дерево для зберігання 100 стиснутих NFT, вам знадобиться +щонайменше "100 листків" або "100 вузлів". ```text // maxDepth=6 -> 64 nodes @@ -84,11 +132,14 @@ nodes_count = 2 ^ maxDepth // maxDepth=7 -> 128 nodes 2^7 = 128 ``` -Ми повинні використовувати значення `maxDepth` рівне `7`, щоб забезпечити можливість зберігати всі наші дані. + +Ми повинні використовувати значення `maxDepth` рівне `7`, щоб забезпечити +можливість зберігати всі наші дані. #### Приклад 2: Мінтинг 15000 NFT -Якщо ви хочете створити дерево для зберігання 15000 стиснутих NFT, вам знадобиться щонайменше "15000 листків" або "15000 вузлів". +Якщо ви хочете створити дерево для зберігання 15000 стиснутих NFT, вам +знадобиться щонайменше "15000 листків" або "15000 вузлів". ```text // maxDepth=13 -> 8192 nodes @@ -97,33 +148,51 @@ nodes_count = 2 ^ maxDepth // maxDepth=14 -> 16384 nodes 2^14 = 16384 ``` -Ми повинні використовувати `maxDepth` рівне `14`, щоб забезпечити можливість зберігати всі наші дані. + +Ми повинні використовувати `maxDepth` рівне `14`, щоб забезпечити можливість +зберігати всі наші дані. #### Чим більша максимальна глибина, тим вища вартість -Значення `maxDepth` є одним із основних чинників вартості під час створення дерева, оскільки ви оплачуєте цю вартість наперед при створенні дерева. Чим більша глибина дерева, тим більше даних (відбитків або хешів) можна зберігати, але тим вища вартість. +Значення `maxDepth` є одним із основних чинників вартості під час створення +дерева, оскільки ви оплачуєте цю вартість наперед при створенні дерева. Чим +більша глибина дерева, тим більше даних (відбитків або хешів) можна зберігати, +але тим вища вартість. --- ### Максимальний розмір буфера (maxBufferSize) -"Максимальний розмір буфера" — це максимальна кількість змін, які можуть бути внесені до дерева, доки кореневий хеш (`root hash`) залишається дійсним. +"Максимальний розмір буфера" — це максимальна кількість змін, які можуть бути +внесені до дерева, доки кореневий хеш (`root hash`) залишається дійсним. -Оскільки кореневий хеш є єдиним хешем для всіх даних листків, зміна будь-якого окремого листка інвалідовує proof, потрібний для всіх наступних спроб змінити будь-який інший листок у звичайному дереві. +Оскільки кореневий хеш є єдиним хешем для всіх даних листків, зміна будь-якого +окремого листка інвалідовує proof, потрібний для всіх наступних спроб змінити +будь-який інший листок у звичайному дереві. -У випадку [Concurrent Tree](#що-таке-concurrent-merkle-tree), існує журнал змін для цих proof, який задається під час створення дерева через параметр `maxBufferSize`. +У випадку [Concurrent Tree](#що-таке-concurrent-merkle-tree), існує журнал змін +для цих proof, який задається під час створення дерева через параметр +`maxBufferSize`. --- ### Глибина козирка (canopyDepth) -"Глибина козирка" або "розмір козирка" визначає кількість рівнів proof, які кешуються або зберігаються on-chain для даного proof-шляху. +"Глибина козирка" або "розмір козирка" визначає кількість рівнів proof, які +кешуються або зберігаються on-chain для даного proof-шляху. -Коли виконується дія оновлення для `leaf` (наприклад, передача права власності), **повний** proof-шлях повинен бути використаний для верифікації початкового права власності на листок. Це здійснюється шляхом обчислення поточного `root hash`. +Коли виконується дія оновлення для `leaf` (наприклад, передача права власності), +**повний** proof-шлях повинен бути використаний для верифікації початкового +права власності на листок. Це здійснюється шляхом обчислення поточного +`root hash`. -Для великих дерев потрібно більше proof-вузлів, щоб виконати цю перевірку. Наприклад, якщо `maxDepth` дорівнює `14`, потрібно `14` proof-вузлів. З використанням козирка частина цих вузлів зберігається on-chain, зменшуючи кількість proof-вузлів, які потрібно включити в транзакції. +Для великих дерев потрібно більше proof-вузлів, щоб виконати цю перевірку. +Наприклад, якщо `maxDepth` дорівнює `14`, потрібно `14` proof-вузлів. З +використанням козирка частина цих вузлів зберігається on-chain, зменшуючи +кількість proof-вузлів, які потрібно включити в транзакції. -Наприклад, дерево з `maxDepth` рівне `14` із козирком розміром `10` потребуватиме лише `4` proof-вузли на транзакцію. +Наприклад, дерево з `maxDepth` рівне `14` із козирком розміром `10` +потребуватиме лише `4` proof-вузли на транзакцію. ![Глибина козирка 1 для Concurrent Merkle Tree з максимальною глибиною 3](/assets/docs/compression/canopy-depth-1.png) @@ -131,19 +200,26 @@ nodes_count = 2 ^ maxDepth #### Чим більша глибина козирка, тим вища вартість -Значення `canopyDepth` також є одним із основних чинників вартості створення дерева. Чим більше proof-вузлів зберігається on-chain, тим вища вартість. +Значення `canopyDepth` також є одним із основних чинників вартості створення +дерева. Чим більше proof-вузлів зберігається on-chain, тим вища вартість. #### Низький козирок обмежує композитність -Низьке значення `canopyDepth` вимагає більше proof-вузлів у кожній транзакції оновлення. Це обмежує можливості для інтеграції вашого дерева з іншими Solana-програмами або dApps. +Низьке значення `canopyDepth` вимагає більше proof-вузлів у кожній транзакції +оновлення. Це обмежує можливості для інтеграції вашого дерева з іншими +Solana-програмами або dApps. -Наприклад, дерево, яке використовується для стиснутих NFT з низьким `canopyDepth`, може дозволяти лише базові дії, як-от передача, але не підтримувати розширені функції, такі як система ставок. +Наприклад, дерево, яке використовується для стиснутих NFT з низьким +`canopyDepth`, може дозволяти лише базові дії, як-от передача, але не +підтримувати розширені функції, такі як система ставок. --- ## Вартість створення дерева -Вартість створення Concurrent Merkle Tree залежить від його параметрів: `maxDepth`, `maxBufferSize`, і `canopyDepth`. Ці параметри визначають необхідний простір (у байтах) для дерева. +Вартість створення Concurrent Merkle Tree залежить від його параметрів: +`maxDepth`, `maxBufferSize`, і `canopyDepth`. Ці параметри визначають необхідний +простір (у байтах) для дерева. Використовуючи метод [`getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getminimumbalanceforrentexemption), @@ -161,7 +237,8 @@ nodes_count = 2 ^ maxDepth Далі, за допомогою функції [`getMinimumBalanceForRentExemption`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getMinimumBalanceForRentExemption), -можна визначити остаточну вартість (у лампортах) для створення дерева, подібно до будь-якого іншого акаунта. +можна визначити остаточну вартість (у лампортах) для створення дерева, подібно +до будь-якого іншого акаунта. ```ts // calculate the space required for the tree @@ -178,7 +255,8 @@ const storageCost = ### Приклади вартості -Нижче наведено кілька прикладів вартості для дерев різного розміру, включаючи кількість можливих листків: +Нижче наведено кілька прикладів вартості для дерев різного розміру, включаючи +кількість можливих листків: **Приклад №1: 16,384 вузлів, вартість 0.222 SOL** @@ -208,7 +286,11 @@ const storageCost = ## Стиснуті NFT -Стиснуті NFT є одним із найпопулярніших варіантів використання стиснення стану на Solana. Завдяки стисненню колекцію з одного мільйона NFT можна створити за `~50 SOL`, у порівнянні з `~12,000 SOL` для її нестиснутої еквівалентної колекції. +Стиснуті NFT є одним із найпопулярніших варіантів використання стиснення стану +на Solana. Завдяки стисненню колекцію з одного мільйона NFT можна створити за +`~50 SOL`, у порівнянні з `~12,000 SOL` для її нестиснутої еквівалентної +колекції. -Якщо ви зацікавлені в створенні стиснутих NFT, ознайомтеся з нашим посібником для розробників: +Якщо ви зацікавлені в створенні стиснутих NFT, ознайомтеся з нашим посібником +для розробників: [створення та передача стиснутих NFT](/content/guides/javascript/compressed-nfts.md). diff --git a/docs/locales/uk/advanced/versions.md b/docs/locales/uk/advanced/versions.md index b3f5c5aaf..998915a05 100644 --- a/docs/locales/uk/advanced/versions.md +++ b/docs/locales/uk/advanced/versions.md @@ -2,15 +2,19 @@ sidebarSortOrder: 3 title: "Версійні Транзакції" description: - "Дослідіть основні концепції Solana: транзакції, версійні транзакції, розширення функціональності в Solana Runtime, таблиці пошуку адрес та інше." + "Дослідіть основні концепції Solana: транзакції, версійні транзакції, + розширення функціональності в Solana Runtime, таблиці пошуку адрес та інше." altRoutes: - /docs/uk/core/transactions/versions --- -Версійні Транзакції - це новий формат транзакцій, який дозволяє додаткову функціональність у Solana Runtime, включаючи +Версійні Транзакції - це новий формат транзакцій, який дозволяє додаткову +функціональність у Solana Runtime, включаючи [Таблиці пошуку адрес](/docs/uk/advanced/lookup-tables.md). -Хоча зміни в ончейн-програмах **НЕ** потрібні для підтримки нової функціональності версійних транзакцій (або для зворотної сумісності), розробники **ПОВИННІ** оновити клієнтський код, щоб уникнути +Хоча зміни в ончейн-програмах **НЕ** потрібні для підтримки нової +функціональності версійних транзакцій (або для зворотної сумісності), розробники +**ПОВИННІ** оновити клієнтський код, щоб уникнути [помилок через різні версії транзакцій](#max-supported-transaction-version). ## Поточні версії транзакцій @@ -23,26 +27,32 @@ Solana Runtime підтримує дві версії транзакцій: ## Максимально підтримувана версія транзакцій -Усі RPC-запити, які повертають транзакцію, **_повинні_** вказувати найвищу версію транзакцій, яку вони підтримують у своїй програмі, використовуючи параметр -`maxSupportedTransactionVersion`, включаючи +Усі RPC-запити, які повертають транзакцію, **_повинні_** вказувати найвищу +версію транзакцій, яку вони підтримують у своїй програмі, використовуючи +параметр `maxSupportedTransactionVersion`, включаючи [`getBlock`](/docs/uk/rpc/http/getBlock.mdx) та [`getTransaction`](/docs/uk/rpc/http/getTransaction.mdx). -RPC-запит завершиться невдачею, якщо буде повернута версійна транзакція, яка має версію вище встановленої `maxSupportedTransactionVersion`. (наприклад, якщо повертається транзакція версії `0`, а встановлено `legacy`) +RPC-запит завершиться невдачею, якщо буде повернута версійна транзакція, яка має +версію вище встановленої `maxSupportedTransactionVersion`. (наприклад, якщо +повертається транзакція версії `0`, а встановлено `legacy`) -> УВАГА: Якщо значення `maxSupportedTransactionVersion` не встановлено, тоді лише транзакції `legacy` будуть дозволені у відповіді RPC. Таким чином, ваші RPC-запити **ПРИЗВЕДУТЬ ДО ПОМИЛКИ**, якщо буде повернута будь-яка транзакція версії `0`. +> УВАГА: Якщо значення `maxSupportedTransactionVersion` не встановлено, тоді +> лише транзакції `legacy` будуть дозволені у відповіді RPC. Таким чином, ваші +> RPC-запити **ПРИЗВЕДУТЬ ДО ПОМИЛКИ**, якщо буде повернута будь-яка транзакція +> версії `0`. ## Як встановити максимально підтримувану версію Ви можете встановити `maxSupportedTransactionVersion`, використовуючи бібліотеку -[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/) -або шляхом прямого надсилання JSON-запитів до RPC-ендпоінту. +[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/) або +шляхом прямого надсилання JSON-запитів до RPC-ендпоінту. ### Використання web3.js Використовуючи бібліотеку -[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/), -ви можете отримати останній блок або конкретну транзакцію: +[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/), ви +можете отримати останній блок або конкретну транзакцію: ```js // підключення до кластера `devnet` та отримання поточного `slot` @@ -80,7 +90,8 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - ## Як створити версійну транзакцію -Версійні транзакції можна створити подібно до старого методу створення транзакцій. Є відмінності у використанні певних бібліотек, які слід враховувати. +Версійні транзакції можна створити подібно до старого методу створення +транзакцій. Є відмінності у використанні певних бібліотек, які слід враховувати. Нижче наведено приклад створення версійної транзакції з використанням бібліотеки `@solana/web3.js` для передачі SOL між двома рахунками. @@ -90,9 +101,11 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - - `payer` - це дійсний гаманець `Keypair`, наповнений SOL - `toAccount` - дійсний `Keypair` -Спочатку імпортуйте бібліотеку web3.js та створіть `connection` до бажаного кластера. +Спочатку імпортуйте бібліотеку web3.js та створіть `connection` до бажаного +кластера. -Далі визначте останній `blockhash` і `minRent`, які будуть потрібні для вашої транзакції та рахунку: +Далі визначте останній `blockhash` і `minRent`, які будуть потрібні для вашої +транзакції та рахунку: ```js const web3 = require("@solana/web3.js"); @@ -105,7 +118,8 @@ let blockhash = await connection .then(res => res.blockhash); ``` -Створіть `array` усіх `instructions`, які ви хочете відправити у вашій транзакції. У прикладі нижче ми створюємо просту інструкцію передачі SOL: +Створіть `array` усіх `instructions`, які ви хочете відправити у вашій +транзакції. У прикладі нижче ми створюємо просту інструкцію передачі SOL: ```js // створення масиву з вашими інструкціями @@ -138,7 +152,8 @@ const transaction = new web3.VersionedTransaction(messageV0); transaction.sign([payer]); ``` -Після того, як ваша `VersionedTransaction` підписана всіма необхідними рахунками, ви можете відправити її до кластера та отримати відповідь: +Після того, як ваша `VersionedTransaction` підписана всіма необхідними +рахунками, ви можете відправити її до кластера та отримати відповідь: ```js // відправка нашої транзакції v0 до кластера @@ -146,8 +161,10 @@ const txId = await connection.sendTransaction(transaction); console.log(`https://explorer.solana.com/tx/${txId}?cluster=devnet`); ``` -> УВАГА: На відміну від `legacy` транзакцій, відправка `VersionedTransaction` через -> `sendTransaction` **НЕ** підтримує підпис транзакцій через передачу масиву `Signers` як другого параметра. Ви повинні підписати транзакцію перед викликом `connection.sendTransaction()`. +> УВАГА: На відміну від `legacy` транзакцій, відправка `VersionedTransaction` +> через `sendTransaction` **НЕ** підтримує підпис транзакцій через передачу +> масиву `Signers` як другого параметра. Ви повинні підписати транзакцію перед +> викликом `connection.sendTransaction()`. ## Додаткові ресурси @@ -159,4 +176,3 @@ console.log(`https://explorer.solana.com/tx/${txId}?cluster=devnet`); - Читання [ухваленої пропозиції](https://docs.anza.xyz/proposals/versioned-transactions) для версійних транзакцій та таблиць пошуку адрес - diff --git a/docs/locales/uk/clients/javascript-reference.md b/docs/locales/uk/clients/javascript-reference.md index c8631101a..1ea13ade9 100644 --- a/docs/locales/uk/clients/javascript-reference.md +++ b/docs/locales/uk/clients/javascript-reference.md @@ -1,8 +1,8 @@ --- title: Web3.js API Приклади description: - Дізнайтеся, як взаємодіяти з блокчейном Solana за допомогою бібліотеки @solana/web3.js - через практичні приклади коду та пояснення. + Дізнайтеся, як взаємодіяти з блокчейном Solana за допомогою бібліотеки + @solana/web3.js через практичні приклади коду та пояснення. --- ## Довідник по Web3 API @@ -19,9 +19,13 @@ description: [Документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html) -Об'єкт `Connection` використовується для взаємодії з [Solana JSON RPC](/docs/uk/rpc). Ви можете використовувати Connection для підтвердження транзакцій, отримання інформації про облікові записи тощо. +Об'єкт `Connection` використовується для взаємодії з +[Solana JSON RPC](/docs/uk/rpc). Ви можете використовувати Connection для +підтвердження транзакцій, отримання інформації про облікові записи тощо. -Створення підключення здійснюється шляхом вказання URL-адреси RPC-кластера та бажаного рівня зобов'язань. Після цього ви можете використовувати цей об'єкт підключення для взаємодії з будь-яким із API JSON RPC Solana. +Створення підключення здійснюється шляхом вказання URL-адреси RPC-кластера та +бажаного рівня зобов'язань. Після цього ви можете використовувати цей об'єкт +підключення для взаємодії з будь-яким із API JSON RPC Solana. #### Приклад використання @@ -58,14 +62,20 @@ console.log(slotLeader); //49AqLYbpJYc2DrzGUAH1fhWJy62yxBxpLEkfJwjKy2jr ``` -Наведений вище приклад показує лише кілька методів класу Connection. Повний список можна знайти у +Наведений вище приклад показує лише кілька методів класу Connection. Повний +список можна знайти у [генерованій документації](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html). ### Транзакція [Документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html) -Транзакція використовується для взаємодії з програмами на блокчейні Solana. Ці транзакції створюються за допомогою TransactionInstructions, які містять усі можливі облікові записи для взаємодії, а також необхідні дані або адреси програм. Кожна TransactionInstruction складається з ключів, даних і programId. Ви можете виконувати кілька інструкцій в одній транзакції, взаємодіючи з кількома програмами одночасно. +Транзакція використовується для взаємодії з програмами на блокчейні Solana. Ці +транзакції створюються за допомогою TransactionInstructions, які містять усі +можливі облікові записи для взаємодії, а також необхідні дані або адреси +програм. Кожна TransactionInstruction складається з ключів, даних і programId. +Ви можете виконувати кілька інструкцій в одній транзакції, взаємодіючи з +кількома програмами одночасно. #### Приклад використання @@ -135,7 +145,9 @@ await web3.sendAndConfirmRawTransaction(connection, rawTransaction); [Документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Keypair.html) -Keypair використовується для створення облікового запису з публічним і секретним ключами в Solana. Ви можете згенерувати Keypair, створити його з seed або секретного ключа. +Keypair використовується для створення облікового запису з публічним і секретним +ключами в Solana. Ви можете згенерувати Keypair, створити його з seed або +секретного ключа. #### Приклад використання @@ -170,20 +182,34 @@ console.log(accountFromSecret.secretKey); // Uint8Array(64) [...] ``` -Використання `generate` генерує випадкову Keypair для облікового запису на Solana. Використання `fromSeed` дозволяє створити Keypair з детермінованим конструктором. `fromSecret` створює Keypair із секретного масиву Uint8Array. Ви можете побачити, що publicKey для Keypair, створеної за допомогою `generate`, і `fromSecret` однакові, оскільки секретний ключ однаковий. +Використання `generate` генерує випадкову Keypair для облікового запису на +Solana. Використання `fromSeed` дозволяє створити Keypair з детермінованим +конструктором. `fromSecret` створює Keypair із секретного масиву Uint8Array. Ви +можете побачити, що publicKey для Keypair, створеної за допомогою `generate`, і +`fromSecret` однакові, оскільки секретний ключ однаковий. + ### Використання `generate` створює випадкову пару ключів для використання як обліковий запис у Solana. -Використання `fromSeed` дозволяє створити пару ключів за допомогою детермінованого конструктора. -`fromSecret` створює пару ключів із секретного масиву Uint8Array. Ви можете побачити, що publicKey для пари ключів `generate` і `fromSecret` є однаковими, оскільки секрет від пари ключів `generate` використовується в `fromSecret`. -**Попередження**: Не використовуйте `fromSeed`, якщо ви не створюєте seed із високою ентропією. Не розголошуйте ваш seed. Ставтеся до seed так само, як до приватного ключа. +Використання `fromSeed` дозволяє створити пару ключів за допомогою +детермінованого конструктора. `fromSecret` створює пару ключів із секретного +масиву Uint8Array. Ви можете побачити, що publicKey для пари ключів `generate` і +`fromSecret` є однаковими, оскільки секрет від пари ключів `generate` +використовується в `fromSecret`. + +**Попередження**: Не використовуйте `fromSeed`, якщо ви не створюєте seed із +високою ентропією. Не розголошуйте ваш seed. Ставтеся до seed так само, як до +приватного ключа. ### PublicKey [Джерело документації](https://solana-labs.github.io/solana-web3.js/v1.x/classes/PublicKey.html) -`PublicKey` використовується в `@solana/web3.js` для транзакцій, пар ключів і програм. Вам потрібен publicKey при зазначенні кожного облікового запису в транзакції, а також як загальний ідентифікатор у Solana. +`PublicKey` використовується в `@solana/web3.js` для транзакцій, пар ключів і +програм. Вам потрібен publicKey при зазначенні кожного облікового запису в +транзакції, а також як загальний ідентифікатор у Solana. -`PublicKey` можна створити за допомогою base58-строки, буфера, Uint8Array, числа або масиву чисел. +`PublicKey` можна створити за допомогою base58-строки, буфера, Uint8Array, числа +або масиву чисел. #### Приклад використання @@ -206,7 +232,9 @@ let programAddressFromKey = await web3.PublicKey.createProgramAddress( [highEntropyBuffer.slice(0, 31)], base58publicKey, ); -console.log(`Згенерована програмна адреса: ${programAddressFromKey.toBase58()}`); +console.log( + `Згенерована програмна адреса: ${programAddressFromKey.toBase58()}`, +); // Згенерована програмна адреса: 3thxPEEz4EDWHNxo1LpEpsAxZryPAHyvNVXJEJWgBgwJ @@ -224,7 +252,10 @@ console.log(`Дійсна програмна адреса: ${validProgramAddress [Джерело документації](https://solana-labs.github.io/solana-web3.js/v1.x/classes/SystemProgram.html) -`SystemProgram` дозволяє створювати облікові записи, виділяти дані облікових записів, призначати облікові записи програмам, працювати з nonce-обліковими записами та переводити лампорти. Ви можете використовувати клас `SystemInstruction` для декодування та читання окремих інструкцій. +`SystemProgram` дозволяє створювати облікові записи, виділяти дані облікових +записів, призначати облікові записи програмам, працювати з nonce-обліковими +записами та переводити лампорти. Ви можете використовувати клас +`SystemInstruction` для декодування та читання окремих інструкцій. #### Приклад використання @@ -313,13 +344,14 @@ await web3.sendAndConfirmTransaction(connection, assignTransaction, [ payer, assignedAccount, ]); - ``` + ### Secp256k1Program [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Secp256k1Program.html) -`Secp256k1Program` використовується для перевірки підписів `Secp256k1`, які використовуються як у Bitcoin, так і в Ethereum. +`Secp256k1Program` використовується для перевірки підписів `Secp256k1`, які +використовуються як у Bitcoin, так і в Ethereum. #### Приклад Використання @@ -381,7 +413,11 @@ await web3.sendAndConfirmTransaction(connection, transaction, [fromPublicKey]); [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Message.html) -`Message` використовується як альтернативний спосіб створення транзакцій. Ви можете створити повідомлення за допомогою облікових записів, заголовка, інструкцій та недавнього блочного хеша, які є частиною транзакції. [Transaction](/docs/uk/clients/javascript.md#Transaction) є `Message` плюс список необхідних підписів для виконання транзакції. +`Message` використовується як альтернативний спосіб створення транзакцій. Ви +можете створити повідомлення за допомогою облікових записів, заголовка, +інструкцій та недавнього блочного хеша, які є частиною транзакції. +[Transaction](/docs/uk/clients/javascript.md#Transaction) є `Message` плюс +список необхідних підписів для виконання транзакції. #### Приклад Використання @@ -443,7 +479,9 @@ await web3.sendAndConfirmTransaction(connection, transaction, [fromPublicKey]); [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Struct.html) -Клас `Struct` використовується для створення структур, сумісних із Rust, у JavaScript. Цей клас сумісний лише з Rust-структурами, закодованими за допомогою Borsh. +Клас `Struct` використовується для створення структур, сумісних із Rust, у +JavaScript. Цей клас сумісний лише з Rust-структурами, закодованими за допомогою +Borsh. #### Приклад Використання @@ -472,7 +510,11 @@ export class Fee extends Struct { [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Enum.html) -Клас `Enum` використовується для представлення сумісного з Rust енумератора у JavaScript. Енумератор буде представлений як строка при логуванні, але може бути правильно закодований/декодований при використанні разом з [Struct](/docs/uk/clients/javascript.md#Struct). Цей клас сумісний лише з Rust-енумераторами, закодованими за допомогою Borsh. +Клас `Enum` використовується для представлення сумісного з Rust енумератора у +JavaScript. Енумератор буде представлений як строка при логуванні, але може бути +правильно закодований/декодований при використанні разом з +[Struct](/docs/uk/clients/javascript.md#Struct). Цей клас сумісний лише з +Rust-енумераторами, закодованими за допомогою Borsh. #### Приклад Використання @@ -498,9 +540,15 @@ export class AccountType extends Enum {} [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/NonceAccount.html) -Зазвичай транзакція відхиляється, якщо поле `recentBlockhash` транзакції є застарілим. Для забезпечення певних кастодіальних послуг використовуються облікові записи `NonceAccount`. Транзакції, які використовують `recentBlockhash`, зафіксовані на блокчейні обліковим записом `NonceAccount`, не старіють доти, доки цей обліковий запис не буде оновлено. +Зазвичай транзакція відхиляється, якщо поле `recentBlockhash` транзакції є +застарілим. Для забезпечення певних кастодіальних послуг використовуються +облікові записи `NonceAccount`. Транзакції, які використовують +`recentBlockhash`, зафіксовані на блокчейні обліковим записом `NonceAccount`, не +старіють доти, доки цей обліковий запис не буде оновлено. -Ви можете створити `NonceAccount`, спочатку створивши звичайний обліковий запис, а потім використовуючи `SystemProgram`, щоб зробити цей обліковий запис `NonceAccount`. +Ви можете створити `NonceAccount`, спочатку створивши звичайний обліковий запис, +а потім використовуючи `SystemProgram`, щоб зробити цей обліковий запис +`NonceAccount`. #### Приклад Використання @@ -575,13 +623,17 @@ console.log(nonceAccountFromInfo); // } ``` -Наведений вище приклад показує як створити `NonceAccount` за допомогою `SystemProgram.createNonceAccount`, а також як отримати `NonceAccount` з accountInfo. Використовуючи nonce, ви можете створювати транзакції офлайн з nonce замість `recentBlockhash`. +Наведений вище приклад показує як створити `NonceAccount` за допомогою +`SystemProgram.createNonceAccount`, а також як отримати `NonceAccount` з +accountInfo. Використовуючи nonce, ви можете створювати транзакції офлайн з +nonce замість `recentBlockhash`. ### VoteAccount [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/VoteAccount.html) -`VoteAccount` — це об'єкт, який дозволяє декодувати облікові записи для голосування з використанням нативної програми голосування в мережі. +`VoteAccount` — це об'єкт, який дозволяє декодувати облікові записи для +голосування з використанням нативної програми голосування в мережі. #### Приклад Використання @@ -653,7 +705,12 @@ VoteAccount { [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/StakeProgram.html) -`StakeProgram` полегшує процес стейкінгу SOL і делегування їх будь-яким валідаторам у мережі. Ви можете використовувати `StakeProgram`, щоб створити стейк-обліковий запис, застейкати SOL, авторизувати облікові записи для виведення стейка, деактивувати стейк і вивести кошти. Клас `StakeInstruction` використовується для декодування та читання додаткових інструкцій з транзакцій, що викликають `StakeProgram`. +`StakeProgram` полегшує процес стейкінгу SOL і делегування їх будь-яким +валідаторам у мережі. Ви можете використовувати `StakeProgram`, щоб створити +стейк-обліковий запис, застейкати SOL, авторизувати облікові записи для +виведення стейка, деактивувати стейк і вивести кошти. Клас `StakeInstruction` +використовується для декодування та читання додаткових інструкцій з транзакцій, +що викликають `StakeProgram`. #### Приклад Використання @@ -749,15 +806,23 @@ await web3.sendAndConfirmTransaction(connection, withdrawTransaction, [ [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Authorized.html) -`Authorized` — це об'єкт, який використовується під час створення авторизованого облікового запису для стейкінгу в Solana. Ви можете окремо призначити `staker` і `withdrawer`, що дозволяє іншому обліковому запису виводити кошти, ніж той, що виконує стейкінг. +`Authorized` — це об'єкт, який використовується під час створення авторизованого +облікового запису для стейкінгу в Solana. Ви можете окремо призначити `staker` і +`withdrawer`, що дозволяє іншому обліковому запису виводити кошти, ніж той, що +виконує стейкінг. -Більше прикладів використання об'єкта `Authorized` ви можете знайти в розділі [`StakeProgram`](/docs/uk/clients/javascript.md#StakeProgram). +Більше прикладів використання об'єкта `Authorized` ви можете знайти в розділі +[`StakeProgram`](/docs/uk/clients/javascript.md#StakeProgram). ### Lockup [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Lockup.html) -`Lockup` використовується разом із [StakeProgram](/docs/uk/clients/javascript.md#StakeProgram) для створення облікового запису. `Lockup` визначає, як довго стейк буде заблокований або недоступний для вилучення. Якщо `Lockup` встановлений на 0 як для епохи, так і для мітки часу Unix, блокування для облікового запису буде відключено. +`Lockup` використовується разом із +[StakeProgram](/docs/uk/clients/javascript.md#StakeProgram) для створення +облікового запису. `Lockup` визначає, як довго стейк буде заблокований або +недоступний для вилучення. Якщо `Lockup` встановлений на 0 як для епохи, так і +для мітки часу Unix, блокування для облікового запису буде відключено. #### Приклад Використання @@ -783,7 +848,10 @@ let createStakeAccountInstruction = StakeProgram.createAccount({ }); ``` -Наведений вище код створює `createStakeAccountInstruction`, який використовується для створення облікового запису за допомогою `StakeProgram`. Блокування встановлено на 0 як для епохи, так і для мітки часу Unix, що відключає блокування для облікового запису. - -Детальніше див. у розділі [StakeProgram](/docs/uk/clients/javascript.md#StakeProgram). +Наведений вище код створює `createStakeAccountInstruction`, який +використовується для створення облікового запису за допомогою `StakeProgram`. +Блокування встановлено на 0 як для епохи, так і для мітки часу Unix, що +відключає блокування для облікового запису. +Детальніше див. у розділі +[StakeProgram](/docs/uk/clients/javascript.md#StakeProgram). diff --git a/docs/locales/uk/clients/javascript.md b/docs/locales/uk/clients/javascript.md index 790d6f6ef..482da4c62 100644 --- a/docs/locales/uk/clients/javascript.md +++ b/docs/locales/uk/clients/javascript.md @@ -4,7 +4,9 @@ title: JavaScript Клієнт для Solana sidebarSortOrder: 2 description: Дізнайтеся, як взаємодіяти з Solana за допомогою клієнтської бібліотеки - JavaScript/TypeScript (@solana/web3.js). У цьому посібнику розглядаються підключення гаманця, транзакції та взаємодія з власними програмами з прикладами коду. + JavaScript/TypeScript (@solana/web3.js). У цьому посібнику розглядаються + підключення гаманця, транзакції та взаємодія з власними програмами з + прикладами коду. --- ## Що таке Solana-Web3.js? @@ -17,11 +19,11 @@ description: ## Загальна термінологія -| Термін | Визначення | -| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Програма | Безстанова виконувана програма, написана для інтерпретації інструкцій. Програми можуть виконувати дії на основі наданих інструкцій. | -| Інструкція | Найменша одиниця програми, яку клієнт може включити в транзакцію. Під час виконання коду інструкція може містити одну або кілька міжпрограмних викликів. | -| Транзакція | Одна або кілька інструкцій, підписаних клієнтом за допомогою одного або кількох Keypair, і виконуються атомарно з двома можливими результатами: успіх або невдача. | +| Термін | Визначення | +| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Програма | Безстанова виконувана програма, написана для інтерпретації інструкцій. Програми можуть виконувати дії на основі наданих інструкцій. | +| Інструкція | Найменша одиниця програми, яку клієнт може включити в транзакцію. Під час виконання коду інструкція може містити одну або кілька міжпрограмних викликів. | +| Транзакція | Одна або кілька інструкцій, підписаних клієнтом за допомогою одного або кількох Keypair, і виконуються атомарно з двома можливими результатами: успіх або невдача. | Для повного списку термінів дивіться [Термінологія Solana](/docs/terminology.md#cross-program-invocation-cpi) @@ -79,7 +81,9 @@ console.log(solanaWeb3); ### Підключення до гаманця -Щоб користувачі могли використовувати ваш dApp або додаток у Solana, їм потрібно отримати доступ до свого Keypair. Keypair - це приватний ключ з відповідним відкритим ключем, який використовується для підпису транзакцій. +Щоб користувачі могли використовувати ваш dApp або додаток у Solana, їм потрібно +отримати доступ до свого Keypair. Keypair - це приватний ключ з відповідним +відкритим ключем, який використовується для підпису транзакцій. Є два способи отримати Keypair: @@ -94,9 +98,11 @@ const { Keypair } = require("@solana/web3.js"); let keypair = Keypair.generate(); ``` -Це згенерує новий Keypair для користувача, який можна використовувати у вашому додатку. +Це згенерує новий Keypair для користувача, який можна використовувати у вашому +додатку. -Ви можете дозволити введення secretKey через текстове поле та отримати Keypair за допомогою `Keypair.fromSecretKey(secretKey)`. +Ви можете дозволити введення secretKey через текстове поле та отримати Keypair +за допомогою `Keypair.fromSecretKey(secretKey)`. ```javascript const { Keypair } = require("@solana/web3.js"); @@ -111,14 +117,23 @@ let secretKey = Uint8Array.from([ let keypair = Keypair.fromSecretKey(secretKey); ``` -Багато гаманців сьогодні дозволяють користувачам імпортувати свій Keypair за допомогою різних розширень або веб-гаманців. Загальна рекомендація - використовувати гаманці, а не Keypair, для підпису транзакцій. Гаманець створює шар розділення між dApp та Keypair, забезпечуючи, що dApp ніколи не має доступу до секретного ключа. Ви можете знайти способи підключення до зовнішніх гаманців за допомогою бібліотеки [wallet-adapter](https://github.com/solana-labs/wallet-adapter). +Багато гаманців сьогодні дозволяють користувачам імпортувати свій Keypair за +допомогою різних розширень або веб-гаманців. Загальна рекомендація - +використовувати гаманці, а не Keypair, для підпису транзакцій. Гаманець створює +шар розділення між dApp та Keypair, забезпечуючи, що dApp ніколи не має доступу +до секретного ключа. Ви можете знайти способи підключення до зовнішніх гаманців +за допомогою бібліотеки +[wallet-adapter](https://github.com/solana-labs/wallet-adapter). ### Створення та відправка транзакцій -Щоб взаємодіяти з програмами на Solana, ви створюєте, підписуєте та відправляєте транзакції до мережі. Транзакції - це колекції інструкцій з підписами. Порядок, в якому інструкції існують у транзакції, визначає порядок їх виконання. +Щоб взаємодіяти з програмами на Solana, ви створюєте, підписуєте та відправляєте +транзакції до мережі. Транзакції - це колекції інструкцій з підписами. Порядок, +в якому інструкції існують у транзакції, визначає порядок їх виконання. -Транзакція в Solana-Web3.js створюється за допомогою -об'єкта [`Transaction`](/docs/clients/javascript.md#Transaction) і додавання бажаних повідомлень, адрес або інструкцій. +Транзакція в Solana-Web3.js створюється за допомогою об'єкта +[`Transaction`](/docs/clients/javascript.md#Transaction) і додавання бажаних +повідомлень, адрес або інструкцій. Приклад транзакції передачі: @@ -143,9 +158,15 @@ transaction.add( ); ``` -Вищенаведений код створює транзакцію, готову до підпису та передачі в мережу. Інструкція `SystemProgram.transfer` була додана до транзакції, що містить суму lamports для відправки, а також публічні ключі `to` і `from`. +Вищенаведений код створює транзакцію, готову до підпису та передачі в мережу. +Інструкція `SystemProgram.transfer` була додана до транзакції, що містить суму +lamports для відправки, а також публічні ключі `to` і `from`. -Все, що залишилося зробити - підписати транзакцію за допомогою Keypair і відправити її через мережу. Ви можете виконати відправку транзакції за допомогою `sendAndConfirmTransaction`, якщо хочете сповістити користувача або зробити щось після завершення транзакції, або використовувати `sendTransaction`, якщо не потрібно чекати підтвердження транзакції. +Все, що залишилося зробити - підписати транзакцію за допомогою Keypair і +відправити її через мережу. Ви можете виконати відправку транзакції за допомогою +`sendAndConfirmTransaction`, якщо хочете сповістити користувача або зробити щось +після завершення транзакції, або використовувати `sendTransaction`, якщо не +потрібно чекати підтвердження транзакції. ```javascript const { @@ -160,13 +181,20 @@ let connection = new Connection(clusterApiUrl("testnet")); sendAndConfirmTransaction(connection, transaction, [keypair]); ``` -Вищенаведений код приймає `TransactionInstruction` за допомогою `SystemProgram`, створює `Transaction` і відправляє її через мережу. Ви використовуєте `Connection`, щоб визначити, до якої мережі Solana ви підключаєтесь, а саме `mainnet-beta`, `testnet` або `devnet`. +Вищенаведений код приймає `TransactionInstruction` за допомогою `SystemProgram`, +створює `Transaction` і відправляє її через мережу. Ви використовуєте +`Connection`, щоб визначити, до якої мережі Solana ви підключаєтесь, а саме +`mainnet-beta`, `testnet` або `devnet`. ### Взаємодія з власними програмами -Попередній розділ розглядає відправлення базових транзакцій. У Solana все, що ви робите, взаємодіє з різними програмами, включаючи транзакцію передачі в попередньому розділі. На момент написання програми на Solana пишуться на Rust або C. +Попередній розділ розглядає відправлення базових транзакцій. У Solana все, що ви +робите, взаємодіє з різними програмами, включаючи транзакцію передачі в +попередньому розділі. На момент написання програми на Solana пишуться на Rust +або C. -Розглянемо `SystemProgram`. Сигнатура методу для виділення простору в вашому обліковому записі в Solana на Rust виглядає так: +Розглянемо `SystemProgram`. Сигнатура методу для виділення простору в вашому +обліковому записі в Solana на Rust виглядає так: ```rust pub fn allocate( @@ -175,11 +203,19 @@ pub fn allocate( ) -> Instruction ``` -У Solana, коли ви хочете взаємодіяти з програмою, ви повинні спочатку знати всі облікові записи, з якими програма буде взаємодіяти. +У Solana, коли ви хочете взаємодіяти з програмою, ви повинні спочатку знати всі +облікові записи, з якими програма буде взаємодіяти. -Ви завжди повинні надавати кожен обліковий запис, з яким програма буде взаємодіяти в інструкції. Крім того, ви повинні вказати, чи є обліковий запис `isSigner` або `isWritable`. +Ви завжди повинні надавати кожен обліковий запис, з яким програма буде +взаємодіяти в інструкції. Крім того, ви повинні вказати, чи є обліковий запис +`isSigner` або `isWritable`. -У методі `allocate` вище потрібен один обліковий запис `pubkey`, а також кількість `space` для виділення. Ми знаємо, що метод `allocate` записує в обліковий запис, виділяючи в ньому простір, роблячи `pubkey` обов'язковим `isWritable`. `isSigner` потрібен, коли ви вказуєте обліковий запис, який виконує інструкцію. У цьому випадку підписувач - це обліковий запис, який викликає виділення простору в собі. +У методі `allocate` вище потрібен один обліковий запис `pubkey`, а також +кількість `space` для виділення. Ми знаємо, що метод `allocate` записує в +обліковий запис, виділяючи в ньому простір, роблячи `pubkey` обов'язковим +`isWritable`. `isSigner` потрібен, коли ви вказуєте обліковий запис, який +виконує інструкцію. У цьому випадку підписувач - це обліковий запис, який +викликає виділення простору в собі. Давайте подивимося, як викликати цю інструкцію за допомогою solana-web3.js: @@ -196,7 +232,9 @@ let airdropSignature = await connection.requestAirdrop( await connection.confirmTransaction({ signature: airdropSignature }); ``` -Спочатку ми налаштовуємо Keypair і підключення, щоб у нас був обліковий запис для виділення на тестовій мережі. Ми також створюємо Keypair для платника і додаємо трохи SOL, щоб оплатити транзакцію виділення. +Спочатку ми налаштовуємо Keypair і підключення, щоб у нас був обліковий запис +для виділення на тестовій мережі. Ми також створюємо Keypair для платника і +додаємо трохи SOL, щоб оплатити транзакцію виділення. ```javascript let allocateTransaction = new web3.Transaction({ @@ -206,7 +244,13 @@ let keys = [{ pubkey: keypair.publicKey, isSigner: true, isWritable: true }]; let params = { space: 100 }; ``` -Ми створюємо транзакцію `allocateTransaction`, об'єкти keys та params. Поле `feePayer` є необов'язковим при створенні транзакції, воно вказує, хто оплачує транзакцію, за замовчуванням використовується pubkey першого підписувача в транзакції. `keys` представляє всі облікові записи, з якими функція програми `allocate` буде взаємодіяти. Оскільки функція `allocate` також вимагає простору, ми створили `params`, щоб його використати пізніше при виклику функції `allocate`. +Ми створюємо транзакцію `allocateTransaction`, об'єкти keys та params. Поле +`feePayer` є необов'язковим при створенні транзакції, воно вказує, хто оплачує +транзакцію, за замовчуванням використовується pubkey першого підписувача в +транзакції. `keys` представляє всі облікові записи, з якими функція програми +`allocate` буде взаємодіяти. Оскільки функція `allocate` також вимагає простору, +ми створили `params`, щоб його використати пізніше при виклику функції +`allocate`. ```javascript let allocateStruct = { @@ -215,7 +259,11 @@ let allocateStruct = { }; ``` -Це створено за допомогою `u32` і `ns64` з `@solana/buffer-layout` для створення payload. Функція `allocate` приймає параметр `space`. Щоб взаємодіяти з функцією, ми повинні надати дані у форматі Buffer. Бібліотека `buffer-layout` допомагає з виділенням буфера та його правильним кодуванням для інтерпретації програмами на Rust в Solana. +Це створено за допомогою `u32` і `ns64` з `@solana/buffer-layout` для створення +payload. Функція `allocate` приймає параметр `space`. Щоб взаємодіяти з +функцією, ми повинні надати дані у форматі Buffer. Бібліотека `buffer-layout` +допомагає з виділенням буфера та його правильним кодуванням для інтерпретації +програмами на Rust в Solana. Давайте розглянемо цю структуру детальніше. @@ -229,7 +277,8 @@ let allocateStruct = { } ``` -`index` встановлений у 8, тому що функція `allocate` знаходиться на 8-й позиції у enum інструкцій для `SystemProgram`. +`index` встановлений у 8, тому що функція `allocate` знаходиться на 8-й позиції +у enum інструкцій для `SystemProgram`. ```rust /* https://github.com/solana-labs/solana/blob/21bc43ed58c63c827ba4db30426965ef3e807180/sdk/program/src/system_instruction.rs#L142-L305 */ @@ -262,8 +311,8 @@ pub enum SystemInstruction { } ``` -`layout` у структурі allocate завжди має мати `u32('instruction')` першим -при використанні для виклику інструкції. +`layout` у структурі allocate завжди має мати `u32('instruction')` першим при +використанні для виклику інструкції. ```javascript { @@ -275,7 +324,11 @@ pub enum SystemInstruction { } ``` -`ns64('space')` - це аргумент для функції `allocate`. Ви можете бачити, що в оригінальній функції `allocate` на Rust, space мав тип `u64`. `u64` є 64-бітовим unsigned integer. У Javascript за замовчуванням підтримуються тільки 53-бітові числа. `ns64` з `@solana/buffer-layout` допомагає з конвертацією типів між Rust і Javascript. Ви можете знайти більше конвертацій типів між Rust і Javascript на +`ns64('space')` - це аргумент для функції `allocate`. Ви можете бачити, що в +оригінальній функції `allocate` на Rust, space мав тип `u64`. `u64` є 64-бітовим +unsigned integer. У Javascript за замовчуванням підтримуються тільки 53-бітові +числа. `ns64` з `@solana/buffer-layout` допомагає з конвертацією типів між Rust +і Javascript. Ви можете знайти більше конвертацій типів між Rust і Javascript на [solana-labs/buffer-layout](https://github.com/solana-labs/buffer-layout). ```javascript @@ -284,7 +337,10 @@ let layoutFields = Object.assign({ instruction: allocateStruct.index }, params); allocateStruct.layout.encode(layoutFields, data); ``` -Використовуючи створений раніше bufferLayout, ми можемо виділити буфер даних. Потім ми присвоюємо наші params `{ space: 100 }`, щоб вони правильно відповідали макету, і кодуємо їх у буфер даних. Тепер дані готові для відправлення до програми. +Використовуючи створений раніше bufferLayout, ми можемо виділити буфер даних. +Потім ми присвоюємо наші params `{ space: 100 }`, щоб вони правильно відповідали +макету, і кодуємо їх у буфер даних. Тепер дані готові для відправлення до +програми. ```javascript allocateTransaction.add( @@ -301,7 +357,8 @@ await web3.sendAndConfirmTransaction(connection, allocateTransaction, [ ]); ``` -Нарешті, ми додаємо інструкцію транзакції з усіма ключами облікових записів, платником, даними та programId і передаємо транзакцію до мережі. +Нарешті, ми додаємо інструкцію транзакції з усіма ключами облікових записів, +платником, даними та programId і передаємо транзакцію до мережі. Повний код можна знайти нижче. diff --git a/docs/locales/uk/clients/rust.md b/docs/locales/uk/clients/rust.md index d058363e7..b9037668c 100644 --- a/docs/locales/uk/clients/rust.md +++ b/docs/locales/uk/clients/rust.md @@ -16,29 +16,33 @@ Rust пакети для Solana - [Створіть і розгорніть вашу першу програму Solana, використовуючи тільки ваш браузер](/content/guides/getstarted/hello-world-in-your-browser.md). Інсталяція не потрібна. -- [Налаштуйте ваше локальне середовище](/docs/uk/intro/installation) і використовуйте локальний тестовий валідатор. +- [Налаштуйте ваше локальне середовище](/docs/uk/intro/installation) і + використовуйте локальний тестовий валідатор. ## Rust Пакети -Нижче наведено найважливіші та найчастіше використовувані Rust пакети для розробки в Solana: +Нижче наведено найважливіші та найчастіше використовувані Rust пакети для +розробки в Solana: -- [`solana-program`] — Імпортується програмами, що працюють у Solana, і компілюється до - SBF. Цей пакет містить багато фундаментальних типів даних і реекспортується з - [`solana-sdk`], який не можна імпортувати у програму Solana. +- [`solana-program`] — Імпортується програмами, що працюють у Solana, і + компілюється до SBF. Цей пакет містить багато фундаментальних типів даних і + реекспортується з [`solana-sdk`], який не можна імпортувати у програму Solana. - [`solana-sdk`] — Базовий SDK для роботи поза мережею, реекспортує - [`solana-program`] і додає більше API на додаток до цього. Більшість програм Solana, - що не працюють у мережі, імпортують цей пакет. + [`solana-program`] і додає більше API на додаток до цього. Більшість програм + Solana, що не працюють у мережі, імпортують цей пакет. - [`solana-client`] — Для взаємодії з вузлом Solana через [JSON RPC API](/docs/uk/rpc). -- [`solana-cli-config`] — Завантаження та збереження конфігураційного файлу Solana CLI. +- [`solana-cli-config`] — Завантаження та збереження конфігураційного + файлу Solana CLI. -- [`solana-clap-utils`] — Рутини для налаштування CLI, використовуючи [`clap`], як у - основному CLI Solana. Включає функції для завантаження всіх типів підписантів, підтримуваних CLI. +- [`solana-clap-utils`] — Рутини для налаштування CLI, використовуючи + [`clap`], як у основному CLI Solana. Включає функції для завантаження всіх + типів підписантів, підтримуваних CLI. [`solana-program`]: https://docs.rs/solana-program [`solana-sdk`]: https://docs.rs/solana-sdk diff --git a/docs/locales/uk/core/accounts.md b/docs/locales/uk/core/accounts.md index f45f08df5..ab7f7bd41 100644 --- a/docs/locales/uk/core/accounts.md +++ b/docs/locales/uk/core/accounts.md @@ -3,10 +3,10 @@ sidebarSortOrder: 1 sidebarLabel: Модель облікових записів Solana title: Модель облікових записів Solana description: - Дізнайтеся про модель облікових записів Solana, включаючи те, як облікові записи зберігають дані - і програми, механіку оренди, власність облікових записів і взаємозв'язок між - програмами та обліковими записами даних. Зрозумійте основні концепції системи - зберігання ключ-значення Solana. + Дізнайтеся про модель облікових записів Solana, включаючи те, як облікові + записи зберігають дані і програми, механіку оренди, власність облікових + записів і взаємозв'язок між програмами та обліковими записами даних. + Зрозумійте основні концепції системи зберігання ключ-значення Solana. --- У Solana всі дані зберігаються в так званих "облікових записах". Спосіб @@ -18,73 +18,84 @@ description: ## Основні моменти -- Облікові записи можуть зберігати до 10 МБ даних, які можуть складатися з виконуваного - коду програми або стану програми. +- Облікові записи можуть зберігати до 10 МБ даних, які можуть складатися з + виконуваного коду програми або стану програми. -- Облікові записи потребують застави в SOL, пропорційної обсягу збережених даних, - яка повністю повертається при закритті облікового запису. +- Облікові записи потребують застави в SOL, пропорційної обсягу збережених + даних, яка повністю повертається при закритті облікового запису. -- Кожен обліковий запис має "власника" програми. Тільки програма, яка володіє обліковим записом, може - змінювати його дані або знімати баланс лампортів. Однак будь-хто може - збільшити баланс. +- Кожен обліковий запис має "власника" програми. Тільки програма, яка володіє + обліковим записом, може змінювати його дані або знімати баланс лампортів. + Однак будь-хто може збільшити баланс. -- Програми (смартконтракти) є безстанними обліковими записами, які зберігають виконуваний код. +- Програми (смартконтракти) є безстанними обліковими записами, які зберігають + виконуваний код. -- Облікові записи даних створюються програмами для зберігання і керування станом програми. +- Облікові записи даних створюються програмами для зберігання і керування станом + програми. -- Вбудовані програми - це вбудовані програми, які включені у середовище виконання Solana. +- Вбудовані програми - це вбудовані програми, які включені у середовище + виконання Solana. -- Системні облікові записи - це спеціальні облікові записи, які зберігають стан кластера мережі. +- Системні облікові записи - це спеціальні облікові записи, які зберігають стан + кластера мережі. ## Обліковий запис -Кожен обліковий запис ідентифікується його унікальною адресою, представленою у форматі 32 байт -як [Ed25519](https://ed25519.cr.yp.to/) `PublicKey`. Ви можете вважати -адресу унікальним ідентифікатором облікового запису. +Кожен обліковий запис ідентифікується його унікальною адресою, представленою у +форматі 32 байт як [Ed25519](https://ed25519.cr.yp.to/) `PublicKey`. Ви можете +вважати адресу унікальним ідентифікатором облікового запису. ![Адреса облікового запису](/assets/docs/core/accounts/account-address.svg) -Цей зв'язок між обліковим записом та його адресою можна розглядати як -пару ключ-значення, де адреса є ключем для пошуку відповідних -даних облікового запису в ланцюжку. +Цей зв'язок між обліковим записом та його адресою можна розглядати як пару +ключ-значення, де адреса є ключем для пошуку відповідних даних облікового запису +в ланцюжку. ### AccountInfo Облікові записи мають [максимальний розмір у 10 МБ](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L85) -(10 мегабайт), а дані, що зберігаються в кожному обліковому записі Solana, мають наступну -структуру, відому як +(10 мегабайт), а дані, що зберігаються в кожному обліковому записі Solana, мають +наступну структуру, відому як [AccountInfo](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/account_info.rs#L19). ![AccountInfo](/assets/docs/core/accounts/accountinfo.svg) `AccountInfo` для кожного облікового запису включає наступні поля: -- `data`: Масив байтів, який зберігає стан облікового запису. Якщо обліковий запис є - програмою (смартконтрактом), це поле зберігає виконуваний код програми. Це поле часто - називають "даними облікового запису". +- `data`: Масив байтів, який зберігає стан облікового запису. Якщо обліковий + запис є програмою (смартконтрактом), це поле зберігає виконуваний код + програми. Це поле часто називають "даними облікового запису". - `executable`: Булевий прапорець, який вказує, чи є обліковий запис програмою. - `lamports`: Числове представлення балансу облікового запису в [лампортах](/docs/terminology.md#lamport), найменшій одиниці SOL (1 SOL = 1 мільярд лампортів). -- `owner`: Вказує публічний ключ (Program ID) програми, яка володіє обліковим записом. +- `owner`: Вказує публічний ключ (Program ID) програми, яка володіє обліковим + записом. -Як ключова частина моделі облікових записів Solana, кожен обліковий запис у Solana має -визначеного "власника", а саме програму. Тільки програма, зазначена як власник облікового запису, може -змінювати дані, що зберігаються в обліковому записі, або знімати баланс лампортів. Важливо зазначити, що, хоча тільки власник може знімати баланс, будь-хто може збільшити баланс. +Як ключова частина моделі облікових записів Solana, кожен обліковий запис у +Solana має визначеного "власника", а саме програму. Тільки програма, зазначена +як власник облікового запису, може змінювати дані, що зберігаються в обліковому +записі, або знімати баланс лампортів. Важливо зазначити, що, хоча тільки власник +може знімати баланс, будь-хто може збільшити баланс. > Для зберігання даних у ланцюжку потрібно передати певну кількість SOL до -> облікового запису. Кількість, що передається, пропорційна розміру даних, що зберігаються в обліковому записі. Ця концепція зазвичай називається "орендою". Однак, ви можете розглядати "оренду" швидше як "депозит", оскільки SOL, виділені для облікового запису, можуть бути повністю відновлені при закритті облікового запису. +> облікового запису. Кількість, що передається, пропорційна розміру даних, що +> зберігаються в обліковому записі. Ця концепція зазвичай називається "орендою". +> Однак, ви можете розглядати "оренду" швидше як "депозит", оскільки SOL, +> виділені для облікового запису, можуть бути повністю відновлені при закритті +> облікового запису. ## Вбудовані програми -Solana містить невелику кількість вбудованих програм, які є частиною -реалізації валідатора і забезпечують різні основні функціональності для -мережі. Ви можете знайти повний список вбудованих програм +Solana містить невелику кількість вбудованих програм, які є частиною реалізації +валідатора і забезпечують різні основні функціональності для мережі. Ви можете +знайти повний список вбудованих програм [тут](https://docs.anza.xyz/runtime/programs). -При розробці користувацьких програм на Solana ви часто будете взаємодіяти з двома -вбудованими програмами: Системною Програмою і Завантажувачем BPF. +При розробці користувацьких програм на Solana ви часто будете взаємодіяти з +двома вбудованими програмами: Системною Програмою і Завантажувачем BPF. ### Системна Програма @@ -97,34 +108,40 @@ Solana містить невелику кількість вбудованих - [Виділення простору](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L70): Встановлює обсяг пам'яті для поля даних кожного облікового запису. - [Призначення власника програми](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L112): - Після створення облікового запису Системною Програмою вона може перепризначити власника - програми іншому обліковому запису програми. Це спосіб, за яким користувацькі програми беруть - у власність нові облікові записи, створені Системною Програмою. + Після створення облікового запису Системною Програмою вона може перепризначити + власника програми іншому обліковому запису програми. Це спосіб, за яким + користувацькі програми беруть у власність нові облікові записи, створені + Системною Програмою. -У Solana "гаманець" просто є обліковим записом, який належить Системній Програмі. Баланс лампортів у гаманці є кількістю SOL, що належать обліковому запису. +У Solana "гаманець" просто є обліковим записом, який належить Системній +Програмі. Баланс лампортів у гаманці є кількістю SOL, що належать обліковому +запису. ![Системний Обліковий Запис](/assets/docs/core/accounts/system-account.svg) -> Тільки облікові записи, що належать Системній Програмі, можуть використовуватися як платники комісій за транзакції. +> Тільки облікові записи, що належать Системній Програмі, можуть +> використовуватися як платники комісій за транзакції. ### Завантажувач BPF [Завантажувач BPF](https://github.com/solana-labs/solana/tree/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src) -є програмою, яка призначена як "власник" усіх інших програм у мережі, -крім Вбудованих Програм. Він відповідає за розгортання, оновлення та виконання користувацьких програм. +є програмою, яка призначена як "власник" усіх інших програм у мережі, крім +Вбудованих Програм. Він відповідає за розгортання, оновлення та виконання +користувацьких програм. ## Системні Облікові Записи -Системні облікові записи - це спеціальні облікові записи, розташовані за попередньо визначеними адресами, які -надають доступ до даних про стан кластера мережі. Ці облікові записи динамічно оновлюються -даними про кластер мережі. Ви можете знайти повний список Системних Облікових Записів +Системні облікові записи - це спеціальні облікові записи, розташовані за +попередньо визначеними адресами, які надають доступ до даних про стан кластера +мережі. Ці облікові записи динамічно оновлюються даними про кластер мережі. Ви +можете знайти повний список Системних Облікових Записів [тут](https://docs.anza.xyz/runtime/sysvars). ## Користувацькі Програми -У Solana "смартконтракти" називаються -[програмами](/docs/core/programs.md). Програма є обліковим записом, який містить -виконуваний код, і позначається прапорцем "виконуваний", який встановлено в значення "true". +У Solana "смартконтракти" називаються [програмами](/docs/core/programs.md). +Програма є обліковим записом, який містить виконуваний код, і позначається +прапорцем "виконуваний", який встановлено в значення "true". Для детального пояснення процесу розгортання програми, зверніться до сторінки [Розгортання Програм](/docs/programs/deploying.md) цієї документації. @@ -135,16 +152,16 @@ Solana містить невелику кількість вбудованих [розгортаються](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L498) на Solana, технічно створюються три окремі облікові записи: -- **Обліковий Запис Програми**: Основний обліковий запис, який представляє програму в ланцюжку. Цей - обліковий запис зберігає адресу виконуваного облікового запису даних (який зберігає - зкомпільований код програми) і право на оновлення програми (адреса, яка - має дозвіл на внесення змін до програми). -- **Виконуваний Обліковий Запис Програми**: Обліковий запис, який містить виконуваний - байт-код програми. -- **Буферний Обліковий Запис**: Тимчасовий обліковий запис, який зберігає байт-код під час - активного розгортання або оновлення програми. Після завершення процесу дані - передаються до Виконуваного Облікового Запису Програми, а буферний обліковий запис - закривається. +- **Обліковий Запис Програми**: Основний обліковий запис, який представляє + програму в ланцюжку. Цей обліковий запис зберігає адресу виконуваного + облікового запису даних (який зберігає зкомпільований код програми) і право на + оновлення програми (адреса, яка має дозвіл на внесення змін до програми). +- **Виконуваний Обліковий Запис Програми**: Обліковий запис, який містить + виконуваний байт-код програми. +- **Буферний Обліковий Запис**: Тимчасовий обліковий запис, який зберігає + байт-код під час активного розгортання або оновлення програми. Після + завершення процесу дані передаються до Виконуваного Облікового Запису + Програми, а буферний обліковий запис закривається. Наприклад, ось посилання на Solana Explorer для Програмного Розширення Токенів [Обліковий Запис Програми](https://explorer.solana.com/address/TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb) @@ -157,28 +174,33 @@ Solana містить невелику кількість вбудованих ![Обліковий Запис Програми](/assets/docs/core/accounts/program-account-simple.svg) -> Адреса "Облікового Запису Програми" зазвичай називається "ID Програми", який використовується для виклику програми. +> Адреса "Облікового Запису Програми" зазвичай називається "ID Програми", який +> використовується для виклику програми. ### Обліковий Запис Даних Програми Solana є "безстанними", тобто облікові записи програм містять лише -виконуваний байт-код програми. Для зберігання та модифікації додаткових даних необхідно створювати нові -облікові записи. Ці облікові записи зазвичай називаються "обліковими записами даних". +виконуваний байт-код програми. Для зберігання та модифікації додаткових даних +необхідно створювати нові облікові записи. Ці облікові записи зазвичай +називаються "обліковими записами даних". -Облікові записи даних можуть зберігати будь-які довільні дані, визначені в коді програми-власника. +Облікові записи даних можуть зберігати будь-які довільні дані, визначені в коді +програми-власника. ![Обліковий Запис Даних](/assets/docs/core/accounts/data-account.svg) -Зверніть увагу, що тільки [Системна Програма](/docs/core/accounts.md#system-program) може -створювати нові облікові записи. Після створення облікового запису Системною Програмою вона може потім -передати власність нового облікового запису іншій програмі. +Зверніть увагу, що тільки +[Системна Програма](/docs/core/accounts.md#system-program) може створювати нові +облікові записи. Після створення облікового запису Системною Програмою вона може +потім передати власність нового облікового запису іншій програмі. -Іншими словами, створення облікового запису даних для користувацької програми вимагає двох кроків: +Іншими словами, створення облікового запису даних для користувацької програми +вимагає двох кроків: 1. Виклик Системної Програми для створення облікового запису, яка потім передає власність користувацькій програмі 2. Виклик користувацької програми, яка тепер володіє обліковим записом, для ініціалізації даних облікового запису, як це визначено в коді програми -Цей процес створення облікового запису даних часто абстрагується як єдиний крок, але -корисно розуміти підлеглий процес. +Цей процес створення облікового запису даних часто абстрагується як єдиний крок, +але корисно розуміти підлеглий процес. diff --git a/docs/locales/uk/core/clusters.md b/docs/locales/uk/core/clusters.md index abf086ecf..b2a5944fe 100644 --- a/docs/locales/uk/core/clusters.md +++ b/docs/locales/uk/core/clusters.md @@ -5,8 +5,8 @@ sidebarSortOrder: 8 description: Дізнайтеся про кластери мережі Solana (Devnet, Testnet і Mainnet Beta), їхні публічні точки доступу RPC, обмеження швидкості та випадки використання. - Дізнайтеся, як підключатися до різних мереж Solana для розробки, тестування - та виробничого середовища. + Дізнайтеся, як підключатися до різних мереж Solana для розробки, тестування та + виробничого середовища. --- Блокчейн Solana має кілька різних груп валідаторів, відомих як @@ -43,18 +43,19 @@ description: ## Основні відомості - Mainnet: Живе виробниче середовище для розгорнутих додатків. -- Devnet: Тестування з публічним доступом для розробників, які експериментують зі - своїми додатками. +- Devnet: Тестування з публічним доступом для розробників, які експериментують + зі своїми додатками. - Testnet: Стрес-тестування для оновлень мережі та продуктивності валідаторів. -**Приклади використання**: Можливо, ви захочете налагодити нову програму на Devnet -або перевірити метрики продуктивності на Testnet перед розгортанням на Mainnet. +**Приклади використання**: Можливо, ви захочете налагодити нову програму на +Devnet або перевірити метрики продуктивності на Testnet перед розгортанням на +Mainnet. -| **Кластер** | **Точка доступу** | **Призначення** | **Примітки** | -| ----------- | ---------------------------------------- | ------------------------------- | ------------------------------ | -| Mainnet | `https://api.mainnet-beta.solana.com` | Живе виробниче середовище | Потребує SOL для транзакцій | -| Devnet | `https://api.devnet.solana.com` | Публічне тестування та розробка | Безкоштовний SOL для тестування| -| Testnet | `https://api.testnet.solana.com` | Тестування валідаторів | Може мати періодичні простої | +| **Кластер** | **Точка доступу** | **Призначення** | **Примітки** | +| ----------- | ------------------------------------- | ------------------------------- | ------------------------------- | +| Mainnet | `https://api.mainnet-beta.solana.com` | Живе виробниче середовище | Потребує SOL для транзакцій | +| Devnet | `https://api.devnet.solana.com` | Публічне тестування та розробка | Безкоштовний SOL для тестування | +| Testnet | `https://api.testnet.solana.com` | Тестування валідаторів | Може мати періодичні простої | ## Devnet @@ -73,8 +74,8 @@ Devnet слугує тестовим майданчиком для будь-ко ### Точка доступу Devnet -- `https://api.devnet.solana.com` - єдиний вузол API, розміщений Solana Labs; - з обмеженнями швидкості +- `https://api.devnet.solana.com` - єдиний вузол API, розміщений Solana Labs; з + обмеженнями швидкості #### Приклад конфігурації командного рядка `solana` @@ -101,14 +102,14 @@ Testnet - це місце, де основні учасники Solana стре - Токени Testnet **не реальні**. - Testnet може піддаватися скиданням журналу. - Testnet включає крани для отримання токенів для тестування додатків. -- Testnet зазвичай працює на новішій гілці випуску програмного забезпечення, - ніж Devnet і Mainnet Beta. +- Testnet зазвичай працює на новішій гілці випуску програмного забезпечення, ніж + Devnet і Mainnet Beta. - Точка доступу Gossip для Testnet: `entrypoint.testnet.solana.com:8001` ### Точка доступу Testnet -- `https://api.testnet.solana.com` - єдиний вузол API, розміщений Solana Labs; - з обмеженнями швидкості +- `https://api.testnet.solana.com` - єдиний вузол API, розміщений Solana Labs; з + обмеженнями швидкості #### Приклад конфігурації командного рядка `solana` @@ -132,7 +133,8 @@ solana config set --url https://api.testnet.solana.com валідаторів та власників токенів. - Токени, випущені на Mainnet Beta, є **реальними** SOL. -- Точка доступу Gossip для Mainnet Beta: `entrypoint.mainnet-beta.solana.com:8001` +- Точка доступу Gossip для Mainnet Beta: + `entrypoint.mainnet-beta.solana.com:8001` ### Точка доступу Mainnet beta @@ -163,9 +165,10 @@ solana config set --url https://api.mainnet-beta.solana.com ## Загальні HTTP-коди помилок -- 403 -- Ваша IP-адреса або вебсайт було заблоковано. Настав час запустити власні - сервери RPC або знайти приватний сервіс. -- 429 -- Ваша IP-адреса перевищує обмеження швидкості. Зменшіть швидкість! Використовуйте +- 403 -- Ваша IP-адреса або вебсайт було заблоковано. Настав час запустити + власні сервери RPC або знайти приватний сервіс. +- 429 -- Ваша IP-адреса перевищує обмеження швидкості. Зменшіть швидкість! + Використовуйте [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) HTTP-заголовок відповіді, щоб визначити, як довго потрібно чекати перед повторною спробою. diff --git a/docs/locales/uk/core/cpi.md b/docs/locales/uk/core/cpi.md index cec59477d..a15da2bb8 100644 --- a/docs/locales/uk/core/cpi.md +++ b/docs/locales/uk/core/cpi.md @@ -8,8 +8,8 @@ description: функціональність у мережі Solana. --- -Виклик між програмами (CPI) відбувається, коли одна програма викликає -інструкції іншої програми. Цей механізм дозволяє складати програми Solana. +Виклик між програмами (CPI) відбувається, коли одна програма викликає інструкції +іншої програми. Цей механізм дозволяє складати програми Solana. Інструкції можна уявити як API-методи, які програма надає мережі, а CPI - це виклик одного API-методу іншим API-методом. @@ -22,17 +22,17 @@ description: розширюються на програму-отримувача (B). - Програма-отримувач (B) може здійснювати подальші CPI до інших програм до максимального рівня глибини 4 (наприклад, B->C, C->D). -- Програми можуть "підписувати" від імені [PDA](/docs/core/pda.md), що - створені з їхнього ID програми. +- Програми можуть "підписувати" від імені [PDA](/docs/core/pda.md), що створені + з їхнього ID програми. > У середовищі виконання програм Solana визначено константу під назвою > [`max_invoke_stack_height`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/program-runtime/src/compute_budget.rs#L31-L35), > яка має значення > [5](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/program-runtime/src/compute_budget.rs#L138). -> Це обмеження встановлює максимальну висоту стеку викликів інструкцій -> програми. Висота стеку починається з 1 для інструкцій транзакції, збільшується -> на 1 кожного разу, коли програма викликає іншу інструкцію. Це ефективно -> обмежує глибину викликів для CPI до 4. +> Це обмеження встановлює максимальну висоту стеку викликів інструкцій програми. +> Висота стеку починається з 1 для інструкцій транзакції, збільшується на 1 +> кожного разу, коли програма викликає іншу інструкцію. Це ефективно обмежує +> глибину викликів для CPI до 4. ## Основні моменти @@ -41,8 +41,8 @@ description: - Привілеї підпису від програми-виклику розширюються на програму-отримувача. -- Під час здійснення CPI програми можуть "підписувати" від імені PDA, - створених із їхнього власного ID програми. +- Під час здійснення CPI програми можуть "підписувати" від імені PDA, створених + із їхнього власного ID програми. - Програма-отримувач може здійснювати додаткові CPI до інших програм до максимальної глибини 4. @@ -50,8 +50,8 @@ description: ## Як написати CPI Написання інструкції для CPI слідує тій самій схемі, що й побудова -[інструкції](/docs/core/transactions.md#instruction) для додавання до транзакції. -Кожна інструкція CPI повинна зазначати таку інформацію: +[інструкції](/docs/core/transactions.md#instruction) для додавання до +транзакції. Кожна інструкція CPI повинна зазначати таку інформацію: - **Адреса програми**: Вказує програму, яка викликається - **Облікові записи**: Перераховує кожен обліковий запис, з якого інструкція @@ -71,9 +71,9 @@ description: Функція [`invoke`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/program.rs#L132) -використовується під час здійснення CPI, який не потребує підписантів PDA. Під час -здійснення CPI підписанти, надані програмі-виклику, автоматично розширюються на -програму-отримувача. +використовується під час здійснення CPI, який не потребує підписантів PDA. Під +час здійснення CPI підписанти, надані програмі-виклику, автоматично розширюються +на програму-отримувача. ```rust pub fn invoke( @@ -117,11 +117,10 @@ pub fn invoke_signed( інструкцію, яка також містить цього підписанта та/або обліковий запис із правом запису. -Хоча PDA не мають -[приватних ключів](/docs/core/pda.md#what-is-a-pda), вони все одно можуть діяти -як підписант в інструкції через CPI. Щоб підтвердити, що PDA створений із -програми, що викликає, необхідно включити насіння, використане для створення -PDA, як `signers_seeds`. +Хоча PDA не мають [приватних ключів](/docs/core/pda.md#what-is-a-pda), вони все +одно можуть діяти як підписант в інструкції через CPI. Щоб підтвердити, що PDA +створений із програми, що викликає, необхідно включити насіння, використане для +створення PDA, як `signers_seeds`. Коли CPI обробляється, середовище виконання Solana [викликає внутрішньо `create_program_address`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/syscalls/cpi.rs#L550) diff --git a/docs/locales/uk/core/fees.md b/docs/locales/uk/core/fees.md index 69689f7d0..87f200807 100644 --- a/docs/locales/uk/core/fees.md +++ b/docs/locales/uk/core/fees.md @@ -20,91 +20,165 @@ altRoutes: - /docs/uk/core/runtime --- -Блокчейн Solana має кілька типів плати та витрат, які виникають під час використання мережі без дозволу. Вони поділяються на кілька специфічних типів: +Блокчейн Solana має кілька типів плати та витрат, які виникають під час +використання мережі без дозволу. Вони поділяються на кілька специфічних типів: - **Транзакційні збори** — плата за обробку транзакцій/інструкцій валідаторами. -- **Пріоритизаційні збори** — додаткова плата для підвищення порядку обробки транзакцій. +- **Пріоритизаційні збори** — додаткова плата для підвищення порядку обробки + транзакцій. - **Оренда** — утримуваний баланс для збереження даних в ончейні. ## Транзакційні збори -Мала плата, яка сплачується за обробку логіки (інструкції) у програмі в ончейні на блокчейні Solana, називається "_транзакційною платою_". +Мала плата, яка сплачується за обробку логіки (інструкції) у програмі в ончейні +на блокчейні Solana, називається "_транзакційною платою_". -Кожна [транзакція](/docs/uk/core/transactions.md#transaction), яка містить одну або більше [інструкцій](/docs/uk/core/transactions.md#instruction), надсилається через мережу, де її обробляє поточний лідер-валідатор. Після підтвердження як глобальної транзакції ця "транзакційна плата" сплачується мережі для підтримки економічної моделі блокчейна Solana. +Кожна [транзакція](/docs/uk/core/transactions.md#transaction), яка містить одну +або більше [інструкцій](/docs/uk/core/transactions.md#instruction), надсилається +через мережу, де її обробляє поточний лідер-валідатор. Після підтвердження як +глобальної транзакції ця "транзакційна плата" сплачується мережі для підтримки +економічної моделі блокчейна Solana. -> Транзакційні збори відрізняються від плати за збереження даних в обліковому записі, відомої як [оренда](#rent). Транзакційні збори сплачуються за обробку інструкцій у мережі Solana, а депозит оренди утримується в обліковому записі для збереження даних в блокчейні та може бути повернутий. +> Транзакційні збори відрізняються від плати за збереження даних в обліковому +> записі, відомої як [оренда](#rent). Транзакційні збори сплачуються за обробку +> інструкцій у мережі Solana, а депозит оренди утримується в обліковому записі +> для збереження даних в блокчейні та може бути повернутий. -На даний момент базова транзакційна плата в Solana встановлена на рівні 5000 лампортів за підпис. На додаток до цієї базової плати, можуть бути додані додаткові [пріоритизаційні збори](#prioritization-fee). +На даний момент базова транзакційна плата в Solana встановлена на рівні 5000 +лампортів за підпис. На додаток до цієї базової плати, можуть бути додані +додаткові [пріоритизаційні збори](#prioritization-fee). ### Навіщо сплачувати транзакційні збори? -Транзакційні збори пропонують багато переваг у економічній моделі Solana, зокрема вони: +Транзакційні збори пропонують багато переваг у економічній моделі Solana, +зокрема вони: -- Забезпечують компенсацію мережі валідаторів за витрачені ресурси CPU/GPU для обробки транзакцій. +- Забезпечують компенсацію мережі валідаторів за витрачені ресурси CPU/GPU для + обробки транзакцій. - Зменшують спам у мережі, запроваджуючи реальну вартість транзакцій. -- Забезпечують довгострокову економічну стабільність мережі через протокольно захоплену мінімальну плату за транзакцію. +- Забезпечують довгострокову економічну стабільність мережі через протокольно + захоплену мінімальну плату за транзакцію. ### Основи економічної моделі -Багато блокчейн-мереж (включаючи Bitcoin та Ethereum) покладаються на інфляційні "протокольні нагороди" для короткострокової підтримки безпеки мережі. У довгостроковій перспективі ці мережі все більше покладаються на "транзакційні збори" для підтримки безпеки. +Багато блокчейн-мереж (включаючи Bitcoin та Ethereum) покладаються на інфляційні +"протокольні нагороди" для короткострокової підтримки безпеки мережі. У +довгостроковій перспективі ці мережі все більше покладаються на "транзакційні +збори" для підтримки безпеки. Те саме стосується Solana. Зокрема: -- Фіксована частка (спочатку 50%) кожної транзакційної плати "спалюється" (знищується), решта надходить до поточного [лідера](/docs/uk/terminology.md#leader), який обробляє транзакцію. -- Запланована глобальна інфляційна ставка забезпечує джерело [нагород](https://docs.anza.xyz/implemented-proposals/staking-rewards), які розподіляються серед [валідаторів Solana](https://docs.anza.xyz/operations). +- Фіксована частка (спочатку 50%) кожної транзакційної плати "спалюється" + (знищується), решта надходить до поточного + [лідера](/docs/uk/terminology.md#leader), який обробляє транзакцію. +- Запланована глобальна інфляційна ставка забезпечує джерело + [нагород](https://docs.anza.xyz/implemented-proposals/staking-rewards), які + розподіляються серед [валідаторів Solana](https://docs.anza.xyz/operations). ### Збір плати -Транзакції повинні мати щонайменше один обліковий запис, який підписав транзакцію та може бути змінений. Ці "записувані підписуючі облікові записи" серіалізуються першими у списку облікових записів, і перший з них завжди використовується як "платник плати". +Транзакції повинні мати щонайменше один обліковий запис, який підписав +транзакцію та може бути змінений. Ці "записувані підписуючі облікові записи" +серіалізуються першими у списку облікових записів, і перший з них завжди +використовується як "платник плати". -Перед обробкою будь-яких інструкцій транзакції баланс облікового запису платника плати [вираховується](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank.rs#L4045-L4064) для оплати транзакційних зборів. Якщо баланс платника плати недостатній для покриття зборів, обробка транзакції припиняється і вона визнається невдалою. +Перед обробкою будь-яких інструкцій транзакції баланс облікового запису платника +плати +[вираховується](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank.rs#L4045-L4064) +для оплати транзакційних зборів. Якщо баланс платника плати недостатній для +покриття зборів, обробка транзакції припиняється і вона визнається невдалою. -Якщо баланс був достатнім, плата буде вирахувана, і виконання інструкцій транзакції почнеться. Якщо будь-яка з інструкцій призведе до помилки, обробка транзакції буде припинена, і зрештою вона буде записана як невдала транзакція в книзі Solana. Плата все одно буде зібрана за ці невдалі транзакції. +Якщо баланс був достатнім, плата буде вирахувана, і виконання інструкцій +транзакції почнеться. Якщо будь-яка з інструкцій призведе до помилки, обробка +транзакції буде припинена, і зрештою вона буде записана як невдала транзакція в +книзі Solana. Плата все одно буде зібрана за ці невдалі транзакції. -Якщо будь-яка з інструкцій повертає помилку або порушує обмеження часу виконання, всі зміни облікових записів **_крім_** вирахування транзакційної плати будуть скасовані. Це тому, що мережа валідаторів вже витратила обчислювальні ресурси для збору транзакцій та початку їх обробки. +Якщо будь-яка з інструкцій повертає помилку або порушує обмеження часу +виконання, всі зміни облікових записів **_крім_** вирахування транзакційної +плати будуть скасовані. Це тому, що мережа валідаторів вже витратила +обчислювальні ресурси для збору транзакцій та початку їх обробки. ### Розподіл плати -Транзакційні збори [частково спалюються](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank/fee_distribution.rs#L55-L64), а решта зборів збираються валідатором, який створив блок, у якому включені відповідні транзакції. Зокрема, [50% спалюються](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/fee_calculator.rs#L79), а [50% розподіляються](https://github.com/anza-xyz/agave/blob/e621336acad4f5d6e5b860eaa1b074b01c99253c/runtime/src/bank/fee_distribution.rs#L58-L62) валідатору, який створив блок. +Транзакційні збори +[частково спалюються](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank/fee_distribution.rs#L55-L64), +а решта зборів збираються валідатором, який створив блок, у якому включені +відповідні транзакції. Зокрема, +[50% спалюються](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/fee_calculator.rs#L79), +а +[50% розподіляються](https://github.com/anza-xyz/agave/blob/e621336acad4f5d6e5b860eaa1b074b01c99253c/runtime/src/bank/fee_distribution.rs#L58-L62) +валідатору, який створив блок. ### Чому спалюються частина зборів? -Як згадано вище, фіксована частка кожної транзакційної плати "спалюється" (знищується). Це зроблено для зміцнення економічної цінності SOL і підтримки безпеки мережі. На відміну від системи, де всі транзакційні збори повністю спалюються, лідери все ще мають стимул включати якомога більше транзакцій у свої слоти (можливість створити блок). +Як згадано вище, фіксована частка кожної транзакційної плати "спалюється" +(знищується). Це зроблено для зміцнення економічної цінності SOL і підтримки +безпеки мережі. На відміну від системи, де всі транзакційні збори повністю +спалюються, лідери все ще мають стимул включати якомога більше транзакцій у свої +слоти (можливість створити блок). -Спалені збори також можуть допомогти запобігти зловмисним валідаторам у цензуруванні транзакцій через врахування в [виборі форку](/docs/uk/terminology.md#fork). +Спалені збори також можуть допомогти запобігти зловмисним валідаторам у +цензуруванні транзакцій через врахування в +[виборі форку](/docs/uk/terminology.md#fork). #### Приклад атаки: -У випадку [форку Proof of History (PoH)](/docs/uk/terminology.md#proof-of-history-poh) з лідером, що займається цензурою або зловживанням: +У випадку +[форку Proof of History (PoH)](/docs/uk/terminology.md#proof-of-history-poh) з +лідером, що займається цензурою або зловживанням: -- через втрати зборів, що виникають через цензуру, очікується, що загальні збори, які будуть спалені, будуть **_меншими_**, ніж у порівнянному чесному форку; -- якщо лідер, який займається цензурою, хоче компенсувати ці втрачені протокольні збори, він повинен буде самостійно замінити спалені збори на своєму форку; +- через втрати зборів, що виникають через цензуру, очікується, що загальні + збори, які будуть спалені, будуть **_меншими_**, ніж у порівнянному чесному + форку; +- якщо лідер, який займається цензурою, хоче компенсувати ці втрачені + протокольні збори, він повинен буде самостійно замінити спалені збори на + своєму форку; - таким чином, потенційно зменшуючи стимул до цензури в першу чергу. ### Обчислення транзакційних зборів -Повна плата за конкретну транзакцію розраховується на основі двох основних частин: +Повна плата за конкретну транзакцію розраховується на основі двох основних +частин: - Статично встановлена базова плата за підпис, і -- Обчислювальні ресурси, використані під час транзакції, виміряні у "[обчислювальних одиницях](/docs/uk/terminology.md#compute-units)". +- Обчислювальні ресурси, використані під час транзакції, виміряні у + "[обчислювальних одиницях](/docs/uk/terminology.md#compute-units)". -Оскільки кожна транзакція може вимагати різної кількості обчислювальних ресурсів, кожній транзакції виділяється максимальна кількість _обчислювальних одиниць_ у рамках "обчислювального бюджету". +Оскільки кожна транзакція може вимагати різної кількості обчислювальних +ресурсів, кожній транзакції виділяється максимальна кількість _обчислювальних +одиниць_ у рамках "обчислювального бюджету". ## Обчислювальний бюджет -Щоб запобігти зловживанню обчислювальними ресурсами, кожній транзакції виділяється "обчислювальний бюджет". Цей бюджет визначає: +Щоб запобігти зловживанню обчислювальними ресурсами, кожній транзакції +виділяється "обчислювальний бюджет". Цей бюджет визначає: -- обчислювальні витрати, пов'язані з різними типами операцій, які може виконувати транзакція (обчислювальні одиниці, спожиті на операцію), -- максимальну кількість обчислювальних одиниць, які може спожити транзакція (ліміт обчислювальних одиниць), -- та операційні межі, яких має дотримуватися транзакція (наприклад, ліміти розміру даних облікового запису). +- обчислювальні витрати, пов'язані з різними типами операцій, які може + виконувати транзакція (обчислювальні одиниці, спожиті на операцію), +- максимальну кількість обчислювальних одиниць, які може спожити транзакція + (ліміт обчислювальних одиниць), +- та операційні межі, яких має дотримуватися транзакція (наприклад, ліміти + розміру даних облікового запису). -Коли транзакція вичерпує свій обчислювальний бюджет (вичерпання обчислювального бюджету) або перевищує межі, наприклад, намагається перевищити [максимальну глибину стеку викликів](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L138) або [максимальний розмір завантажених даних облікового запису](#accounts-data-size-limit), виконання транзакції припиняється, і повертається помилка. Це призводить до невдалої транзакції та жодних змін стану (окрім збору плати за транзакцію). +Коли транзакція вичерпує свій обчислювальний бюджет (вичерпання обчислювального +бюджету) або перевищує межі, наприклад, намагається перевищити +[максимальну глибину стеку викликів](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L138) +або +[максимальний розмір завантажених даних облікового запису](#accounts-data-size-limit), +виконання транзакції припиняється, і повертається помилка. Це призводить до +невдалої транзакції та жодних змін стану (окрім збору плати за транзакцію). ### Ліміт розміру даних облікового запису -Транзакція може встановлювати максимальну кількість байтів даних облікового запису, які їй дозволено завантажувати, включивши інструкцію `SetLoadedAccountsDataSizeLimit` (не перевищуючи абсолютний максимум часу виконання). Якщо `SetLoadedAccountsDataSizeLimit` не надано, транзакція за замовчуванням використовує значення часу виконання [`MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L137-L139). +Транзакція може встановлювати максимальну кількість байтів даних облікового +запису, які їй дозволено завантажувати, включивши інструкцію +`SetLoadedAccountsDataSizeLimit` (не перевищуючи абсолютний максимум часу +виконання). Якщо `SetLoadedAccountsDataSizeLimit` не надано, транзакція за +замовчуванням використовує значення часу виконання +[`MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L137-L139). -Функцію `ComputeBudgetInstruction::set_loaded_accounts_data_size_limit` можна використовувати для створення цієї інструкції. +Функцію `ComputeBudgetInstruction::set_loaded_accounts_data_size_limit` можна +використовувати для створення цієї інструкції. ```rust let instruction = ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(100_000); @@ -112,13 +186,28 @@ let instruction = ComputeBudgetInstruction::set_loaded_accounts_data_size_limit( ### Обчислювальні одиниці -Усі операції, виконані ончейн у рамках транзакції, вимагають різного обсягу обчислювальних ресурсів, які витрачаються валідаторами під час обробки (обчислювальна вартість). Найменшою одиницею виміру цих ресурсів є _"обчислювальна одиниця"_. - -Під час обробки транзакції обчислювальні одиниці поступово споживаються кожною з її інструкцій, виконуваних ончейн (вичерпуючи бюджет). Оскільки кожна інструкція виконує різну логіку (запис у облікові записи, CPI, виконання системних викликів тощо), кожна може споживати [різну кількість](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L133-L178) обчислювальних одиниць. - -> Програма може записувати деталі про використання своїх обчислювальних ресурсів, включаючи залишок у виділеному обчислювальному бюджеті. Більше інформації ви можете знайти в цьому посібнику з [оптимізації використання обчислювальних ресурсів](/content/guides/advanced/how-to-optimize-compute.md). - -Кожній транзакції виділяється [ліміт обчислювальних одиниць](#compute-unit-limit), або за замовчуванням встановлений часом виконання, або шляхом явного запиту на вищий ліміт. Якщо транзакція перевищує свій ліміт обчислювальних одиниць, її обробка зупиняється, що призводить до невдалої транзакції. +Усі операції, виконані ончейн у рамках транзакції, вимагають різного обсягу +обчислювальних ресурсів, які витрачаються валідаторами під час обробки +(обчислювальна вартість). Найменшою одиницею виміру цих ресурсів є +_"обчислювальна одиниця"_. + +Під час обробки транзакції обчислювальні одиниці поступово споживаються кожною з +її інструкцій, виконуваних ончейн (вичерпуючи бюджет). Оскільки кожна інструкція +виконує різну логіку (запис у облікові записи, CPI, виконання системних викликів +тощо), кожна може споживати +[різну кількість](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L133-L178) +обчислювальних одиниць. + +> Програма може записувати деталі про використання своїх обчислювальних +> ресурсів, включаючи залишок у виділеному обчислювальному бюджеті. Більше +> інформації ви можете знайти в цьому посібнику з +> [оптимізації використання обчислювальних ресурсів](/content/guides/advanced/how-to-optimize-compute.md). + +Кожній транзакції виділяється +[ліміт обчислювальних одиниць](#compute-unit-limit), або за замовчуванням +встановлений часом виконання, або шляхом явного запиту на вищий ліміт. Якщо +транзакція перевищує свій ліміт обчислювальних одиниць, її обробка зупиняється, +що призводить до невдалої транзакції. Нижче наведено кілька поширених операцій, які мають обчислювальну вартість: @@ -132,60 +221,116 @@ let instruction = ComputeBudgetInstruction::set_loaded_accounts_data_size_limit( - міжпрограмні виклики (CPI) - криптографічні операції -> Для [міжпрограмних викликів](/docs/uk/core/cpi.md) викликана інструкція успадковує обчислювальний бюджет і ліміти свого батька. Якщо викликана інструкція споживає залишок бюджету транзакції або перевищує ліміт, весь ланцюжок викликів і обробка транзакції верхнього рівня зупиняються. +> Для [міжпрограмних викликів](/docs/uk/core/cpi.md) викликана інструкція +> успадковує обчислювальний бюджет і ліміти свого батька. Якщо викликана +> інструкція споживає залишок бюджету транзакції або перевищує ліміт, весь +> ланцюжок викликів і обробка транзакції верхнього рівня зупиняються. -Детальнішу інформацію про всі операції, які споживають обчислювальні одиниці, ви можете знайти в [ComputeBudget](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L19-L123) в часі виконання Solana. +Детальнішу інформацію про всі операції, які споживають обчислювальні одиниці, ви +можете знайти в +[ComputeBudget](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L19-L123) +в часі виконання Solana. ### Ліміт обчислювальних одиниць -Кожна транзакція має максимальну кількість обчислювальних одиниць (CU), які вона може спожити, що називається _"лімітом обчислювальних одиниць"_. У часі виконання Solana встановлено абсолютний максимальний ліміт [1,4 мільйона CU](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L19) на транзакцію та за замовчуванням [200 тисяч CU на інструкцію](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L18). - -Транзакція може запитувати більш конкретний і оптимальний ліміт обчислювальних одиниць, включивши одну інструкцію `SetComputeUnitLimit`. Це може бути як вищий, так і нижчий ліміт. Але він ніколи не може перевищувати абсолютний максимальний ліміт на транзакцію. - -Хоча ліміт обчислювальних одиниць за замовчуванням підходить для простих транзакцій, він часто є менш оптимальним (як для часу виконання, так і для користувача). Для складніших транзакцій, наприклад, виклику програм, що виконують декілька CPI, може знадобитися запит вищого ліміту обчислювальних одиниць для транзакції. - -Запит оптимальних лімітів обчислювальних одиниць для вашої транзакції є важливим для зменшення витрат на транзакцію та кращого планування вашої транзакції в мережі. Гаманці, dApps та інші сервіси повинні переконатися, що їхні запити на обчислювальні одиниці є оптимальними, щоб забезпечити найкращий досвід для своїх користувачів. - -> Для отримання додаткової інформації та найкращих практик прочитайте цей посібник про [запит оптимальних лімітів обчислювальних ресурсів](/content/guides/advanced/how-to-request-optimal-compute.md). +Кожна транзакція має максимальну кількість обчислювальних одиниць (CU), які вона +може спожити, що називається _"лімітом обчислювальних одиниць"_. У часі +виконання Solana встановлено абсолютний максимальний ліміт +[1,4 мільйона CU](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L19) +на транзакцію та за замовчуванням +[200 тисяч CU на інструкцію](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L18). + +Транзакція може запитувати більш конкретний і оптимальний ліміт обчислювальних +одиниць, включивши одну інструкцію `SetComputeUnitLimit`. Це може бути як вищий, +так і нижчий ліміт. Але він ніколи не може перевищувати абсолютний максимальний +ліміт на транзакцію. + +Хоча ліміт обчислювальних одиниць за замовчуванням підходить для простих +транзакцій, він часто є менш оптимальним (як для часу виконання, так і для +користувача). Для складніших транзакцій, наприклад, виклику програм, що +виконують декілька CPI, може знадобитися запит вищого ліміту обчислювальних +одиниць для транзакції. + +Запит оптимальних лімітів обчислювальних одиниць для вашої транзакції є важливим +для зменшення витрат на транзакцію та кращого планування вашої транзакції в +мережі. Гаманці, dApps та інші сервіси повинні переконатися, що їхні запити на +обчислювальні одиниці є оптимальними, щоб забезпечити найкращий досвід для своїх +користувачів. + +> Для отримання додаткової інформації та найкращих практик прочитайте цей +> посібник про +> [запит оптимальних лімітів обчислювальних ресурсів](/content/guides/advanced/how-to-request-optimal-compute.md). ### Ціна обчислювальної одиниці -Якщо транзакція бажає сплатити вищу плату, щоб підвищити пріоритетність її обробки, вона може встановити _"ціну обчислювальної одиниці"_. Ця ціна, у поєднанні з [лімітом обчислювальних одиниць](#compute-unit-limit), буде використовуватися для визначення плати за пріоритизацію транзакції. +Якщо транзакція бажає сплатити вищу плату, щоб підвищити пріоритетність її +обробки, вона може встановити _"ціну обчислювальної одиниці"_. Ця ціна, у +поєднанні з [лімітом обчислювальних одиниць](#compute-unit-limit), буде +використовуватися для визначення плати за пріоритизацію транзакції. -За замовчуванням [ціна обчислювальної одиниці не встановлена](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L38), що призводить до відсутності додаткової плати за пріоритизацію. +За замовчуванням +[ціна обчислювальної одиниці не встановлена](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L38), +що призводить до відсутності додаткової плати за пріоритизацію. ## Пріоритизаційні збори -Як частина [Compute Budget](#compute-budget), час виконання підтримує транзакції, що сплачують **опціональну** плату, відому як _"плата за пріоритизацію"_. Сплата цієї додаткової плати допомагає підвищити пріоритетність транзакції у порівнянні з іншими під час обробки, що призводить до швидшого виконання. +Як частина [Compute Budget](#compute-budget), час виконання підтримує +транзакції, що сплачують **опціональну** плату, відому як _"плата за +пріоритизацію"_. Сплата цієї додаткової плати допомагає підвищити пріоритетність +транзакції у порівнянні з іншими під час обробки, що призводить до швидшого +виконання. ### Як розраховується плата за пріоритизацію -Плата за пріоритизацію транзакції розраховується шляхом множення її **_ліміту обчислювальних одиниць_** на **_ціну обчислювальної одиниці_** (вимірюється в _мікролампортах_). Ці значення можна встановити один раз на транзакцію, включивши такі інструкції Compute Budget: +Плата за пріоритизацію транзакції розраховується шляхом множення її **_ліміту +обчислювальних одиниць_** на **_ціну обчислювальної одиниці_** (вимірюється в +_мікролампортах_). Ці значення можна встановити один раз на транзакцію, +включивши такі інструкції Compute Budget: -- [`SetComputeUnitLimit`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L47-L50) — встановлення максимальної кількості обчислювальних одиниць, які може спожити транзакція. -- [`SetComputeUnitPrice`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L52-L55) — встановлення бажаної додаткової плати, яку транзакція готова сплатити для підвищення пріоритетності. +- [`SetComputeUnitLimit`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L47-L50) + — встановлення максимальної кількості обчислювальних одиниць, які може спожити + транзакція. +- [`SetComputeUnitPrice`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L52-L55) + — встановлення бажаної додаткової плати, яку транзакція готова сплатити для + підвищення пріоритетності. -Якщо інструкція `SetComputeUnitLimit` не надана, буде використовуватися [ліміт обчислювальних одиниць за замовчуванням](#compute-unit-limit). +Якщо інструкція `SetComputeUnitLimit` не надана, буде використовуватися +[ліміт обчислювальних одиниць за замовчуванням](#compute-unit-limit). -Якщо інструкція `SetComputeUnitPrice` не надана, транзакція за замовчуванням матиме найнижчий пріоритет (тобто відсутність пріоритизаційної плати). +Якщо інструкція `SetComputeUnitPrice` не надана, транзакція за замовчуванням +матиме найнижчий пріоритет (тобто відсутність пріоритизаційної плати). ### Як встановити плату за пріоритизацію -Плата за пріоритизацію транзакції встановлюється шляхом включення інструкції `SetComputeUnitPrice` та, за бажанням, інструкції `SetComputeUnitLimit`. Час виконання використовуватиме ці значення для розрахунку плати за пріоритизацію, яка буде використовуватися для пріоритизації даної транзакції у блоці. +Плата за пріоритизацію транзакції встановлюється шляхом включення інструкції +`SetComputeUnitPrice` та, за бажанням, інструкції `SetComputeUnitLimit`. Час +виконання використовуватиме ці значення для розрахунку плати за пріоритизацію, +яка буде використовуватися для пріоритизації даної транзакції у блоці. -Ви можете створити кожну з цих інструкцій за допомогою функцій Rust або `@solana/web3.js`. Потім кожну інструкцію можна включити в транзакцію та надіслати до кластера як звичайно. Дивіться також [найкращі практики](#prioritization-fee-best-practices) нижче. +Ви можете створити кожну з цих інструкцій за допомогою функцій Rust або +`@solana/web3.js`. Потім кожну інструкцію можна включити в транзакцію та +надіслати до кластера як звичайно. Дивіться також +[найкращі практики](#prioritization-fee-best-practices) нижче. -На відміну від інших інструкцій усередині транзакції Solana, інструкції Compute Budget **НЕ** вимагають жодних облікових записів. Транзакція з кількома інструкціями одного типу завершиться невдачею. +На відміну від інших інструкцій усередині транзакції Solana, інструкції Compute +Budget **НЕ** вимагають жодних облікових записів. Транзакція з кількома +інструкціями одного типу завершиться невдачею. -Транзакції можуть містити лише **одну інструкцію кожного типу** інструкцій обчислювального бюджету. Дублікати інструкцій призведуть до помилки [`TransactionError::DuplicateInstruction`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/transaction/error.rs#L143-L145) і, зрештою, до невдачі транзакції. +Транзакції можуть містити лише **одну інструкцію кожного типу** інструкцій +обчислювального бюджету. Дублікати інструкцій призведуть до помилки +[`TransactionError::DuplicateInstruction`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/transaction/error.rs#L143-L145) +і, зрештою, до невдачі транзакції. #### Rust -Бібліотека `solana-sdk` включає функції в рамках [`ComputeBudgetInstruction`](https://docs.rs/solana-sdk/latest/solana_sdk/compute_budget/enum.ComputeBudgetInstruction.html) для створення інструкцій для встановлення _ліміту обчислювальних одиниць_ та _ціни обчислювальної одиниці_. +Бібліотека `solana-sdk` включає функції в рамках +[`ComputeBudgetInstruction`](https://docs.rs/solana-sdk/latest/solana_sdk/compute_budget/enum.ComputeBudgetInstruction.html) +для створення інструкцій для встановлення _ліміту обчислювальних одиниць_ та +_ціни обчислювальної одиниці_. ```rust let instruction = ComputeBudgetInstruction::set_compute_unit_limit(300_000); @@ -194,9 +339,13 @@ let instruction = ComputeBudgetInstruction::set_compute_unit_limit(300_000); ```rust let instruction = ComputeBudgetInstruction::set_compute_unit_price(1); ``` + #### Javascript -Бібліотека `@solana/web3.js` включає функції в класі [`ComputeBudgetProgram`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/ComputeBudgetProgram.html) для створення інструкцій для встановлення _ліміту обчислювальних одиниць_ та _ціни обчислювальної одиниці_. +Бібліотека `@solana/web3.js` включає функції в класі +[`ComputeBudgetProgram`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/ComputeBudgetProgram.html) +для створення інструкцій для встановлення _ліміту обчислювальних одиниць_ та +_ціни обчислювальної одиниці_. ```js const instruction = ComputeBudgetProgram.setComputeUnitLimit({ @@ -212,54 +361,109 @@ const instruction = ComputeBudgetProgram.setComputeUnitPrice({ ### Найкращі практики для плати за пріоритизацію -Нижче наведено загальну інформацію про найкращі практики для пріоритизаційних зборів. Більш детальну інформацію можна знайти в цьому посібнику про [запит оптимального використання обчислювальних ресурсів](/content/guides/advanced/how-to-request-optimal-compute.md), включаючи симуляцію транзакції для визначення її приблизного використання обчислювальних ресурсів. +Нижче наведено загальну інформацію про найкращі практики для пріоритизаційних +зборів. Більш детальну інформацію можна знайти в цьому посібнику про +[запит оптимального використання обчислювальних ресурсів](/content/guides/advanced/how-to-request-optimal-compute.md), +включаючи симуляцію транзакції для визначення її приблизного використання +обчислювальних ресурсів. #### Запитуйте мінімальну кількість обчислювальних одиниць -Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць, необхідну для виконання, щоб мінімізувати збори. Також зауважте, що збори не коригуються, якщо кількість запитаних обчислювальних одиниць перевищує фактично спожиту кількість у виконаній транзакції. +Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць, +необхідну для виконання, щоб мінімізувати збори. Також зауважте, що збори не +коригуються, якщо кількість запитаних обчислювальних одиниць перевищує фактично +спожиту кількість у виконаній транзакції. #### Отримуйте останні пріоритизаційні збори -Перед надсиланням транзакції до кластеру ви можете скористатися методом RPC [`getRecentPrioritizationFees`](/docs/uk/rpc/http/getRecentPrioritizationFees.mdx), щоб отримати список останніх сплачених пріоритизаційних зборів у нещодавно оброблених блоках вузла. +Перед надсиланням транзакції до кластеру ви можете скористатися методом RPC +[`getRecentPrioritizationFees`](/docs/uk/rpc/http/getRecentPrioritizationFees.mdx), +щоб отримати список останніх сплачених пріоритизаційних зборів у нещодавно +оброблених блоках вузла. -Ви можете використовувати ці дані для оцінки відповідної плати за пріоритизацію для вашої транзакції, щоб: +Ви можете використовувати ці дані для оцінки відповідної плати за пріоритизацію +для вашої транзакції, щоб: -(a) підвищити ймовірність її обробки кластером та -(b) мінімізувати сплачені збори. +(a) підвищити ймовірність її обробки кластером та (b) мінімізувати сплачені +збори. ## Оренда -Плата, що депонується на кожен [Обліковий запис Solana](/docs/uk/core/accounts.md) для збереження його пов'язаних даних в ончейні, називається "_орендою_". Ця плата утримується у звичайному балансі лампортів на кожному обліковому записі та може бути повернута під час закриття облікового запису. - -> Оренда відрізняється від [транзакційних зборів](#transaction-fees). Оренда "сплачується" (утримується в Обліковому записі) для збереження даних на блокчейні Solana та може бути повернута. У той час як транзакційні збори сплачуються за обробку [інструкцій](/docs/uk/core/transactions.md#instructions) у мережі. - -Усі облікові записи повинні підтримувати достатньо високий баланс лампортів (відносно їх виділеного простору), щоб стати [звільненими від оренди](#rent-exempt) і залишатися на блокчейні Solana. Будь-яка транзакція, що намагається зменшити баланс облікового запису нижче його відповідного мінімального балансу для звільнення від оренди, завершиться невдачею (якщо тільки баланс не зменшується до нуля). - -Коли власник облікового запису більше не бажає зберігати ці дані в ончейні та доступними в глобальному стані, він може закрити обліковий запис і повернути орендний депозит. - -Це здійснюється шляхом виведення (переказу) усього балансу лампортів облікового запису на інший обліковий запис (наприклад, ваш гаманець). Зменшивши баланс облікового запису до рівно `0`, час виконання видалить обліковий запис і його пов'язані дані з мережі в процесі _"[збирання сміття](#garbage-collection)"_. +Плата, що депонується на кожен +[Обліковий запис Solana](/docs/uk/core/accounts.md) для збереження його +пов'язаних даних в ончейні, називається "_орендою_". Ця плата утримується у +звичайному балансі лампортів на кожному обліковому записі та може бути повернута +під час закриття облікового запису. + +> Оренда відрізняється від [транзакційних зборів](#transaction-fees). Оренда +> "сплачується" (утримується в Обліковому записі) для збереження даних на +> блокчейні Solana та може бути повернута. У той час як транзакційні збори +> сплачуються за обробку +> [інструкцій](/docs/uk/core/transactions.md#instructions) у мережі. + +Усі облікові записи повинні підтримувати достатньо високий баланс лампортів +(відносно їх виділеного простору), щоб стати +[звільненими від оренди](#rent-exempt) і залишатися на блокчейні Solana. +Будь-яка транзакція, що намагається зменшити баланс облікового запису нижче його +відповідного мінімального балансу для звільнення від оренди, завершиться +невдачею (якщо тільки баланс не зменшується до нуля). + +Коли власник облікового запису більше не бажає зберігати ці дані в ончейні та +доступними в глобальному стані, він може закрити обліковий запис і повернути +орендний депозит. + +Це здійснюється шляхом виведення (переказу) усього балансу лампортів облікового +запису на інший обліковий запис (наприклад, ваш гаманець). Зменшивши баланс +облікового запису до рівно `0`, час виконання видалить обліковий запис і його +пов'язані дані з мережі в процесі _"[збирання сміття](#garbage-collection)"_. ### Ставка оренди -Ставка оренди Solana встановлюється на рівні всієї мережі, головним чином базуючись на часі виконання -"[лампорти _за_ байт _за_ рік](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/rent.rs#L27-L34)". Наразі ставка оренди є статичною величиною та зберігається в +Ставка оренди Solana встановлюється на рівні всієї мережі, головним чином +базуючись на часі виконання +"[лампорти _за_ байт _за_ рік](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/rent.rs#L27-L34)". +Наразі ставка оренди є статичною величиною та зберігається в [системній змінній Rent](https://docs.anza.xyz/runtime/sysvars#rent). -Ця ставка оренди використовується для розрахунку точної суми оренди, яка повинна бути утримана в обліковому записі для виділеного простору облікового запису (тобто кількість даних, які можуть бути збережені в обліковому записі). Чим більше простору виділяє обліковий запис, тим вищим буде утриманий орендний депозит. +Ця ставка оренди використовується для розрахунку точної суми оренди, яка повинна +бути утримана в обліковому записі для виділеного простору облікового запису +(тобто кількість даних, які можуть бути збережені в обліковому записі). Чим +більше простору виділяє обліковий запис, тим вищим буде утриманий орендний +депозит. ### Звільнення від оренди -Облікові записи повинні підтримувати баланс лампортів, що перевищує мінімум, необхідний для зберігання відповідних даних в ончейні. Це називається "_звільненням від оренди_", а цей баланс називається "_мінімальним балансом для звільнення від оренди_". - -> Нові облікові записи (та програми) на Solana **ЗОБОВ'ЯЗАНІ** бути ініціалізовані з достатньою кількістю лампортів, щоб стати _звільненими від оренди_. Так було не завжди. Раніше час виконання періодично та автоматично стягував плату з кожного облікового запису, що мав баланс нижче мінімуму для звільнення від оренди. Зрештою, такі облікові записи знижувалися до нульового балансу та видалялися з глобального стану (якщо їх не поповнювали вручну). - -У процесі створення нового облікового запису необхідно переконатися, що ви депонуєте достатньо лампортів, щоб перевищити цей мінімальний баланс. Все, що нижче цього мінімального порогу, призведе до невдачі транзакції. - -Кожного разу, коли баланс облікового запису зменшується, час виконання перевіряє, чи залишиться баланс цього облікового запису вище мінімального балансу для звільнення від оренди. Якщо тільки баланс не знижується до рівно `0` (закриття облікового запису), транзакції, які спричиняють падіння балансу облікового запису нижче порогу звільнення від оренди, завершаться невдачею. - -Специфічний мінімальний баланс для облікового запису, щоб стати звільненим від оренди, залежить від поточної [ставки оренди](#rent-rate) блокчейну та бажаного обсягу простору, який обліковий запис хоче виділити (розмір облікового запису). Тому рекомендується використовувати RPC-метод [`getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx) для розрахунку конкретного балансу для заданого розміру облікового запису. - -Суму необхідного орендного депозиту також можна оцінити за допомогою підкоманди CLI [`solana rent`](https://docs.anza.xyz/cli/usage#solana-rent). +Облікові записи повинні підтримувати баланс лампортів, що перевищує мінімум, +необхідний для зберігання відповідних даних в ончейні. Це називається +"_звільненням від оренди_", а цей баланс називається "_мінімальним балансом для +звільнення від оренди_". + +> Нові облікові записи (та програми) на Solana **ЗОБОВ'ЯЗАНІ** бути +> ініціалізовані з достатньою кількістю лампортів, щоб стати _звільненими від +> оренди_. Так було не завжди. Раніше час виконання періодично та автоматично +> стягував плату з кожного облікового запису, що мав баланс нижче мінімуму для +> звільнення від оренди. Зрештою, такі облікові записи знижувалися до нульового +> балансу та видалялися з глобального стану (якщо їх не поповнювали вручну). + +У процесі створення нового облікового запису необхідно переконатися, що ви +депонуєте достатньо лампортів, щоб перевищити цей мінімальний баланс. Все, що +нижче цього мінімального порогу, призведе до невдачі транзакції. + +Кожного разу, коли баланс облікового запису зменшується, час виконання +перевіряє, чи залишиться баланс цього облікового запису вище мінімального +балансу для звільнення від оренди. Якщо тільки баланс не знижується до рівно `0` +(закриття облікового запису), транзакції, які спричиняють падіння балансу +облікового запису нижче порогу звільнення від оренди, завершаться невдачею. + +Специфічний мінімальний баланс для облікового запису, щоб стати звільненим від +оренди, залежить від поточної [ставки оренди](#rent-rate) блокчейну та бажаного +обсягу простору, який обліковий запис хоче виділити (розмір облікового запису). +Тому рекомендується використовувати RPC-метод +[`getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx) +для розрахунку конкретного балансу для заданого розміру облікового запису. + +Суму необхідного орендного депозиту також можна оцінити за допомогою підкоманди +CLI [`solana rent`](https://docs.anza.xyz/cli/usage#solana-rent). ```shell solana rent 15000 @@ -269,16 +473,29 @@ Rent per byte-year: 0.00000348 SOL Rent per epoch: 0.000288276 SOL Rent-exempt minimum: 0.10529088 SOL ``` + ### Збирання сміття -Облікові записи, які не підтримують баланс лампортів більше нуля, видаляються з мережі в процесі, відомому як _збирання сміття_. Цей процес виконується, щоб зменшити загальну кількість збережених у мережі даних, які більше не використовуються або не підтримуються. +Облікові записи, які не підтримують баланс лампортів більше нуля, видаляються з +мережі в процесі, відомому як _збирання сміття_. Цей процес виконується, щоб +зменшити загальну кількість збережених у мережі даних, які більше не +використовуються або не підтримуються. -Після успішного зменшення балансу облікового запису до рівно `0` транзакцією, збирання сміття виконується автоматично часом виконання. Будь-яка транзакція, яка намагається зменшити баланс облікового запису нижче його мінімального балансу для звільнення від оренди (що не дорівнює нулю), завершиться невдачею. +Після успішного зменшення балансу облікового запису до рівно `0` транзакцією, +збирання сміття виконується автоматично часом виконання. Будь-яка транзакція, +яка намагається зменшити баланс облікового запису нижче його мінімального +балансу для звільнення від оренди (що не дорівнює нулю), завершиться невдачею. Важливо зазначити, що збирання сміття відбувається **після** завершення виконання транзакції. Якщо є інструкція "закрити" обліковий запис, зменшивши баланс облікового запису до нуля, обліковий запис може бути "повторно відкритий" у тій самій транзакції за допомогою наступної інструкції. Якщо стан облікового запису не було очищено в інструкції "закрити", наступна інструкція "повторного відкриття" матиме той самий стан облікового запису. Це є проблемою безпеки, тому важливо знати точний момент, коли збирання сміття набирає чинності. -Навіть після того, як обліковий запис було видалено з мережі (через збирання сміття), він все ще може мати транзакції, пов'язані з його адресою (або в історії, або в майбутньому). Незважаючи на те, що блокчейн-експлорер Solana може відображати повідомлення типу "обліковий запис не знайдено", ви все одно можете переглядати історію транзакцій, пов'язаних із цим обліковим записом. +Навіть після того, як обліковий запис було видалено з мережі (через збирання +сміття), він все ще може мати транзакції, пов'язані з його адресою (або в +історії, або в майбутньому). Незважаючи на те, що блокчейн-експлорер Solana може +відображати повідомлення типу "обліковий запис не знайдено", ви все одно можете +переглядати історію транзакцій, пов'язаних із цим обліковим записом. -Ви можете прочитати [запропоновану реалізацію](https://docs.anza.xyz/implemented-proposals/persistent-account-storage#garbage-collection) для збирання сміття, щоб дізнатися більше. \ No newline at end of file +Ви можете прочитати +[запропоновану реалізацію](https://docs.anza.xyz/implemented-proposals/persistent-account-storage#garbage-collection) +для збирання сміття, щоб дізнатися більше. diff --git a/docs/locales/uk/core/index.md b/docs/locales/uk/core/index.md index b084e320e..8743b8699 100644 --- a/docs/locales/uk/core/index.md +++ b/docs/locales/uk/core/index.md @@ -2,78 +2,116 @@ title: Основні концепції sidebarSortOrder: 2 description: - Дізнайтеся про основні концепції блокчейну Solana, включаючи облікові записи, транзакції, програми, адреси, отримані від програм, міжпрограмні виклики та як працюють токени на Solana. + Дізнайтеся про основні концепції блокчейну Solana, включаючи облікові записи, + транзакції, програми, адреси, отримані від програм, міжпрограмні виклики та як + працюють токени на Solana. --- -Розвивайте глибоке розуміння основних концепцій, які роблять Solana унікальним серед інших блокчейнів. Розуміння "моделі програмування Solana" через ці ключові концепції дуже важливе для максимального успіху як розробника блокчейну Solana. +Розвивайте глибоке розуміння основних концепцій, які роблять Solana унікальним +серед інших блокчейнів. Розуміння "моделі програмування Solana" через ці ключові +концепції дуже важливе для максимального успіху як розробника блокчейну Solana. ## Модель облікових записів Solana -У Solana всі дані зберігаються в тому, що називається "обліковими записами". Організація даних у блокчейні Solana нагадує [сховище ключів і значень](https://uk.wikipedia.org/wiki/Key%E2%80%93value_%D0%B1%D0%B0%D0%B7%D0%B0_%D0%B4%D0%B0%D0%BD%D0%B8%D1%85), де кожен запис у базі даних називається "обліковим записом". +У Solana всі дані зберігаються в тому, що називається "обліковими записами". +Організація даних у блокчейні Solana нагадує +[сховище ключів і значень](https://uk.wikipedia.org/wiki/Key%E2%80%93value_%D0%B1%D0%B0%D0%B7%D0%B0_%D0%B4%D0%B0%D0%BD%D0%B8%D1%85), +де кожен запис у базі даних називається "обліковим записом". Дізнайтеся більше про [Облікові записи](/docs/core/accounts.md) тут. ## Транзакції та інструкції -У Solana ми надсилаємо [транзакції](/docs/core/transactions#transaction), щоб взаємодіяти з мережею. Транзакції включають одну або більше [інструкцій](/docs/core/transactions#instruction), кожна з яких представляє конкретну операцію для обробки. Логіка виконання інструкцій зберігається в [програмах](/docs/core/programs), розгорнутих у мережі Solana, де кожна програма має свій власний набір інструкцій. +У Solana ми надсилаємо [транзакції](/docs/core/transactions#transaction), щоб +взаємодіяти з мережею. Транзакції включають одну або більше +[інструкцій](/docs/core/transactions#instruction), кожна з яких представляє +конкретну операцію для обробки. Логіка виконання інструкцій зберігається в +[програмах](/docs/core/programs), розгорнутих у мережі Solana, де кожна програма +має свій власний набір інструкцій. -Дізнайтеся більше про [Транзакції](/docs/core/transactions.md) та [Інструкції](/docs/core/transactions.md#instruction) тут. +Дізнайтеся більше про [Транзакції](/docs/core/transactions.md) та +[Інструкції](/docs/core/transactions.md#instruction) тут. ## Плата на Solana -Блокчейн Solana має кілька типів зборів та витрат, які виникають при використанні мережі без дозволу. Вони поділяються на кілька основних типів: +Блокчейн Solana має кілька типів зборів та витрат, які виникають при +використанні мережі без дозволу. Вони поділяються на кілька основних типів: -- [Транзакційні збори](/docs/core/fees.md#transaction-fees) — плата за обробку транзакцій/інструкцій валідаторами. -- [Пріоритизаційні збори](/docs/core/fees.md#prioritization-fees) — опціональна плата для підвищення порядку обробки транзакцій. -- [Оренда](/docs/core/fees.md#rent) — утримуваний баланс для збереження даних в ончейні. +- [Транзакційні збори](/docs/core/fees.md#transaction-fees) — плата за обробку + транзакцій/інструкцій валідаторами. +- [Пріоритизаційні збори](/docs/core/fees.md#prioritization-fees) — опціональна + плата для підвищення порядку обробки транзакцій. +- [Оренда](/docs/core/fees.md#rent) — утримуваний баланс для збереження даних в + ончейні. Дізнайтеся більше про [Плату на Solana](/docs/core/fees.md) тут. ## Програми на Solana -У екосистемі Solana "смарт-контракти" називаються програмами. Кожна програма є ончейн-обліковим записом, що зберігає виконувану логіку, організовану у функції, що називаються _інструкціями_, і викликаються через функції обробників інструкцій у відповідній розгорнутій програмі. +У екосистемі Solana "смарт-контракти" називаються програмами. Кожна програма є +ончейн-обліковим записом, що зберігає виконувану логіку, організовану у функції, +що називаються _інструкціями_, і викликаються через функції обробників +інструкцій у відповідній розгорнутій програмі. Дізнайтеся більше про [Програми на Solana](/docs/core/programs.md) тут. ## Адреси, отримані від програм -Адреси, отримані від програм (Program Derived Addresses, PDAs), надають розробникам Solana дві основні можливості: +Адреси, отримані від програм (Program Derived Addresses, PDAs), надають +розробникам Solana дві основні можливості: -- **Детерміновані адреси облікових записів**: PDAs забезпечують механізм детермінованого отримання адреси за допомогою комбінації опціональних "насіння" (заданих вхідних даних) і конкретного ідентифікатора програми. -- **Дозволити підписання програмою**: Час виконання Solana дозволяє програмам "підписувати" PDAs, які отримані від їх ідентифікатора програми. +- **Детерміновані адреси облікових записів**: PDAs забезпечують механізм + детермінованого отримання адреси за допомогою комбінації опціональних + "насіння" (заданих вхідних даних) і конкретного ідентифікатора програми. +- **Дозволити підписання програмою**: Час виконання Solana дозволяє програмам + "підписувати" PDAs, які отримані від їх ідентифікатора програми. -Можна уявити PDAs як спосіб створення ончейн-структур, схожих на хеш-таблиці, з набору заданих вхідних даних (наприклад, рядків, чисел та інших адрес облікових записів). +Можна уявити PDAs як спосіб створення ончейн-структур, схожих на хеш-таблиці, з +набору заданих вхідних даних (наприклад, рядків, чисел та інших адрес облікових +записів). Дізнайтеся більше про [Адреси, отримані від програм](/docs/core/pda.md) тут. ## Міжпрограмні виклики -Міжпрограмний виклик (Cross Program Invocation, CPI) означає, що одна програма викликає інструкції іншої програми. Цей механізм дозволяє програмам Solana бути композитивними. +Міжпрограмний виклик (Cross Program Invocation, CPI) означає, що одна програма +викликає інструкції іншої програми. Цей механізм дозволяє програмам Solana бути +композитивними. -Можна уявити інструкції як API-ендпоінти, які програма надає мережі, а CPI як один API, що викликає інший API внутрішньо. +Можна уявити інструкції як API-ендпоінти, які програма надає мережі, а CPI як +один API, що викликає інший API внутрішньо. Дізнайтеся більше про [Міжпрограмні виклики](/docs/core/cpi.md) тут. ## Токени на Solana -Токени — це цифрові активи, які представляють право власності на різні категорії активів. Токенізація дозволяє оцифровувати права власності, виступаючи фундаментальним компонентом для управління як взаємозамінними, так і невзаємозамінними активами. +Токени — це цифрові активи, які представляють право власності на різні категорії +активів. Токенізація дозволяє оцифровувати права власності, виступаючи +фундаментальним компонентом для управління як взаємозамінними, так і +невзаємозамінними активами. -- Взаємозамінні токени представляють взаємозамінні та подільні активи одного типу і вартості (наприклад, USDC). -- Невзаємозамінні токени (NFT) представляють право власності на неподільні активи (наприклад, твори мистецтва). +- Взаємозамінні токени представляють взаємозамінні та подільні активи одного + типу і вартості (наприклад, USDC). +- Невзаємозамінні токени (NFT) представляють право власності на неподільні + активи (наприклад, твори мистецтва). Дізнайтеся більше про [Токени на Solana](/docs/core/tokens.md) тут. ## Кластери та кінцеві точки -Блокчейн Solana має кілька різних груп валідаторів, відомих як [Кластери](/docs/core/clusters.md). Кожна з них виконує різні завдання в екосистемі та має спеціалізовані вузли API для виконання запитів [JSON-RPC](/docs/rpc/index.mdx) для свого кластеру. +Блокчейн Solana має кілька різних груп валідаторів, відомих як +[Кластери](/docs/core/clusters.md). Кожна з них виконує різні завдання в +екосистемі та має спеціалізовані вузли API для виконання запитів +[JSON-RPC](/docs/rpc/index.mdx) для свого кластеру. -Індивідуальні вузли в кластері належать і управляються третіми сторонами, причому для кожного з них доступна публічна кінцева точка. +Індивідуальні вузли в кластері належать і управляються третіми сторонами, +причому для кожного з них доступна публічна кінцева точка. -Є три основні кластери в мережі Solana, кожен з яких має свою публічну кінцеву точку: +Є три основні кластери в мережі Solana, кожен з яких має свою публічну кінцеву +точку: - Mainnet - `https://api.mainnet-beta.solana.com` - Devnet - `https://api.devnet.solana.com` - Testnet - `https://api.testnet.solana.com` Дізнайтеся більше про [Кластери та кінцеві точки](/docs/core/clusters.md) тут. - diff --git a/docs/locales/uk/core/pda.md b/docs/locales/uk/core/pda.md index 3221b2f8f..b3451e66e 100644 --- a/docs/locales/uk/core/pda.md +++ b/docs/locales/uk/core/pda.md @@ -3,16 +3,19 @@ title: Програмно Виведені Адреси (PDA) sidebarLabel: Програмно Виведені Адреси sidebarSortOrder: 5 description: - Дізнайтеся про Програмно Виведені Адреси (PDA) в Solana — детерміновані - адреси облікових записів, які забезпечують безпечне підписання програмами. - Розберіться у виведенні PDA, канонічних бампах і створенні облікових записів PDA. + Дізнайтеся про Програмно Виведені Адреси (PDA) в Solana — детерміновані адреси + облікових записів, які забезпечують безпечне підписання програмами. + Розберіться у виведенні PDA, канонічних бампах і створенні облікових записів + PDA. --- -Програмно Виведені Адреси (PDA) надають розробникам у Solana два основних варіанти використання: +Програмно Виведені Адреси (PDA) надають розробникам у Solana два основних +варіанти використання: - **Детерміновані адреси облікових записів**: PDA надають механізм для детермінованого виведення адреси за допомогою комбінації необов’язкових - "сідів" (заздалегідь визначених вхідних даних) та певного ідентифікатора програми. + "сідів" (заздалегідь визначених вхідних даних) та певного ідентифікатора + програми. - **Забезпечення підписання програмами**: Рантайм Solana дозволяє програмам "підписуватися" від імені PDA, які виведені з їхнього ідентифікатора програми. @@ -27,14 +30,14 @@ description: ![Програмно Виведена Адреса](/assets/docs/core/pda/pda.svg) Важливо розуміти, що просте виведення Програмно Виведеної Адреси (PDA) не -автоматично створює обліковий запис у блокчейні за цією адресою. Облікові -записи з PDA як адресою в блокчейні повинні бути явно створені через програму, -яка використовувалась для виведення адреси. Можна уявити виведення PDA як -пошук адреси на карті. Мати адресу — це ще не означає, що за цією адресою -щось побудовано. - -> У цьому розділі буде розглянуто деталі виведення PDA. Деталі того, як -> програми використовують PDA для підписання, будуть розглянуті в розділі +автоматично створює обліковий запис у блокчейні за цією адресою. Облікові записи +з PDA як адресою в блокчейні повинні бути явно створені через програму, яка +використовувалась для виведення адреси. Можна уявити виведення PDA як пошук +адреси на карті. Мати адресу — це ще не означає, що за цією адресою щось +побудовано. + +> У цьому розділі буде розглянуто деталі виведення PDA. Деталі того, як програми +> використовують PDA для підписання, будуть розглянуті в розділі > [Взаємодія між програмами (CPI)](/docs/uk/core/cpi.md), оскільки це потребує > контексту для обох концепцій. @@ -58,11 +61,12 @@ description: PDA — це адреси, які виводяться детерміновано та виглядають як стандартні публічні ключі, але не мають асоційованих приватних ключів. Це означає, що жоден -зовнішній користувач не може згенерувати дійсний підпис для цієї адреси. -Однак, рантайм Solana дозволяє програмам програмно "підписуватися" від імені -PDA без необхідності у приватному ключі. +зовнішній користувач не може згенерувати дійсний підпис для цієї адреси. Однак, +рантайм Solana дозволяє програмам програмно "підписуватися" від імені PDA без +необхідності у приватному ключі. -Для контексту, [Keypairs](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/signer/keypair.rs#L25) +Для контексту, +[Keypairs](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/signer/keypair.rs#L25) у Solana є точками на кривій Ed25519 (еліптична криптографія), які мають публічний ключ і відповідний приватний ключ. Ми часто використовуємо публічні ключі як унікальні ідентифікатори для нових облікових записів у блокчейні, а @@ -86,13 +90,13 @@ PDA може бути використана як адреса (унікальн Виведення PDA вимагає 3 вхідних даних. - **Необов’язкові сіди**: Заздалегідь визначені вхідні дані (наприклад, рядок, - число, інші адреси облікових записів), які використовуються для виведення - PDA. Ці вхідні дані конвертуються в буфер байтів. + число, інші адреси облікових записів), які використовуються для виведення PDA. + Ці вхідні дані конвертуються в буфер байтів. - **Бамп сід**: Додатковий вхідний параметр (зі значенням між 255-0), який використовується для забезпечення того, що згенерований PDA знаходиться поза кривою Ed25519. Цей бамп сід (починаючи з 255) додається до необов’язкових - сідів під час генерації PDA, щоб "виштовхнути" точку за межі кривої - Ed25519. Бамп сід іноді називають "нонсом". + сідів під час генерації PDA, щоб "виштовхнути" точку за межі кривої Ed25519. + Бамп сід іноді називають "нонсом". - **Ідентифікатор програми**: Адреса програми, з якої виведений PDA. Ця ж програма може "підписуватися" від імені PDA. @@ -130,14 +134,16 @@ const [PDA, bump] = PublicKey.findProgramAddressSync([], programId); console.log(`PDA: ${PDA}`); console.log(`Bump: ${bump}`); ``` + Ви можете запустити цей приклад на -[Solana Playground](https://beta.solpg.io/66031e5acffcf4b13384cfef). Виведення PDA та -бамп сіда завжди буде однаковим: +[Solana Playground](https://beta.solpg.io/66031e5acffcf4b13384cfef). Виведення +PDA та бамп сіда завжди буде однаковим: ``` PDA: Cu7NwqCXSmsR5vgGA3Vw9uYVViPi3kQvkbKByVQ8nPY9 Bump: 255 ``` + У наступному прикладі додається необов’язковий сід "helloWorld". ```ts /string/ @@ -154,9 +160,10 @@ const [PDA, bump] = PublicKey.findProgramAddressSync( console.log(`PDA: ${PDA}`); console.log(`Bump: ${bump}`); ``` + Ви також можете запустити цей приклад на -[Solana Playground](https://beta.solpg.io/66031ee5cffcf4b13384cff0). Виведення PDA та -бамп сіда завжди буде однаковим: +[Solana Playground](https://beta.solpg.io/66031ee5cffcf4b13384cff0). Виведення +PDA та бамп сіда завжди буде однаковим: ``` PDA: 46GZzzetjCURsdFPb7rcnspbEMnCBXe9kpjrsZAkKb6X @@ -182,8 +189,8 @@ Bump: 254 Значення бамп сіда починається з 255 і зменшується на 1, доки не буде знайдено дійсний PDA (поза кривою). -Ви можете відтворити попередній приклад, використовуючи `createProgramAddressSync` -та явно передавши бамп сід зі значенням 254. +Ви можете відтворити попередній приклад, використовуючи +`createProgramAddressSync` та явно передавши бамп сід зі значенням 254. ```ts /bump/ import { PublicKey } from "@solana/web3.js"; @@ -199,6 +206,7 @@ const PDA = PublicKey.createProgramAddressSync( console.log(`PDA: ${PDA}`); ``` + Запустіть цей приклад вище на [Solana Playground](https://beta.solpg.io/66031f8ecffcf4b13384cff1). За однакових сідів та ідентифікатора програми, виведення PDA буде відповідати @@ -211,11 +219,11 @@ PDA: 46GZzzetjCURsdFPb7rcnspbEMnCBXe9kpjrsZAkKb6X ### Канонічний бамп "Канонічний бамп" відноситься до першого значення бамп сіда (починаючи з 255 і -зменшуючи на 1), яке виводить дійсний PDA. З метою безпеки програм -рекомендовано використовувати лише PDA, виведені з канонічного бампа. +зменшуючи на 1), яке виводить дійсний PDA. З метою безпеки програм рекомендовано +використовувати лише PDA, виведені з канонічного бампа. -Використовуючи попередній приклад як орієнтир, приклад нижче намагається -вивести PDA, використовуючи всі значення бамп сіда від 255 до 0. +Використовуючи попередній приклад як орієнтир, приклад нижче намагається вивести +PDA, використовуючи всі значення бамп сіда від 255 до 0. ```ts import { PublicKey } from "@solana/web3.js"; @@ -236,7 +244,8 @@ for (let bump = 255; bump >= 0; bump--) { } } ``` -Запустіть приклад на + +Запустіть приклад на [Solana Playground](https://beta.solpg.io/66032009cffcf4b13384cff2), і ви повинні побачити наступний результат: @@ -250,12 +259,13 @@ bump 250: Error: Invalid seeds, address must fall off the curve ... // remaining bump outputs ``` -Як і очікувалось, бамп сід 255 викликає помилку, а перший бамп сід, який виводить -дійсний PDA, дорівнює 254. + +Як і очікувалось, бамп сід 255 викликає помилку, а перший бамп сід, який +виводить дійсний PDA, дорівнює 254. Однак зверніть увагу, що бамп сіди 253-251 також виводять дійсні PDA з різними -адресами. Це означає, що для заданих необов’язкових сідів та `programId` бамп сід -з іншим значенням все ще може вивести дійсний PDA. +адресами. Це означає, що для заданих необов’язкових сідів та `programId` бамп +сід з іншим значенням все ще може вивести дійсний PDA. При створенні програм на Solana рекомендовано додавати перевірки безпеки, @@ -271,10 +281,10 @@ bump 250: Error: Invalid seeds, address must fall off the curve показує, як створити обліковий запис, використовуючи PDA як адресу нового облікового запису. Програма написана з використанням фреймворку Anchor. -У файлі `lib.rs` ви знайдете наступну програму, яка включає єдину інструкцію -для створення нового облікового запису з використанням PDA як адреси -облікового запису. Новий обліковий запис зберігає адресу `user` та `bump` сід, -який використовувався для виведення PDA. +У файлі `lib.rs` ви знайдете наступну програму, яка включає єдину інструкцію для +створення нового облікового запису з використанням PDA як адреси облікового +запису. Новий обліковий запис зберігає адресу `user` та `bump` сід, який +використовувався для виведення PDA. ```rust filename="lib.rs" {11-14,26-29} use anchor_lang::prelude::*; @@ -321,9 +331,10 @@ pub struct DataAccount { pub bump: u8, } ``` -Сіди, які використовуються для виведення PDA, включають зафіксований рядок `data` -та адресу облікового запису `user`, передану в інструкції. Фреймворк Anchor -автоматично виводить канонічний `bump` сід. + +Сіди, які використовуються для виведення PDA, включають зафіксований рядок +`data` та адресу облікового запису `user`, передану в інструкції. Фреймворк +Anchor автоматично виводить канонічний `bump` сід. ```rust /data/ /user.key()/ /bump/ #[account( @@ -335,8 +346,9 @@ pub struct DataAccount { )] pub pda_account: Account<'info, DataAccount>, ``` -Обмеження `init` вказує Anchor викликати Системну Програму для створення нового -облікового запису з використанням PDA як адреси. Це виконується за допомогою + +Обмеження `init` вказує Anchor викликати Системну Програму для створення нового +облікового запису з використанням PDA як адреси. Це виконується за допомогою [Взаємодії між програмами (CPI)](/docs/uk/core/cpi.md). ```rust /init/ @@ -349,10 +361,10 @@ pub pda_account: Account<'info, DataAccount>, )] pub pda_account: Account<'info, DataAccount>, ``` -У тестовому файлі (`pda-account.test.ts`), розташованому за посиланням на -Solana Playground, наданим вище, ви знайдете еквівалентний код на Javascript -для виведення PDA. +У тестовому файлі (`pda-account.test.ts`), розташованому за посиланням на Solana +Playground, наданим вище, ви знайдете еквівалентний код на Javascript для +виведення PDA. ```ts /data/ /user.publicKey/ const [PDA] = PublicKey.findProgramAddressSync( @@ -360,10 +372,11 @@ const [PDA] = PublicKey.findProgramAddressSync( program.programId, ); ``` -Далі надсилається транзакція для виклику інструкції `initialize`, щоб створити -новий обліковий запис у блокчейні з використанням PDA як адреси. Після надсилання -транзакції PDA використовується для отримання облікового запису в блокчейні, -який був створений за цією адресою. + +Далі надсилається транзакція для виклику інструкції `initialize`, щоб створити +новий обліковий запис у блокчейні з використанням PDA як адреси. Після +надсилання транзакції PDA використовується для отримання облікового запису в +блокчейні, який був створений за цією адресою. ```ts /initialize()/ /PDA/ {14} it("Is initialized!", async () => { @@ -383,6 +396,8 @@ it("Fetch Account", async () => { console.log(JSON.stringify(pdaAccount, null, 2)); }); ``` -Зверніть увагу, що якщо ви викликаєте інструкцію `initialize` більше одного разу, -використовуючи ту саму адресу `user` як сід, транзакція завершиться помилкою. -Це відбувається тому, що обліковий запис вже існує за виведеною адресою. + +Зверніть увагу, що якщо ви викликаєте інструкцію `initialize` більше одного +разу, використовуючи ту саму адресу `user` як сід, транзакція завершиться +помилкою. Це відбувається тому, що обліковий запис вже існує за виведеною +адресою. diff --git a/docs/locales/uk/core/programs.md b/docs/locales/uk/core/programs.md index fc4d35564..0c796f12f 100644 --- a/docs/locales/uk/core/programs.md +++ b/docs/locales/uk/core/programs.md @@ -8,85 +8,89 @@ description: та перевірки програм у мережі Solana. --- -У екосистемі Solana "смарт-контракти" називаються програмами. Кожна -[програма](/docs/uk/core/accounts.md#program-account) є обліковим записом у блокчейні, -який зберігає виконувану логіку, організовану у вигляді конкретних функцій, які -називаються [інструкціями](/docs/uk/core/transactions.md#instruction). +У екосистемі Solana "смарт-контракти" називаються програмами. Кожна +[програма](/docs/uk/core/accounts.md#program-account) є обліковим записом у +блокчейні, який зберігає виконувану логіку, організовану у вигляді конкретних +функцій, які називаються +[інструкціями](/docs/uk/core/transactions.md#instruction). ## Основні моменти -- Програми — це облікові записи у блокчейні, які містять виконуваний код. Цей код - організований у вигляді окремих функцій, відомих як інструкції. +- Програми — це облікові записи у блокчейні, які містять виконуваний код. Цей + код організований у вигляді окремих функцій, відомих як інструкції. -- Програми не зберігають стану, але можуть включати інструкції для створення нових - облікових записів, які використовуються для зберігання та управління станом програми. +- Програми не зберігають стану, але можуть включати інструкції для створення + нових облікових записів, які використовуються для зберігання та управління + станом програми. -- Програми можуть оновлюватися за допомогою "авторитету оновлення". Програма стає - незмінною, коли авторитет оновлення встановлюється у значення null. +- Програми можуть оновлюватися за допомогою "авторитету оновлення". Програма + стає незмінною, коли авторитет оновлення встановлюється у значення null. -- Перевірювані збірки дозволяють користувачам переконатися, що програми у блокчейні - відповідають доступному публічно вихідному коду. +- Перевірювані збірки дозволяють користувачам переконатися, що програми у + блокчейні відповідають доступному публічно вихідному коду. ## Написання програм Solana -Програми Solana зазвичай пишуться мовою програмування +Програми Solana зазвичай пишуться мовою програмування [Rust](https://doc.rust-lang.org/book/) з використанням двох підходів: -- [Anchor](/docs/uk/programs/anchor): Фреймворк, створений для розробки програм Solana. - Він забезпечує швидший і простіший спосіб написання програм, використовуючи макроси - Rust для значного зменшення обсягу шаблонного коду. Для початківців рекомендується - починати з фреймворку Anchor. +- [Anchor](/docs/uk/programs/anchor): Фреймворк, створений для розробки програм + Solana. Він забезпечує швидший і простіший спосіб написання програм, + використовуючи макроси Rust для значного зменшення обсягу шаблонного коду. Для + початківців рекомендується починати з фреймворку Anchor. -- [Нативний Rust](/content/guides/getstarted/intro-to-native-rust.md): Цей підхід - передбачає написання програм Solana на Rust без використання фреймворків. Він - надає більше гнучкості, але супроводжується підвищеною складністю. +- [Нативний Rust](/content/guides/getstarted/intro-to-native-rust.md): Цей + підхід передбачає написання програм Solana на Rust без використання + фреймворків. Він надає більше гнучкості, але супроводжується підвищеною + складністю. ## Оновлення програм Solana -Програми у блокчейні можуть бути -[безпосередньо змінені](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L675) -обліковим записом, призначеним як "авторитет оновлення", зазвичай це обліковий +Програми у блокчейні можуть бути +[безпосередньо змінені](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L675) +обліковим записом, призначеним як "авторитет оновлення", зазвичай це обліковий запис, який початково розгорнув програму. -Якщо -[авторитет оновлення](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L865) -скасований і встановлений у `None`, програма стає незмінною і більше не може бути оновлена. +Якщо +[авторитет оновлення](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L865) +скасований і встановлений у `None`, програма стає незмінною і більше не може +бути оновлена. ## Перевірювані програми -Забезпечення цілісності та перевірюваності коду у блокчейні є важливим. -Перевірювана збірка гарантує, що виконуваний код, розгорнутий у блокчейні, може -бути незалежно перевірений на відповідність його публічному вихідному коду -будь-якою третьою стороною. Цей процес підвищує прозорість і довіру, дозволяючи +Забезпечення цілісності та перевірюваності коду у блокчейні є важливим. +Перевірювана збірка гарантує, що виконуваний код, розгорнутий у блокчейні, може +бути незалежно перевірений на відповідність його публічному вихідному коду +будь-якою третьою стороною. Цей процес підвищує прозорість і довіру, дозволяючи виявляти розбіжності між вихідним кодом і розгорнутою програмою. -Спільнота розробників Solana створила інструменти для підтримки перевірюваних -збірок, які дозволяють як розробникам, так і користувачам переконатися, що +Спільнота розробників Solana створила інструменти для підтримки перевірюваних +збірок, які дозволяють як розробникам, так і користувачам переконатися, що програми у блокчейні точно відображають їхній публічний вихідний код. -- **Пошук перевірених програм**: Для швидкої перевірки програм користувачі можуть - знайти адресу програми у [SolanaFM](https://solana.fm/) Explorer і перейти на - вкладку "Verification". Приклад перевіреної програми можна побачити +- **Пошук перевірених програм**: Для швидкої перевірки програм користувачі + можуть знайти адресу програми у [SolanaFM](https://solana.fm/) Explorer і + перейти на вкладку "Verification". Приклад перевіреної програми можна побачити [тут](https://solana.fm/address/PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY). -- **Інструменти перевірки**: CLI - [Solana Verifiable Build](https://github.com/Ellipsis-Labs/solana-verifiable-build) - від Ellipsis Labs дозволяє незалежно перевірити програми у блокчейні на відповідність - опублікованому вихідному коду. +- **Інструменти перевірки**: CLI + [Solana Verifiable Build](https://github.com/Ellipsis-Labs/solana-verifiable-build) + від Ellipsis Labs дозволяє незалежно перевірити програми у блокчейні на + відповідність опублікованому вихідному коду. -- **Підтримка перевірюваних збірок в Anchor**: Anchor має вбудовану підтримку - перевірюваних збірок. Деталі можна знайти у +- **Підтримка перевірюваних збірок в Anchor**: Anchor має вбудовану підтримку + перевірюваних збірок. Деталі можна знайти у [документації Anchor](https://www.anchor-lang.com/docs/verifiable-builds). ## Berkeley Packet Filter (BPF) -Solana використовує [інфраструктуру компілятора LLVM](https://llvm.org/) для -компіляції програм у файли формату -[Executable and Linkable Format (ELF)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format). -Ці файли включають модифіковану версію байт-коду -[Berkeley Packet Filter (eBPF)](https://en.wikipedia.org/wiki/EBPF) для програм Solana, -відомого як "Solana Bytecode Format" (sBPF). +Solana використовує [інфраструктуру компілятора LLVM](https://llvm.org/) для +компіляції програм у файли формату +[Executable and Linkable Format (ELF)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format). +Ці файли включають модифіковану версію байт-коду +[Berkeley Packet Filter (eBPF)](https://en.wikipedia.org/wiki/EBPF) для програм +Solana, відомого як "Solana Bytecode Format" (sBPF). -Використання LLVM дозволяє Solana підтримувати будь-яку мову програмування, яка -може компілюватися у BPF-бекенд LLVM. Це значно підвищує гнучкість Solana як платформи -для розробки. +Використання LLVM дозволяє Solana підтримувати будь-яку мову програмування, яка +може компілюватися у BPF-бекенд LLVM. Це значно підвищує гнучкість Solana як +платформи для розробки. diff --git a/docs/locales/uk/core/tokens.md b/docs/locales/uk/core/tokens.md index 62700b186..c9cd3812a 100644 --- a/docs/locales/uk/core/tokens.md +++ b/docs/locales/uk/core/tokens.md @@ -3,9 +3,9 @@ title: "Токени на Solana" sidebarSortOrder: 7 description: Дізнайтеся про токени Solana (SPL Tokens), включаючи взаємозамінні та - невзаємозамінні токени, Програму Токенів, Програму Розширень Токенів, - облікові записи випуску токенів, токен-облікові записи, а також практичні - приклади створення і управління токенами на Solana. + невзаємозамінні токени, Програму Токенів, Програму Розширень Токенів, облікові + записи випуску токенів, токен-облікові записи, а також практичні приклади + створення і управління токенами на Solana. --- Токени — це цифрові активи, які представляють право власності на різні категорії @@ -19,11 +19,11 @@ description: активи (наприклад, витвори мистецтва). У цьому розділі буде розглянуто основи представлення токенів у Solana. Ці токени -називаються SPL +називаються SPL ([Solana Program Library](https://github.com/solana-labs/solana-program-library)). -- [Програма Токенів](#token-program) містить всю логіку інструкцій для - взаємодії з токенами в мережі (як взаємозамінними, так і невзаємозамінними). +- [Програма Токенів](#token-program) містить всю логіку інструкцій для взаємодії + з токенами в мережі (як взаємозамінними, так і невзаємозамінними). - [Обліковий запис випуску токенів](#mint-account) представляє певний тип токена і зберігає глобальні метадані, такі як загальна кількість токенів і авторитет @@ -32,10 +32,10 @@ description: - [Токен-обліковий запис](#token-account) відстежує індивідуальну власність на певну кількість токенів конкретного типу (облікового запису випуску токенів). -> Наразі існує дві версії Програми Токенів: оригінальна +> Наразі існує дві версії Програми Токенів: оригінальна > [Програма Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) -> і -> [Програма Розширень Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program-2022) +> і +> [Програма Розширень Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program-2022) > (Token2022). Програма Розширень Токенів працює так само, як і оригінальна > Програма Токенів, але з додатковими функціями і покращеннями. Для створення > нових токенів рекомендовано використовувати Програму Розширень Токенів. @@ -57,16 +57,18 @@ description: облікового запису випуску токенів. - Асоційований Токен-обліковий запис — це токен-обліковий запис, створений із - адреси, отриманої із адреси власника та адреси облікового запису випуску токенів. + адреси, отриманої із адреси власника та адреси облікового запису випуску + токенів. ## Програма Токенів -[Програма Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) +[Програма Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) містить всю логіку інструкцій для взаємодії з токенами в мережі (як -взаємозамінними, так і невзаємозамінними). Усі токени на Solana фактично є -[даними облікових записів](/docs/uk/core/accounts.md#data-account), якими володіє Програма Токенів. +взаємозамінними, так і невзаємозамінними). Усі токени на Solana фактично є +[даними облікових записів](/docs/uk/core/accounts.md#data-account), якими +володіє Програма Токенів. -Повний список інструкцій Програми Токенів можна знайти +Повний список інструкцій Програми Токенів можна знайти [тут](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/instruction.rs). ![Програма Токенів](/assets/docs/core/tokens/token-program.svg) @@ -74,33 +76,37 @@ description: Кілька найчастіше використовуваних інструкцій включають: - [`InitializeMint`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L29): - Створення нового облікового запису випуску токенів для представлення нового типу токена. + Створення нового облікового запису випуску токенів для представлення нового + типу токена. - [`InitializeAccount`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L84): - Створення нового токен-облікового запису для зберігання одиниць певного типу токенів (випуску). + Створення нового токен-облікового запису для зберігання одиниць певного типу + токенів (випуску). - [`MintTo`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L522): - Створення нових одиниць певного типу токенів і додавання їх до токен-облікового запису. - Це збільшує кількість токенів і може виконуватися лише авторитетом випуску - облікового запису випуску токенів. + Створення нових одиниць певного типу токенів і додавання їх до + токен-облікового запису. Це збільшує кількість токенів і може виконуватися + лише авторитетом випуску облікового запису випуску токенів. - [`Transfer`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L228): - Передача одиниць певного типу токенів із одного токен-облікового запису в інший. + Передача одиниць певного типу токенів із одного токен-облікового запису в + інший. ### Обліковий запис випуску токенів -Токени на Solana унікально ідентифікуються за адресою -[Облікового запису випуску токенів](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32), -яким володіє Програма Токенів. Цей обліковий запис фактично є глобальним лічильником -для певного токена і зберігає дані, такі як: +Токени на Solana унікально ідентифікуються за адресою +[Облікового запису випуску токенів](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32), +яким володіє Програма Токенів. Цей обліковий запис фактично є глобальним +лічильником для певного токена і зберігає дані, такі як: - Загальна кількість: Загальна кількість токенів. - Десяткові знаки: Точність токена у десяткових знаках. - Авторитет випуску: Обліковий запис, уповноважений створювати нові одиниці токенів, таким чином збільшуючи кількість. -- Авторитет замороження: Обліковий запис, уповноважений заморожувати токени, - щоб їх не можна було передати із "токен-облікових записів". +- Авторитет замороження: Обліковий запис, уповноважений заморожувати токени, щоб + їх не можна було передати із "токен-облікових записів". ![Обліковий запис випуску токенів](/assets/docs/core/tokens/mint-account.svg) -Повна інформація, яка зберігається в кожному обліковому записі випуску токенів, включає: +Повна інформація, яка зберігається в кожному обліковому записі випуску токенів, +включає: ```rust pub struct Mint { @@ -119,21 +125,26 @@ pub struct Mint { pub freeze_authority: COption, } ``` -Для довідки, ось посилання на Solana Explorer для + +Для довідки, ось посилання на Solana Explorer для [Облікового запису випуску USDC](https://explorer.solana.com/address/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v). ### Токен-обліковий запис -Для відстеження індивідуальної власності на кожну одиницю певного токена має бути -створений інший тип облікового запису даних, яким володіє Програма Токенів. Цей -обліковий запис називається +Для відстеження індивідуальної власності на кожну одиницю певного токена має +бути створений інший тип облікового запису даних, яким володіє Програма Токенів. +Цей обліковий запис називається [Токен-обліковий запис](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L89-L110). -Найчастіше згадувані дані, які зберігаються в Токен-обліковому записі, включають: +Найчастіше згадувані дані, які зберігаються в Токен-обліковому записі, +включають: -- **Випуск (Mint)**: Тип токена, одиниці якого зберігаються в Токен-обліковому записі. -- **Власник (Owner)**: Обліковий запис, уповноважений передавати токени з Токен-облікового запису. -- **Кількість (Amount)**: Кількість одиниць токена, які наразі зберігаються в Токен-обліковому записі. +- **Випуск (Mint)**: Тип токена, одиниці якого зберігаються в Токен-обліковому + записі. +- **Власник (Owner)**: Обліковий запис, уповноважений передавати токени з + Токен-облікового запису. +- **Кількість (Amount)**: Кількість одиниць токена, які наразі зберігаються в + Токен-обліковому записі. ![Токен-обліковий запис](/assets/docs/core/tokens/token-account.svg) @@ -163,19 +174,21 @@ pub struct Account { pub close_authority: COption, } ``` -Щоб гаманець міг володіти одиницями певного токена, потрібно створити токен-обліковий -запис для конкретного типу токена (випуску), який призначає гаманець власником -цього токен-облікового запису. Гаманець може створювати кілька токен-облікових -записів для одного і того ж типу токена, але кожен токен-обліковий запис може -належати лише одному гаманцю і зберігати одиниці лише одного типу токена. + +Щоб гаманець міг володіти одиницями певного токена, потрібно створити +токен-обліковий запис для конкретного типу токена (випуску), який призначає +гаманець власником цього токен-облікового запису. Гаманець може створювати +кілька токен-облікових записів для одного і того ж типу токена, але кожен +токен-обліковий запис може належати лише одному гаманцю і зберігати одиниці лише +одного типу токена. ![Взаємозв'язок облікових записів](/assets/docs/core/tokens/token-account-relationship.svg) -> Зверніть увагу, що дані кожного Токен-облікового запису містять поле `owner`, яке -> використовується для визначення того, хто має авторитет над цим Токен-обліковим записом. -> Це окремо від власника програми, зазначеного у -> [AccountInfo](/docs/uk/core/accounts.md#accountinfo), яким є Програма Токенів для всіх -> Токен-облікових записів. +> Зверніть увагу, що дані кожного Токен-облікового запису містять поле `owner`, +> яке використовується для визначення того, хто має авторитет над цим +> Токен-обліковим записом. Це окремо від власника програми, зазначеного у +> [AccountInfo](/docs/uk/core/accounts.md#accountinfo), яким є Програма Токенів +> для всіх Токен-облікових записів. ### Асоційований токен-обліковий запис @@ -195,11 +208,13 @@ pub struct Account { Це вводить ключове поняття в розробці Solana: [Програмно Виведена Адреса (PDA)](/docs/uk/core/pda.md). Концептуально PDA надає детермінований спосіб генерації адреси з використанням заздалегідь визначених -вхідних даних. Це дозволяє нам легко знайти адресу облікового запису в майбутньому. +вхідних даних. Це дозволяє нам легко знайти адресу облікового запису в +майбутньому. -Ось [приклад на Solana Playground](https://beta.solpg.io/656a2dd0fb53fa325bfd0c41), +Ось +[приклад на Solana Playground](https://beta.solpg.io/656a2dd0fb53fa325bfd0c41), який виводить адресу і власника Асоційованого токен-облікового запису USDC. Він -завжди генерує +завжди генерує [одну й ту саму адресу](https://explorer.solana.com/address/4kokFKCFMxpCpG41yLYkLEqXW8g1WPfCt2NC9KGivY6N) для одного і того ж випуску і власника. @@ -211,9 +226,10 @@ const associatedTokenAccountAddress = getAssociatedTokenAddressSync( OWNER_ADDRESS, ); ``` -Зокрема, адреса для Асоційованого токен-облікового запису виводиться за допомогою -наступних вхідних даних. Ось -[приклад на Solana Playground](https://beta.solpg.io/656a31d0fb53fa325bfd0c42), + +Зокрема, адреса для Асоційованого токен-облікового запису виводиться за +допомогою наступних вхідних даних. Ось +[приклад на Solana Playground](https://beta.solpg.io/656a31d0fb53fa325bfd0c42), який генерує ту саму адресу, що й у попередньому прикладі. ```ts @@ -228,25 +244,26 @@ const [PDA, bump] = PublicKey.findProgramAddressSync( ASSOCIATED_TOKEN_PROGRAM_ID, ); ``` + Щоб два гаманці могли зберігати одиниці одного і того ж типу токена, кожен -гаманець потребує свого токен-облікового запису для конкретного облікового запису -випуску токенів. Зображення нижче демонструє, як виглядає ця структура взаємозв'язку облікових записів. +гаманець потребує свого токен-облікового запису для конкретного облікового +запису випуску токенів. Зображення нижче демонструє, як виглядає ця структура +взаємозв'язку облікових записів. ![Розширений взаємозв'язок облікових записів](/assets/docs/core/tokens/token-account-relationship-ata.svg) ## Приклади роботи з токенами -CLI [`spl-token`](https://docs.anza.xyz/cli) можна використовувати для експериментів -з SPL токенами. У прикладах нижче ми використовуватимемо -[Solana Playground](https://beta.solpg.io/) для виконання CLI-команд прямо в +CLI [`spl-token`](https://docs.anza.xyz/cli) можна використовувати для +експериментів з SPL токенами. У прикладах нижче ми використовуватимемо +[Solana Playground](https://beta.solpg.io/) для виконання CLI-команд прямо в браузері без необхідності встановлення CLI локально. -Створення токенів і облікових записів вимагає SOL для депозитів за оренду -облікових записів та оплати транзакційних комісій. Якщо ви вперше використовуєте -Solana Playground, створіть гаманець у Playground і виконайте команду -`solana airdrop` у терміналі Playground. Ви також можете отримати SOL для -devnet, використовуючи публічний -[веб-фасет](https://faucet.solana.com/). +Створення токенів і облікових записів вимагає SOL для депозитів за оренду +облікових записів та оплати транзакційних комісій. Якщо ви вперше використовуєте +Solana Playground, створіть гаманець у Playground і виконайте команду +`solana airdrop` у терміналі Playground. Ви також можете отримати SOL для +devnet, використовуючи публічний [веб-фасет](https://faucet.solana.com/). ```sh solana airdrop 2 @@ -257,28 +274,29 @@ Run `spl-token --help` for a full description of available commands. ```sh spl-token --help ``` -Крім того, ви можете встановити CLI `spl-token` локально, використовуючи наступну -команду. Для цього спочатку потрібно + +Крім того, ви можете встановити CLI `spl-token` локально, використовуючи +наступну команду. Для цього спочатку потрібно [встановити Rust](https://rustup.rs/). > У наступних розділах адреси облікових записів, які відображаються під час -> виконання CLI-команд, можуть відрізнятися від прикладів, наведених нижче. Будь ласка, -> використовуйте адреси, які відображаються у вашому терміналі Playground, під час -> виконання команд. Наприклад, адреса, отримана в результаті виконання `create-token`, -> є обліковим записом випуску токенів, де ваш гаманець Playground призначений -> авторитетом випуску. +> виконання CLI-команд, можуть відрізнятися від прикладів, наведених нижче. Будь +> ласка, використовуйте адреси, які відображаються у вашому терміналі +> Playground, під час виконання команд. Наприклад, адреса, отримана в результаті +> виконання `create-token`, є обліковим записом випуску токенів, де ваш гаманець +> Playground призначений авторитетом випуску. ### Створення нового токена -Щоб створити новий токен -([обліковий запис випуску токенів](#mint-account)), виконайте наступну команду -в терміналі Solana Playground. +Щоб створити новий токен ([обліковий запис випуску токенів](#mint-account)), +виконайте наступну команду в терміналі Solana Playground. ```sh spl-token create-token ``` -Ви повинні побачити результат, подібний до наведеного нижче. Ви можете переглянути -деталі як токена, так і транзакції у + +Ви повинні побачити результат, подібний до наведеного нижче. Ви можете +переглянути деталі як токена, так і транзакції у [Solana Explorer](https://explorer.solana.com/?cluster=devnet), використовуючи `Address` (адресу) та `Signature` (підпис). @@ -293,19 +311,22 @@ Decimals: 9 Signature: 44fvKfT1ezBUwdzrCys3fvCdFxbLMnNvBstds76QZyE6cXag5NupBprSXwxPTzzjrC3cA6nvUZaLFTvmcKyzxrm1 ``` + Нові токени спочатку мають нульовий запас. Ви можете перевірити поточний запас токена, використовуючи наступну команду: ```sh spl-token supply ``` + Запуск команди `supply` для новоствореного токена поверне значення `0`: ```sh /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ spl-token supply 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg ``` + У своїй основі створення нового облікового запису випуску токенів (Mint Account) -вимагає надсилання транзакції з двома інструкціями. Ось приклад на Javascript у +вимагає надсилання транзакції з двома інструкціями. Ось приклад на Javascript у [Solana Playground](https://beta.solpg.io/660ce32ecffcf4b13384d00f). 1. Виклик Системної Програми для створення нового облікового запису з достатнім @@ -317,28 +338,30 @@ spl-token supply 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg ### Створення Токен-облікового запису -Щоб зберігати одиниці певного токена, вам потрібно спочатку створити +Щоб зберігати одиниці певного токена, вам потрібно спочатку створити [токен-обліковий запис](#token-account). Для створення нового токен-облікового запису скористайтеся наступною командою: ```sh spl-token create-account [OPTIONS] ``` + Наприклад, виконання наступної команди в терміналі Solana Playground: -```sh /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ +````sh /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ spl-token create-account 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg ```: Виведе наступний результат -- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9`це адреса токен-облікового запису, створеного для зберігання одиниць токена, +- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9`це адреса токен-облікового запису, створеного для зберігання одиниць токена, вказаного в команді `create-account`. ```shell filename="Terminal Output" /AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9/ Creating account AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9 Signature: 2BtrynuCLX9CNofFiaw6Yzbx6hit66pup9Sk7aFjwU2NEbFz7NCHD9w9sWhrCfEd73XveAGK1DxFpJoQZPXU9tS1 -``` -За замовчуванням команда `create-account` створює +```` + +За замовчуванням команда `create-account` створює [асоційований токен-обліковий запис](#associated-token-account) з адресою вашого гаманця як власника токен-облікового запису. @@ -348,33 +371,37 @@ Signature: 2BtrynuCLX9CNofFiaw6Yzbx6hit66pup9Sk7aFjwU2NEbFz7NCHD9w9sWhrCfEd73Xve ```sh spl-token create-account --owner ``` -Наприклад, виконання наступної команди: + +Наприклад, виконання наступної команди: + ```sh /2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR/ spl-token create-account --owner 2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg ``` Виведе наступний результат: -- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` — це адреса токен-облікового запису, - створеного для зберігання одиниць токена, вказаного в команді `create-account` - (`99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg`), і який належить адресі, - вказаній після прапора `--owner` - (`2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR`). Це корисно, коли вам потрібно - створити токен-обліковий запис для іншого користувача. +- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` — це адреса токен-облікового + запису, створеного для зберігання одиниць токена, вказаного в команді + `create-account` (`99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg`), і який + належить адресі, вказаній після прапора `--owner` + (`2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR`). Це корисно, коли вам + потрібно створити токен-обліковий запис для іншого користувача. ```shell filename="Terminal Output" /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ Creating account Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt Signature: 44vqKdfzspT592REDPY4goaRJH3uJ3Ce13G4BCuUHg35dVUbHuGTHvqn4ZjYF9BGe9QrjMfe9GmuLkQhSZCBQuEt ``` + За лаштунками створення Асоційованого токен-облікового запису потребує однієї інструкції, яка викликає [Програму Асоційованих Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src). -Ось приклад на Javascript у +Ось приклад на Javascript у [Solana Playground](https://beta.solpg.io/660ce868cffcf4b13384d011). -Програма Асоційованих Токенів використовує -[Перехресні Виклики Програм (CPI)](/docs/uk/core/cpi.md) для виконання наступного: +Програма Асоційованих Токенів використовує +[Перехресні Виклики Програм (CPI)](/docs/uk/core/cpi.md) для виконання +наступного: - [Виклик Системної Програми](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src/tools/account.rs#L19) для створення нового облікового запису, використовуючи надану PDA як адресу @@ -402,18 +429,21 @@ Signature: 44vqKdfzspT592REDPY4goaRJH3uJ3Ce13G4BCuUHg35dVUbHuGTHvqn4ZjYF9BGe9Qrj spl-token mint [OPTIONS] [--] [RECIPIENT_TOKEN_ACCOUNT_ADDRESS] ``` -Наприклад, виконання наступної команди: +Наприклад, виконання наступної команди: ```sh spl-token mint 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 ``` Виведе наступний результат: -- `99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg` — це адреса облікового запису - випуску токенів, для якого випускаються токени (збільшуючи загальну кількість). -- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` — це адреса токен-облікового запису - вашого гаманця, до якого випускаються одиниці токена (збільшуючи кількість). +- `99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg` — це адреса облікового запису + випуску токенів, для якого випускаються токени (збільшуючи загальну + кількість). + +- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` — це адреса токен-облікового + запису вашого гаманця, до якого випускаються одиниці токена (збільшуючи + кількість). ```shell filename="Terminal Output" /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ /AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9/ Minting 100 tokens @@ -422,19 +452,24 @@ Minting 100 tokens Signature: 2NJ1m7qCraPSBAVxbr2ssmWZmBU9Jc8pDtJAnyZsZJRcaYCYMqq1oRY1gqA4ddQno3g3xcnny5fzr1dvsnFKMEqG ``` -Щоб випустити токени до іншого токен-облікового запису, вкажіть адресу -потрібного облікового запису одержувача токенів. + +Щоб випустити токени до іншого токен-облікового запису, вкажіть адресу +потрібного облікового запису одержувача токенів. Наприклад, виконання наступної команди: ```sh /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ spl-token mint 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 -- Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt ``` + Повертає наступний результат: - - 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg — це адреса облікового запису випуску токенів, для якого випускаються токени (збільшуючи загальну кількість). +- 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg — це адреса облікового запису + випуску токенів, для якого випускаються токени (збільшуючи загальну + кількість). - - Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt — це адреса токен-облікового запису, до якого випускаються одиниці токена (збільшуючи кількість). +- Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt — це адреса токен-облікового + запису, до якого випускаються одиниці токена (збільшуючи кількість). ```shell filename="Terminal Output" /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ Minting 100 tokens @@ -443,10 +478,12 @@ Minting 100 tokens Signature: 3SQvNM3o9DsTiLwcEkSPT1Edr14RgE2wC54TEjonEP2swyVCp2jPWYWdD6RwXUGpvDNUkKWzVBZVFShn5yntxVd7 ``` -За лаштунками створення нових одиниць токена потребує виклику інструкції `MintTo` -у Програмі Токенів. Ця інструкція повинна бути підписана авторитетом випуску. -Інструкція випускає нові одиниці токена до Токен-облікового запису та збільшує -загальну кількість у Обліковому записі випуску токенів. Ось приклад на Javascript у + +За лаштунками створення нових одиниць токена потребує виклику інструкції +`MintTo` у Програмі Токенів. Ця інструкція повинна бути підписана авторитетом +випуску. Інструкція випускає нові одиниці токена до Токен-облікового запису та +збільшує загальну кількість у Обліковому записі випуску токенів. Ось приклад на +Javascript у [Solana Playground](https://beta.solpg.io/660cea45cffcf4b13384d012). ### Передача токенів @@ -458,17 +495,21 @@ Signature: 3SQvNM3o9DsTiLwcEkSPT1Edr14RgE2wC54TEjonEP2swyVCp2jPWYWdD6RwXUGpvDNUk spl-token transfer [OPTIONS] ``` + Наприклад, виконання наступної команди: + ```sh spl-token transfer 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt ``` + Повертає наступний результат: -- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` — це адреса токен-облікового запису, - з якого передаються токени. Це буде адреса вашого токен-облікового запису для - вказаного токена, який передається. -- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` — це адреса токен-облікового запису, - до якого передаються токени. +- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` — це адреса токен-облікового + запису, з якого передаються токени. Це буде адреса вашого токен-облікового + запису для вказаного токена, який передається. + +- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` — це адреса токен-облікового + запису, до якого передаються токени. ```shell filename="Terminal Output" /AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9/ /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ Transfer 100 tokens @@ -477,21 +518,23 @@ Transfer 100 tokens Signature: 5y6HVwV8V2hHGLTVmTmdySRiEUCZnWmkasAvJ7J6m7JR46obbGKCBqUFgLpZu5zQGwM4Xy6GZ4M5LKd1h6Padx3o ``` -За лаштунками, передача токенів потребує виклику інструкції `Transfer` у Програмі Токенів. -Ця інструкція повинна бути підписана власником токен-облікового запису відправника. -Інструкція передає одиниці токена з одного Токен-облікового запису до іншого. -Ось приклад на Javascript у + +За лаштунками, передача токенів потребує виклику інструкції `Transfer` у +Програмі Токенів. Ця інструкція повинна бути підписана власником +токен-облікового запису відправника. Інструкція передає одиниці токена з одного +Токен-облікового запису до іншого. Ось приклад на Javascript у [Solana Playground](https://beta.solpg.io/660ced84cffcf4b13384d013). -Важливо розуміти, що як у відправника, так і у одержувача повинні існувати токен-облікові -записи для конкретного типу токена, який передається. Відправник може додати додаткові -інструкції до транзакції для створення токен-облікового запису одержувача, який, як правило, -є Асоційованим Токен-обліковим записом. +Важливо розуміти, що як у відправника, так і у одержувача повинні існувати +токен-облікові записи для конкретного типу токена, який передається. Відправник +може додати додаткові інструкції до транзакції для створення токен-облікового +запису одержувача, який, як правило, є Асоційованим Токен-обліковим записом. ### Створення метаданих токенів -Програма Розширень Токенів дозволяє додавати настроювані метадані (наприклад, назву, -символ, посилання на зображення) безпосередньо до Облікового запису випуску токенів. +Програма Розширень Токенів дозволяє додавати настроювані метадані (наприклад, +назву, символ, посилання на зображення) безпосередньо до Облікового запису +випуску токенів. Щоб використовувати параметри CLI для розширень токенів, переконайтеся, що ви маєте @@ -500,15 +543,17 @@ Signature: 5y6HVwV8V2hHGLTVmTmdySRiEUCZnWmkasAvJ7J6m7JR46obbGKCBqUFgLpZu5zQGwM4X `cargo install --version 3.4.0 spl-token-cli` -Щоб створити новий токен із увімкненим розширенням метаданих, скористайтеся наступною командою: +Щоб створити новий токен із увімкненим розширенням метаданих, скористайтеся +наступною командою: ```sh spl-token create-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb --enable-metadata ``` + Команда повертає наступний результат: -- `BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP` — це адреса нового токена, +- `BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP` — це адреса нового токена, створеного з увімкненим розширенням метаданих. ```shell filename="Terminal Output" /BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP/ @@ -520,7 +565,8 @@ Decimals: 9 Signature: 5iQofFeXdYhMi9uTzZghcq8stAaa6CY6saUwcdnELST13eNSifiuLbvR5DnRt311frkCTUh5oecj8YEvZSB3wfai ``` -Після створення нового токена з увімкненим розширенням метаданих використовуйте + +Після створення нового токена з увімкненим розширенням метаданих використовуйте наступну команду для ініціалізації метаданих: ```sh @@ -528,24 +574,24 @@ spl-token initialize-metadata ``` -Токен URI зазвичай є посиланням на позаблокові метадані, які ви хочете -асоціювати з токеном. Приклад формату JSON можна знайти +Токен URI зазвичай є посиланням на позаблокові метадані, які ви хочете +асоціювати з токеном. Приклад формату JSON можна знайти [тут](https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json). -Наприклад, виконання наступної команди дозволить зберегти додаткові метадані +Наприклад, виконання наступної команди дозволить зберегти додаткові метадані безпосередньо в зазначеному обліковому записі випуску токенів: ```sh /BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP/ spl-token initialize-metadata BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP "TokenName" "TokenSymbol" "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json" ``` -Ви можете знайти адресу облікового запису випуску токенів у експлорері, щоб -переглянути метадані. Наприклад, ось токен, створений із увімкненим розширенням -метаданих, у експлорері +Ви можете знайти адресу облікового запису випуску токенів у експлорері, щоб +переглянути метадані. Наприклад, ось токен, створений із увімкненим розширенням +метаданих, у експлорері [SolanaFm](https://solana.fm/address/BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP?cluster=devnet-solana). -Дізнатися більше можна у -[Посібнику з Розширення Метаданих](https://solana.com/developers/guides/token-extensions/metadata-pointer). -Деталі щодо різних Розширень Токенів ви знайдете у -[Посібнику Початківця з Розширень Токенів](https://solana.com/developers/guides/token-extensions/getting-started) +Дізнатися більше можна у +[Посібнику з Розширення Метаданих](https://solana.com/developers/guides/token-extensions/metadata-pointer). +Деталі щодо різних Розширень Токенів ви знайдете у +[Посібнику Початківця з Розширень Токенів](https://solana.com/developers/guides/token-extensions/getting-started) та [документації SPL](https://spl.solana.com/token-2022/extensions). diff --git a/docs/locales/uk/core/transactions.md b/docs/locales/uk/core/transactions.md index 610c168fd..400dfe83b 100644 --- a/docs/locales/uk/core/transactions.md +++ b/docs/locales/uk/core/transactions.md @@ -10,9 +10,9 @@ description: У Solana ми надсилаємо [транзакції](/docs/uk/core/transactions#transaction), щоб взаємодіяти з мережею. Транзакції включають одну або більше [інструкцій](/docs/uk/core/transactions#instruction), кожна з яких представляє -конкретну операцію, що має бути оброблена. Логіка виконання інструкцій зберігається -в [програмах](/docs/uk/core/programs), розгорнутих у мережі Solana, і кожна програма -зберігає свій набір інструкцій. +конкретну операцію, що має бути оброблена. Логіка виконання інструкцій +зберігається в [програмах](/docs/uk/core/programs), розгорнутих у мережі Solana, +і кожна програма зберігає свій набір інструкцій. Нижче наведено основні деталі щодо виконання транзакцій: @@ -75,8 +75,9 @@ description: ### Простий переказ SOL -Ось приклад із [Solana Playground](https://beta.solpg.io/656a0ea7fb53fa325bfd0c3e), -який демонструє, як створити інструкцію переказу SOL за допомогою методу +Ось приклад із +[Solana Playground](https://beta.solpg.io/656a0ea7fb53fa325bfd0c3e), який +демонструє, як створити інструкцію переказу SOL за допомогою методу `SystemProgram.transfer`: ```typescript @@ -93,11 +94,13 @@ const transferInstruction = SystemProgram.transfer({ // Додавання інструкції переказу до нової транзакції const transaction = new Transaction().add(transferInstruction); ``` -Запустіть скрипт і перевірте деталі транзакції, що виводяться в консоль. У наступних розділах ми розглянемо, що відбувається "під капотом". + +Запустіть скрипт і перевірте деталі транзакції, що виводяться в консоль. У +наступних розділах ми розглянемо, що відбувається "під капотом". ## Транзакція -Транзакція Solana +Транзакція Solana [transaction](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/transaction/mod.rs#L173) складається з: @@ -110,30 +113,43 @@ const transaction = new Transaction().add(transferInstruction); Структура повідомлення транзакції складається з: -- [Заголовка повідомлення](/docs/uk/core/transactions#message-header): Вказує кількість підписантів та облікових записів тільки для читання. -- [Масиву адрес облікових записів](/docs/uk/core/transactions#array-of-account-addresses): Масив адрес облікових записів, необхідних для інструкцій у транзакції. -- [Недавнього блоку хешу](/docs/uk/core/transactions#recent-blockhash): Використовується як мітка часу для транзакції. -- [Масиву інструкцій](/docs/uk/core/transactions#array-of-instructions): Масив інструкцій, які слід виконати. +- [Заголовка повідомлення](/docs/uk/core/transactions#message-header): Вказує + кількість підписантів та облікових записів тільки для читання. +- [Масиву адрес облікових записів](/docs/uk/core/transactions#array-of-account-addresses): + Масив адрес облікових записів, необхідних для інструкцій у транзакції. +- [Недавнього блоку хешу](/docs/uk/core/transactions#recent-blockhash): + Використовується як мітка часу для транзакції. +- [Масиву інструкцій](/docs/uk/core/transactions#array-of-instructions): Масив + інструкцій, які слід виконати. ![Повідомлення транзакції](/assets/docs/core/transactions/legacy_message.png) ### Розмір транзакції -Мережа Solana дотримується максимального розміру пакета (MTU) у 1280 байт, що відповідає -[MTU IPv6](https://en.wikipedia.org/wiki/IPv6_packet). Це забезпечує швидку та надійну передачу інформації у кластері через UDP. Після врахування необхідних заголовків (40 байт для IPv6 та 8 байт для заголовка фрагмента), -[1232 байти залишаються для даних пакета](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/packet.rs#L16-L21), таких як серіалізовані транзакції. +Мережа Solana дотримується максимального розміру пакета (MTU) у 1280 байт, що +відповідає [MTU IPv6](https://en.wikipedia.org/wiki/IPv6_packet). Це забезпечує +швидку та надійну передачу інформації у кластері через UDP. Після врахування +необхідних заголовків (40 байт для IPv6 та 8 байт для заголовка фрагмента), +[1232 байти залишаються для даних пакета](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/packet.rs#L16-L21), +таких як серіалізовані транзакції. -Це означає, що загальний розмір транзакції Solana обмежений 1232 байтами. Підписи та повідомлення у комбінації не можуть перевищувати цей ліміт. +Це означає, що загальний розмір транзакції Solana обмежений 1232 байтами. +Підписи та повідомлення у комбінації не можуть перевищувати цей ліміт. -- Підписи: Кожен підпис займає 64 байти. Кількість підписів може варіювати залежно від вимог транзакції. -- Повідомлення: Повідомлення включає інструкції, облікові записи та додаткові метадані. Кожен обліковий запис займає 32 байти. Загальний розмір облікових записів плюс метадані може варіювати залежно від інструкцій у транзакції. +- Підписи: Кожен підпис займає 64 байти. Кількість підписів може варіювати + залежно від вимог транзакції. +- Повідомлення: Повідомлення включає інструкції, облікові записи та додаткові + метадані. Кожен обліковий запис займає 32 байти. Загальний розмір облікових + записів плюс метадані може варіювати залежно від інструкцій у транзакції. ![Формат транзакції](/assets/docs/core/transactions/issues_with_legacy_txs.png) ### Заголовок повідомлення [Заголовок повідомлення](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/mod.rs#L96) -вказує на привілеї облікових записів, включених у масив адрес транзакції. Він складається з трьох байтів, кожен з яких містить ціле число типу u8, що колективно вказує: +вказує на привілеї облікових записів, включених у масив адрес транзакції. Він +складається з трьох байтів, кожен з яких містить ціле число типу u8, що +колективно вказує: 1. Кількість необхідних підписів для транзакції. 2. Кількість облікових записів тільки для читання, які потребують підписів. @@ -143,7 +159,8 @@ const transaction = new Transaction().add(transferInstruction); ### Формат компактного масиву -Компактний масив у контексті повідомлення транзакції посилається на масив, серіалізований у наступному форматі: +Компактний масив у контексті повідомлення транзакції посилається на масив, +серіалізований у наступному форматі: 1. Довжина масиву, закодована як [compact-u16](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/short_vec.rs). @@ -151,18 +168,22 @@ const transaction = new Transaction().add(transferInstruction); ![Формат компактного масиву](/assets/docs/core/transactions/compact_array_format.png) -Цей метод кодування використовується для вказівки довжин як -[масиву адрес облікових записів](/docs/uk/core/transactions#array-of-account-addresses), так і -[масиву інструкцій](/docs/uk/core/transactions#array-of-instructions) у повідомленні транзакції. +Цей метод кодування використовується для вказівки довжин як +[масиву адрес облікових записів](/docs/uk/core/transactions#array-of-account-addresses), +так і [масиву інструкцій](/docs/uk/core/transactions#array-of-instructions) у +повідомленні транзакції. ### Масив адрес облікових записів -Повідомлення транзакції включає масив, що містить усі +Повідомлення транзакції включає масив, що містить усі [адреси облікових записів](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L119), необхідні для інструкцій у транзакції. -Цей масив починається з кодування -[compact-u16](/docs/uk/core/transactions#compact-array-format) довжини масиву, після чого йдуть адреси, впорядковані за привілеями облікових записів. Метадані в заголовку повідомлення використовуються для визначення кількості облікових записів у кожному розділі. +Цей масив починається з кодування +[compact-u16](/docs/uk/core/transactions#compact-array-format) довжини масиву, +після чого йдуть адреси, впорядковані за привілеями облікових записів. Метадані +в заголовку повідомлення використовуються для визначення кількості облікових +записів у кожному розділі. - Облікові записи, що є змінюваними та підписантами. - Облікові записи тільки для читання, що є підписантами. @@ -173,42 +194,66 @@ const transaction = new Transaction().add(transferInstruction); ### Недавній блок-хеш -Усі транзакції включають +Усі транзакції включають [недавній блок-хеш](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L122), -який використовується як мітка часу для транзакції. Блок-хеш запобігає дублюванню транзакцій і виключає застарілі транзакції. - -Максимальний вік блок-хеша для транзакції становить 150 блоків (~1 хвилина, якщо час блоку складає 400 мс). Якщо блок-хеш транзакції старіший за 150 блоків від останнього блок-хеша, вона вважається протермінованою. Це означає, що транзакції, які не були оброблені вчасно, ніколи не будуть виконані. - -Ви можете скористатися RPC-методом -[`getLatestBlockhash`](/docs/uk/rpc/http/getlatestblockhash), -щоб отримати поточний блок-хеш і останню висоту блоку, на якій блок-хеш залишатиметься дійсним. Ось приклад у +який використовується як мітка часу для транзакції. Блок-хеш запобігає +дублюванню транзакцій і виключає застарілі транзакції. + +Максимальний вік блок-хеша для транзакції становить 150 блоків (~1 хвилина, якщо +час блоку складає 400 мс). Якщо блок-хеш транзакції старіший за 150 блоків від +останнього блок-хеша, вона вважається протермінованою. Це означає, що +транзакції, які не були оброблені вчасно, ніколи не будуть виконані. + +Ви можете скористатися RPC-методом +[`getLatestBlockhash`](/docs/uk/rpc/http/getlatestblockhash), щоб отримати +поточний блок-хеш і останню висоту блоку, на якій блок-хеш залишатиметься +дійсним. Ось приклад у [Solana Playground](https://beta.solpg.io/661a06e1cffcf4b13384d046). + ### Масив інструкцій -Повідомлення транзакції включає масив усіх +Повідомлення транзакції включає масив усіх [інструкцій](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L128), які запитуються для обробки. Інструкції у повідомленні транзакції мають формат [CompiledInstruction](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L633). -Подібно до масиву адрес облікових записів, цей компактний масив починається з кодування -[compact-u16](/docs/uk/core/transactions#compact-array-format) кількості інструкцій, після чого йде масив інструкцій. Кожна інструкція в масиві вказує наступну інформацію: - -1. **Program ID**: Ідентифікатор програми в мережі, яка оброблятиме інструкцію. Це представлено у вигляді індексу типу u8, що вказує на адресу програми у масиві адрес облікових записів. -2. **Компактний масив індексів адрес облікових записів**: Масив індексів типу u8, що вказує на масив адрес облікових записів для кожного облікового запису, потрібного для інструкції. -3. **Компактний масив байтів даних**: Масив байтів типу u8, специфічний для викликаної програми. Ці дані вказують, яку інструкцію викликати у програмі, разом із будь-якими додатковими даними, потрібними для виконання інструкції (наприклад, аргументами функції). +Подібно до масиву адрес облікових записів, цей компактний масив починається з +кодування [compact-u16](/docs/uk/core/transactions#compact-array-format) +кількості інструкцій, після чого йде масив інструкцій. Кожна інструкція в масиві +вказує наступну інформацію: + +1. **Program ID**: Ідентифікатор програми в мережі, яка оброблятиме інструкцію. + Це представлено у вигляді індексу типу u8, що вказує на адресу програми у + масиві адрес облікових записів. +2. **Компактний масив індексів адрес облікових записів**: Масив індексів типу + u8, що вказує на масив адрес облікових записів для кожного облікового запису, + потрібного для інструкції. +3. **Компактний масив байтів даних**: Масив байтів типу u8, специфічний для + викликаної програми. Ці дані вказують, яку інструкцію викликати у програмі, + разом із будь-якими додатковими даними, потрібними для виконання інструкції + (наприклад, аргументами функції). ![Компактний масив інструкцій](/assets/docs/core/transactions/compact_array_of_ixs.png) ### Приклад структури транзакції -Нижче наведено приклад структури транзакції, яка включає одну інструкцію для -[передачі SOL](/docs/uk/core/transactions#basic-example). Тут показано деталі повідомлення, включаючи заголовок, ключі облікових записів, блок-хеш та інструкції, разом із підписом для транзакції. +Нижче наведено приклад структури транзакції, яка включає одну інструкцію для +[передачі SOL](/docs/uk/core/transactions#basic-example). Тут показано деталі +повідомлення, включаючи заголовок, ключі облікових записів, блок-хеш та +інструкції, разом із підписом для транзакції. -- `header`: Містить дані, які використовуються для вказання привілеїв читання/запису та підписання у масиві `accountKeys`. -- `accountKeys`: Масив, що включає адреси облікових записів для всіх інструкцій у транзакції. +- `header`: Містить дані, які використовуються для вказання привілеїв + читання/запису та підписання у масиві `accountKeys`. +- `accountKeys`: Масив, що включає адреси облікових записів для всіх інструкцій + у транзакції. - `recentBlockhash`: Блок-хеш, включений у транзакцію під час її створення. -- `instructions`: Масив, що включає всі інструкції у транзакції. Кожен `account` та `programIdIndex` в інструкції посилаються на масив `accountKeys` за індексом. -- `signatures`: Масив, що включає підписи для всіх облікових записів, потрібних як підписанти для інструкцій у транзакції. Підпис створюється шляхом підписання повідомлення транзакції за допомогою відповідного приватного ключа для облікового запису. +- `instructions`: Масив, що включає всі інструкції у транзакції. Кожен `account` + та `programIdIndex` в інструкції посилаються на масив `accountKeys` за + індексом. +- `signatures`: Масив, що включає підписи для всіх облікових записів, потрібних + як підписанти для інструкцій у транзакції. Підпис створюється шляхом + підписання повідомлення транзакції за допомогою відповідного приватного ключа + для облікового запису. ```json "transaction": { @@ -242,45 +287,58 @@ const transaction = new Transaction().add(transferInstruction); ] } ``` + ## Інструкція [Інструкція](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L329) -— це запит на виконання конкретної дії в мережі. Це найменша неподільна одиниця логіки виконання у -[програмі](/docs/uk/core/accounts#program-account). +— це запит на виконання конкретної дії в мережі. Це найменша неподільна одиниця +логіки виконання у [програмі](/docs/uk/core/accounts#program-account). -При створенні інструкції для додавання до транзакції кожна інструкція повинна включати наступну інформацію: +При створенні інструкції для додавання до транзакції кожна інструкція повинна +включати наступну інформацію: - **Адреса програми**: Вказує програму, яку буде викликано. -- **Облікові записи**: Перелік кожного облікового запису, з якого інструкція читає або до якого пише, включаючи інші програми, за допомогою структури `AccountMeta`. -- **Дані інструкції**: Масив байтів, що вказує, який - [обробник інструкцій](/docs/uk/terminology#instruction-handler) викликати у програмі, а також будь-які додаткові дані, необхідні обробнику інструкцій (аргументи функції). +- **Облікові записи**: Перелік кожного облікового запису, з якого інструкція + читає або до якого пише, включаючи інші програми, за допомогою структури + `AccountMeta`. +- **Дані інструкції**: Масив байтів, що вказує, який + [обробник інструкцій](/docs/uk/terminology#instruction-handler) викликати у + програмі, а також будь-які додаткові дані, необхідні обробнику інструкцій + (аргументи функції). ![Інструкція транзакції](/assets/docs/core/transactions/instruction.svg) ### AccountMeta -Для кожного облікового запису, необхідного для інструкції, потрібно вказати наступну інформацію: +Для кожного облікового запису, необхідного для інструкції, потрібно вказати +наступну інформацію: - `pubkey`: Адреса облікового запису в мережі. - `is_signer`: Вказує, чи є обліковий запис підписантом у транзакції. - `is_writable`: Вказує, чи будуть змінені дані облікового запису. -Ця інформація називається +Ця інформація називається [AccountMeta](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L539). ![AccountMeta](/assets/docs/core/transactions/accountmeta.svg) -Завдяки вказанню всіх облікових записів, необхідних для інструкції, і зазначенню, які з них можуть бути змінені, транзакції можуть виконуватися паралельно. +Завдяки вказанню всіх облікових записів, необхідних для інструкції, і +зазначенню, які з них можуть бути змінені, транзакції можуть виконуватися +паралельно. -Наприклад, дві транзакції, які не включають жодних облікових записів, що записують в той самий стан, можуть виконуватися одночасно. +Наприклад, дві транзакції, які не включають жодних облікових записів, що +записують в той самий стан, можуть виконуватися одночасно. ### Приклад структури інструкції -Нижче наведено приклад структури інструкції для -[передачі SOL](/docs/uk/core/transactions#basic-examples), яка деталізує ключі облікових записів, ідентифікатор програми та дані, необхідні для інструкції. +Нижче наведено приклад структури інструкції для +[передачі SOL](/docs/uk/core/transactions#basic-examples), яка деталізує ключі +облікових записів, ідентифікатор програми та дані, необхідні для інструкції. -- `keys`: Містить `AccountMeta` для кожного облікового запису, необхідного для інструкції. -- `programId`: Адреса програми, яка містить логіку виконання для викликаної інструкції. +- `keys`: Містить `AccountMeta` для кожного облікового запису, необхідного для + інструкції. +- `programId`: Адреса програми, яка містить логіку виконання для викликаної + інструкції. - `data`: Дані інструкції у вигляді буфера байтів. ``` @@ -301,13 +359,18 @@ const transaction = new Transaction().add(transferInstruction); "data": [2,0,0,0,128,150,152,0,0,0,0,0] } ``` + ## Розширений приклад -Деталі створення програмних інструкцій часто приховуються клієнтськими бібліотеками. Проте, якщо такої бібліотеки немає, завжди можна вручну створити інструкцію. +Деталі створення програмних інструкцій часто приховуються клієнтськими +бібліотеками. Проте, якщо такої бібліотеки немає, завжди можна вручну створити +інструкцію. ### Ручна передача SOL -Ось приклад на [Solana Playground](https://beta.solpg.io/656a102efb53fa325bfd0c3f), який демонструє, як вручну створити інструкцію для передачі SOL: +Ось приклад на +[Solana Playground](https://beta.solpg.io/656a102efb53fa325bfd0c3f), який +демонструє, як вручну створити інструкцію для передачі SOL: ```typescript // Define the amount to transfer @@ -336,5 +399,9 @@ const transferInstruction = new TransactionInstruction({ // Add the transfer instruction to a new transaction const transaction = new Transaction().add(transferInstruction); ``` -Під капотом [простий приклад](/docs/uk/core/transactions#simple-sol-transfer) з використанням методу `SystemProgram.transfer` функціонально еквівалентний більш детальному прикладу вище. Метод `SystemProgram.transfer` просто приховує деталі створення буфера даних інструкції та `AccountMeta` для кожного облікового запису, необхідного для інструкції. +Під капотом [простий приклад](/docs/uk/core/transactions#simple-sol-transfer) з +використанням методу `SystemProgram.transfer` функціонально еквівалентний більш +детальному прикладу вище. Метод `SystemProgram.transfer` просто приховує деталі +створення буфера даних інструкції та `AccountMeta` для кожного облікового +запису, необхідного для інструкції. diff --git a/docs/locales/uk/economics/index.md b/docs/locales/uk/economics/index.md index ecfa6d94f..512f698e6 100644 --- a/docs/locales/uk/economics/index.md +++ b/docs/locales/uk/economics/index.md @@ -8,14 +8,45 @@ sidebarSortOrder: 5 **Може бути змінено.** -Криптоекономічна система Solana розроблена для сприяння здоровій, довгостроковій самопідтримуваній економіці, в якій стимули учасників узгоджуються із забезпеченням безпеки та децентралізації мережі. Основними учасниками цієї економіки є валідаційні клієнти. Їхній внесок у мережу, перевірка стану та відповідні механізми стимулювання розглядаються нижче. +Криптоекономічна система Solana розроблена для сприяння здоровій, довгостроковій +самопідтримуваній економіці, в якій стимули учасників узгоджуються із +забезпеченням безпеки та децентралізації мережі. Основними учасниками цієї +економіки є валідаційні клієнти. Їхній внесок у мережу, перевірка стану та +відповідні механізми стимулювання розглядаються нижче. -Основними каналами винагород для учасників є винагороди, засновані на протоколі, та транзакційні комісії. Винагороди, засновані на протоколі, генеруються за рахунок інфляційного випуску згідно з визначеним протоколом графіком інфляції. Ці винагороди становитимуть загальну винагороду на основі протоколу, яка буде надаватися валідаційним клієнтам, решта забезпечується за рахунок транзакційних комісій. У перші дні роботи мережі ймовірно, що винагороди, засновані на протоколі, розподілені згідно з попередньо визначеним графіком випуску, стануть основним стимулом для учасників мережі. +Основними каналами винагород для учасників є винагороди, засновані на протоколі, +та транзакційні комісії. Винагороди, засновані на протоколі, генеруються за +рахунок інфляційного випуску згідно з визначеним протоколом графіком інфляції. +Ці винагороди становитимуть загальну винагороду на основі протоколу, яка буде +надаватися валідаційним клієнтам, решта забезпечується за рахунок транзакційних +комісій. У перші дні роботи мережі ймовірно, що винагороди, засновані на +протоколі, розподілені згідно з попередньо визначеним графіком випуску, стануть +основним стимулом для учасників мережі. -Ці винагороди розраховуються за кожну епоху і розподіляються серед активного делегованого стейку та набору валідаторів (з урахуванням комісії валідаторів). Як описано нижче, річний рівень інфляції ґрунтується на визначеному дисінфляційному графіку. Це забезпечує мережі передбачуваність поставок, що підтримує довгострокову економічну стабільність та безпеку. +Ці винагороди розраховуються за кожну епоху і розподіляються серед активного +делегованого стейку та набору валідаторів (з урахуванням комісії валідаторів). +Як описано нижче, річний рівень інфляції ґрунтується на визначеному +дисінфляційному графіку. Це забезпечує мережі передбачуваність поставок, що +підтримує довгострокову економічну стабільність та безпеку. -Транзакційні комісії є переказами між учасниками, що додаються до взаємодії з мережею як стимул та компенсація за включення і виконання запропонованої транзакції. Також обговорюється механізм довгострокової економічної стабільності та захисту від розгалужень через часткове спалювання кожної транзакційної комісії. +Транзакційні комісії є переказами між учасниками, що додаються до взаємодії з +мережею як стимул та компенсація за включення і виконання запропонованої +транзакції. Також обговорюється механізм довгострокової економічної стабільності +та захисту від розгалужень через часткове спалювання кожної транзакційної +комісії. -Спочатку подано огляд дизайну інфляції. Цей розділ починається з визначення та уточнення [Термінології](/docs/uk/economics/inflation/terminology.md), що часто використовується у подальшому обговоренні інфляції та пов'язаних компонентів. Далі ми окреслюємо запропонований [Графік Інфляції](/docs/uk/economics/inflation/inflation_schedule.md) Solana, тобто конкретні параметри, які унікально визначають інфляційний випуск, керований протоколом, з плином часу. Наступним є короткий розділ про [Скориговану Доходність Стейкінгу](/docs/uk/economics/inflation/_adjusted_staking_yield.md) і те, як розбавлення токенів може вплинути на поведінку стейкінгу. +Спочатку подано огляд дизайну інфляції. Цей розділ починається з визначення та +уточнення [Термінології](/docs/uk/economics/inflation/terminology.md), що часто +використовується у подальшому обговоренні інфляції та пов'язаних компонентів. +Далі ми окреслюємо запропонований +[Графік Інфляції](/docs/uk/economics/inflation/inflation_schedule.md) Solana, +тобто конкретні параметри, які унікально визначають інфляційний випуск, +керований протоколом, з плином часу. Наступним є короткий розділ про +[Скориговану Доходність Стейкінгу](/docs/uk/economics/inflation/_adjusted_staking_yield.md) +і те, як розбавлення токенів може вплинути на поведінку стейкінгу. -Огляд [Транзакційних Комісій](/docs/uk/core/fees.md#transaction-fees) у Solana супроводжується обговоренням [Економіки Оренди для Зберігання](/docs/uk/core/fees.md#rent), у якому описується реалізація орендної плати за зберігання для обліку зовнішніх витрат на підтримання активного стану реєстру. +Огляд [Транзакційних Комісій](/docs/uk/core/fees.md#transaction-fees) у Solana +супроводжується обговоренням +[Економіки Оренди для Зберігання](/docs/uk/core/fees.md#rent), у якому +описується реалізація орендної плати за зберігання для обліку зовнішніх витрат +на підтримання активного стану реєстру. diff --git a/docs/locales/uk/economics/inflation/_adjusted_staking_yield.md b/docs/locales/uk/economics/inflation/_adjusted_staking_yield.md index a515b96f7..566f3676d 100644 --- a/docs/locales/uk/economics/inflation/_adjusted_staking_yield.md +++ b/docs/locales/uk/economics/inflation/_adjusted_staking_yield.md @@ -4,19 +4,33 @@ title: Скоригована Дохідність Стейкінгу ### Дилюція Токенів -Подібним чином ми можемо розглянути очікувану _Дилюцію Стейкінгу_ (тобто _Скориговану Дохідність Стейкінгу_) та _Дилюцію Нестейкінгованих Токенів_, як було визначено раніше. У цьому контексті _дилюція_ означає зміну фракційного представлення (тобто частки власності) набору токенів у рамках більшого пулу. У цьому сенсі дилюція може бути позитивною (збільшення частки власності, стейкінгова дилюція / _Скоригована Дохідність Стейкінгу_) або негативною (зменшення частки власності, нестейкінгова дилюція). - -Нас цікавить відносна зміна власності стейкінгованих і нестейкінгованих токенів у міру збільшення загального пулу токенів через інфляційний випуск. Як було зазначено, цей випуск розподіляється лише серед власників стейкінгованих токенів, збільшуючи їх частку у _Загальному Поточному Обсязі_. - -Продовжуючи з тими ж параметрами _Графіку Інфляції_, що й раніше, ми бачимо зростання частки стейкінгового пулу, як показано нижче. +Подібним чином ми можемо розглянути очікувану _Дилюцію Стейкінгу_ (тобто +_Скориговану Дохідність Стейкінгу_) та _Дилюцію Нестейкінгованих Токенів_, як +було визначено раніше. У цьому контексті _дилюція_ означає зміну фракційного +представлення (тобто частки власності) набору токенів у рамках більшого пулу. У +цьому сенсі дилюція може бути позитивною (збільшення частки власності, +стейкінгова дилюція / _Скоригована Дохідність Стейкінгу_) або негативною +(зменшення частки власності, нестейкінгова дилюція). + +Нас цікавить відносна зміна власності стейкінгованих і нестейкінгованих токенів +у міру збільшення загального пулу токенів через інфляційний випуск. Як було +зазначено, цей випуск розподіляється лише серед власників стейкінгованих +токенів, збільшуючи їх частку у _Загальному Поточному Обсязі_. + +Продовжуючи з тими ж параметрами _Графіку Інфляції_, що й раніше, ми бачимо +зростання частки стейкінгового пулу, як показано нижче. ![Графік зростання частки стейкінгового пулу](/assets/docs/economics/example_staked_supply_w_range_initial_stake.png) -Через цю відносну зміну у представництві частка стейкінгу будь-якого власника токенів також змінюється як функція _Графіку Інфляції_ та частки стейкінгованих токенів. +Через цю відносну зміну у представництві частка стейкінгу будь-якого власника +токенів також змінюється як функція _Графіку Інфляції_ та частки стейкінгованих +токенів. ### Розрахунок Дилюції Нестейкінгованих Токенів -Особливий інтерес викликає _Дилюція Нестейкінгованих Токенів_, або $D_{us}$. У випадку нестейкінгованих токенів дилюція залежить лише від _Графіку Інфляції_, оскільки кількість нестейкінгованих токенів не змінюється з часом. +Особливий інтерес викликає _Дилюція Нестейкінгованих Токенів_, або $D_{us}$. У +випадку нестейкінгованих токенів дилюція залежить лише від _Графіку Інфляції_, +оскільки кількість нестейкінгованих токенів не змінюється з часом. $$ \begin{aligned} @@ -25,7 +39,8 @@ $$ \end{aligned} $$ -Оскільки випуск інфляції лише збільшує загальну кількість токенів, а нестейкінгована кількість залишається незмінною: +Оскільки випуск інфляції лише збільшує загальну кількість токенів, а +нестейкінгована кількість залишається незмінною: $$ \begin{aligned} @@ -41,7 +56,8 @@ $$ ### Оцінка Скоригованої Дохідності Стейкінгу -Ми також можемо розрахувати _Скориговану Дохідність Стейкінгу_ $Y_{adj}$ як зміну частки стейкінгованих токенів у пулі: +Ми також можемо розрахувати _Скориговану Дохідність Стейкінгу_ $Y_{adj}$ як +зміну частки стейкінгованих токенів у пулі: $$ Y_{adj} = \frac{P_s(t_2) - P_s(t_1)}{P_s(t_1)} @@ -55,12 +71,17 @@ $$ ### Відносна Дилюція -Відношення $D_{us}/Y_{adj}$ дозволяє зрозуміти, наскільки сильніше нестейкінговані токени піддаються дилюції у порівнянні зі стейкінгованими: +Відношення $D_{us}/Y_{adj}$ дозволяє зрозуміти, наскільки сильніше +нестейкінговані токени піддаються дилюції у порівнянні зі стейкінгованими: $$ \frac{D_{us}}{Y_{adj}} = \frac{ P_s }{ 1 - P_s } $$ -На основі цього видно, що збільшення частки стейкінгованих токенів значно збільшує дилюцію нестейкінгованих токенів. Наприклад, якщо $80\%$ токенів мережі стейкінговано, власник нестейкінгованих токенів зіткнеться з дилюцією у $400\%$ більшою, ніж стейкінгований власник. +На основі цього видно, що збільшення частки стейкінгованих токенів значно +збільшує дилюцію нестейкінгованих токенів. Наприклад, якщо $80\%$ токенів мережі +стейкінговано, власник нестейкінгованих токенів зіткнеться з дилюцією у $400\%$ +більшою, ніж стейкінгований власник. -Це підкреслює стимул для власників токенів до стейкінгу, щоб отримати _Дохідність Стейкінгу_ та уникнути _Дилюції Нестейкінгованих Токенів_. +Це підкреслює стимул для власників токенів до стейкінгу, щоб отримати +_Дохідність Стейкінгу_ та уникнути _Дилюції Нестейкінгованих Токенів_. diff --git a/docs/locales/uk/economics/inflation/inflation-schedule.md b/docs/locales/uk/economics/inflation/inflation-schedule.md index f9d69885d..dab4750e1 100644 --- a/docs/locales/uk/economics/inflation/inflation-schedule.md +++ b/docs/locales/uk/economics/inflation/inflation-schedule.md @@ -6,37 +6,78 @@ altRoutes: - /docs/uk/intro/economics --- -Як було зазначено вище, _Графік Інфляції_ мережі унікально описується трьома параметрами: _Початкова Ставка Інфляції_, _Ставка Дезінфляції_ та _Довгострокова Ставка Інфляції_. При розгляді цих значень слід враховувати багато факторів: +Як було зазначено вище, _Графік Інфляції_ мережі унікально описується трьома +параметрами: _Початкова Ставка Інфляції_, _Ставка Дезінфляції_ та _Довгострокова +Ставка Інфляції_. При розгляді цих значень слід враховувати багато факторів: -- Значна частина SOL, випущених через інфляцію, буде розподілена між власниками стейкінгу пропорційно до кількості стейкінгованих SOL. Ми хочемо переконатися, що дизайн _Графіку Інфляції_ забезпечує розумну _Дохідність Стейкінгу_ для власників токенів, які делегують SOL, та провайдерів послуг валідації (через комісії, які беруться з _Дохідності Стейкінгу_). -- Основний драйвер _Дохідності Стейкінгу_ — це кількість SOL у стейкінгу, поділена на загальну кількість SOL (% від загальної кількості SOL у стейкінгу). Таким чином, розподіл і делегування токенів серед валідаторів є важливими факторами при визначенні початкових параметрів інфляції. -- Обмеження дохідності — це поточна область досліджень, яка може вплинути на _Дохідність Стейкінгу_. Це не враховано у цій дискусії чи в моделюванні нижче. -- Загальний випуск токенів — тобто якою ми очікуємо _Поточну Загальну Пропозицію_ через 10 чи 20 років? -- Довгострокова, стабільна інфляція є важливим фактором не тільки для сталого підтримання екосистеми валідаторів і грантових програм Фонду Solana, але також має бути налаштована з урахуванням очікуваних втрат і спалювання токенів з часом. -- Темпи очікуваного зростання використання мережі як фактор для розгляду ставки дезінфляції. З часом ми плануємо зниження інфляції та очікуємо зростання використання. +- Значна частина SOL, випущених через інфляцію, буде розподілена між власниками + стейкінгу пропорційно до кількості стейкінгованих SOL. Ми хочемо переконатися, + що дизайн _Графіку Інфляції_ забезпечує розумну _Дохідність Стейкінгу_ для + власників токенів, які делегують SOL, та провайдерів послуг валідації (через + комісії, які беруться з _Дохідності Стейкінгу_). +- Основний драйвер _Дохідності Стейкінгу_ — це кількість SOL у стейкінгу, + поділена на загальну кількість SOL (% від загальної кількості SOL у + стейкінгу). Таким чином, розподіл і делегування токенів серед валідаторів є + важливими факторами при визначенні початкових параметрів інфляції. +- Обмеження дохідності — це поточна область досліджень, яка може вплинути на + _Дохідність Стейкінгу_. Це не враховано у цій дискусії чи в моделюванні нижче. +- Загальний випуск токенів — тобто якою ми очікуємо _Поточну Загальну + Пропозицію_ через 10 чи 20 років? +- Довгострокова, стабільна інфляція є важливим фактором не тільки для сталого + підтримання екосистеми валідаторів і грантових програм Фонду Solana, але також + має бути налаштована з урахуванням очікуваних втрат і спалювання токенів з + часом. +- Темпи очікуваного зростання використання мережі як фактор для розгляду ставки + дезінфляції. З часом ми плануємо зниження інфляції та очікуємо зростання + використання. -Виходячи з цих міркувань і обговорень у спільноті після початкового дизайну, Фонд Solana пропонує наступні параметри _Графіку Інфляції_: +Виходячи з цих міркувань і обговорень у спільноті після початкового дизайну, +Фонд Solana пропонує наступні параметри _Графіку Інфляції_: - Початкова Ставка Інфляції: 8% - Ставка Дезінфляції: -15% - Довгострокова Ставка Інфляції: 1.5% -Ці параметри визначають запропонований _Графік Інфляції_. Нижче показано наслідки цих параметрів. Ці графіки лише показують вплив інфляційного випуску, заданого _Графіком Інфляції_, як параметризовано вище. Вони _не враховують_ інші фактори, які можуть вплинути на _Загальну Пропозицію_, такі як спалювання комісій/рент, штрафи чи інші непередбачувані події знищення токенів у майбутньому. Тому тут представлено **верхню межу** кількості SOL, випущених через інфляцію. +Ці параметри визначають запропонований _Графік Інфляції_. Нижче показано +наслідки цих параметрів. Ці графіки лише показують вплив інфляційного випуску, +заданого _Графіком Інфляції_, як параметризовано вище. Вони _не враховують_ інші +фактори, які можуть вплинути на _Загальну Пропозицію_, такі як спалювання +комісій/рент, штрафи чи інші непередбачувані події знищення токенів у +майбутньому. Тому тут представлено **верхню межу** кількості SOL, випущених +через інфляцію. ![Графік прикладу запропонованого графіку інфляції](/assets/docs/economics/proposed_inflation_schedule.png) -На графіку вище показано відсоток річної ставки інфляції з часом, виходячи з запропонованих параметрів інфляції. +На графіку вище показано відсоток річної ставки інфляції з часом, виходячи з +запропонованих параметрів інфляції. ![Графік прикладу загальної пропозиції](/assets/docs/economics/proposed_total_supply.png) -Подібним чином, тут показано _Поточну Загальну Пропозицію_ SOL [млн] з часом, за умови початкової _Поточна Загальна Пропозиція_ `488,587,349 SOL` (тобто, у цьому прикладі, взято _Поточну Загальну Пропозицію_ станом на `2020-01-25` і моделюється інфляція, починаючи з цього дня). +Подібним чином, тут показано _Поточну Загальну Пропозицію_ SOL [млн] з часом, за +умови початкової _Поточна Загальна Пропозиція_ `488,587,349 SOL` (тобто, у цьому +прикладі, взято _Поточну Загальну Пропозицію_ станом на `2020-01-25` і +моделюється інфляція, починаючи з цього дня). -Відставляючи осторонь доступність валідаторів і комісії, очікувані показники _Дохідності Стейкінгу_ та _Скоригованої Дохідності Стейкінгу_ є в першу чергу функцією % від загального SOL у стейкінгу. Тому ми можемо моделювати _Дохідність Стейкінгу_, якщо введемо додатковий параметр _% Стейкінгованих SOL_: +Відставляючи осторонь доступність валідаторів і комісії, очікувані показники +_Дохідності Стейкінгу_ та _Скоригованої Дохідності Стейкінгу_ є в першу чергу +функцією % від загального SOL у стейкінгу. Тому ми можемо моделювати _Дохідність +Стейкінгу_, якщо введемо додатковий параметр _% Стейкінгованих SOL_: -Цей параметр має бути оцінений, оскільки це динамічна властивість власників токенів і стимулів стейкінгу. Значення _% Стейкінгованих SOL_, представлені тут, варіюються від 60% до 90%, що, на нашу думку, охоплює ймовірний діапазон, який ми очікуємо, базуючись на зворотному зв’язку від спільнот інвесторів і валідаторів, а також спостереженнях на порівнянних протоколах Proof-of-Stake. +Цей параметр має бути оцінений, оскільки це динамічна властивість власників +токенів і стимулів стейкінгу. Значення _% Стейкінгованих SOL_, представлені тут, +варіюються від 60% до 90%, що, на нашу думку, охоплює ймовірний діапазон, який +ми очікуємо, базуючись на зворотному зв’язку від спільнот інвесторів і +валідаторів, а також спостереженнях на порівнянних протоколах Proof-of-Stake. ![Графік прикладу дохідності стейкінгу](/assets/docs/economics/example_staked_yields.png) -На графіку вище показано приклад _Дохідності Стейкінгу_, яку може очікувати учасник стейкінгу з часом у мережі Solana з вказаним _Графіком Інфляції_. Це ідеалізована _Дохідність Стейкінгу_, оскільки вона не враховує вплив доступності валідаторів на винагороди, комісії валідаторів, можливе обмеження дохідності та можливі інциденти зі штрафами. Вона також ігнорує, що _% Стейкінгованих SOL_ є динамічним за своєю суттю — економічні стимули, створені цим _Графіком Інфляції_, стають більш зрозумілими, коли враховується _Дилюція Токенів_ (див. розділ **Скоригована Дохідність Стейкінгу** нижче). +На графіку вище показано приклад _Дохідності Стейкінгу_, яку може очікувати +учасник стейкінгу з часом у мережі Solana з вказаним _Графіком Інфляції_. Це +ідеалізована _Дохідність Стейкінгу_, оскільки вона не враховує вплив доступності +валідаторів на винагороди, комісії валідаторів, можливе обмеження дохідності та +можливі інциденти зі штрафами. Вона також ігнорує, що _% Стейкінгованих SOL_ є +динамічним за своєю суттю — економічні стимули, створені цим _Графіком +Інфляції_, стають більш зрозумілими, коли враховується _Дилюція Токенів_ (див. +розділ **Скоригована Дохідність Стейкінгу** нижче). diff --git a/docs/locales/uk/economics/inflation/terminology.md b/docs/locales/uk/economics/inflation/terminology.md index bdd0cbe94..23debb50c 100644 --- a/docs/locales/uk/economics/inflation/terminology.md +++ b/docs/locales/uk/economics/inflation/terminology.md @@ -3,44 +3,86 @@ sidebarLabel: Терміни, Пов’язані з Інфляцією title: Терміни, Пов’язані з Інфляцією --- -При обговоренні інфляції та пов’язаних компонентів (наприклад, винагород/дохідності/відсотків) використовується багато термінів. Тут ми намагаємося визначити та уточнити деякі загальновживані поняття: +При обговоренні інфляції та пов’язаних компонентів (наприклад, +винагород/дохідності/відсотків) використовується багато термінів. Тут ми +намагаємося визначити та уточнити деякі загальновживані поняття: ### Поточна Загальна Пропозиція [SOL] -Загальна кількість токенів (заблокованих або незаблокованих), які були створені (через генезисний блок або інфляцію протоколу) мінус будь-які токени, які були спалені (через комісії за транзакції або інші механізми) чи списані. Під час запуску мережі було створено 500,000,000 SOL у генезисному блоці. З того часу Поточна Загальна Пропозиція зменшилася через спалювання комісій за транзакції та заплановану подію зменшення кількості токенів. _Поточну Загальну Пропозицію_ Solana можна знайти за адресою: https://explorer.solana.com/supply +Загальна кількість токенів (заблокованих або незаблокованих), які були створені +(через генезисний блок або інфляцію протоколу) мінус будь-які токени, які були +спалені (через комісії за транзакції або інші механізми) чи списані. Під час +запуску мережі було створено 500,000,000 SOL у генезисному блоці. З того часу +Поточна Загальна Пропозиція зменшилася через спалювання комісій за транзакції та +заплановану подію зменшення кількості токенів. _Поточну Загальну Пропозицію_ +Solana можна знайти за адресою: https://explorer.solana.com/supply ### Ставка Інфляції [%] -Протокол Solana автоматично створює нові токени за заздалегідь визначеним графіком інфляції (обговорено нижче). _Ставка Інфляції [%]_ — це річний темп зростання _Поточна Загальна Пропозиція_ на будь-який момент часу. +Протокол Solana автоматично створює нові токени за заздалегідь визначеним +графіком інфляції (обговорено нижче). _Ставка Інфляції [%]_ — це річний темп +зростання _Поточна Загальна Пропозиція_ на будь-який момент часу. ### Графік Інфляції -Детерміноване описання випуску токенів з часом. Фонд Solana пропонує дезінфляційний _Графік Інфляції_. Тобто інфляція починається з найвищого значення, а її темп зменшується з часом, доки не стабілізується на заздалегідь визначеному довгостроковому рівні (див. обговорення нижче). Цей графік повністю та унікально параметризується трьома числами: +Детерміноване описання випуску токенів з часом. Фонд Solana пропонує +дезінфляційний _Графік Інфляції_. Тобто інфляція починається з найвищого +значення, а її темп зменшується з часом, доки не стабілізується на заздалегідь +визначеному довгостроковому рівні (див. обговорення нижче). Цей графік повністю +та унікально параметризується трьома числами: -- **Початкова Ставка Інфляції [%]**: Початкова _Ставка Інфляції_ для моменту активації інфляції. Темп випуску токенів може тільки знижуватися з цього моменту. +- **Початкова Ставка Інфляції [%]**: Початкова _Ставка Інфляції_ для моменту + активації інфляції. Темп випуску токенів може тільки знижуватися з цього + моменту. - **Ставка Дезінфляції [%]**: Темп, з яким зменшується _Ставка Інфляції_. -- **Довгострокова Ставка Інфляції [%]**: Стабільна, довгострокова _Ставка Інфляції_. +- **Довгострокова Ставка Інфляції [%]**: Стабільна, довгострокова _Ставка + Інфляції_. ### Ефективна Ставка Інфляції [%] -Фактична ставка інфляції, що спостерігається в мережі Solana, після врахування інших факторів, які можуть зменшити _Поточну Загальну Пропозицію_. Зазначимо, що створення токенів поза описаним _Графіком Інфляції_ неможливе. +Фактична ставка інфляції, що спостерігається в мережі Solana, після врахування +інших факторів, які можуть зменшити _Поточну Загальну Пропозицію_. Зазначимо, що +створення токенів поза описаним _Графіком Інфляції_ неможливе. -- Хоча _Графік Інфляції_ визначає, як протокол випускає SOL, він не враховує одночасного знищення токенів через різні фактори. Основний механізм спалювання токенів — це спалювання частини кожної комісії за транзакцію. 50% кожної комісії за транзакцію спалюється, решта залишається валідатору, який обробив транзакцію. -- Додаткові фактори, такі як втрата приватних ключів і списання токенів, також слід враховувати в комплексному аналізі _Ефективної Ставки Інфляції_. Наприклад, оцінюється, що 10–20% всіх BTC втрачені та недоступні, і мережі можуть зазнавати подібних щорічних втрат на рівні 1–2%. +- Хоча _Графік Інфляції_ визначає, як протокол випускає SOL, він не враховує + одночасного знищення токенів через різні фактори. Основний механізм спалювання + токенів — це спалювання частини кожної комісії за транзакцію. 50% кожної + комісії за транзакцію спалюється, решта залишається валідатору, який обробив + транзакцію. +- Додаткові фактори, такі як втрата приватних ключів і списання токенів, також + слід враховувати в комплексному аналізі _Ефективної Ставки Інфляції_. + Наприклад, оцінюється, що 10–20% всіх BTC втрачені та недоступні, і мережі + можуть зазнавати подібних щорічних втрат на рівні 1–2%. ### Дохідність Стейкінгу [%] -Темп повернення (також відомий як _відсоток_), який отримується за SOL, поставлені на стейкінг у мережі. Зазвичай він зазначається як річний темп (наприклад, "дохідність стейкінгу в мережі наразі становить 10% на рік"). - -- _Дохідність стейкінгу_ дуже цікавить валідаторів і власників токенів, які бажають делегувати свої токени, щоб уникнути розмивання токенів через інфляцію (масштаб якої обговорено нижче). -- 100% інфляційних випусків розподіляються між власниками стейкінгованих токенів пропорційно до їхнього стейкінгованого SOL, а також валідаторами, які стягують комісію з винагороди, отриманої за делегований SOL. - - Може бути враховано майбутнє розділення інфляційних випусків із введенням _Архіваторів_ у економіку. _Архіватори_ — це учасники мережі, які надають децентралізовані послуги зберігання, і їх також слід стимулювати розподілом токенів з інфляційних випусків за цю послугу. -- _Дохідність Стейкінгу_ можна розрахувати за _Графіком Інфляції_ разом із часткою _Поточна Загальна Пропозиція_, що перебуває в стейкінгу. +Темп повернення (також відомий як _відсоток_), який отримується за SOL, +поставлені на стейкінг у мережі. Зазвичай він зазначається як річний темп +(наприклад, "дохідність стейкінгу в мережі наразі становить 10% на рік"). + +- _Дохідність стейкінгу_ дуже цікавить валідаторів і власників токенів, які + бажають делегувати свої токени, щоб уникнути розмивання токенів через інфляцію + (масштаб якої обговорено нижче). +- 100% інфляційних випусків розподіляються між власниками стейкінгованих токенів + пропорційно до їхнього стейкінгованого SOL, а також валідаторами, які стягують + комісію з винагороди, отриманої за делегований SOL. + - Може бути враховано майбутнє розділення інфляційних випусків із введенням + _Архіваторів_ у економіку. _Архіватори_ — це учасники мережі, які надають + децентралізовані послуги зберігання, і їх також слід стимулювати розподілом + токенів з інфляційних випусків за цю послугу. +- _Дохідність Стейкінгу_ можна розрахувати за _Графіком Інфляції_ разом із + часткою _Поточна Загальна Пропозиція_, що перебуває в стейкінгу. ### Дилюція Токенів [%] -Розмивання визначається тут як зміна пропорційного представлення набору токенів у більшому наборі через введення нових токенів. У практичному сенсі ми обговорюємо розмивання стейкінгованих або нестейкінгованих токенів через введення та розподіл інфляційних випусків по мережі. +Розмивання визначається тут як зміна пропорційного представлення набору токенів +у більшому наборі через введення нових токенів. У практичному сенсі ми +обговорюємо розмивання стейкінгованих або нестейкінгованих токенів через +введення та розподіл інфляційних випусків по мережі. ### Скоригована Дохідність Стейкінгу [%] -Повна оцінка потенціалу заробітку від стейкінгу токенів повинна враховувати стейкінговану _Дилюцію Токенів_ та її вплив на _Дохідність Стейкінгу_. Для цього ми визначаємо _Скориговану Дохідність Стейкінгу_ як зміну фракційної власності токенів у стейкінгу через розподіл інфляційних випусків. +Повна оцінка потенціалу заробітку від стейкінгу токенів повинна враховувати +стейкінговану _Дилюцію Токенів_ та її вплив на _Дохідність Стейкінгу_. Для цього +ми визначаємо _Скориговану Дохідність Стейкінгу_ як зміну фракційної власності +токенів у стейкінгу через розподіл інфляційних випусків. diff --git a/docs/locales/uk/economics/staking/index.md b/docs/locales/uk/economics/staking/index.md index 09160d228..7f9a56564 100644 --- a/docs/locales/uk/economics/staking/index.md +++ b/docs/locales/uk/economics/staking/index.md @@ -3,86 +3,97 @@ sidebarLabel: Стейкінг title: Стейкінг у Solana --- -_Примітка перед читанням: Усі згадки про збільшення значень стосуються абсолютних -показників балансу SOL. Цей документ не містить жодних припущень щодо +_Примітка перед читанням: Усі згадки про збільшення значень стосуються +абсолютних показників балансу SOL. Цей документ не містить жодних припущень щодо грошової вартості SOL у будь-який час._ Стейкуючи ваші токени SOL, ви допомагаєте забезпечувати безпеку мережі та [отримувати винагороди](https://docs.anza.xyz/implemented-proposals/staking-rewards) у процесі цього. -Ви можете здійснювати стейкінг, делегуючи ваші токени валідаторам, які обробляють транзакції -та забезпечують роботу мережі. - -Делегування стейкінгу — це фінансова модель з розподіленим ризиком і винагородою, яка може -забезпечити дохід для власників токенів, делегованих на тривалий період. Це досягається -шляхом узгодження фінансових інтересів власників токенів (делегаторів) та валідаторів, -яким вони делегують токени. - -Чим більше стейку делеговано валідатору, тим частіше цей валідатор обирається для запису -нових транзакцій до реєстру. Чим більше транзакцій записує валідатор, тим більше винагород -отримують валідатор і його делегатори. Валідатори, які налаштовують свої системи для обробки -більшої кількості транзакцій, заробляють пропорційно більше винагород і допомагають -підтримувати мережу якомога швидшою та стабільнішою. - -Валідатори несуть витрати на обслуговування та підтримку своїх систем, і ці витрати передаються -делегаторам у формі комісії, яка стягується як відсоток від зароблених винагород. Ця комісія -називається _комісією валідатора_. Оскільки валідатори отримують більше винагород за більше -делегованого стейку, вони можуть конкурувати між собою, пропонуючи найнижчу комісію за свої послуги. - -Хоча це не реалізовано в протоколі Solana сьогодні, у майбутньому делегатори можуть ризикувати -втратити токени через процес, відомий як _слешинг_. Слешинг передбачає вилучення та знищення частини -SOL валідатора у відповідь на навмисну зловмисну поведінку, наприклад, створення недійсних транзакцій -або цензурування певних типів транзакцій чи учасників мережі. - -На даний момент у протоколі Solana немає реалізації слешингу. Для отримання додаткової інформації -про слешинг перегляньте +Ви можете здійснювати стейкінг, делегуючи ваші токени валідаторам, які +обробляють транзакції та забезпечують роботу мережі. + +Делегування стейкінгу — це фінансова модель з розподіленим ризиком і +винагородою, яка може забезпечити дохід для власників токенів, делегованих на +тривалий період. Це досягається шляхом узгодження фінансових інтересів власників +токенів (делегаторів) та валідаторів, яким вони делегують токени. + +Чим більше стейку делеговано валідатору, тим частіше цей валідатор обирається +для запису нових транзакцій до реєстру. Чим більше транзакцій записує валідатор, +тим більше винагород отримують валідатор і його делегатори. Валідатори, які +налаштовують свої системи для обробки більшої кількості транзакцій, заробляють +пропорційно більше винагород і допомагають підтримувати мережу якомога швидшою +та стабільнішою. + +Валідатори несуть витрати на обслуговування та підтримку своїх систем, і ці +витрати передаються делегаторам у формі комісії, яка стягується як відсоток від +зароблених винагород. Ця комісія називається _комісією валідатора_. Оскільки +валідатори отримують більше винагород за більше делегованого стейку, вони можуть +конкурувати між собою, пропонуючи найнижчу комісію за свої послуги. + +Хоча це не реалізовано в протоколі Solana сьогодні, у майбутньому делегатори +можуть ризикувати втратити токени через процес, відомий як _слешинг_. Слешинг +передбачає вилучення та знищення частини SOL валідатора у відповідь на навмисну +зловмисну поведінку, наприклад, створення недійсних транзакцій або цензурування +певних типів транзакцій чи учасників мережі. + +На даний момент у протоколі Solana немає реалізації слешингу. Для отримання +додаткової інформації про слешинг перегляньте [дорожню карту слешингу](https://docs.anza.xyz/proposals/optimistic-confirmation-and-slashing#slashing-roadmap). ## Як здійснити стейкінг моїх токенів SOL? -Ви можете здійснити стейкінг SOL, перемістивши свої токени в гаманець, який підтримує стейкінг. Гаманець -надасть інструкції для створення облікового запису стейкінгу та делегування. +Ви можете здійснити стейкінг SOL, перемістивши свої токени в гаманець, який +підтримує стейкінг. Гаманець надасть інструкції для створення облікового запису +стейкінгу та делегування. #### Підтримувані Гаманці -Багато веб- та мобільних гаманців підтримують операції стейкінгу Solana. Будь ласка, перевірте -статус підтримки у розробників вашого улюбленого гаманця. +Багато веб- та мобільних гаманців підтримують операції стейкінгу Solana. Будь +ласка, перевірте статус підтримки у розробників вашого улюбленого гаманця. #### Інструменти командного рядка Solana -- Інструменти командного рядка Solana дозволяють виконувати всі операції стейкінгу в поєднанні з - гаманцем у вигляді файлу ключів, паперовим гаманцем або підключеним Ledger Nano. +- Інструменти командного рядка Solana дозволяють виконувати всі операції + стейкінгу в поєднанні з гаманцем у вигляді файлу ключів, паперовим гаманцем + або підключеним Ledger Nano. [Команди для стейкінгу за допомогою інструментів командного рядка Solana](https://docs.anza.xyz/cli/examples/delegate-stake). #### Створення Облікового Запису Стейкінгу -Виконуйте інструкції гаманця для створення облікового запису стейкінгу. Цей обліковий запис -відрізняється від облікових записів, які використовуються для відправлення та отримання токенів. +Виконуйте інструкції гаманця для створення облікового запису стейкінгу. Цей +обліковий запис відрізняється від облікових записів, які використовуються для +відправлення та отримання токенів. #### Вибір Валідатора -Дотримуйтесь інструкцій гаманця для вибору валідатора. Ви можете отримати інформацію про потенційно -ефективних валідаторів за посиланнями нижче. Фонд Solana не рекомендує конкретних валідаторів. +Дотримуйтесь інструкцій гаманця для вибору валідатора. Ви можете отримати +інформацію про потенційно ефективних валідаторів за посиланнями нижче. Фонд +Solana не рекомендує конкретних валідаторів. -Сайт solanabeach.io створений і підтримується одним з наших валідаторів, -Staking Facilities. Він надає графічну інформацію про мережу в цілому, а також -список кожного валідатора з деякими останніми статистиками їхньої продуктивності. +Сайт solanabeach.io створений і підтримується одним з наших валідаторів, Staking +Facilities. Він надає графічну інформацію про мережу в цілому, а також список +кожного валідатора з деякими останніми статистиками їхньої продуктивності. - https://solanabeach.io -Для перегляду статистики виробництва блоків використовуйте інструменти командного рядка Solana: +Для перегляду статистики виробництва блоків використовуйте інструменти +командного рядка Solana: - `solana validators` - `solana block-production` -Команда Solana не надає рекомендацій щодо інтерпретації цієї інформації. Виконуйте власне дослідження. +Команда Solana не надає рекомендацій щодо інтерпретації цієї інформації. +Виконуйте власне дослідження. #### Делегування Стейку -Виконуйте інструкції гаманця для делегування вашого стейку обраному вами валідатору. +Виконуйте інструкції гаманця для делегування вашого стейку обраному вами +валідатору. ## Деталі Облікового Запису Стейкінгу -Для отримання додаткової інформації про операції та дозволи, пов’язані з обліковим записом стейкінгу, -дивіться [Облікові Записи Стейкінгу](/docs/uk/economics/staking/stake-accounts.md) +Для отримання додаткової інформації про операції та дозволи, пов’язані з +обліковим записом стейкінгу, дивіться +[Облікові Записи Стейкінгу](/docs/uk/economics/staking/stake-accounts.md) diff --git a/docs/locales/uk/economics/staking/stake-accounts.md b/docs/locales/uk/economics/staking/stake-accounts.md index 9eb222c24..683a6d5a2 100644 --- a/docs/locales/uk/economics/staking/stake-accounts.md +++ b/docs/locales/uk/economics/staking/stake-accounts.md @@ -3,23 +3,46 @@ sidebarLabel: Облікові Записи Стейкінгу title: Облікові Записи Стейкінгу --- -Обліковий запис стейкінгу на Solana може використовуватися для делегування токенів валідаторам у мережі з можливістю отримання винагород для власника облікового запису стейкінгу. Облікові записи стейкінгу створюються та керуються інакше, ніж традиційні адреси гаманців, відомі як _системні облікові записи_. Системний обліковий запис здатний лише надсилати та отримувати SOL від інших облікових записів у мережі, тоді як обліковий запис стейкінгу підтримує складніші операції, необхідні для управління делегуванням токенів. - -Облікові записи стейкінгу на Solana також працюють інакше, ніж у інших блокчейн-мережах Proof-of-Stake, з якими ви могли бути знайомі. У цьому документі описується загальна структура та функції облікового запису стейкінгу Solana. +Обліковий запис стейкінгу на Solana може використовуватися для делегування +токенів валідаторам у мережі з можливістю отримання винагород для власника +облікового запису стейкінгу. Облікові записи стейкінгу створюються та керуються +інакше, ніж традиційні адреси гаманців, відомі як _системні облікові записи_. +Системний обліковий запис здатний лише надсилати та отримувати SOL від інших +облікових записів у мережі, тоді як обліковий запис стейкінгу підтримує +складніші операції, необхідні для управління делегуванням токенів. + +Облікові записи стейкінгу на Solana також працюють інакше, ніж у інших +блокчейн-мережах Proof-of-Stake, з якими ви могли бути знайомі. У цьому +документі описується загальна структура та функції облікового запису стейкінгу +Solana. #### Адреса Облікового Запису -Кожен обліковий запис стейкінгу має унікальну адресу, яка може використовуватися для перегляду інформації про обліковий запис через командний рядок або будь-які інструменти дослідження мережі. Однак, на відміну від адреси гаманця, власник ключової пари адреси не обов'язково має контроль над обліковим записом. Насправді, для адреси облікового запису стейкінгу може навіть не існувати ключова пара чи приватний ключ. +Кожен обліковий запис стейкінгу має унікальну адресу, яка може використовуватися +для перегляду інформації про обліковий запис через командний рядок або будь-які +інструменти дослідження мережі. Однак, на відміну від адреси гаманця, власник +ключової пари адреси не обов'язково має контроль над обліковим записом. +Насправді, для адреси облікового запису стейкінгу може навіть не існувати +ключова пара чи приватний ключ. -Ключова пара створюється лише під час [створення облікового запису стейкінгу за допомогою інструментів командного рядка](https://docs.anza.xyz/cli/examples/delegate-stake#create-a-stake-account). Нова ключова пара створюється виключно для забезпечення унікальності адреси облікового запису стейкінгу. +Ключова пара створюється лише під час +[створення облікового запису стейкінгу за допомогою інструментів командного рядка](https://docs.anza.xyz/cli/examples/delegate-stake#create-a-stake-account). +Нова ключова пара створюється виключно для забезпечення унікальності адреси +облікового запису стейкінгу. #### Розуміння Авторитетів Облікового Запису -Деякі типи облікових записів можуть мати один або більше _авторитетів підпису_, пов’язаних з обліковим записом. Авторитет облікового запису використовується для підпису певних транзакцій для облікового запису, яким він керує. Це відрізняється від інших блокчейнів, де власник ключової пари контролює всі дії облікового запису. +Деякі типи облікових записів можуть мати один або більше _авторитетів підпису_, +пов’язаних з обліковим записом. Авторитет облікового запису використовується для +підпису певних транзакцій для облікового запису, яким він керує. Це +відрізняється від інших блокчейнів, де власник ключової пари контролює всі дії +облікового запису. -Кожен обліковий запис стейкінгу має два авторитети підпису, які вказані їхніми відповідними адресами: +Кожен обліковий запис стейкінгу має два авторитети підпису, які вказані їхніми +відповідними адресами: - _Авторитет стейкінгу_ використовується для підпису транзакцій, пов’язаних із: + - Делегуванням стейку - Деактивацією делегування стейку - Розділенням облікового запису на два окремі @@ -33,24 +56,32 @@ title: Облікові Записи Стейкінгу #### Множинне Делегування -Один обліковий запис стейкінгу може бути делегований лише одному валідатору. Усі токени в обліковому записі є або делегованими, або неделегованими. Щоб делегувати частину токенів кільком валідаторам, потрібно створити кілька облікових записів стейкінгу. +Один обліковий запис стейкінгу може бути делегований лише одному валідатору. Усі +токени в обліковому записі є або делегованими, або неделегованими. Щоб +делегувати частину токенів кільком валідаторам, потрібно створити кілька +облікових записів стейкінгу. #### Об'єднання Облікових Записів -Два облікові записи стейкінгу з однаковими авторитетами та параметрами блокування можуть бути об’єднані в один. +Два облікові записи стейкінгу з однаковими авторитетами та параметрами +блокування можуть бути об’єднані в один. #### Розігрів та Охолодження Делегування -Процес делегування або деактивації делегування не є миттєвим і може займати кілька [епох](/docs/terminology.md#epoch). +Процес делегування або деактивації делегування не є миттєвим і може займати +кілька [епох](/docs/terminology.md#epoch). #### Блокування -Облікові записи стейкінгу можуть мати блокування, яке забороняє виведення токенів до досягнення певної дати або епохи. +Облікові записи стейкінгу можуть мати блокування, яке забороняє виведення +токенів до досягнення певної дати або епохи. #### Видалення Облікового Запису -Обліковий запис стейкінгу, баланс якого дорівнює 0 SOL, автоматично припиняє існувати. +Обліковий запис стейкінгу, баланс якого дорівнює 0 SOL, автоматично припиняє +існувати. #### Перегляд Облікових Записів Стейкінгу -Інформацію про обліковий запис стейкінгу можна переглянути через [Solana Explorer](http://explorer.solana.com/accounts). +Інформацію про обліковий запис стейкінгу можна переглянути через +[Solana Explorer](http://explorer.solana.com/accounts). diff --git a/docs/locales/uk/economics/staking/stake-programming.md b/docs/locales/uk/economics/staking/stake-programming.md index f914000a2..ce5511476 100644 --- a/docs/locales/uk/economics/staking/stake-programming.md +++ b/docs/locales/uk/economics/staking/stake-programming.md @@ -2,14 +2,30 @@ title: Програмування Стейкінгу --- -Для максимізації розподілу стейку, децентралізації та стійкості до цензури в мережі Solana, стейкінг може виконуватись програмно. Команда та спільнота розробили кілька програм для роботи як на ланцюгу, так і поза ним, щоб зробити управління стейками простішим. +Для максимізації розподілу стейку, децентралізації та стійкості до цензури в +мережі Solana, стейкінг може виконуватись програмно. Команда та спільнота +розробили кілька програм для роботи як на ланцюгу, так і поза ним, щоб зробити +управління стейками простішим. #### Stake-o-matic, також відомий як боти автоделегування -Ця позаланцюгова програма управляє великою кількістю валідаторів, яким делегує стейк центральний орган. Фонд Solana використовує бота автоделегування для регулярного делегування свого стейку "неспійманим" валідаторам, які відповідають визначеним вимогам продуктивності. +Ця позаланцюгова програма управляє великою кількістю валідаторів, яким делегує +стейк центральний орган. Фонд Solana використовує бота автоделегування для +регулярного делегування свого стейку "неспійманим" валідаторам, які відповідають +визначеним вимогам продуктивності. #### Stake Pools -Ця програма на ланцюгу об'єднує SOL для стейкінгу, яким управляє менеджер, дозволяючи власникам SOL здійснювати стейкінг та отримувати винагороди без необхідності управляти стейками. Користувачі депонують SOL в обмін на SPL-токени (похідні стейкінгу), які представляють їхню частку в пулі стейкінгу. Менеджер пулу здійснює стейкінг внесених SOL відповідно до своєї стратегії, можливо, використовуючи варіант бота автоделегування, описаного вище. Коли стейки отримують винагороди, вартість пулу та токенів пулу пропорційно зростає. Нарешті, власники токенів пулу можуть повернути SPL-токени назад у пул стейкінгу для викупу SOL, тим самим беручи участь у децентралізації з мінімальними зусиллями. +Ця програма на ланцюгу об'єднує SOL для стейкінгу, яким управляє менеджер, +дозволяючи власникам SOL здійснювати стейкінг та отримувати винагороди без +необхідності управляти стейками. Користувачі депонують SOL в обмін на SPL-токени +(похідні стейкінгу), які представляють їхню частку в пулі стейкінгу. Менеджер +пулу здійснює стейкінг внесених SOL відповідно до своєї стратегії, можливо, +використовуючи варіант бота автоделегування, описаного вище. Коли стейки +отримують винагороди, вартість пулу та токенів пулу пропорційно зростає. +Нарешті, власники токенів пулу можуть повернути SPL-токени назад у пул стейкінгу +для викупу SOL, тим самим беручи участь у децентралізації з мінімальними +зусиллями. -Детальнішу інформацію можна знайти в [документації SPL Stake Pool](https://spl.solana.com/stake-pool). +Детальнішу інформацію можна знайти в +[документації SPL Stake Pool](https://spl.solana.com/stake-pool). diff --git a/docs/locales/uk/index.md b/docs/locales/uk/index.md index 10ac0c1ec..94f35a425 100644 --- a/docs/locales/uk/index.md +++ b/docs/locales/uk/index.md @@ -4,8 +4,8 @@ title: Документація Solana seoTitle: Дізнайтеся, як працює блокчейн Solana description: "Solana — це високопродуктивний блокчейн, створений для масового впровадження. - Дізнайтеся, чому Solana є найкращим вибором для розробників, які прагнуть створювати - масштабовані блокчейн-додатки." + Дізнайтеся, чому Solana є найкращим вибором для розробників, які прагнуть + створювати масштабовані блокчейн-додатки." altRoutes: - /docs/intro/history - /docs/intro @@ -13,61 +13,93 @@ altRoutes: isHiddenInNavSidebar: true --- -Solana — це блокчейн, створений для масового використання. Це високопродуктивна мережа, яка використовується для різних сфер, включаючи фінанси, NFT, платежі та ігри. Solana працює як єдина глобальна станова машина, є відкритою, інтероперабельною та децентралізованою. +Solana — це блокчейн, створений для масового використання. Це високопродуктивна +мережа, яка використовується для різних сфер, включаючи фінанси, NFT, платежі та +ігри. Solana працює як єдина глобальна станова машина, є відкритою, +інтероперабельною та децентралізованою. ## Початок роботи -Пориньте у світ Solana, щоб почати створювати або налаштовувати своє локальне середовище. +Пориньте у світ Solana, щоб почати створювати або налаштовувати своє локальне +середовище. -- [Швидкий старт](/docs/intro/quick-start) — Створіть і розгорніть свою першу програму на Solana прямо у браузері за допомогою Solana Playground -- [Налаштування локального середовища](/docs/intro/installation) — Встановіть CLI Solana для налаштування локального середовища розробки +- [Швидкий старт](/docs/intro/quick-start) — Створіть і розгорніть свою першу + програму на Solana прямо у браузері за допомогою Solana Playground +- [Налаштування локального середовища](/docs/intro/installation) — Встановіть + CLI Solana для налаштування локального середовища розробки ## Почніть навчання -Поглиблено вивчіть основні концепції, які роблять Solana унікальною серед інших блокчейнів. +Поглиблено вивчіть основні концепції, які роблять Solana унікальною серед інших +блокчейнів. - [Акаунти](/docs/core/accounts) — Механізм зберігання даних і стану для Solana -- [Комісії в Solana](/docs/core/fees) — Різні витрати, пов’язані з використанням мережі -- [Транзакції](/docs/core/transactions) — Набір інструкцій для виконання блокчейном -- [Програми](/docs/core/programs) — Виконуваний код для виконання дій у блокчейні -- [Програмно похідні адреси](/docs/core/pda) — Детерміновано створені адреси, які дозволяють програмам Solana програмно "підписувати" транзакції -- [Виклики між програмами](/docs/core/cpi) — Основний механізм "композованості" Solana, який дозволяє програмам "викликати" одна одну +- [Комісії в Solana](/docs/core/fees) — Різні витрати, пов’язані з використанням + мережі +- [Транзакції](/docs/core/transactions) — Набір інструкцій для виконання + блокчейном +- [Програми](/docs/core/programs) — Виконуваний код для виконання дій у + блокчейні +- [Програмно похідні адреси](/docs/core/pda) — Детерміновано створені адреси, + які дозволяють програмам Solana програмно "підписувати" транзакції +- [Виклики між програмами](/docs/core/cpi) — Основний механізм "композованості" + Solana, який дозволяє програмам "викликати" одна одну ## Розуміння архітектури Дізнайтеся, як працює блокчейн Proof-of-Stake у основі Solana. -- [Валідатори](https://docs.anza.xyz/validator/anatomy) — окремі вузли, які є основою мережі -- [Кластери](/docs/core/clusters) — група валідаторів, що працюють разом для досягнення консенсусу +- [Валідатори](https://docs.anza.xyz/validator/anatomy) — окремі вузли, які є + основою мережі +- [Кластери](/docs/core/clusters) — група валідаторів, що працюють разом для + досягнення консенсусу ## Запуск валідатора -Дізнайтеся, що потрібно для роботи валідатора Solana та забезпечення безпеки мережі. +Дізнайтеся, що потрібно для роботи валідатора Solana та забезпечення безпеки +мережі. -- [Системні вимоги](https://docs.anza.xyz/operations/requirements) — Рекомендовані апаратні вимоги та очікувана кількість SOL, необхідна для запуску валідатора -- [Швидкий старт](https://docs.anza.xyz/operations/setup-a-validator) — Налаштуйте валідатор і підключіться до кластера вперше +- [Системні вимоги](https://docs.anza.xyz/operations/requirements) — + Рекомендовані апаратні вимоги та очікувана кількість SOL, необхідна для + запуску валідатора +- [Швидкий старт](https://docs.anza.xyz/operations/setup-a-validator) — + Налаштуйте валідатор і підключіться до кластера вперше ## Чому Solana? -Створена для масштабування, Solana призначена для того, щоб блокчейн-додатки могли досягати мільйонів користувачів. Замість оптимізації під блокчейн-рівень розробники можуть зосередитися на створенні додатків, які досягнуть відповідності ринку. Мережа не тільки може масштабуватися для поточних потреб блокчейн-додатків, але й постійно оптимізується з урахуванням досвіду користувачів. +Створена для масштабування, Solana призначена для того, щоб блокчейн-додатки +могли досягати мільйонів користувачів. Замість оптимізації під блокчейн-рівень +розробники можуть зосередитися на створенні додатків, які досягнуть +відповідності ринку. Мережа не тільки може масштабуватися для поточних потреб +блокчейн-додатків, але й постійно оптимізується з урахуванням досвіду +користувачів. -Створення найкращого користувацького досвіду є головним пріоритетом для розробників. У блокчейнах користувацький досвід часто обмежений базовими технологіями, що спричиняє повільний час відгуку та високі комісії. Низькі комісії Solana та час підтвердження в 400 мс дозволяють розробникам створювати зручні для користувачів додатки, доступні кожному. +Створення найкращого користувацького досвіду є головним пріоритетом для +розробників. У блокчейнах користувацький досвід часто обмежений базовими +технологіями, що спричиняє повільний час відгуку та високі комісії. Низькі +комісії Solana та час підтвердження в 400 мс дозволяють розробникам створювати +зручні для користувачів додатки, доступні кожному. ## Особливості Solana -| Функція | Опис | -| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Розробка програм на блокчейні | Можливість розробляти та розгортати програми на блокчейні. Користувачі можуть взаємодіяти з цими програмами без дозволу, усуваючи потребу у посередниках для створення додатків. | -| 400 мс для блоків | Кожна транзакція користувачів у Solana підтверджується в блоці. З цільовим часом 400 мс для кожного блоку, взаємодія користувачів є швидкою, забезпечуючи найкращий у своєму класі досвід. | -| Низькі комісії | Комісії в Solana відомі своєю низькістю. Середня комісія становить 0.00064 SOL за транзакцію, що дозволяє створювати додатки для користувачів з усього світу, незалежно від їх походження. | -| Висока пропускна здатність | Масштабування до тисяч транзакцій за секунду, Solana створена для масштабування відповідно до потреб користувачів вашого додатку. | +| Функція | Опис | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Розробка програм на блокчейні | Можливість розробляти та розгортати програми на блокчейні. Користувачі можуть взаємодіяти з цими програмами без дозволу, усуваючи потребу у посередниках для створення додатків. | +| 400 мс для блоків | Кожна транзакція користувачів у Solana підтверджується в блоці. З цільовим часом 400 мс для кожного блоку, взаємодія користувачів є швидкою, забезпечуючи найкращий у своєму класі досвід. | +| Низькі комісії | Комісії в Solana відомі своєю низькістю. Середня комісія становить 0.00064 SOL за транзакцію, що дозволяє створювати додатки для користувачів з усього світу, незалежно від їх походження. | +| Висока пропускна здатність | Масштабування до тисяч транзакцій за секунду, Solana створена для масштабування відповідно до потреб користувачів вашого додатку. | ## Як користуватися цими документами -Зліва ви знайдете бічну панель документації. Вона містить документацію у порядку від базової до більш просунутої інформації. Якщо ви новачок у Solana, рекомендуємо почати з самого верху і рухатися вниз. Однак ви можете читати їх у будь-якому порядку, який вам подобається. +Зліва ви знайдете бічну панель документації. Вона містить документацію у порядку +від базової до більш просунутої інформації. Якщо ви новачок у Solana, +рекомендуємо почати з самого верху і рухатися вниз. Однак ви можете читати їх у +будь-якому порядку, який вам подобається. -Коли будете готові почати створення, ознайомтеся з посібником [Швидкий старт](/docs/intro/quick-start). +Коли будете готові почати створення, ознайомтеся з посібником +[Швидкий старт](/docs/intro/quick-start). ## Потрібна допомога? -Отримайте допомогу від спільноти Solana на [Solana StackExchange](https://solana.stackexchange.com). +Отримайте допомогу від спільноти Solana на +[Solana StackExchange](https://solana.stackexchange.com). diff --git a/docs/locales/uk/intro/dev.md b/docs/locales/uk/intro/dev.md index ac56bb2d1..725c8aeb0 100644 --- a/docs/locales/uk/intro/dev.md +++ b/docs/locales/uk/intro/dev.md @@ -13,32 +13,61 @@ keywords: Ласкаво просимо до документації для розробників Solana! -На цій сторінці зібрано все, що вам потрібно знати для початку розробки на Solana, включаючи основні вимоги, принципи роботи та інструменти, необхідні для старту. +На цій сторінці зібрано все, що вам потрібно знати для початку розробки на +Solana, включаючи основні вимоги, принципи роботи та інструменти, необхідні для +старту. ## Огляд Розробки на Високому Рівні Розробку на Solana можна розділити на дві основні частини: -1. **Розробка Програм на Блокчейні**: Тут ви створюєте та розгортаєте користувацькі програми безпосередньо у блокчейні. Після розгортання будь-хто, хто знає, як із ними працювати, може їх використовувати. Ці програми можна писати на Rust, C або C++. Rust наразі має найбільшу підтримку для розробки програм на блокчейні. -2. **Клієнтська Розробка**: Це створення програмного забезпечення (децентралізованих додатків або dApps), яке взаємодіє з програмами на блокчейні. Ваші додатки можуть надсилати транзакції для виконання дій у блокчейні. Клієнтську розробку можна виконувати на будь-якій мові програмування. - -"Зв'язок" між клієнтською та блокчейн-частиною забезпечується [Solana JSON RPC API](https://solana.com/docs/rpc). Клієнтська частина надсилає запити RPC до мережі Solana для взаємодії з програмами на блокчейні. Це дуже схоже на звичайний процес розробки між frontend і backend. Головна відмінність у роботі з Solana — це те, що backend є глобальним блокчейном без дозволів. Це означає, що будь-хто може взаємодіяти з вашою програмою на блокчейні без необхідності видачі API-ключів або будь-яких інших форм дозволів. +1. **Розробка Програм на Блокчейні**: Тут ви створюєте та розгортаєте + користувацькі програми безпосередньо у блокчейні. Після розгортання будь-хто, + хто знає, як із ними працювати, може їх використовувати. Ці програми можна + писати на Rust, C або C++. Rust наразі має найбільшу підтримку для розробки + програм на блокчейні. +2. **Клієнтська Розробка**: Це створення програмного забезпечення + (децентралізованих додатків або dApps), яке взаємодіє з програмами на + блокчейні. Ваші додатки можуть надсилати транзакції для виконання дій у + блокчейні. Клієнтську розробку можна виконувати на будь-якій мові + програмування. + +"Зв'язок" між клієнтською та блокчейн-частиною забезпечується +[Solana JSON RPC API](https://solana.com/docs/rpc). Клієнтська частина надсилає +запити RPC до мережі Solana для взаємодії з програмами на блокчейні. Це дуже +схоже на звичайний процес розробки між frontend і backend. Головна відмінність у +роботі з Solana — це те, що backend є глобальним блокчейном без дозволів. Це +означає, що будь-хто може взаємодіяти з вашою програмою на блокчейні без +необхідності видачі API-ключів або будь-яких інших форм дозволів. ![Як клієнти працюють із блокчейном Solana](/assets/docs/intro/developer_flow.png) -Розробка на Solana відрізняється від інших блокчейнів завдяки своїм високо-композитним програмам на блокчейні. Це означає, що ви можете будувати на базі вже існуючих програм, часто без необхідності створення власних. Наприклад, якщо ви хочете працювати з токенами, ви можете використовувати [Token Program](/docs/uk/core/tokens.md), який вже розгорнутий у мережі. Уся розробка вашого додатка буде клієнтською, на обраній вами мові програмування. +Розробка на Solana відрізняється від інших блокчейнів завдяки своїм +високо-композитним програмам на блокчейні. Це означає, що ви можете будувати на +базі вже існуючих програм, часто без необхідності створення власних. Наприклад, +якщо ви хочете працювати з токенами, ви можете використовувати +[Token Program](/docs/uk/core/tokens.md), який вже розгорнутий у мережі. Уся +розробка вашого додатка буде клієнтською, на обраній вами мові програмування. -Розробники, які хочуть будувати на Solana, знайдуть, що стек розробки дуже схожий на інші. Основна відмінність у тому, що ви працюєте з блокчейном і повинні враховувати, як користувачі взаємодіють із вашим додатком на блокчейні, а не тільки у frontend. Розробка на Solana все ще включає CI/CD, тестування, інструменти для налагодження, frontend і backend, як і будь-який звичайний процес розробки. +Розробники, які хочуть будувати на Solana, знайдуть, що стек розробки дуже +схожий на інші. Основна відмінність у тому, що ви працюєте з блокчейном і +повинні враховувати, як користувачі взаємодіють із вашим додатком на блокчейні, +а не тільки у frontend. Розробка на Solana все ще включає CI/CD, тестування, +інструменти для налагодження, frontend і backend, як і будь-який звичайний +процес розробки. ## Що Вам Потрібно для Початку -Для початку розробки на Solana вам знадобляться різні інструменти залежно від того, чи ви розробляєте клієнтські додатки, програми на блокчейні або обидва. +Для початку розробки на Solana вам знадобляться різні інструменти залежно від +того, чи ви розробляєте клієнтські додатки, програми на блокчейні або обидва. ### Клієнтська Розробка Якщо ви розробляєте програми на блокчейні, вам потрібно знати Rust. -Якщо ж ви розробляєте клієнтські додатки, ви можете працювати на будь-якій мові програмування, з якою вам зручно. Solana має SDK, створені спільнотою, щоб допомогти розробникам взаємодіяти з мережею Solana на більшості популярних мов: +Якщо ж ви розробляєте клієнтські додатки, ви можете працювати на будь-якій мові +програмування, з якою вам зручно. Solana має SDK, створені спільнотою, щоб +допомогти розробникам взаємодіяти з мережею Solana на більшості популярних мов: | Мова | SDK | | ---------- | -------------------------------------------------------------------------------------------------------- | @@ -53,71 +82,116 @@ keywords: | C# | [solnet](https://github.com/bmresearch/Solnet) | | GdScript | [godot](https://github.com/Virus-Axel/godot-solana-sdk/) | -Вам також знадобиться підключення до RPC для взаємодії з мережею. Ви можете скористатися [провайдером RPC](https://solana.com/rpc) або [запустити власний RPC-вузол](https://docs.anza.xyz/operations/setup-an-rpc-node). +Вам також знадобиться підключення до RPC для взаємодії з мережею. Ви можете +скористатися [провайдером RPC](https://solana.com/rpc) або +[запустити власний RPC-вузол](https://docs.anza.xyz/operations/setup-an-rpc-node). -Щоб швидко розпочати роботу з фронтендом для вашого додатка, ви можете згенерувати налаштовуваний каркас Solana, ввівши наступну команду у ваш CLI: +Щоб швидко розпочати роботу з фронтендом для вашого додатка, ви можете +згенерувати налаштовуваний каркас Solana, ввівши наступну команду у ваш CLI: ```bash npx create-solana-dapp ``` -Ця команда створить новий проєкт із усіма необхідними файлами та базовою конфігурацією для початку розробки на Solana. Каркас включатиме як приклад фронтенда, так і шаблон програми на блокчейні (якщо ви його обрали). Ви можете ознайомитися з [документацією `create-solana-dapp`](https://github.com/solana-developers/create-solana-dapp?tab=readme-ov-file#create-solana-dapp), щоб дізнатися більше. +Ця команда створить новий проєкт із усіма необхідними файлами та базовою +конфігурацією для початку розробки на Solana. Каркас включатиме як приклад +фронтенда, так і шаблон програми на блокчейні (якщо ви його обрали). Ви можете +ознайомитися з +[документацією `create-solana-dapp`](https://github.com/solana-developers/create-solana-dapp?tab=readme-ov-file#create-solana-dapp), +щоб дізнатися більше. ### Розробка Програм на Блокчейні -Розробка програм на блокчейні включає написання програм на Rust, C або C++. Спочатку переконайтеся, що у вас встановлений Rust. Ви можете зробити це за допомогою наступної команди: +Розробка програм на блокчейні включає написання програм на Rust, C або C++. +Спочатку переконайтеся, що у вас встановлений Rust. Ви можете зробити це за +допомогою наступної команди: ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -Вам також потрібно встановити [Solana CLI](/docs/uk/intro/installation.md), щоб компілювати та розгортати ваші програми. Ви можете встановити Solana CLI, виконавши наступну команду: - +Вам також потрібно встановити [Solana CLI](/docs/uk/intro/installation.md), щоб +компілювати та розгортати ваші програми. Ви можете встановити Solana CLI, +виконавши наступну команду: ```bash sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)" ``` -Використовуючи Solana CLI, рекомендується запускати локальний валідатор для тестування вашої програми. Щоб запустити локальний валідатор після встановлення Solana CLI, виконайте наступну команду: - +Використовуючи Solana CLI, рекомендується запускати локальний валідатор для +тестування вашої програми. Щоб запустити локальний валідатор після встановлення +Solana CLI, виконайте наступну команду: ```bash solana-test-validator ``` -Це запустить локальний валідатор на вашій машині, який ви можете використовувати для тестування ваших програм. Ви можете [докладніше прочитати про локальну розробку в цьому посібнику](/docs/uk/intro/installation.md). - -Під час розробки програм на блокчейні ви можете вибрати між написанням програм на чистому Rust (без фреймворку) або використанням фреймворку Anchor. Anchor спрощує розробку на Solana, надаючи високорівневий API для розробників. Подумайте про Anchor як про використання React для створення вебсайтів замість чистого Javascript і HTML. Хоча Javascript і HTML дають вам більше контролю, React прискорює розробку та робить її простішою. Докладніше про [Anchor](https://www.anchor-lang.com/) можна дізнатися на їхньому сайті. - -Вам знадобиться спосіб тестування вашої програми. Ось кілька способів тестування залежно від ваших уподобань щодо мови програмування: - -- [solana-program-test](https://docs.rs/solana-program-test/latest/solana_program_test/) — фреймворк для тестування, написаний на Rust. -- [solana-bankrun](https://kevinheavey.github.io/solana-bankrun/) — фреймворк для тестування, написаний для тестів на Typescript. -- [bankrun](https://kevinheavey.github.io/solders/tutorials/bankrun.html) — фреймворк для тестування, написаний для тестів на Python. - -Якщо ви не хочете розробляти програми локально, існує також [онлайн IDE Solana Playground](https://beta.solpg.io). Solana Playground дозволяє писати, тестувати та розгортати програми на Solana. Ви можете розпочати роботу з Solana Playground, [слідувавши нашому посібнику швидкого старту](/docs/uk/intro/quick-start). +Це запустить локальний валідатор на вашій машині, який ви можете використовувати +для тестування ваших програм. Ви можете +[докладніше прочитати про локальну розробку в цьому посібнику](/docs/uk/intro/installation.md). + +Під час розробки програм на блокчейні ви можете вибрати між написанням програм +на чистому Rust (без фреймворку) або використанням фреймворку Anchor. Anchor +спрощує розробку на Solana, надаючи високорівневий API для розробників. +Подумайте про Anchor як про використання React для створення вебсайтів замість +чистого Javascript і HTML. Хоча Javascript і HTML дають вам більше контролю, +React прискорює розробку та робить її простішою. Докладніше про +[Anchor](https://www.anchor-lang.com/) можна дізнатися на їхньому сайті. + +Вам знадобиться спосіб тестування вашої програми. Ось кілька способів тестування +залежно від ваших уподобань щодо мови програмування: + +- [solana-program-test](https://docs.rs/solana-program-test/latest/solana_program_test/) + — фреймворк для тестування, написаний на Rust. +- [solana-bankrun](https://kevinheavey.github.io/solana-bankrun/) — фреймворк + для тестування, написаний для тестів на Typescript. +- [bankrun](https://kevinheavey.github.io/solders/tutorials/bankrun.html) — + фреймворк для тестування, написаний для тестів на Python. + +Якщо ви не хочете розробляти програми локально, існує також +[онлайн IDE Solana Playground](https://beta.solpg.io). Solana Playground +дозволяє писати, тестувати та розгортати програми на Solana. Ви можете розпочати +роботу з Solana Playground, +[слідувавши нашому посібнику швидкого старту](/docs/uk/intro/quick-start). ### Середовища Розробки -Вибір правильного середовища залежно від вашої роботи дуже важливий. У Solana є кілька середовищ (кластерів) для забезпечення якісного тестування та CI/CD практик: +Вибір правильного середовища залежно від вашої роботи дуже важливий. У Solana є +кілька середовищ (кластерів) для забезпечення якісного тестування та CI/CD +практик: -- **Mainnet Beta**: Продуктивна мережа, де відбувається вся дія. Транзакції тут коштують реальних грошей. -- **Devnet**: Мережа для забезпечення якості, де ви розгортаєте ваші програми для тестування перед розгортанням у продуктивне середовище. Це як "середовище для постановки". -- **Local**: Локальна мережа, яку ви запускаєте на своїй машині за допомогою `solana-test-validator` для тестування ваших програм. Це має бути вашим першим вибором під час розробки. +- **Mainnet Beta**: Продуктивна мережа, де відбувається вся дія. Транзакції тут + коштують реальних грошей. +- **Devnet**: Мережа для забезпечення якості, де ви розгортаєте ваші програми + для тестування перед розгортанням у продуктивне середовище. Це як "середовище + для постановки". +- **Local**: Локальна мережа, яку ви запускаєте на своїй машині за допомогою + `solana-test-validator` для тестування ваших програм. Це має бути вашим першим + вибором під час розробки. ## Побудова на Основі Прикладів -Під час початку розробки на Solana є кілька ресурсів, які допоможуть прискорити ваш шлях: +Під час початку розробки на Solana є кілька ресурсів, які допоможуть прискорити +ваш шлях: -- [Solana Cookbook](https://solana.com/developers/cookbook): Збірка довідників і фрагментів коду для допомоги у розробці на Solana. -- [Приклади Програм Solana](https://github.com/solana-developers/program-examples): Репозиторій прикладів програм, що надають будівельні блоки для різних дій у ваших програмах. -- [Посібники](https://solana.com/developers/guides): Посібники та інструкції, які проведуть вас через процес розробки на Solana. +- [Solana Cookbook](https://solana.com/developers/cookbook): Збірка довідників і + фрагментів коду для допомоги у розробці на Solana. +- [Приклади Програм Solana](https://github.com/solana-developers/program-examples): + Репозиторій прикладів програм, що надають будівельні блоки для різних дій у + ваших програмах. +- [Посібники](https://solana.com/developers/guides): Посібники та інструкції, + які проведуть вас через процес розробки на Solana. ## Отримання Підтримки -Найкращу підтримку ви можете знайти на [Solana StackExchange](https://solana.stackexchange.com/). Спочатку пошукайте своє питання там — є велика ймовірність, що вже існує схоже питання з відповіддю. Якщо його там немає, додайте нове питання! Не забудьте включити якомога більше деталей у ваше питання, і, будь ласка, використовуйте текст (а не скріншоти) для відображення повідомлень про помилки, щоб інші люди з такою ж проблемою могли знайти ваше питання! +Найкращу підтримку ви можете знайти на +[Solana StackExchange](https://solana.stackexchange.com/). Спочатку пошукайте +своє питання там — є велика ймовірність, що вже існує схоже питання з +відповіддю. Якщо його там немає, додайте нове питання! Не забудьте включити +якомога більше деталей у ваше питання, і, будь ласка, використовуйте текст (а не +скріншоти) для відображення повідомлень про помилки, щоб інші люди з такою ж +проблемою могли знайти ваше питання! ## Наступні кроки [Тепер ви готові почати створювати на Solana!](/docs/uk/intro/quick-start) - diff --git a/docs/locales/uk/intro/installation.md b/docs/locales/uk/intro/installation.md index fb7dce6fc..117c101dd 100644 --- a/docs/locales/uk/intro/installation.md +++ b/docs/locales/uk/intro/installation.md @@ -14,50 +14,64 @@ altRoutes: - /setup --- -Цей розділ охоплює етапи налаштування локального середовища для розробки на Solana. +Цей розділ охоплює етапи налаштування локального середовища для розробки на +Solana. ## Встановлення Залежностей -- Користувачі Windows повинні спочатку встановити WSL (Windows Subsystem for Linux), а потім встановити залежності, зазначені в розділі Linux нижче. -- Користувачі Linux повинні спочатку встановити залежності, зазначені в розділі Linux нижче. +- Користувачі Windows повинні спочатку встановити WSL (Windows Subsystem for + Linux), а потім встановити залежності, зазначені в розділі Linux нижче. +- Користувачі Linux повинні спочатку встановити залежності, зазначені в розділі + Linux нижче. - Користувачі Mac повинні почати з інструкцій з установки Rust нижче. Для розробки програм Solana на Windows **необхідно використовувати -[WSL](https://learn.microsoft.com/en-us/windows/wsl/install)** (Windows Subsystem for Linux). Усі додаткові залежності необхідно встановлювати через термінал Linux. +[WSL](https://learn.microsoft.com/en-us/windows/wsl/install)** (Windows +Subsystem for Linux). Усі додаткові залежності необхідно встановлювати через +термінал Linux. -Після встановлення WSL встановіть залежності, зазначені в розділі Linux нижче, перш ніж переходити до установки Rust, Solana CLI та Anchor CLI. +Після встановлення WSL встановіть залежності, зазначені в розділі Linux нижче, +перш ніж переходити до установки Rust, Solana CLI та Anchor CLI. Щоб встановити WSL, виконайте наступну команду у Windows PowerShell: - ```shell wsl --install ``` -Процес встановлення запропонує вам створити обліковий запис користувача за замовчуванням. +Процес встановлення запропонує вам створити обліковий запис користувача за +замовчуванням. ![WSL Install](/assets/docs/intro/installation/wsl-install.png) -За замовчуванням WSL встановлює Ubuntu. Ви можете відкрити термінал Linux, ввівши "Ubuntu" у пошуковому рядку. +За замовчуванням WSL встановлює Ubuntu. Ви можете відкрити термінал Linux, +ввівши "Ubuntu" у пошуковому рядку. ![WSL Ubuntu](/assets/docs/intro/installation/wsl-ubuntu-search.png) -Якщо ваш термінал Ubuntu виглядає так, як на зображенні нижче, ви можете зіткнутися з проблемою, коли комбінація `ctrl + v` (вставити) не працює у терміналі. +Якщо ваш термінал Ubuntu виглядає так, як на зображенні нижче, ви можете +зіткнутися з проблемою, коли комбінація `ctrl + v` (вставити) не працює у +терміналі. ![Ubuntu Terminal](/assets/docs/intro/installation/wsl-ubuntu-terminal-1.png) -Якщо виникла ця проблема, відкрийте Windows Terminal, ввівши "Terminal" у пошуковому рядку. +Якщо виникла ця проблема, відкрийте Windows Terminal, ввівши "Terminal" у +пошуковому рядку. ![Windows Terminal](/assets/docs/intro/installation/wsl-windows-terminal.png) -Далі закрийте Windows Terminal і знову відкрийте термінал Linux, ввівши "Ubuntu" у пошуку. Тепер термінал має виглядати так, як на зображенні нижче, і комбінація `ctrl + v` (вставити) має працювати. +Далі закрийте Windows Terminal і знову відкрийте термінал Linux, ввівши "Ubuntu" +у пошуку. Тепер термінал має виглядати так, як на зображенні нижче, і комбінація +`ctrl + v` (вставити) має працювати. ![Ubuntu Terminal](/assets/docs/intro/installation/wsl-ubuntu-terminal-2.png) -Якщо ви використовуєте VS Code, розширення [WSL extension](https://code.visualstudio.com/docs/remote/wsl-tutorial) дозволяє використовувати WSL та VS Code разом. +Якщо ви використовуєте VS Code, розширення +[WSL extension](https://code.visualstudio.com/docs/remote/wsl-tutorial) дозволяє +використовувати WSL та VS Code разом. ![WSL Setup in VS Code](/assets/docs/intro/installation/wsl-vscode.png) @@ -65,7 +79,9 @@ wsl --install ![WSL: Ubuntu](/assets/docs/intro/installation/wsl-vscode-ubuntu.png) -Після налаштування WSL всі додаткові залежності потрібно встановлювати через термінал Linux. Встановіть залежності, зазначені в розділі Linux нижче, перш ніж переходити до встановлення Rust, Solana CLI та Anchor CLI. +Після налаштування WSL всі додаткові залежності потрібно встановлювати через +термінал Linux. Встановіть залежності, зазначені в розділі Linux нижче, перш ніж +переходити до встановлення Rust, Solana CLI та Anchor CLI. @@ -77,8 +93,8 @@ wsl --install ```shell sudo apt-get update ``` -Далі встановіть наступні залежності: +Далі встановіть наступні залежності: ```shell sudo apt-get install -y \ @@ -87,7 +103,9 @@ sudo apt-get install -y \ libudev-dev llvm libclang-dev \ protobuf-compiler libssl-dev ``` -Якщо під час встановлення `protobuf-compiler` ви зіткнетеся з такою помилкою, спочатку переконайтеся, що виконали команду `sudo apt-get update`: + +Якщо під час встановлення `protobuf-compiler` ви зіткнетеся з такою помилкою, +спочатку переконайтеся, що виконали команду `sudo apt-get update`: ``` Package protobuf-compiler is not available, but is referred to by another package. @@ -102,9 +120,11 @@ is only available from another source ### Встановлення Rust -Програми Solana пишуться на [мові програмування Rust](https://www.rust-lang.org/). +Програми Solana пишуться на +[мові програмування Rust](https://www.rust-lang.org/). -Рекомендований метод встановлення Rust — це [rustup](https://www.rust-lang.org/tools/install). +Рекомендований метод встановлення Rust — це +[rustup](https://www.rust-lang.org/tools/install). Виконайте наступну команду для встановлення Rust: @@ -135,7 +155,8 @@ source "$HOME/.cargo/env.fish" # For fish -Виконайте наступну команду, щоб оновити змінну середовища PATH і включити директорію `bin` Cargo: +Виконайте наступну команду, щоб оновити змінну середовища PATH і включити +директорію `bin` Cargo: ```shell . "$HOME/.cargo/env" @@ -155,17 +176,22 @@ rustc 1.80.1 (3f5fd8dd4 2024-08-06) ### Встановлення Solana CLI -Solana CLI надає всі необхідні інструменти для створення та розгортання програм Solana. +Solana CLI надає всі необхідні інструменти для створення та розгортання програм +Solana. -Встановіть набір інструментів Solana CLI за допомогою офіційної команди встановлення: +Встановіть набір інструментів Solana CLI за допомогою офіційної команди +встановлення: ```shell sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)" ``` -Ви можете замінити `stable` на тег релізу, який відповідає версії програмного забезпечення потрібного релізу (наприклад, `v2.0.3`), або використовувати один із трьох символічних назв каналів: `stable`, `beta` або `edge`. +Ви можете замінити `stable` на тег релізу, який відповідає версії програмного +забезпечення потрібного релізу (наприклад, `v2.0.3`), або використовувати один +із трьох символічних назв каналів: `stable`, `beta` або `edge`. -Якщо ви встановлюєте Solana CLI вперше, ви можете побачити таке повідомлення із запитом на додавання змінної середовища PATH: +Якщо ви встановлюєте Solana CLI вперше, ви можете побачити таке повідомлення із +запитом на додавання змінної середовища PATH: ``` Close and reopen your terminal to apply the PATH changes or run the following in your existing shell: @@ -176,7 +202,9 @@ export PATH="/Users/test/.local/share/solana/install/active_release/bin:$PATH" -Якщо ви використовуєте термінал Linux або WSL, ви можете додати змінну середовища PATH у файл конфігурації вашої оболонки, виконавши команду, зазначену під час встановлення, або перезапустивши термінал. +Якщо ви використовуєте термінал Linux або WSL, ви можете додати змінну +середовища PATH у файл конфігурації вашої оболонки, виконавши команду, зазначену +під час встановлення, або перезапустивши термінал. ```shell export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" @@ -185,16 +213,19 @@ export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" -Якщо ви використовуєте Mac із оболонкою `zsh`, виконання стандартної команди `export PATH`, зазначеної під час встановлення, не зберігається після закриття термінала. +Якщо ви використовуєте Mac із оболонкою `zsh`, виконання стандартної команди +`export PATH`, зазначеної під час встановлення, не зберігається після закриття +термінала. -Замість цього ви можете додати PATH у файл конфігурації оболонки, виконавши наступну команду: +Замість цього ви можете додати PATH у файл конфігурації оболонки, виконавши +наступну команду: ```shell echo 'export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"' >> ~/.zshrc ``` -Далі виконайте наступну команду, щоб оновити сесію термінала, або перезапустіть термінал. - +Далі виконайте наступну команду, щоб оновити сесію термінала, або перезапустіть +термінал. ```shell source ~/.zshrc @@ -205,27 +236,28 @@ source ~/.zshrc Щоб перевірити, чи встановлення було успішним, перевірте версію Solana CLI: - ```shell solana --version ``` -Ви повинні побачити результат, схожий на наступний: +Ви повинні побачити результат, схожий на наступний: ``` solana-cli 1.18.22 (src:9efdd74b; feat:4215500110, client:Agave) ``` -Ви можете переглянути всі доступні версії у [репозиторії Agave на Github](https://github.com/anza-xyz/agave/releases). +Ви можете переглянути всі доступні версії у +[репозиторії Agave на Github](https://github.com/anza-xyz/agave/releases). -Agave — це клієнт валідатора від [Anza](https://www.anza.xyz/), раніше відомий як клієнт валідатора Solana Labs. +Agave — це клієнт валідатора від [Anza](https://www.anza.xyz/), раніше відомий +як клієнт валідатора Solana Labs. -Щоб оновити Solana CLI до останньої версії, ви можете використати наступну команду: - +Щоб оновити Solana CLI до останньої версії, ви можете використати наступну +команду: ```shell agave-install update @@ -233,38 +265,43 @@ agave-install update ### Встановлення Anchor CLI -[Anchor](https://www.anchor-lang.com/) — це фреймворк для розробки програм на Solana. Anchor використовує макроси Rust, щоб спростити процес написання програм на Solana. +[Anchor](https://www.anchor-lang.com/) — це фреймворк для розробки програм на +Solana. Anchor використовує макроси Rust, щоб спростити процес написання програм +на Solana. Існує два способи встановлення Anchor CLI та інструментів: -1. За допомогою Anchor Version Manager (AVM) — **рекомендований спосіб встановлення**, оскільки він спрощує оновлення версій Anchor у майбутньому. -2. Без AVM — вимагає більш ручного процесу для оновлення версій Anchor у майбутньому. +1. За допомогою Anchor Version Manager (AVM) — **рекомендований спосіб + встановлення**, оскільки він спрощує оновлення версій Anchor у майбутньому. +2. Без AVM — вимагає більш ручного процесу для оновлення версій Anchor у + майбутньому. -Менеджер версій Anchor (AVM) дозволяє встановлювати та керувати різними версіями Anchor на вашій системі, включаючи зручне оновлення версій у майбутньому. +Менеджер версій Anchor (AVM) дозволяє встановлювати та керувати різними версіями +Anchor на вашій системі, включаючи зручне оновлення версій у майбутньому. Встановіть AVM за допомогою наступної команди: ```shell cargo install --git https://github.com/coral-xyz/anchor avm --force ``` -Перевірте, щоб переконатися, що AVM було встановлено та він доступний: +Перевірте, щоб переконатися, що AVM було встановлено та він доступний: ```shell avm --version ``` -Встановіть останню версію Anchor CLI за допомогою AVM: +Встановіть останню версію Anchor CLI за допомогою AVM: ```shell avm install latest avm use latest ``` -Або встановіть конкретну версію Anchor CLI, вказавши бажану версію: +Або встановіть конкретну версію Anchor CLI, вказавши бажану версію: ```shell avm install 0.30.1 @@ -290,7 +327,8 @@ cargo install --git https://github.com/coral-xyz/anchor --tag v0.30.1 anchor-cli -Під час встановлення ви можете побачити таке попередження. Однак це не впливає на процес встановлення. +Під час встановлення ви можете побачити таке попередження. Однак це не впливає +на процес встановлення. @@ -329,7 +367,8 @@ anchor --version anchor-cli 0.30.1 ``` -Під час встановлення Anchor CLI на Linux або WSL ви можете зіткнутися з такою помилкою: +Під час встановлення Anchor CLI на Linux або WSL ви можете зіткнутися з такою +помилкою: ``` error: could not exec the linker cc = note: Permission denied (os error 13) @@ -342,12 +381,15 @@ error: could not exec the linker cc = note: Permission denied (os error 13) #### Node.js та Yarn -Node.js та Yarn необхідні для запуску тестового файлу (TypeScript), створеного за допомогою команди `anchor init`. (Шаблон тестів на Rust також доступний за допомогою `anchor init --test-template rust`) +Node.js та Yarn необхідні для запуску тестового файлу (TypeScript), створеного +за допомогою команди `anchor init`. (Шаблон тестів на Rust також доступний за +допомогою `anchor init --test-template rust`) -Рекомендований спосіб встановлення Node — використання [Node Version Manager (nvm)](https://github.com/nvm-sh/nvm). +Рекомендований спосіб встановлення Node — використання +[Node Version Manager (nvm)](https://github.com/nvm-sh/nvm). Встановіть nvm за допомогою наступної команди: @@ -387,11 +429,13 @@ v22.7.0 ```shell npm install --global yarn ``` + Щоб перевірити, чи встановлення було успішним, перевірте версію Yarn: ``` yarn --version ``` + Ви повинні побачити наступний результат: ``` @@ -409,6 +453,7 @@ yarn --version ``` error: not a directory: '.../solana-release/bin/sdk/sbf/dependencies/platform-tools/rust/lib' ``` + Спробуйте ці рішення: 1. Примусове встановлення за допомогою наступної команди: @@ -433,16 +478,19 @@ rm -rf ~/.cache/solana/* version = 3 ``` -Дивіться [це обговорення](https://github.com/coral-xyz/anchor/issues/3392) для отримання додаткової інформації. - +Дивіться [це обговорення](https://github.com/coral-xyz/anchor/issues/3392) для +отримання додаткової інформації. -Після застосування будь-якого з рішень спробуйте знову виконати команду `anchor build`. +Після застосування будь-якого з рішень спробуйте знову виконати команду +`anchor build`. -Якщо ви використовуєте Linux або WSL і стикаєтеся з такими помилками під час виконання команди `anchor test` після створення нового проєкту Anchor, це може бути через відсутність Node.js або Yarn: +Якщо ви використовуєте Linux або WSL і стикаєтеся з такими помилками під час +виконання команди `anchor test` після створення нового проєкту Anchor, це може +бути через відсутність Node.js або Yarn: ``` Permission denied (os error 13) @@ -456,7 +504,8 @@ No such file or directory (os error 2) ## Основи Solana CLI -Цей розділ ознайомить вас із деякими поширеними командами Solana CLI для початку роботи. +Цей розділ ознайомить вас із деякими поширеними командами Solana CLI для початку +роботи. @@ -464,7 +513,6 @@ No such file or directory (os error 2) Щоб переглянути вашу поточну конфігурацію: - ```shell solana config get ``` @@ -479,7 +527,8 @@ Keypair Path: /Users/test/.config/solana/id.json Commitment: confirmed ``` -RPC URL та Websocket URL вказують кластер Solana, до якого CLI надсилатиме запити. За замовчуванням це буде mainnet-beta. +RPC URL та Websocket URL вказують кластер Solana, до якого CLI надсилатиме +запити. За замовчуванням це буде mainnet-beta. Ви можете оновити кластер Solana CLI за допомогою наступних команд: @@ -489,6 +538,7 @@ solana config set --url devnet solana config set --url localhost solana config set --url testnet ``` + Ви також можете використовувати наступні скорочені опції: ``` @@ -498,14 +548,19 @@ solana config set -ul # For localhost solana config set -ut # For testnet ``` -Шлях до ключової пари (Keypair Path) вказує розташування гаманця за замовчуванням, який використовується Solana CLI (для оплати комісій за транзакції та розгортання програм). Шлях за замовчуванням: `~/.config/solana/id.json`. У наступному кроці описано, як створити ключову пару за цим шляхом. +Шлях до ключової пари (Keypair Path) вказує розташування гаманця за +замовчуванням, який використовується Solana CLI (для оплати комісій за +транзакції та розгортання програм). Шлях за замовчуванням: +`~/.config/solana/id.json`. У наступному кроці описано, як створити ключову пару +за цим шляхом. ### Створення Гаманця -Для взаємодії з мережею Solana за допомогою Solana CLI вам потрібен гаманець Solana, поповнений SOL. - -Щоб створити ключову пару за замовчуванням у Keypair Path, виконайте наступну команду: +Для взаємодії з мережею Solana за допомогою Solana CLI вам потрібен гаманець +Solana, поповнений SOL. +Щоб створити ключову пару за замовчуванням у Keypair Path, виконайте наступну +команду: ```shell solana-keygen new @@ -534,11 +589,14 @@ cream bleak tortoise ocean nasty game gift forget fancy salon mimic amazing -Якщо у вас вже є гаманець у файловій системі, збережений у місці за замовчуванням, ця команда **НЕ** перезапише його, якщо ви явно не використаєте прапорець `--force`. +Якщо у вас вже є гаманець у файловій системі, збережений у місці за +замовчуванням, ця команда **НЕ** перезапише його, якщо ви явно не використаєте +прапорець `--force`. -Після створення ключової пари ви можете отримати адресу (публічний ключ) цієї пари за допомогою наступної команди: +Після створення ключової пари ви можете отримати адресу (публічний ключ) цієї +пари за допомогою наступної команди: ```shell solana address @@ -546,43 +604,47 @@ solana address ### Airdrop SOL -Після налаштування локального гаманця запросіть airdrop SOL для поповнення вашого гаманця. SOL потрібні для оплати комісій за транзакції та розгортання програм. +Після налаштування локального гаманця запросіть airdrop SOL для поповнення +вашого гаманця. SOL потрібні для оплати комісій за транзакції та розгортання +програм. Встановіть ваш кластер на devnet: - ```shell solana config set -ud ``` Далі запросіть airdrop SOL у devnet: - ```shell solana airdrop 2 ``` Щоб перевірити баланс SOL вашого гаманця, виконайте наступну команду: - ```shell solana balance ``` -Команда `solana airdrop` наразі обмежена 5 SOL за запит у devnet. Помилки можуть виникати через обмеження частоти запитів. +Команда `solana airdrop` наразі обмежена 5 SOL за запит у devnet. Помилки можуть +виникати через обмеження частоти запитів. -Як альтернативу, ви можете отримати SOL у devnet за допомогою [Solana Web Faucet](https://faucet.solana.com). +Як альтернативу, ви можете отримати SOL у devnet за допомогою +[Solana Web Faucet](https://faucet.solana.com). ### Запуск Локального Валідатора -Solana CLI постачається з вбудованим [тестовим валідатором](https://docs.anza.xyz/cli/examples/test-validator). Запуск локального валідатора дозволить вам розгортати та тестувати програми локально. - -У окремому терміналі виконайте наступну команду, щоб запустити локальний валідатор: +Solana CLI постачається з вбудованим +[тестовим валідатором](https://docs.anza.xyz/cli/examples/test-validator). +Запуск локального валідатора дозволить вам розгортати та тестувати програми +локально. +У окремому терміналі виконайте наступну команду, щоб запустити локальний +валідатор: ```shell solana-test-validator @@ -590,8 +652,8 @@ solana-test-validator -У WSL вам може знадобитися спочатку перейти до папки, де у вас є права запису за замовчуванням: - +У WSL вам може знадобитися спочатку перейти до папки, де у вас є права запису за +замовчуванням: ```shell cd ~ @@ -602,7 +664,8 @@ solana-test-validator -Переконайтеся, що оновили конфігурацію Solana CLI до `localhost` перед виконанням команд: +Переконайтеся, що оновили конфігурацію Solana CLI до `localhost` перед +виконанням команд: ```shell solana config set -ul diff --git a/docs/locales/uk/intro/quick-start/cross-program-invocation.md b/docs/locales/uk/intro/quick-start/cross-program-invocation.md index 58f36f10d..efc88ee2b 100644 --- a/docs/locales/uk/intro/quick-start/cross-program-invocation.md +++ b/docs/locales/uk/intro/quick-start/cross-program-invocation.md @@ -3,30 +3,30 @@ sidebarLabel: Крос-програмні виклики title: Крос-програмні виклики sidebarSortOrder: 5 description: - Дізнайтеся, як реалізувати крос-програмні виклики (CPIs) у програмах Solana - за допомогою фреймворку Anchor. У цьому підручнику демонструється, як - здійснювати переказ SOL між акаунтами, взаємодіяти з Системною програмою та - працювати з адресами, отриманими від програми (PDAs), у CPIs. Ідеально - підходить для розробників, які хочуть створювати інтегровані програми Solana. + Дізнайтеся, як реалізувати крос-програмні виклики (CPIs) у програмах Solana за + допомогою фреймворку Anchor. У цьому підручнику демонструється, як здійснювати + переказ SOL між акаунтами, взаємодіяти з Системною програмою та працювати з + адресами, отриманими від програми (PDAs), у CPIs. Ідеально підходить для + розробників, які хочуть створювати інтегровані програми Solana. --- У цьому розділі ми оновимо програму CRUD з попереднього розділу про PDA, щоб -додати крос-програмні виклики (CPIs). Ми модифікуємо програму, щоб -забезпечити переказ SOL між акаунтами в інструкціях `update` та `delete`, -демонструючи, як взаємодіяти з іншими програмами (у цьому випадку з -Системною програмою) зсередини нашої програми. +додати крос-програмні виклики (CPIs). Ми модифікуємо програму, щоб забезпечити +переказ SOL між акаунтами в інструкціях `update` та `delete`, демонструючи, як +взаємодіяти з іншими програмами (у цьому випадку з Системною програмою) +зсередини нашої програми. Метою цього розділу є покрокове пояснення процесу реалізації CPIs у програмі Solana за допомогою фреймворку Anchor, спираючись на концепції PDA, які ми -розглядали в попередньому розділі. Для отримання додаткової інформації -перейдіть на сторінку [Крос-програмні виклики](/docs/uk/core/cpi). +розглядали в попередньому розділі. Для отримання додаткової інформації перейдіть +на сторінку [Крос-програмні виклики](/docs/uk/core/cpi). ### Модифікація інструкції Update -Спочатку ми реалізуємо простий механізм "оплати за оновлення" шляхом -модифікації структури `Update` та функції `update`. +Спочатку ми реалізуємо простий механізм "оплати за оновлення" шляхом модифікації +структури `Update` та функції `update`. Розпочнемо з оновлення файлу `lib.rs`, щоб включити до області видимості елементи з модуля `system_program`. @@ -46,7 +46,9 @@ use anchor_lang::system_program::{transfer, Transfer}; -Далі оновіть структуру Update, щоб включити додатковий акаунт під назвою `vault_account`. Цей акаунт, який контролюється нашою програмою, отримуватиме SOL від користувача, коли той оновлює свій акаунт повідомлень. +Далі оновіть структуру Update, щоб включити додатковий акаунт під назвою +`vault_account`. Цей акаунт, який контролюється нашою програмою, отримуватиме +SOL від користувача, коли той оновлює свій акаунт повідомлень. ```rs filename="lib.rs" #[account( @@ -90,7 +92,9 @@ pub struct Update<'info> { Ми додаємо новий акаунт під назвою `vault_account` до нашої структури `Update`. Цей акаунт служить програмно-контрольованим "сейфом", який буде отримувати SOL від користувачів, коли вони оновлюють свої повідомлення. -Використовуючи PDA (Program Derived Address) для сейфа, ми створюємо програмно-контрольований акаунт, унікальний для кожного користувача, що дозволяє нам управляти коштами користувачів у межах логіки нашої програми. +Використовуючи PDA (Program Derived Address) для сейфа, ми створюємо +програмно-контрольований акаунт, унікальний для кожного користувача, що дозволяє +нам управляти коштами користувачів у межах логіки нашої програми. --- @@ -100,26 +104,31 @@ pub struct Update<'info> { Адреса акаунта є PDA, що отримується за допомогою сідів: `[b"vault", user.key().as_ref()]` - **Відсутність приватного ключа**: - Оскільки це PDA, він не має приватного ключа, тому лише наша програма може "підписуватися" за цю адресу під час виконання CPIs. + Оскільки це PDA, він не має приватного ключа, тому лише наша програма може + "підписуватися" за цю адресу під час виконання CPIs. - **Тип акаунта**: - Це акаунт типу `SystemAccount`, який належить до Системної програми, як і звичайні гаманці. + Це акаунт типу `SystemAccount`, який належить до Системної програми, як і + звичайні гаманці. --- Ця структура дозволяє нашій програмі: - Генерувати унікальні, детерміновані адреси для кожного "сейфа" користувача. -- Контролювати кошти без необхідності використання приватного ключа для підписання транзакцій. +- Контролювати кошти без необхідності використання приватного ключа для + підписання транзакцій. --- -У інструкції `delete` ми покажемо, як наша програма може "підписуватися" за цей PDA під час CPI. +У інструкції `delete` ми покажемо, як наша програма може "підписуватися" за цей +PDA під час CPI. --- Далі: реалізуйте логіку CPI в інструкції `update` -Реалізуйте логіку CPI для переказу **0.001 SOL** з акаунта користувача на акаунт сейфа. +Реалізуйте логіку CPI для переказу **0.001 SOL** з акаунта користувача на акаунт +сейфа. ```rs filename="lib.rs" let transfer_accounts = Transfer { @@ -158,9 +167,12 @@ transfer(cpi_context, 1_000_000)?; -В інструкції `update` ми реалізуємо виклик між програмами (CPI), щоб викликати інструкцію `transfer` Системної програми. Це демонструє, як виконати CPI у межах нашої програми, забезпечуючи композиційність програм у Solana. +В інструкції `update` ми реалізуємо виклик між програмами (CPI), щоб викликати +інструкцію `transfer` Системної програми. Це демонструє, як виконати CPI у межах +нашої програми, забезпечуючи композиційність програм у Solana. -Структура `Transfer` визначає необхідні акаунти для інструкції `transfer` Системної програми: +Структура `Transfer` визначає необхідні акаунти для інструкції `transfer` +Системної програми: - `from` - Акаунт користувача (джерело коштів) - `to` - Акаунт сейфа (ціль для переказу коштів) @@ -171,7 +183,8 @@ transfer(cpi_context, 1_000_000)?; to: ctx.accounts.vault_account.to_account_info(), }; ``` -`CpiContext` визначає: + + `CpiContext` визначає: - Програму, яку потрібно викликати (Системна програма) - Акаунти, необхідні для CPI (визначені у структурі `Transfer`) @@ -188,13 +201,16 @@ transfer(cpi_context, 1_000_000)?; - `cpi_context` (програму та акаунти) - Суму для переказу (1,000,000 лампортів, що еквівалентно 0.001 SOL) - ```rs filename="lib.rs" transfer(cpi_context, 1_000_000)?; ``` --- -Налаштування для CPI відповідає тому, як створюються інструкції на стороні клієнта, де ми вказуємо програму, акаунти та дані інструкції для виклику конкретної інструкції. Коли викликається інструкція `update` нашої програми, вона внутрішньо викликає інструкцію переказу Системної програми. + +Налаштування для CPI відповідає тому, як створюються інструкції на стороні +клієнта, де ми вказуємо програму, акаунти та дані інструкції для виклику +конкретної інструкції. Коли викликається інструкція `update` нашої програми, +вона внутрішньо викликає інструкцію переказу Системної програми. @@ -204,11 +220,15 @@ transfer(cpi_context, 1_000_000)?; ```shell filename="Terminal" build ``` + ### Змініть Інструкцію Delete -Ми реалізуємо механізм "повернення коштів при видаленні", змінивши структуру `Delete` та функцію `delete`. +Ми реалізуємо механізм "повернення коштів при видаленні", змінивши структуру +`Delete` та функцію `delete`. -Спершу оновіть структуру `Delete`, додавши до неї `vault_account`. Це дозволить нам переказати всі SOL із сейфа назад користувачеві, коли він закриває свій акаунт повідомлення. +Спершу оновіть структуру `Delete`, додавши до неї `vault_account`. Це дозволить +нам переказати всі SOL із сейфа назад користувачеві, коли він закриває свій +акаунт повідомлення. ```rs filename="lib.rs" #[account( @@ -219,7 +239,8 @@ build pub vault_account: SystemAccount<'info>, ``` -Також додайте `system_program`, оскільки CPI для переказу вимагає виклику Системної програми. +Також додайте `system_program`, оскільки CPI для переказу вимагає виклику +Системної програми. ```rs filename="lib.rs" pub system_program: Program<'info, System>, @@ -256,12 +277,15 @@ pub struct Delete<'info> { Акаунт `vault_account` використовує той самий PDA, що і в структурі `Update`. -Додавання `vault_account` до структури `Delete` дозволяє нашій програмі отримати доступ до сейфа користувача під час виконання інструкції видалення, щоб переказати накопичені SOL назад користувачеві. +Додавання `vault_account` до структури `Delete` дозволяє нашій програмі отримати +доступ до сейфа користувача під час виконання інструкції видалення, щоб +переказати накопичені SOL назад користувачеві. -Далі реалізуйте логіку CPI в інструкції `delete`, щоб переказати SOL із сейфа назад на акаунт користувача. +Далі реалізуйте логіку CPI в інструкції `delete`, щоб переказати SOL із сейфа +назад на акаунт користувача. ```rs filename="lib.rs" let user_key = ctx.accounts.user.key(); @@ -279,7 +303,8 @@ let cpi_context = CpiContext::new( transfer(cpi_context, ctx.accounts.vault_account.lamports())?; ``` -Зверніть увагу, що ми оновили `_ctx: Context` до `ctx: Context`, оскільки будемо використовувати контекст у тілі функції. +Зверніть увагу, що ми оновили `_ctx: Context` до `ctx: Context`, +оскільки будемо використовувати контекст у тілі функції. @@ -318,19 +343,21 @@ let user_key = ctx.accounts.user.key(); let signer_seeds: &[&[&[u8]]] = &[&[b"vault", user_key.as_ref(), &[ctx.bumps.vault_account]]]; ``` -Структура `Transfer` визначає необхідні акаунти для інструкції переказу Системної програми: + +Структура `Transfer` визначає необхідні акаунти для інструкції переказу +Системної програми: - `from`: Акаунт сейфа (джерело коштів) - `to`: Акаунт користувача (ціль для переказу коштів) - ```rs filename="lib.rs" let transfer_accounts = Transfer { from: ctx.accounts.vault_account.to_account_info(), to: ctx.accounts.user.to_account_info(), }; ``` -`CpiContext` визначає: + + `CpiContext` визначає: - Програму, яку потрібно викликати (Системна програма) - Акаунти, задіяні у переказі (визначені у структурі `Transfer`) @@ -342,7 +369,9 @@ let signer_seeds: &[&[&[u8]]] = transfer_accounts, ).with_signer(signer_seeds); ``` -Функція `transfer` викликає інструкцію переказу в Системній програмі, передаючи: + + Функція `transfer` викликає інструкцію переказу в Системній програмі, + передаючи: - `cpi_context` (програму, акаунти та підписувач на основі PDA) - Суму для переказу (весь баланс акаунта сейфа) @@ -350,7 +379,11 @@ let signer_seeds: &[&[&[u8]]] = ```rs filename="lib.rs" transfer(cpi_context, ctx.accounts.vault_account.lamports())?; ``` -Ця реалізація CPI демонструє, як програми можуть використовувати PDA для управління коштами. Коли викликається інструкція `delete` нашої програми, вона внутрішньо викликає інструкцію переказу Системної програми, підписуючи за PDA, щоб авторизувати переказ усіх коштів із сейфа назад користувачеві. + + Ця реалізація CPI демонструє, як програми можуть використовувати PDA для + управління коштами. Коли викликається інструкція `delete` нашої програми, вона + внутрішньо викликає інструкцію переказу Системної програми, підписуючи за PDA, + щоб авторизувати переказ усіх коштів із сейфа назад користувачеві. @@ -363,7 +396,10 @@ build ### Розгортання Програми -Після внесення цих змін нам потрібно повторно розгорнути оновлену програму. Це забезпечує доступність модифікованої програми для тестування. У Solana оновлення програми вимагає лише розгортання скомпільованої програми за тим самим ідентифікатором програми (program ID). +Після внесення цих змін нам потрібно повторно розгорнути оновлену програму. Це +забезпечує доступність модифікованої програми для тестування. У Solana оновлення +програми вимагає лише розгортання скомпільованої програми за тим самим +ідентифікатором програми (program ID). ```shell filename="Terminal" deploy @@ -381,22 +417,28 @@ Deployment successful. Completed in 17s. -Лише орган влади оновлення (upgrade authority) програми може її оновити. Орган влади оновлення встановлюється під час розгортання програми, і це єдиний акаунт, який має дозвіл модифікувати або закривати програму. Якщо орган влади оновлення відкликається, програма стає незмінною і її ніколи не можна буде закрити або оновити. +Лише орган влади оновлення (upgrade authority) програми може її оновити. Орган +влади оновлення встановлюється під час розгортання програми, і це єдиний акаунт, +який має дозвіл модифікувати або закривати програму. Якщо орган влади оновлення +відкликається, програма стає незмінною і її ніколи не можна буде закрити або +оновити. -Під час розгортання програм у Solana Playground гаманцем Playground є орган влади оновлення для всіх ваших програм. +Під час розгортання програм у Solana Playground гаманцем Playground є орган +влади оновлення для всіх ваших програм. ### Оновлення Файлу Тестів -Далі ми оновимо наш файл `anchor.test.ts`, щоб включити новий акаунт сейфа у наші інструкції. Це вимагає отримання PDA сейфа та його включення до викликів інструкцій `update` і `delete`. +Далі ми оновимо наш файл `anchor.test.ts`, щоб включити новий акаунт сейфа у +наші інструкції. Це вимагає отримання PDA сейфа та його включення до викликів +інструкцій `update` і `delete`. #### Отримання PDA Сейфа Спершу додайте код для отримання PDA сейфа: - ```ts filename="anchor.test.ts" const [vaultPda, vaultBump] = PublicKey.findProgramAddressSync( [Buffer.from("vault"), wallet.publicKey.toBuffer()], @@ -489,7 +531,8 @@ const transactionSignature = await program.methods ### Перезапуск Тестів -Після внесення цих змін запустіть тести, щоб переконатися, що все працює, як очікувалося: +Після внесення цих змін запустіть тести, щоб переконатися, що все працює, як +очікувалося: ```shell filename="Terminal" test @@ -531,22 +574,34 @@ Running tests... ![Delete CPI](/assets/docs/intro/quickstart/cpi-delete.png) -Якщо ви зіткнулися з помилками, ви можете переглянути [фінальний код](https://beta.solpg.io/668304cfcffcf4b13384d20a). +Якщо ви зіткнулися з помилками, ви можете переглянути +[фінальний код](https://beta.solpg.io/668304cfcffcf4b13384d20a). ## Наступні Кроки -Ви завершили посібник з швидкого старту Solana! Ви дізналися про акаунти, транзакції, PDA, CPI та розгорнули власні програми. +Ви завершили посібник з швидкого старту Solana! Ви дізналися про акаунти, +транзакції, PDA, CPI та розгорнули власні програми. -Відвідайте сторінки [Основні Концепції](/docs/uk/core/accounts) для більш детального пояснення тем, розглянутих у цьому посібнику. +Відвідайте сторінки [Основні Концепції](/docs/uk/core/accounts) для більш +детального пояснення тем, розглянутих у цьому посібнику. -Додаткові навчальні матеріали доступні на сторінці [Ресурси для Розробників](/developers). +Додаткові навчальні матеріали доступні на сторінці +[Ресурси для Розробників](/developers). ### Досліджуйте Більше Прикладів -Якщо ви віддаєте перевагу навчанню через приклади, перегляньте [Репозиторій з Прикладами Програм](https://github.com/solana-developers/program-examples) для різноманітних прикладів програм. +Якщо ви віддаєте перевагу навчанню через приклади, перегляньте +[Репозиторій з Прикладами Програм](https://github.com/solana-developers/program-examples) +для різноманітних прикладів програм. -Solana Playground пропонує зручну функцію, яка дозволяє імпортувати або переглядати проєкти за їх посиланнями на GitHub. Наприклад, відкрийте це [посилання Solana Playground](https://beta.solpg.io/https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor), щоб переглянути Anchor-проєкт із цього [репозиторію GitHub](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor). +Solana Playground пропонує зручну функцію, яка дозволяє імпортувати або +переглядати проєкти за їх посиланнями на GitHub. Наприклад, відкрийте це +[посилання Solana Playground](https://beta.solpg.io/https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor), +щоб переглянути Anchor-проєкт із цього +[репозиторію GitHub](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor). -Натисніть кнопку `Import` і введіть ім'я проєкту, щоб додати його до свого списку проєктів у Solana Playground. Після імпорту проєкту всі зміни автоматично зберігаються та залишаються у середовищі Playground. +Натисніть кнопку `Import` і введіть ім'я проєкту, щоб додати його до свого +списку проєктів у Solana Playground. Після імпорту проєкту всі зміни автоматично +зберігаються та залишаються у середовищі Playground. diff --git a/docs/locales/uk/intro/quick-start/deploying-programs.md b/docs/locales/uk/intro/quick-start/deploying-programs.md index ddcbbc83a..f81745580 100644 --- a/docs/locales/uk/intro/quick-start/deploying-programs.md +++ b/docs/locales/uk/intro/quick-start/deploying-programs.md @@ -3,14 +3,19 @@ sidebarLabel: Розгортання Програм title: Розгортання Вашої Першої Програми Solana sidebarSortOrder: 3 description: - Дізнайтеся, як створити, розгорнути та протестувати вашу першу програму Solana за допомогою - фреймворку Anchor та Solana Playground. Цей посібник для початківців демонструє, як створити просту програму, - розгорнути її на devnet, виконати тести та закрити програму. + Дізнайтеся, як створити, розгорнути та протестувати вашу першу програму Solana + за допомогою фреймворку Anchor та Solana Playground. Цей посібник для + початківців демонструє, як створити просту програму, розгорнути її на devnet, + виконати тести та закрити програму. --- -У цьому розділі ми створимо, розгорнемо та протестуємо просту програму Solana за допомогою фреймворку Anchor. Наприкінці ви розгорнете свою першу програму у блокчейні Solana! +У цьому розділі ми створимо, розгорнемо та протестуємо просту програму Solana за +допомогою фреймворку Anchor. Наприкінці ви розгорнете свою першу програму у +блокчейні Solana! -Мета цього розділу — ознайомити вас із Solana Playground. Ми розглянемо більш детальний приклад у розділах про PDA та CPI. Для отримання додаткової інформації відвідайте сторінку [Програми на Solana](/docs/core/programs). +Мета цього розділу — ознайомити вас із Solana Playground. Ми розглянемо більш +детальний приклад у розділах про PDA та CPI. Для отримання додаткової інформації +відвідайте сторінку [Програми на Solana](/docs/core/programs). @@ -20,7 +25,8 @@ description: - Натисніть кнопку "Create a new project" у лівій панелі. -- Введіть назву проєкту, виберіть Anchor як фреймворк, потім натисніть кнопку "Create". +- Введіть назву проєкту, виберіть Anchor як фреймворк, потім натисніть кнопку + "Create". ![Новий Проєкт](/assets/docs/intro/quickstart/pg-new-project.gif) @@ -66,12 +72,15 @@ pub struct NewAccount { На даний момент ми розглянемо лише загальний огляд коду програми: -- Макрос `declare_id!` визначає адресy вашої програми у блокчейні. Ця адреса буде автоматично оновлена, коли ми скомпілюємо програму на наступному етапі. +- Макрос `declare_id!` визначає адресy вашої програми у блокчейні. Ця адреса + буде автоматично оновлена, коли ми скомпілюємо програму на наступному етапі. ```rs declare_id!("11111111111111111111111111111111"); ``` -- Макрос `#[program]` позначає модуль, який містить функції, що представляють інструкції програми. + +- Макрос `#[program]` позначає модуль, який містить функції, що представляють + інструкції програми. ```rs #[program] @@ -84,28 +93,38 @@ pub struct NewAccount { } } ``` -У цьому прикладі інструкція `initialize` приймає два параметри: -1. `ctx: Context` — надає доступ до акаунтів, необхідних для цієї інструкції, як це зазначено у структурі `Initialize`. -2. `data: u64` — параметр інструкції, який передається під час виклику інструкції. + У цьому прикладі інструкція `initialize` приймає два параметри: -Тіло функції встановлює значення поля `data` для `new_account` відповідно до переданого аргументу `data`, а потім виводить повідомлення до журналу програми. +1. `ctx: Context` — надає доступ до акаунтів, необхідних для цієї + інструкції, як це зазначено у структурі `Initialize`. +2. `data: u64` — параметр інструкції, який передається під час виклику + інструкції. -- Макрос `#[derive(Accounts)]` використовується для визначення структури, яка задає акаунти, необхідні для певної інструкції, де кожне поле представляє окремий акаунт. +Тіло функції встановлює значення поля `data` для `new_account` відповідно до +переданого аргументу `data`, а потім виводить повідомлення до журналу програми. -Типи полів (наприклад, `Signer<'info>`) і обмеження (наприклад, `#[account(mut)]`) використовуються Anchor для автоматичного виконання стандартних перевірок безпеки, пов'язаних із валідацією акаунтів. +- Макрос `#[derive(Accounts)]` використовується для визначення структури, яка + задає акаунти, необхідні для певної інструкції, де кожне поле представляє + окремий акаунт. - ```rs - #[derive(Accounts)] - pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, - } - ``` -- Макрос `#[account]` використовується для визначення структури, яка представляє структуру даних акаунта, створеного та керованого програмою. +Типи полів (наприклад, `Signer<'info>`) і обмеження (наприклад, +`#[account(mut)]`) використовуються Anchor для автоматичного виконання +стандартних перевірок безпеки, пов'язаних із валідацією акаунтів. + +```rs +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} +``` + +- Макрос `#[account]` використовується для визначення структури, яка представляє + структуру даних акаунта, створеного та керованого програмою. ```rs #[account] @@ -124,7 +143,9 @@ pub struct NewAccount { ```shell filename="Terminal" build ``` -Зверніть увагу, що адреса у `declare_id!()` була оновлена. Це адреса вашої програми у блокчейні. + +Зверніть увагу, що адреса у `declare_id!()` була оновлена. Це адреса вашої +програми у блокчейні. @@ -139,7 +160,9 @@ Build successful. Completed in 1.46s. Після компіляції програми виконайте команду `deploy` у терміналі, щоб розгорнути програму в мережі (за замовчуванням devnet). Для розгортання програми необхідно виділити SOL для акаунта у блокчейні, який зберігатиме програму. -Перед розгортанням переконайтеся, що у вас достатньо SOL. Ви можете отримати devnet SOL, виконавши команду `solana airdrop 5` у терміналі Playground або скориставшись [веб-фонтаном](https://faucet.solana.com/). +Перед розгортанням переконайтеся, що у вас достатньо SOL. Ви можете отримати +devnet SOL, виконавши команду `solana airdrop 5` у терміналі Playground або +скориставшись [веб-фонтаном](https://faucet.solana.com/). ```shell filename="Terminal" deploy @@ -158,7 +181,8 @@ Deployment successful. Completed in 19s. -Альтернативно, ви також можете скористатися кнопками `Build` і `Deploy` на лівій панелі. +Альтернативно, ви також можете скористатися кнопками `Build` і `Deploy` на лівій +панелі. ![Build and Deploy](/assets/docs/intro/quickstart/pg-build-deploy.png) @@ -166,7 +190,9 @@ Deployment successful. Completed in 19s. ### Тестування Програми -Разом із стартовим кодом включений тестовий файл, який знаходиться у `tests/anchor.test.ts`. У цьому файлі показано, як викликати інструкцію `initialize` у стартовій програмі з клієнта. +Разом із стартовим кодом включений тестовий файл, який знаходиться у +`tests/anchor.test.ts`. У цьому файлі показано, як викликати інструкцію +`initialize` у стартовій програмі з клієнта. ```ts filename="anchor.test.ts" // No imports needed: web3, anchor, pg and more are globally available @@ -204,11 +230,14 @@ describe("Test", () => { }); }); ``` -Щоб запустити тестовий файл після розгортання програми, виконайте команду `test` у терміналі. + +Щоб запустити тестовий файл після розгортання програми, виконайте команду `test` +у терміналі. ```shell filename="Terminal" test ``` + Ви повинні побачити результат, який вказує, що тест пройшов успішно. @@ -231,7 +260,8 @@ Running tests... ![Run Test](/assets/docs/intro/quickstart/pg-test.png) -Потім ви можете переглянути журнали транзакцій, виконавши команду `solana confirm -v` та вказавши хеш транзакції (підпис) із результатів тесту: +Потім ви можете переглянути журнали транзакцій, виконавши команду +`solana confirm -v` та вказавши хеш транзакції (підпис) із результатів тесту: ```shell filename="Terminal" solana confirm -v [TxHash] @@ -289,7 +319,10 @@ Confirmed -Альтернативно, ви можете переглянути деталі транзакції на [SolanaFM](https://solana.fm/) або [Solana Explorer](https://explorer.solana.com/?cluster=devnet), здійснивши пошук за підписом (хешем) транзакції. +Альтернативно, ви можете переглянути деталі транзакції на +[SolanaFM](https://solana.fm/) або +[Solana Explorer](https://explorer.solana.com/?cluster=devnet), здійснивши пошук +за підписом (хешем) транзакції. Нагадуємо, що потрібно оновити підключення до кластеру (мережі) у вибраному Explorer, щоб воно відповідало кластеру Solana Playground. За замовчуванням у Solana Playground використовується кластер devnet. @@ -297,9 +330,11 @@ Confirmed ### Закриття Програми -Нарешті, SOL, виділений для програми у блокчейні, може бути повністю повернутий шляхом закриття програми. +Нарешті, SOL, виділений для програми у блокчейні, може бути повністю повернутий +шляхом закриття програми. -Ви можете закрити програму, виконавши наступну команду та вказавши адресу програми, яка знаходиться у `declare_id!()`: +Ви можете закрити програму, виконавши наступну команду та вказавши адресу +програми, яка знаходиться у `declare_id!()`: ```shell filename="Terminal" solana program close [ProgramID] @@ -322,14 +357,18 @@ Closed Program Id 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r, 2.79511512 SOL r -Тільки орган влади оновлення програми може її закрити. Орган влади оновлення встановлюється під час розгортання програми, і це єдиний акаунт, який має дозвіл модифікувати або закривати програму. Якщо орган влади оновлення відкликається, програма стає незмінною і її ніколи не можна буде закрити або оновити. +Тільки орган влади оновлення програми може її закрити. Орган влади оновлення +встановлюється під час розгортання програми, і це єдиний акаунт, який має дозвіл +модифікувати або закривати програму. Якщо орган влади оновлення відкликається, +програма стає незмінною і її ніколи не можна буде закрити або оновити. -Під час розгортання програм у Solana Playground гаманцем Playground є орган влади оновлення для всіх ваших програм. +Під час розгортання програм у Solana Playground гаманцем Playground є орган +влади оновлення для всіх ваших програм. -Вітаємо! Ви щойно створили та розгорнули свою першу програму Solana за допомогою фреймворку Anchor! +Вітаємо! Ви щойно створили та розгорнули свою першу програму Solana за допомогою +фреймворку Anchor! - diff --git a/docs/locales/uk/intro/quick-start/index.md b/docs/locales/uk/intro/quick-start/index.md index 1a164ae56..3d22ddc46 100644 --- a/docs/locales/uk/intro/quick-start/index.md +++ b/docs/locales/uk/intro/quick-start/index.md @@ -8,33 +8,48 @@ description: Solana Playground – без необхідності встановлення. --- -Ласкаво просимо до посібника з швидкого старту Solana! Цей практичний посібник ознайомить вас із ключовими концепціями створення програм на Solana, незалежно від вашого попереднього досвіду. Після завершення цього уроку у вас буде базове розуміння розробки на Solana, і ви зможете досліджувати більш складні теми. +Ласкаво просимо до посібника з швидкого старту Solana! Цей практичний посібник +ознайомить вас із ключовими концепціями створення програм на Solana, незалежно +від вашого попереднього досвіду. Після завершення цього уроку у вас буде базове +розуміння розробки на Solana, і ви зможете досліджувати більш складні теми. ## Чого Ви Навчитеся У цьому уроці ви дізнаєтеся про: - **Розуміння акаунтів**: Дослідження зберігання даних у мережі Solana. -- **Надсилання транзакцій**: Взаємодія з мережею Solana шляхом надсилання транзакцій. -- **Створення та розгортання програм**: Створіть свою першу програму Solana та розгорніть її в мережі. -- **Program Derived Addresses (PDA)**: Як використовувати PDA для створення детермінованих адрес акаунтів. -- **Cross-Program Invocations (CPI)**: Як зробити так, щоб ваші програми взаємодіяли з іншими програмами на Solana. - -Найкраще те, що вам нічого не потрібно встановлювати! Ми будемо використовувати Solana Playground, браузерне середовище розробки, для всіх наших прикладів. Це означає, що ви можете слідувати урокам, копіювати та вставляти код і одразу бачити результати прямо у вашому браузері. Базові знання програмування бажані, але не обов’язкові. +- **Надсилання транзакцій**: Взаємодія з мережею Solana шляхом надсилання + транзакцій. +- **Створення та розгортання програм**: Створіть свою першу програму Solana та + розгорніть її в мережі. +- **Program Derived Addresses (PDA)**: Як використовувати PDA для створення + детермінованих адрес акаунтів. +- **Cross-Program Invocations (CPI)**: Як зробити так, щоб ваші програми + взаємодіяли з іншими програмами на Solana. + +Найкраще те, що вам нічого не потрібно встановлювати! Ми будемо використовувати +Solana Playground, браузерне середовище розробки, для всіх наших прикладів. Це +означає, що ви можете слідувати урокам, копіювати та вставляти код і одразу +бачити результати прямо у вашому браузері. Базові знання програмування бажані, +але не обов’язкові. Давайте почнемо будувати на Solana! ## Solana Playground -Solana Playground (Solpg) – це браузерне середовище розробки, яке дозволяє швидко розробляти, розгортати та тестувати програми Solana! +Solana Playground (Solpg) – це браузерне середовище розробки, яке дозволяє +швидко розробляти, розгортати та тестувати програми Solana! -Відкрийте нову вкладку у своєму браузері та перейдіть на [https://beta.solpg.io/](https://beta.solpg.io/). +Відкрийте нову вкладку у своєму браузері та перейдіть на +[https://beta.solpg.io/](https://beta.solpg.io/). ### Створення Гаманця Playground -Якщо ви новачок у Solana Playground, першим кроком буде створення гаманця Playground. Цей гаманець дозволить вам взаємодіяти з мережею Solana безпосередньо з вашого браузера. +Якщо ви новачок у Solana Playground, першим кроком буде створення гаманця +Playground. Цей гаманець дозволить вам взаємодіяти з мережею Solana +безпосередньо з вашого браузера. #### Крок 1. Підключіться до Playground @@ -44,11 +59,13 @@ Solana Playground (Solpg) – це браузерне середовище ро #### Крок 2. Створіть Свій Гаманець -Вам буде запропоновано зберегти ключову пару вашого гаманця. За бажанням збережіть ключову пару для резервної копії, а потім натисніть "Continue". +Вам буде запропоновано зберегти ключову пару вашого гаманця. За бажанням +збережіть ключову пару для резервної копії, а потім натисніть "Continue". ![Create Playground Wallet](/assets/docs/intro/quickstart/pg-create-wallet.png) -Тепер ви повинні побачити адресу вашого гаманця, баланс SOL і підключений кластер (за замовчуванням devnet) у нижній частині вікна. +Тепер ви повинні побачити адресу вашого гаманця, баланс SOL і підключений +кластер (за замовчуванням devnet) у нижній частині вікна. ![Connected](/assets/docs/intro/quickstart/pg-connected.png) @@ -58,8 +75,14 @@ Solana Playground (Solpg) – це браузерне середовище ро Декілька корисних визначень: -- **_адреса гаманця_**: Унікальний ідентифікатор цифрового гаманця, який використовується для надсилання або отримання криптоактивів у блокчейні. Це схоже на електронну адресу чи номер банківського рахунку – щоб хтось надіслав вам криптовалюту, йому потрібна ваша адреса гаманця. -- **_підключений кластер_**: Набір вузлів мережі, які працюють разом, щоб підтримувати синхронізовану копію блокчейна. Кластери важливі для надання децентралізованого розподіленого реєстру, перевірки транзакцій, забезпечення безпеки ланцюга та виконання програм (смарт-контрактів). +- **_адреса гаманця_**: Унікальний ідентифікатор цифрового гаманця, який + використовується для надсилання або отримання криптоактивів у блокчейні. Це + схоже на електронну адресу чи номер банківського рахунку – щоб хтось надіслав + вам криптовалюту, йому потрібна ваша адреса гаманця. +- **_підключений кластер_**: Набір вузлів мережі, які працюють разом, щоб + підтримувати синхронізовану копію блокчейна. Кластери важливі для надання + децентралізованого розподіленого реєстру, перевірки транзакцій, забезпечення + безпеки ланцюга та виконання програм (смарт-контрактів). ### Отримання Devnet SOL @@ -74,8 +97,8 @@ Solana Playground (Solpg) – це браузерне середовище ро #### Варіант 1: Використання Терміналу Playground -Щоб поповнити ваш гаманець Playground devnet SOL, виконайте у терміналі Playground команду: - +Щоб поповнити ваш гаманець Playground devnet SOL, виконайте у терміналі +Playground команду: ```shell filename="Terminal" solana airdrop 5 @@ -83,9 +106,11 @@ solana airdrop 5 #### Варіант 2: Використання Devnet Faucet -Якщо команда airdrop не працює (через обмеження або помилки), скористайтеся [Web Faucet](https://faucet.solana.com/). +Якщо команда airdrop не працює (через обмеження або помилки), скористайтеся +[Web Faucet](https://faucet.solana.com/). -- Введіть адресу свого гаманця (знаходиться в нижній частині екрана Playground) і виберіть суму +- Введіть адресу свого гаманця (знаходиться в нижній частині екрана Playground) + і виберіть суму - Натисніть "Confirm Airdrop", щоб отримати ваш devnet SOL ![Faucet Airdrop](/assets/docs/intro/quickstart/faucet-airdrop.gif) diff --git a/docs/locales/uk/intro/quick-start/program-derived-address.md b/docs/locales/uk/intro/quick-start/program-derived-address.md index e025756e1..e259518a8 100644 --- a/docs/locales/uk/intro/quick-start/program-derived-address.md +++ b/docs/locales/uk/intro/quick-start/program-derived-address.md @@ -11,21 +11,31 @@ description: використовувати PDAs у програмах Solana. --- -У цьому розділі ми розглянемо, як створити базову CRUD (Create, Read, Update, Delete) програму. Програма зберігатиме повідомлення користувача, використовуючи Program Derived Address (PDA) як адресу акаунта. +У цьому розділі ми розглянемо, як створити базову CRUD (Create, Read, Update, +Delete) програму. Програма зберігатиме повідомлення користувача, використовуючи +Program Derived Address (PDA) як адресу акаунта. -Мета цього розділу – провести вас через етапи створення і тестування програми Solana, використовуючи фреймворк Anchor, і показати, як використовувати PDA у програмі. Для отримання додаткової інформації відвідайте сторінку [Programs Derived Address](/docs/uk/core/pda). +Мета цього розділу – провести вас через етапи створення і тестування програми +Solana, використовуючи фреймворк Anchor, і показати, як використовувати PDA у +програмі. Для отримання додаткової інформації відвідайте сторінку +[Programs Derived Address](/docs/uk/core/pda). -Для довідки ось [фінальний код](https://beta.solpg.io/668304cfcffcf4b13384d20a), завершений після розгляду розділів PDA і CPI. +Для довідки ось [фінальний код](https://beta.solpg.io/668304cfcffcf4b13384d20a), +завершений після розгляду розділів PDA і CPI. ### Стартовий Код -Почніть, відкривши це [посилання на Solana Playground](https://beta.solpg.io/66734b7bcffcf4b13384d1ad) зі стартовим кодом. Потім натисніть кнопку "Import", щоб додати програму до вашого списку проєктів у Solana Playground. +Почніть, відкривши це +[посилання на Solana Playground](https://beta.solpg.io/66734b7bcffcf4b13384d1ad) +зі стартовим кодом. Потім натисніть кнопку "Import", щоб додати програму до +вашого списку проєктів у Solana Playground. ![Import](/assets/docs/intro/quickstart/pg-import.png) -У файлі `lib.rs` ви знайдете шаблон програми з інструкціями `create`, `update` і `delete`, які ми реалізуємо на наступних етапах. +У файлі `lib.rs` ви знайдете шаблон програми з інструкціями `create`, `update` і +`delete`, які ми реалізуємо на наступних етапах. ```rs filename="lib.rs" use anchor_lang::prelude::*; @@ -61,7 +71,9 @@ pub struct Delete {} #[account] pub struct MessageAccount {} ``` -Перед початком виконайте команду `build` у терміналі Playground, щоб переконатися, що стартова програма успішно компілюється. + +Перед початком виконайте команду `build` у терміналі Playground, щоб +переконатися, що стартова програма успішно компілюється. ```shell filename="Terminal" build @@ -81,7 +93,8 @@ Build successful. Completed in 3.50s. ### Визначення Типу Акаунта Повідомлення -Спочатку визначимо структуру акаунта повідомлення, який створюватиме наша програма. Це дані, які ми зберігатимемо в акаунті, створеному програмою. +Спочатку визначимо структуру акаунта повідомлення, який створюватиме наша +програма. Це дані, які ми зберігатимемо в акаунті, створеному програмою. У файлі `lib.rs` оновіть структуру `MessageAccount` наступним кодом: @@ -112,17 +125,27 @@ pub struct MessageAccount { -Макрос `#[account]` у програмі Anchor використовується для позначення структур, які представляють дані акаунта (тип даних, що зберігається у полі даних `AccountInfo`). +Макрос `#[account]` у програмі Anchor використовується для позначення структур, +які представляють дані акаунта (тип даних, що зберігається у полі даних +`AccountInfo`). -У цьому прикладі ми визначаємо структуру `MessageAccount` для зберігання повідомлення, створеного користувачами, яка містить три поля: +У цьому прикладі ми визначаємо структуру `MessageAccount` для зберігання +повідомлення, створеного користувачами, яка містить три поля: -- `user` — `Pubkey`, який представляє користувача, що створив акаунт повідомлення. +- `user` — `Pubkey`, який представляє користувача, що створив акаунт + повідомлення. - `message` — `String`, який містить повідомлення користувача. -- `bump` — `u8`, що зберігає ["bump" seed](/docs/uk/core/pda#canonical-bump), використаний для отримання адреси, створеної програмою (PDA). Зберігання цього значення економить обчислювальні ресурси, оскільки усуває необхідність повторного обчислення для кожного використання в наступних інструкціях. +- `bump` — `u8`, що зберігає ["bump" seed](/docs/uk/core/pda#canonical-bump), + використаний для отримання адреси, створеної програмою (PDA). Зберігання цього + значення економить обчислювальні ресурси, оскільки усуває необхідність + повторного обчислення для кожного використання в наступних інструкціях. -Коли акаунт створюється, дані `MessageAccount` будуть серіалізовані та збережені у полі даних нового акаунта. +Коли акаунт створюється, дані `MessageAccount` будуть серіалізовані та збережені +у полі даних нового акаунта. -Пізніше, під час читання з акаунта, ці дані можна буде десеріалізувати назад у тип даних `MessageAccount`. Процес створення та читання даних акаунта буде продемонстровано у розділі тестування. +Пізніше, під час читання з акаунта, ці дані можна буде десеріалізувати назад у +тип даних `MessageAccount`. Процес створення та читання даних акаунта буде +продемонстровано у розділі тестування. @@ -132,13 +155,17 @@ pub struct MessageAccount { ```shell filename="Terminal" build ``` -Ми визначили, як виглядатиме наш акаунт повідомлення. Далі ми реалізуємо інструкції програми. + +Ми визначили, як виглядатиме наш акаунт повідомлення. Далі ми реалізуємо +інструкції програми. ### Реалізація Інструкції Create -Тепер реалізуємо інструкцію `create` для створення та ініціалізації `MessageAccount`. +Тепер реалізуємо інструкцію `create` для створення та ініціалізації +`MessageAccount`. -Почніть із визначення акаунтів, необхідних для цієї інструкції, оновивши структуру `Create` наступним кодом: +Почніть із визначення акаунтів, необхідних для цієї інструкції, оновивши +структуру `Create` наступним кодом: ```rs filename="lib.rs" #[derive(Accounts)] @@ -188,9 +215,13 @@ pub struct Create<'info> { Макрос `#[derive(Accounts)]` у програмі Anchor використовується для позначення структур, які представляють список акаунтів, необхідних для інструкції, де кожне поле в структурі є акаунтом. -Кожен акаунт (поле) у структурі позначається типом акаунта (наприклад, `Signer<'info>`) і може бути додатково позначений обмеженнями (наприклад, `#[account(mut)]`). Тип акаунта разом із обмеженнями акаунта використовуються для виконання перевірок безпеки акаунтів, переданих до інструкції. +Кожен акаунт (поле) у структурі позначається типом акаунта (наприклад, +`Signer<'info>`) і може бути додатково позначений обмеженнями (наприклад, +`#[account(mut)]`). Тип акаунта разом із обмеженнями акаунта використовуються +для виконання перевірок безпеки акаунтів, переданих до інструкції. -Назви кожного поля використовуються лише для нашого розуміння і не впливають на валідацію акаунтів, однак рекомендується використовувати описові імена акаунтів. +Назви кожного поля використовуються лише для нашого розуміння і не впливають на +валідацію акаунтів, однак рекомендується використовувати описові імена акаунтів. --- @@ -199,48 +230,60 @@ pub struct Create<'info> { 1. `user: Signer<'info>` - Представляє користувача, який створює акаунт повідомлення. - - Позначений як змінний (`#[account(mut)]`), оскільки оплачує створення нового акаунта. - - Повинен бути підписувачем, щоб підтвердити транзакцію, оскільки лампорти будуть списані з акаунта. + - Позначений як змінний (`#[account(mut)]`), оскільки оплачує створення + нового акаунта. + - Повинен бути підписувачем, щоб підтвердити транзакцію, оскільки лампорти + будуть списані з акаунта. 2. `message_account: Account<'info, MessageAccount>` - Новий акаунт, створений для зберігання повідомлення користувача. - Обмеження `init` вказує, що акаунт буде створено в інструкції. - - Обмеження `seeds` і `bump` вказують, що адреса акаунта є Program Derived Address (PDA). + - Обмеження `seeds` і `bump` вказують, що адреса акаунта є Program Derived + Address (PDA). - `payer = user` вказує акаунт, який оплачує створення нового акаунта. - `space` вказує кількість байтів, виділених для поля даних нового акаунта. 3. `system_program: Program<'info, System>` - Необхідна для створення нових акаунтів. - - На рівні механіки обмеження `init` викликає Системну програму для створення нового акаунта з виділенням вказаного `space` та переназначає власника програми на поточну програму. + - На рівні механіки обмеження `init` викликає Системну програму для створення + нового акаунта з виділенням вказаного `space` та переназначає власника + програми на поточну програму. --- -Анотація `#[instruction(message: String)]` дозволяє структурі `Create` отримувати доступ до параметра `message` з інструкції `create`. +Анотація `#[instruction(message: String)]` дозволяє структурі `Create` +отримувати доступ до параметра `message` з інструкції `create`. --- -Обмеження `seeds` і `bump` використовуються разом для вказівки, що адреса акаунта є Program Derived Address (PDA). +Обмеження `seeds` і `bump` використовуються разом для вказівки, що адреса +акаунта є Program Derived Address (PDA). ```rs filename="lib.rs" seeds = [b"message", user.key().as_ref()], bump, ``` -Обмеження `seeds` визначає необов’язкові вхідні значення, які використовуються для отримання PDA: + +Обмеження `seeds` визначає необов’язкові вхідні значення, які використовуються +для отримання PDA: - `b"message"` — Жорстко закодований рядок як перше значення seed. - `user.key().as_ref()` — Публічний ключ акаунта `user` як друге значення seed. -Обмеження `bump` вказує Anchor автоматично знайти та використовувати правильний bump seed. Anchor використовує `seeds` і `bump` для отримання PDA. +Обмеження `bump` вказує Anchor автоматично знайти та використовувати правильний +bump seed. Anchor використовує `seeds` і `bump` для отримання PDA. --- -Розрахунок `space` (8 + 32 + 4 + message.len() + 1) виділяє простір для даних типу `MessageAccount`: +Розрахунок `space` (8 + 32 + 4 + message.len() + 1) виділяє простір для даних +типу `MessageAccount`: - Дискримінатор акаунта Anchor (ідентифікатор): 8 байтів - Адреса користувача (Pubkey): 32 байти -- Повідомлення користувача (String): 4 байти для довжини + змінна довжина повідомлення +- Повідомлення користувача (String): 4 байти для довжини + змінна довжина + повідомлення - Bump seed для PDA (u8): 1 байт ```rs filename="lib.rs" @@ -251,14 +294,19 @@ pub struct MessageAccount { pub bump: u8, } ``` -Усі акаунти, створені за допомогою програми Anchor, вимагають 8 байтів для дискримінатора акаунта, який є ідентифікатором типу акаунта і генерується автоматично під час створення акаунта. -Тип `String` вимагає 4 байти для зберігання довжини рядка, а решта — це фактичні дані. +Усі акаунти, створені за допомогою програми Anchor, вимагають 8 байтів для +дискримінатора акаунта, який є ідентифікатором типу акаунта і генерується +автоматично під час створення акаунта. + +Тип `String` вимагає 4 байти для зберігання довжини рядка, а решта — це фактичні +дані. -Далі реалізуйте бізнес-логіку для інструкції `create`, оновивши функцію `create` наступним кодом: +Далі реалізуйте бізнес-логіку для інструкції `create`, оновивши функцію `create` +наступним кодом: ```rs filename="lib.rs" pub fn create(ctx: Context, message: String) -> Result<()> { @@ -292,9 +340,11 @@ pub fn create(ctx: Context, message: String) -> Result<()> { -Функція `create` реалізує логіку для ініціалізації даних нового акаунта повідомлення. Вона приймає два параметри: +Функція `create` реалізує логіку для ініціалізації даних нового акаунта +повідомлення. Вона приймає два параметри: -1. `ctx: Context` — Надає доступ до акаунтів, зазначених у структурі `Create`. +1. `ctx: Context` — Надає доступ до акаунтів, зазначених у структурі + `Create`. 2. `message: String` — Повідомлення користувача, яке буде збережено. Тіло функції виконує наступну логіку: @@ -304,15 +354,17 @@ pub fn create(ctx: Context, message: String) -> Result<()> { ```rs msg!("Create Message: {}", message); ``` + 2. Ініціалізація Даних Акаунта: - Отримує доступ до `message_account` з контексту. - + ```rs let account_data = &mut ctx.accounts.message_account; ``` + - Встановлює поле `user` як публічний ключ акаунта `user`. - + ```rs account_data.user = ctx.accounts.user.key(); ``` @@ -322,7 +374,9 @@ pub fn create(ctx: Context, message: String) -> Result<()> { ```rs account_data.message = message; ``` - - Встановлює значення `bump`, використане для отримання PDA, отримане з `ctx.bumps.message_account`. + + - Встановлює значення `bump`, використане для отримання PDA, отримане з + `ctx.bumps.message_account`. ```rs account_data.bump = ctx.bumps.message_account; @@ -336,11 +390,14 @@ pub fn create(ctx: Context, message: String) -> Result<()> { ```shell filename="Terminal" build ``` + ### Реалізація Інструкції Update -Далі реалізуйте інструкцію `update` для оновлення `MessageAccount` новим повідомленням. +Далі реалізуйте інструкцію `update` для оновлення `MessageAccount` новим +повідомленням. -Як і раніше, першим кроком є визначення акаунтів, необхідних для інструкції `update`. +Як і раніше, першим кроком є визначення акаунтів, необхідних для інструкції +`update`. Оновіть структуру `Update` наступним кодом: @@ -397,7 +454,8 @@ pub struct Update<'info> { 1. `user: Signer<'info>` - Представляє користувача, який оновлює акаунт повідомлення. - - Позначений як змінний (`#[account(mut)]`), оскільки може оплачувати додатковий простір для `message_account`, якщо це необхідно. + - Позначений як змінний (`#[account(mut)]`), оскільки може оплачувати + додатковий простір для `message_account`, якщо це необхідно. - Повинен бути підписувачем для підтвердження транзакції. 2. `message_account: Account<'info, MessageAccount>` @@ -410,15 +468,19 @@ pub struct Update<'info> { 3. `system_program: Program<'info, System>` - Необхідна для можливої зміни розміру простору акаунта. - - Обмеження `realloc` викликає Системну програму для налаштування розміру даних акаунта. + - Обмеження `realloc` викликає Системну програму для налаштування розміру + даних акаунта. --- -Зверніть увагу, що обмеження `bump = message_account.bump` використовує bump seed, який зберігається в `message_account`, замість того, щоб Anchor обчислював його знову. +Зверніть увагу, що обмеження `bump = message_account.bump` використовує bump +seed, який зберігається в `message_account`, замість того, щоб Anchor обчислював +його знову. --- -Анотація `#[instruction(message: String)]` дозволяє структурі `Update` отримувати доступ до параметра `message` з інструкції `update`. +Анотація `#[instruction(message: String)]` дозволяє структурі `Update` +отримувати доступ до параметра `message` з інструкції `update`. @@ -454,7 +516,8 @@ pub fn update(ctx: Context, message: String) -> Result<()> { Функція `update` реалізує логіку для модифікації існуючого акаунта повідомлення. Вона приймає два параметри: -1. `ctx: Context` — Надає доступ до акаунтів, зазначених у структурі `Update`. +1. `ctx: Context` — Надає доступ до акаунтів, зазначених у структурі + `Update`. 2. `message: String` — Нове повідомлення, яке замінить існуюче. Тіло функції виконує такі дії: @@ -473,6 +536,7 @@ pub fn update(ctx: Context, message: String) -> Result<()> { ```shell filename="Terminal" build ``` + ### Реалізація Інструкції Delete Далі реалізуйте інструкцію `delete` для закриття `MessageAccount`. @@ -525,15 +589,18 @@ pub struct Delete<'info> { 1. `user: Signer<'info>` - Представляє користувача, який закриває акаунт повідомлення. - - Позначений як змінний (`#[account(mut)]`), оскільки він отримуватиме лампорти з закритого акаунта. - - Повинен бути підписувачем, щоб гарантувати, що тільки відповідний користувач може закрити свій акаунт повідомлення. + - Позначений як змінний (`#[account(mut)]`), оскільки він отримуватиме + лампорти з закритого акаунта. + - Повинен бути підписувачем, щоб гарантувати, що тільки відповідний + користувач може закрити свій акаунт повідомлення. 2. `message_account: Account<'info, MessageAccount>` - Акаунт, який буде закритий. - Обмеження `mut` вказує, що цей акаунт буде змінено. - Обмеження `seeds` і `bump` гарантують, що акаунт є правильним PDA. - - Обмеження `close = user` вказує, що цей акаунт буде закритий, а його лампорти передані в акаунт `user`. + - Обмеження `close = user` вказує, що цей акаунт буде закритий, а його + лампорти передані в акаунт `user`. @@ -566,9 +633,13 @@ pub fn delete(_ctx: Context) -> Result<()> { Функція `delete` приймає один параметр: -1. `_ctx: Context` — Надає доступ до акаунтів, зазначених у структурі `Delete`. Використання `_ctx` вказує, що контекст не буде використовуватися в тілі функції. +1. `_ctx: Context` — Надає доступ до акаунтів, зазначених у структурі + `Delete`. Використання `_ctx` вказує, що контекст не буде використовуватися в + тілі функції. -Тіло функції лише виводить повідомлення у журнали програми за допомогою макроса `msg!()`. Додаткова логіка не потрібна, оскільки фактичне закриття акаунта виконується за допомогою обмеження `close` у структурі `Delete`. +Тіло функції лише виводить повідомлення у журнали програми за допомогою макроса +`msg!()`. Додаткова логіка не потрібна, оскільки фактичне закриття акаунта +виконується за допомогою обмеження `close` у структурі `Delete`. @@ -581,7 +652,8 @@ build ### Розгортання Програми -Базова CRUD-програма завершена. Розгорніть програму, виконавши команду `deploy` у терміналі Playground. +Базова CRUD-програма завершена. Розгорніть програму, виконавши команду `deploy` +у терміналі Playground. ```shell filename="Terminal" deploy @@ -614,6 +686,7 @@ describe("pda", () => { it("Delete Message Account", async () => {}); }); ``` + Додайте наведений нижче код всередину блоку `describe`, але перед секціями `it`. ```ts filename="anchor.test.ts" @@ -654,15 +727,17 @@ const [messagePda, messageBump] = PublicKey.findProgramAddressSync( У цьому розділі ми просто налаштовуємо тестовий файл. -Solana Playground спрощує початкову підготовку: `pg.program` дозволяє отримати доступ до клієнтської бібліотеки для взаємодії з програмою, а `pg.wallet` представляє ваш гаманець у Playground. +Solana Playground спрощує початкову підготовку: `pg.program` дозволяє отримати +доступ до клієнтської бібліотеки для взаємодії з програмою, а `pg.wallet` +представляє ваш гаманець у Playground. ```ts filename="anchor.test.ts" const program = pg.program; const wallet = pg.wallet; ``` -У рамках налаштування ми отримуємо PDA акаунта повідомлення. Це демонструє, як отримати PDA у Javascript, використовуючи сіди, визначені у програмі. - +У рамках налаштування ми отримуємо PDA акаунта повідомлення. Це демонструє, як +отримати PDA у Javascript, використовуючи сіди, визначені у програмі. ```ts filename="anchor.test.ts" const [messagePda, messageBump] = PublicKey.findProgramAddressSync( @@ -674,8 +749,9 @@ const [messagePda, messageBump] = PublicKey.findProgramAddressSync( -Запустіть тестовий файл, виконавши команду `test` у терміналі Playground, щоб переконатися, що файл працює, як очікувалося. Ми реалізуємо тести на наступних етапах. - +Запустіть тестовий файл, виконавши команду `test` у терміналі Playground, щоб +переконатися, що файл працює, як очікувалося. Ми реалізуємо тести на наступних +етапах. ```shell filename="Terminal" test @@ -702,7 +778,6 @@ Running tests... Оновіть перший тест наступним кодом: - ```ts filename="anchor.test.ts" it("Create Message Account", async () => { const message = "Hello, World!"; @@ -757,8 +832,8 @@ it("Create Message Account", async () => { -Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `create`, передаючи "Hello, World!" як повідомлення. - +Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `create`, передаючи +"Hello, World!" як повідомлення. ```ts filename="anchor.test.ts" const message = "Hello, World!"; @@ -770,8 +845,8 @@ const transactionSignature = await program.methods .rpc({ commitment: "confirmed" }); ``` -Після надсилання транзакції та створення акаунта ми отримуємо акаунт за його адресою (`messagePda`). - +Після надсилання транзакції та створення акаунта ми отримуємо акаунт за його +адресою (`messagePda`). ```ts filename="anchor.test.ts" const messageAccount = await program.account.messageAccount.fetch( @@ -780,8 +855,8 @@ const messageAccount = await program.account.messageAccount.fetch( ); ``` -Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей транзакції. - +Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей +транзакції. ```ts filename="anchor.test.ts" console.log(JSON.stringify(messageAccount, null, 2)); @@ -798,7 +873,6 @@ console.log( Оновіть другий тест наступним кодом: - ```ts filename="anchor.test.ts" it("Update Message Account", async () => { const message = "Hello, Solana!"; @@ -853,8 +927,8 @@ it("Update Message Account", async () => { -Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `update`, передаючи "Hello, Solana!" як нове повідомлення. - +Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `update`, передаючи +"Hello, Solana!" як нове повідомлення. ```ts filename="anchor.test.ts" const message = "Hello, Solana!"; @@ -866,7 +940,8 @@ const transactionSignature = await program.methods .rpc({ commitment: "confirmed" }); ``` -Після надсилання транзакції та оновлення акаунта ми отримуємо акаунт за його адресою (`messagePda`). +Після надсилання транзакції та оновлення акаунта ми отримуємо акаунт за його +адресою (`messagePda`). ```ts filename="anchor.test.ts" const messageAccount = await program.account.messageAccount.fetch( @@ -875,8 +950,8 @@ const messageAccount = await program.account.messageAccount.fetch( ); ``` -Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей транзакції. - +Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей +транзакції. ```ts filename="anchor.test.ts" console.log(JSON.stringify(messageAccount, null, 2)); @@ -893,7 +968,6 @@ console.log( Оновіть третій тест наступним кодом: - ```ts filename="anchor.test.ts" it("Delete Message Account", async () => { const transactionSignature = await program.methods @@ -946,8 +1020,8 @@ it("Delete Message Account", async () => { -Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `delete` для закриття акаунта повідомлення. - +Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `delete` для закриття +акаунта повідомлення. ```ts filename="anchor.test.ts" const transactionSignature = await program.methods @@ -958,8 +1032,9 @@ const transactionSignature = await program.methods .rpc({ commitment: "confirmed" }); ``` -Після надсилання транзакції та закриття акаунта ми намагаємося отримати акаунт за його адресою (`messagePda`), використовуючи `fetchNullable`, оскільки ми очікуємо, що результат буде `null`, тому що акаунт закритий. - +Після надсилання транзакції та закриття акаунта ми намагаємося отримати акаунт +за його адресою (`messagePda`), використовуючи `fetchNullable`, оскільки ми +очікуємо, що результат буде `null`, тому що акаунт закритий. ```ts filename="anchor.test.ts" const messageAccount = await program.account.messageAccount.fetchNullable( @@ -968,8 +1043,8 @@ const messageAccount = await program.account.messageAccount.fetchNullable( ); ``` -Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей транзакції, де дані акаунта повинні бути відображені як `null`. - +Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей +транзакції, де дані акаунта повинні бути відображені як `null`. ```ts filename="anchor.test.ts" console.log(JSON.stringify(messageAccount, null, 2)); @@ -984,8 +1059,8 @@ console.log( ### Запуск Тестів -Після налаштування тестів запустіть тестовий файл, виконавши команду `test` у терміналі Playground. - +Після налаштування тестів запустіть тестовий файл, виконавши команду `test` у +терміналі Playground. ```shell filename="Terminal" test diff --git a/docs/locales/uk/intro/quick-start/reading-from-network.md b/docs/locales/uk/intro/quick-start/reading-from-network.md index 1403a31ef..e7dd00e7f 100644 --- a/docs/locales/uk/intro/quick-start/reading-from-network.md +++ b/docs/locales/uk/intro/quick-start/reading-from-network.md @@ -4,33 +4,47 @@ title: Читання з Мережі sidebarSortOrder: 1 description: Дізнайтеся, як зчитувати дані з блокчейн-мережі Solana. Цей посібник охоплює - отримання акаунтів гаманців, програмних акаунтів і акаунтів випуску токенів - за допомогою JavaScript/TypeScript із практичними прикладами на основі - бібліотеки Solana web3.js. + отримання акаунтів гаманців, програмних акаунтів і акаунтів випуску токенів за + допомогою JavaScript/TypeScript із практичними прикладами на основі бібліотеки + Solana web3.js. --- -Давайте розглянемо, як зчитувати дані з мережі Solana. Ми отримаємо кілька різних акаунтів, щоб зрозуміти структуру акаунта Solana. +Давайте розглянемо, як зчитувати дані з мережі Solana. Ми отримаємо кілька +різних акаунтів, щоб зрозуміти структуру акаунта Solana. -У Solana всі дані містяться у так званих "акаунтах". Ви можете думати про дані в Solana як про загальнодоступну базу даних із єдиною таблицею "Accounts", де кожен запис у цій таблиці є окремим акаунтом. +У Solana всі дані містяться у так званих "акаунтах". Ви можете думати про дані в +Solana як про загальнодоступну базу даних із єдиною таблицею "Accounts", де +кожен запис у цій таблиці є окремим акаунтом. -Акаунти Solana можуть містити "стан" або виконувані програми, які можна розглядати як записи в одній таблиці "Accounts". Кожен акаунт має "адресу" (публічний ключ), яка є унікальним ідентифікатором для доступу до відповідних даних у блокчейні. +Акаунти Solana можуть містити "стан" або виконувані програми, які можна +розглядати як записи в одній таблиці "Accounts". Кожен акаунт має "адресу" +(публічний ключ), яка є унікальним ідентифікатором для доступу до відповідних +даних у блокчейні. Акаунти Solana можуть містити: -- **Стан**: Дані, які призначені для зчитування і зберігання. Це може бути інформація про токени, дані користувачів або будь-які інші дані, визначені у програмі. -- **Виконувані програми**: Акаунти, які містять фактичний код програм Solana. Вони включають інструкції, які можна виконувати у мережі. +- **Стан**: Дані, які призначені для зчитування і зберігання. Це може бути + інформація про токени, дані користувачів або будь-які інші дані, визначені у + програмі. +- **Виконувані програми**: Акаунти, які містять фактичний код програм Solana. + Вони включають інструкції, які можна виконувати у мережі. -Цей поділ програмного коду та стану програми є ключовою особливістю Моделі Акаунтів Solana. Для отримання додаткової інформації відвідайте сторінку [Модель Акаунтів Solana](/docs/uk/core/accounts). +Цей поділ програмного коду та стану програми є ключовою особливістю Моделі +Акаунтів Solana. Для отримання додаткової інформації відвідайте сторінку +[Модель Акаунтів Solana](/docs/uk/core/accounts). ## Отримання Гаманця Playground -Почнемо з розгляду знайомого акаунта — вашого власного гаманця Playground! Ми отримаємо цей акаунт і розглянемо його структуру, щоб зрозуміти, як виглядає базовий акаунт Solana. +Почнемо з розгляду знайомого акаунта — вашого власного гаманця Playground! Ми +отримаємо цей акаунт і розглянемо його структуру, щоб зрозуміти, як виглядає +базовий акаунт Solana. ### Відкриття Прикладу 1 -Натисніть це [посилання](https://beta.solpg.io/6671c5e5cffcf4b13384d198), щоб відкрити приклад у Solana Playground. Ви побачите такий код: +Натисніть це [посилання](https://beta.solpg.io/6671c5e5cffcf4b13384d198), щоб +відкрити приклад у Solana Playground. Ви побачите такий код: ```ts filename="client.ts" const address = pg.wallet.publicKey; @@ -73,7 +87,8 @@ console.log(JSON.stringify(accountInfo, null, 2)); run ``` -Ви повинні побачити деталі вашого акаунта гаманця, включаючи його баланс у лампортах, із результатом, схожим на наступний: +Ви повинні побачити деталі вашого акаунта гаманця, включаючи його баланс у +лампортах, із результатом, схожим на наступний: @@ -98,23 +113,36 @@ Running client... -Ваш гаманець насправді є лише акаунтом, яким керує Системна програма. Основна мета акаунта гаманця — зберігати баланс SOL (значення у полі `lamports`). +Ваш гаманець насправді є лише акаунтом, яким керує Системна програма. Основна +мета акаунта гаманця — зберігати баланс SOL (значення у полі `lamports`). --- -В основі всі акаунти Solana представлені у стандартному форматі, який називається `AccountInfo`. Тип даних [AccountInfo](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/account_info.rs#L19-L36) є базовою структурою даних для всіх акаунтів Solana. +В основі всі акаунти Solana представлені у стандартному форматі, який +називається `AccountInfo`. Тип даних +[AccountInfo](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/account_info.rs#L19-L36) +є базовою структурою даних для всіх акаунтів Solana. Розберемо поля у виведених даних: -- `data` — Це поле містить те, що ми зазвичай називаємо "даними" акаунта. Для гаманця воно порожнє (0 байтів), але інші акаунти використовують це поле для зберігання будь-яких довільних даних у вигляді серіалізованого буфера байтів. +- `data` — Це поле містить те, що ми зазвичай називаємо "даними" акаунта. Для + гаманця воно порожнє (0 байтів), але інші акаунти використовують це поле для + зберігання будь-яких довільних даних у вигляді серіалізованого буфера байтів. -> Коли дані "буферизуються" таким чином, вони зберігають свою цілісність і можуть пізніше бути десеріалізовані назад у свій початковий вигляд для використання у програмах. Цей процес широко використовується в блокчейні для ефективної обробки даних. +> Коли дані "буферизуються" таким чином, вони зберігають свою цілісність і +> можуть пізніше бути десеріалізовані назад у свій початковий вигляд для +> використання у програмах. Цей процес широко використовується в блокчейні для +> ефективної обробки даних. -- `executable` — Прапорець, який вказує, чи є акаунт виконуваною програмою. Для гаманців та будь-яких акаунтів, які зберігають стан, значення `false`. -- `owner` — Це поле показує, яка програма контролює акаунт. Для гаманців це завжди Системна програма з адресою `11111111111111111111111111111111`. +- `executable` — Прапорець, який вказує, чи є акаунт виконуваною програмою. Для + гаманців та будь-яких акаунтів, які зберігають стан, значення `false`. +- `owner` — Це поле показує, яка програма контролює акаунт. Для гаманців це + завжди Системна програма з адресою `11111111111111111111111111111111`. - `lamports` — Баланс акаунта у лампортах (1 SOL = 1,000,000,000 лампортів). -- `rentEpoch` — Поле, пов’язане зі старим механізмом збору оренди Solana (наразі не використовується). -- `space` — Вказує ємність (довжину) поля `data`, але не є полем типу `AccountInfo`. +- `rentEpoch` — Поле, пов’язане зі старим механізмом збору оренди Solana (наразі + не використовується). +- `space` — Вказує ємність (довжину) поля `data`, але не є полем типу + `AccountInfo`. @@ -123,13 +151,15 @@ Running client... ## Отримання Програми Token Program -Далі ми розглянемо програму Token Extensions, яка є виконуваною програмою для взаємодії з токенами на Solana. +Далі ми розглянемо програму Token Extensions, яка є виконуваною програмою для +взаємодії з токенами на Solana. ### Відкриття Прикладу 2 -Натисніть це [посилання](https://beta.solpg.io/6671c6e7cffcf4b13384d199), щоб відкрити приклад у Solana Playground. Ви побачите такий код: +Натисніть це [посилання](https://beta.solpg.io/6671c6e7cffcf4b13384d199), щоб +відкрити приклад у Solana Playground. Ви побачите такий код: ```ts filename="client.ts" {3} import { PublicKey } from "@solana/web3.js"; @@ -139,17 +169,20 @@ const accountInfo = await pg.connection.getAccountInfo(address); console.log(JSON.stringify(accountInfo, null, 2)); ``` -Замість отримання вашого гаманця Playground, тут ми отримуємо адресу акаунта програми Token Extensions. + +Замість отримання вашого гаманця Playground, тут ми отримуємо адресу акаунта +програми Token Extensions. ### Запуск Прикладу 2 Запустіть код, виконавши команду `run` у терміналі. - ```shell filename="Terminal" run ``` -Ознайомтеся з виведеними даними та тим, чим цей акаунт програми відрізняється від вашого акаунта гаманця. + +Ознайомтеся з виведеними даними та тим, чим цей акаунт програми відрізняється +від вашого акаунта гаманця. @@ -180,13 +213,19 @@ Running client... -Програма Token Extensions є виконуваним акаунтом програми, але має таку ж структуру `AccountInfo`. +Програма Token Extensions є виконуваним акаунтом програми, але має таку ж +структуру `AccountInfo`. Основні відмінності в `AccountInfo`: -- **`executable`** — Встановлено у `true`, що вказує на те, що цей акаунт є виконуваною програмою. -- **`data`** — Містить серіалізовані дані (на відміну від порожніх даних у акаунті гаманця). Дані для акаунта програми зберігають адресу іншого акаунта (Program Executable Data Account), який містить байт-код програми. -- **`owner`** — Акаунт належить завантажувачу Upgradable BPF Loader (`BPFLoaderUpgradeab1e11111111111111111111111`), спеціальній програмі, яка управляє виконуваними акаунтами. +- **`executable`** — Встановлено у `true`, що вказує на те, що цей акаунт є + виконуваною програмою. +- **`data`** — Містить серіалізовані дані (на відміну від порожніх даних у + акаунті гаманця). Дані для акаунта програми зберігають адресу іншого акаунта + (Program Executable Data Account), який містить байт-код програми. +- **`owner`** — Акаунт належить завантажувачу Upgradable BPF Loader + (`BPFLoaderUpgradeab1e11111111111111111111111`), спеціальній програмі, яка + управляє виконуваними акаунтами. --- @@ -195,7 +234,8 @@ Running client... та його відповідного [Program Executable Data Account](https://explorer.solana.com/address/DoU57AYuPFu2QU514RktNPG22QhApEjnKxnBcu4BHDTY). -Program Executable Data Account містить скомпільований байт-код програми Token Extensions +Program Executable Data Account містить скомпільований байт-код програми Token +Extensions [вихідний код](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program-2022/src). @@ -205,14 +245,15 @@ Program Executable Data Account містить скомпільований ба ## Отримання Акаунта Mint -На цьому етапі ми розглянемо акаунт Mint, який представляє унікальний токен у мережі Solana. +На цьому етапі ми розглянемо акаунт Mint, який представляє унікальний токен у +мережі Solana. ### Відкриття Прикладу 3 -Натисніть це [посилання](https://beta.solpg.io/6671c9aecffcf4b13384d19a), щоб відкрити приклад у Solana Playground. Ви побачите такий код: - +Натисніть це [посилання](https://beta.solpg.io/6671c9aecffcf4b13384d19a), щоб +відкрити приклад у Solana Playground. Ви побачите такий код: ```ts filename="client.ts" {3} import { PublicKey } from "@solana/web3.js"; @@ -222,13 +263,13 @@ const accountInfo = await pg.connection.getAccountInfo(address); console.log(JSON.stringify(accountInfo, null, 2)); ``` + У цьому прикладі ми отримаємо адресу існуючого акаунта Mint у devnet. ### Запуск Прикладу 3 Запустіть код, виконавши команду `run`. - ```shell filename="Terminal" run ``` @@ -264,20 +305,33 @@ Running client... Основні відмінності в `AccountInfo`: -- **`owner`** — Акаунт mint належить програмі Token Extensions (`TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`). -- **`executable`** — Встановлено у `false`, оскільки цей акаунт зберігає стан, а не виконуваний код. -- **`data`** — Містить серіалізовані дані про токен (авторитет випуску, загальну кількість, кількість знаків після коми тощо). +- **`owner`** — Акаунт mint належить програмі Token Extensions + (`TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`). +- **`executable`** — Встановлено у `false`, оскільки цей акаунт зберігає стан, а + не виконуваний код. +- **`data`** — Містить серіалізовані дані про токен (авторитет випуску, загальну + кількість, кількість знаків після коми тощо). ### Десеріалізація Даних Акаунта Mint -Щоб зчитати поле `data` з будь-якого акаунта, потрібно десеріалізувати буфер даних у очікуваний тип даних. Це часто виконується за допомогою допоміжних функцій клієнтських бібліотек для конкретної програми. +Щоб зчитати поле `data` з будь-якого акаунта, потрібно десеріалізувати буфер +даних у очікуваний тип даних. Це часто виконується за допомогою допоміжних +функцій клієнтських бібліотек для конкретної програми. -**Десеріалізація** — це процес перетворення даних зі збереженого формату (наприклад, необроблених байтів або JSON) назад у використовуваний структурований формат у програмі. У блокчейні це включає взяття необроблених, закодованих даних із мережі та їх перетворення назад в об'єкти, класи або читабельні структури, щоб розробники могли отримати доступ до конкретної інформації та маніпулювати нею у програмі. Десеріалізація є важливою для інтерпретації даних акаунтів або транзакцій, отриманих із мережі, у формі, яку програма може обробляти і відображати осмислено. +**Десеріалізація** — це процес перетворення даних зі збереженого формату +(наприклад, необроблених байтів або JSON) назад у використовуваний +структурований формат у програмі. У блокчейні це включає взяття необроблених, +закодованих даних із мережі та їх перетворення назад в об'єкти, класи або +читабельні структури, щоб розробники могли отримати доступ до конкретної +інформації та маніпулювати нею у програмі. Десеріалізація є важливою для +інтерпретації даних акаунтів або транзакцій, отриманих із мережі, у формі, яку +програма може обробляти і відображати осмислено. -Відкрийте цей [приклад](https://beta.solpg.io/6671cd8acffcf4b13384d19b) у Solana Playground. Ви побачите такий код: +Відкрийте цей [приклад](https://beta.solpg.io/6671cd8acffcf4b13384d19b) у Solana +Playground. Ви побачите такий код: ```ts filename="client.ts" import { PublicKey } from "@solana/web3.js"; @@ -294,13 +348,15 @@ const mintData = await getMint( console.log(mintData); ``` -Цей приклад використовує функцію `getMint`, яка автоматично десеріалізує поле `data` акаунта Mint. +Цей приклад використовує функцію `getMint`, яка автоматично десеріалізує поле +`data` акаунта Mint. Запустіть код, виконавши команду `run`. ```shell filename="Terminal" run ``` + Ви повинні побачити наступні десеріалізовані дані акаунта Mint. @@ -321,20 +377,25 @@ Running client... -Функція `getMint` десеріалізує дані акаунта у тип даних [Mint](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32), визначений у вихідному коді програми Token Extensions. +Функція `getMint` десеріалізує дані акаунта у тип даних +[Mint](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32), +визначений у вихідному коді програми Token Extensions. - **`address`** — Адреса акаунта Mint. - **`mintAuthority`** — Авторитет, який може випускати нові токени. - **`supply`** — Загальна кількість токенів в обігу. - **`decimals`** — Кількість десяткових знаків для токена. - **`isInitialized`** — Чи були дані Mint ініціалізовані. -- **`freezeAuthority`** — Авторитет, який має право заморожувати акаунти токенів. -- **`tlvData`** — Додаткові дані для Token Extensions (вимагають подальшої десеріалізації). +- **`freezeAuthority`** — Авторитет, який має право заморожувати акаунти + токенів. +- **`tlvData`** — Додаткові дані для Token Extensions (вимагають подальшої + десеріалізації). -Ви можете переглянути повністю десеріалізовані [дані акаунта Mint](https://explorer.solana.com/address/C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR?cluster=devnet), включаючи активовані Token Extensions, у Solana Explorer. +Ви можете переглянути повністю десеріалізовані +[дані акаунта Mint](https://explorer.solana.com/address/C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR?cluster=devnet), +включаючи активовані Token Extensions, у Solana Explorer. - diff --git a/docs/locales/uk/intro/quick-start/writing-to-network.md b/docs/locales/uk/intro/quick-start/writing-to-network.md index 1e17da27f..37bbbc4bf 100644 --- a/docs/locales/uk/intro/quick-start/writing-to-network.md +++ b/docs/locales/uk/intro/quick-start/writing-to-network.md @@ -4,23 +4,33 @@ title: Запис у Мережу sidebarSortOrder: 2 description: Дізнайтеся, як взаємодіяти з мережею Solana шляхом надсилання транзакцій та - інструкцій. Слідуйте покроковим прикладам для переказу токенів SOL та створення - нових токенів за допомогою System Program та Token Extensions Program. + інструкцій. Слідуйте покроковим прикладам для переказу токенів SOL та + створення нових токенів за допомогою System Program та Token Extensions + Program. --- -Тепер, коли ми розглянули зчитування даних із мережі Solana, давайте навчимося записувати дані до неї. У Solana взаємодія з мережею здійснюється шляхом надсилання транзакцій, що складаються з інструкцій. Ці інструкції визначаються програмами, які містять бізнес-логіку про те, як мають оновлюватися акаунти. +Тепер, коли ми розглянули зчитування даних із мережі Solana, давайте навчимося +записувати дані до неї. У Solana взаємодія з мережею здійснюється шляхом +надсилання транзакцій, що складаються з інструкцій. Ці інструкції визначаються +програмами, які містять бізнес-логіку про те, як мають оновлюватися акаунти. -Розглянемо два поширені операції, переказ SOL і створення токена, щоб продемонструвати, як створювати і надсилати транзакції. Для отримання додаткової інформації відвідайте сторінки [Транзакції та Інструкції](/docs/uk/core/transactions) і [Комісії у Solana](/docs/uk/core/fees). +Розглянемо два поширені операції, переказ SOL і створення токена, щоб +продемонструвати, як створювати і надсилати транзакції. Для отримання додаткової +інформації відвідайте сторінки +[Транзакції та Інструкції](/docs/uk/core/transactions) і +[Комісії у Solana](/docs/uk/core/fees). ## Переказ SOL -Почнемо із простої операції переказу SOL з вашого гаманця на інший акаунт. Це вимагає виклику інструкції переказу у System Program. +Почнемо із простої операції переказу SOL з вашого гаманця на інший акаунт. Це +вимагає виклику інструкції переказу у System Program. ### Відкриття Прикладу 1 -Натисніть це [посилання](https://beta.solpg.io/6671d85ecffcf4b13384d19e), щоб відкрити приклад у Solana Playground. Ви побачите такий код: +Натисніть це [посилання](https://beta.solpg.io/6671d85ecffcf4b13384d19e), щоб +відкрити приклад у Solana Playground. Ви побачите такий код: ```ts filename="client.ts" import { @@ -97,7 +107,8 @@ console.log( ); ``` -- Виводить посилання на SolanaFM у термінал Playground для перегляду деталей транзакції. +- Виводить посилання на SolanaFM у термінал Playground для перегляду деталей + транзакції. ```ts console.log( @@ -113,12 +124,12 @@ console.log( Запустіть код, виконавши команду `run`. - ```shell filename="Terminal" run ``` -Натисніть на посилання у виведених даних, щоб переглянути деталі транзакції у SolanaFM Explorer. +Натисніть на посилання у виведених даних, щоб переглянути деталі транзакції у +SolanaFM Explorer. @@ -134,13 +145,16 @@ Running client... ![Transfer SOL](/assets/docs/intro/quickstart/transfer-sol.png) -Ви щойно надіслали свою першу транзакцію у Solana! Зверніть увагу, як ми створили інструкцію, додали її до транзакції, а потім відправили цю транзакцію до мережі. Це базовий процес для створення будь-якої транзакції. +Ви щойно надіслали свою першу транзакцію у Solana! Зверніть увагу, як ми +створили інструкцію, додали її до транзакції, а потім відправили цю транзакцію +до мережі. Це базовий процес для створення будь-якої транзакції. ## Створення Токена -Тепер створимо новий токен шляхом створення та ініціалізації акаунта Mint. Для цього потрібні дві інструкції: +Тепер створимо новий токен шляхом створення та ініціалізації акаунта Mint. Для +цього потрібні дві інструкції: - Виклик System Program для створення нового акаунта. - Виклик Token Extensions Program для ініціалізації даних акаунта. @@ -149,7 +163,8 @@ Running client... ### Відкриття Прикладу 2 -Натисніть це [посилання](https://beta.solpg.io/6671da4dcffcf4b13384d19f), щоб відкрити приклад у Solana Playground. Ви побачите наступний код: +Натисніть це [посилання](https://beta.solpg.io/6671da4dcffcf4b13384d19f), щоб +відкрити приклад у Solana Playground. Ви побачите наступний код: ```ts filename="client.ts" import { @@ -226,6 +241,7 @@ console.log( Цей скрипт виконує наступні кроки: - Налаштовує ваш гаманець Playground і з'єднання з devnet Solana: + ```ts const wallet = pg.wallet; const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); @@ -243,7 +259,8 @@ console.log( const rentLamports = await getMinimumBalanceForRentExemptMint(connection); ``` -- Створює інструкцію для створення нового акаунта mint, вказуючи програму Token Extensions (TOKEN_2022_PROGRAM_ID) як власника нового акаунта: +- Створює інструкцію для створення нового акаунта mint, вказуючи програму Token + Extensions (TOKEN_2022_PROGRAM_ID) як власника нового акаунта: ```ts const createAccountInstruction = SystemProgram.createAccount({ @@ -276,7 +293,10 @@ console.log( ); ``` -- Відправляє та підтверджує транзакцію. Гаманець і ключова пара mint передаються як підписувачі транзакції. Гаманець потрібен для оплати створення нового акаунта, а ключова пара mint потрібна, оскільки її публічний ключ використовується як адреса нового акаунта: +- Відправляє та підтверджує транзакцію. Гаманець і ключова пара mint передаються + як підписувачі транзакції. Гаманець потрібен для оплати створення нового + акаунта, а ключова пара mint потрібна, оскільки її публічний ключ + використовується як адреса нового акаунта: ```ts const transactionSignature = await sendAndConfirmTransaction( @@ -286,7 +306,8 @@ console.log( ); ``` -- Виводить посилання для перегляду транзакції та деталей акаунта mint на SolanaFM: +- Виводить посилання для перегляду транзакції та деталей акаунта mint на + SolanaFM: ```ts console.log( @@ -316,7 +337,8 @@ run - Одне для деталей транзакції - Інше для новоствореного акаунта mint -Натисніть на посилання, щоб переглянути деталі транзакції та новостворений акаунт mint у SolanaFM. +Натисніть на посилання, щоб переглянути деталі транзакції та новостворений +акаунт mint у SolanaFM. @@ -337,6 +359,9 @@ Mint Account: https://solana.fm/address/CoZ3Nz488rmATDhy1hPk5fvwSZaipCngvf8rYBYV ![Mint Account](/assets/docs/intro/quickstart/mint-account.png) -Зверніть увагу, як цього разу ми створили транзакцію з кількома інструкціями. Спочатку ми створили новий акаунт, а потім ініціалізували його дані як mint. Таким чином створюються складніші транзакції, які включають інструкції з кількох програм. +Зверніть увагу, як цього разу ми створили транзакцію з кількома інструкціями. +Спочатку ми створили новий акаунт, а потім ініціалізували його дані як mint. +Таким чином створюються складніші транзакції, які включають інструкції з кількох +програм. diff --git a/docs/locales/uk/intro/wallets.md b/docs/locales/uk/intro/wallets.md index f12d22c36..e3af2e607 100644 --- a/docs/locales/uk/intro/wallets.md +++ b/docs/locales/uk/intro/wallets.md @@ -4,32 +4,67 @@ title: Посібник із Гаманців Solana sidebarSortOrder: 3 --- -Цей документ описує різні варіанти гаманців, доступних користувачам Solana, які хочуть надсилати, отримувати та взаємодіяти з токенами SOL у блокчейні Solana. +Цей документ описує різні варіанти гаманців, доступних користувачам Solana, які +хочуть надсилати, отримувати та взаємодіяти з токенами SOL у блокчейні Solana. ## Що таке Гаманець? -Криптогаманець — це пристрій або програма, яка зберігає набір ключів і може використовуватися для надсилання, отримання та відстеження володіння криптовалютами. Гаманці можуть мати різні форми. Гаманець може бути каталогом або файлом у файловій системі вашого комп’ютера, аркушем паперу або спеціалізованим пристроєм, який називається _апаратний гаманець_. Також існують різні програми для смартфонів і комп’ютерів, які надають зручний спосіб створення та управління гаманцями. +Криптогаманець — це пристрій або програма, яка зберігає набір ключів і може +використовуватися для надсилання, отримання та відстеження володіння +криптовалютами. Гаманці можуть мати різні форми. Гаманець може бути каталогом +або файлом у файловій системі вашого комп’ютера, аркушем паперу або +спеціалізованим пристроєм, який називається _апаратний гаманець_. Також існують +різні програми для смартфонів і комп’ютерів, які надають зручний спосіб +створення та управління гаманцями. ### Keypair -[_Keypair_](/docs/uk/terminology.md#keypair) — це безпечно згенерований [_секретний ключ_](#secret-key) і його криптографічно виведений [_публічний ключ_](#public-key). Секретний ключ та його відповідний публічний ключ разом називаються _ключовою парою_. Гаманець містить колекцію однієї або кількох ключових пар і надає засоби для взаємодії з ними. +[_Keypair_](/docs/uk/terminology.md#keypair) — це безпечно згенерований +[_секретний ключ_](#secret-key) і його криптографічно виведений +[_публічний ключ_](#public-key). Секретний ключ та його відповідний публічний +ключ разом називаються _ключовою парою_. Гаманець містить колекцію однієї або +кількох ключових пар і надає засоби для взаємодії з ними. ### Публічний ключ -[_Публічний ключ_](/docs/uk/terminology.md#public-key-pubkey) (часто скорочується до _pubkey_) відомий як _адреса для отримання_ гаманця або просто його _адреса_. Адресу гаманця **можна вільно передавати та показувати**. Коли інша сторона збирається надіслати певну кількість криптовалюти на гаманець, їй потрібно знати адресу для отримання. Залежно від реалізації блокчейну, адреса також може використовуватися для перегляду певної інформації про гаманець, наприклад, балансу, але вона не дозволяє змінювати гаманець або знімати з нього токени. +[_Публічний ключ_](/docs/uk/terminology.md#public-key-pubkey) (часто +скорочується до _pubkey_) відомий як _адреса для отримання_ гаманця або просто +його _адреса_. Адресу гаманця **можна вільно передавати та показувати**. Коли +інша сторона збирається надіслати певну кількість криптовалюти на гаманець, їй +потрібно знати адресу для отримання. Залежно від реалізації блокчейну, адреса +також може використовуватися для перегляду певної інформації про гаманець, +наприклад, балансу, але вона не дозволяє змінювати гаманець або знімати з нього +токени. ### Секретний ключ -[_Секретний ключ_](/docs/uk/terminology.md#private-key) (також називається _приватним ключем_) потрібен для цифрового підпису будь-яких транзакцій для відправлення криптовалюти на іншу адресу або внесення змін до гаманця. Секретний ключ **ніколи не повинен бути переданий іншим**. Якщо хтось отримає доступ до секретного ключа гаманця, він може зняти всі токени, які він містить. Якщо секретний ключ гаманця втрачено, будь-які токени, відправлені на адресу цього гаманця, **назавжди втрачені**. +[_Секретний ключ_](/docs/uk/terminology.md#private-key) (також називається +_приватним ключем_) потрібен для цифрового підпису будь-яких транзакцій для +відправлення криптовалюти на іншу адресу або внесення змін до гаманця. Секретний +ключ **ніколи не повинен бути переданий іншим**. Якщо хтось отримає доступ до +секретного ключа гаманця, він може зняти всі токени, які він містить. Якщо +секретний ключ гаманця втрачено, будь-які токени, відправлені на адресу цього +гаманця, **назавжди втрачені**. ## Безпека -Різні рішення для гаманців пропонують різні підходи до безпеки ключової пари, взаємодії з нею та підписання транзакцій для використання/витрачання токенів. Деякі є простішими у використанні, ніж інші. Деякі забезпечують більш безпечне зберігання та резервне копіювання секретних ключів. Solana підтримує кілька типів гаманців, тому ви можете обрати правильний баланс між безпекою та зручністю. +Різні рішення для гаманців пропонують різні підходи до безпеки ключової пари, +взаємодії з нею та підписання транзакцій для використання/витрачання токенів. +Деякі є простішими у використанні, ніж інші. Деякі забезпечують більш безпечне +зберігання та резервне копіювання секретних ключів. Solana підтримує кілька +типів гаманців, тому ви можете обрати правильний баланс між безпекою та +зручністю. -**Якщо ви хочете отримувати токени SOL у блокчейні Solana, вам спочатку потрібно створити гаманець.** +**Якщо ви хочете отримувати токени SOL у блокчейні Solana, вам спочатку потрібно +створити гаманець.** ## Підтримувані Гаманці -Кілька гаманців на основі браузера та мобільних додатків підтримують Solana. Знайдіть варіанти, які можуть підійти вам, на сторінці [Solana Wallets](https://solana.com/wallets). +Кілька гаманців на основі браузера та мобільних додатків підтримують Solana. +Знайдіть варіанти, які можуть підійти вам, на сторінці +[Solana Wallets](https://solana.com/wallets). -Для досвідчених користувачів або розробників більше підходять [гаманці командного рядка](https://docs.anza.xyz/cli/wallets), оскільки нові функції в блокчейні Solana завжди спочатку підтримуються в командному рядку, перш ніж бути інтегрованими у сторонні рішення. +Для досвідчених користувачів або розробників більше підходять +[гаманці командного рядка](https://docs.anza.xyz/cli/wallets), оскільки нові +функції в блокчейні Solana завжди спочатку підтримуються в командному рядку, +перш ніж бути інтегрованими у сторонні рішення. diff --git a/docs/locales/uk/more/exchange.md b/docs/locales/uk/more/exchange.md index 19a773cbc..9958a67a3 100644 --- a/docs/locales/uk/more/exchange.md +++ b/docs/locales/uk/more/exchange.md @@ -2,19 +2,27 @@ title: Додати Solana на Вашу Біржу --- -Цей посібник описує, як додати нативний токен Solana (SOL) до вашої криптовалютної біржі. +Цей посібник описує, як додати нативний токен Solana (SOL) до вашої +криптовалютної біржі. ## Налаштування Ноди -Ми наполегливо рекомендуємо налаштувати щонайменше дві ноди на високопродуктивних комп’ютерах або хмарних інстанціях, своєчасно оновлювати їх до нових версій і відстежувати роботу сервісу за допомогою вбудованих інструментів моніторингу. +Ми наполегливо рекомендуємо налаштувати щонайменше дві ноди на +високопродуктивних комп’ютерах або хмарних інстанціях, своєчасно оновлювати їх +до нових версій і відстежувати роботу сервісу за допомогою вбудованих +інструментів моніторингу. Це налаштування дозволяє вам: -- мати самостійно керований шлюз до кластеру Solana mainnet-beta для отримання даних і надсилання транзакцій на виведення +- мати самостійно керований шлюз до кластеру Solana mainnet-beta для отримання + даних і надсилання транзакцій на виведення - мати повний контроль над тим, скільки історичних даних блоків зберігається - забезпечувати доступність вашого сервісу навіть у разі відмови однієї з нод -Ноди Solana вимагають відносно високої обчислювальної потужності для обробки швидких блоків і високої пропускної здатності (TPS). Для конкретних вимог дивіться [рекомендації щодо апаратного забезпечення](https://docs.anza.xyz/operations/requirements). +Ноди Solana вимагають відносно високої обчислювальної потужності для обробки +швидких блоків і високої пропускної здатності (TPS). Для конкретних вимог +дивіться +[рекомендації щодо апаратного забезпечення](https://docs.anza.xyz/operations/requirements). Щоб запустити ноду API: @@ -35,70 +43,132 @@ solana-validator \ --only-known-rpc ``` -Налаштуйте параметр `--ledger` для бажаного розташування зберігання леджера та параметр `--rpc-port` для порту, який ви хочете зробити доступним. +Налаштуйте параметр `--ledger` для бажаного розташування зберігання леджера та +параметр `--rpc-port` для порту, який ви хочете зробити доступним. -Параметри `--entrypoint` та `--expected-genesis-hash` є специфічними для кластера, до якого ви приєднуєтеся. +Параметри `--entrypoint` та `--expected-genesis-hash` є специфічними для +кластера, до якого ви приєднуєтеся. [Поточні параметри для Mainnet Beta](https://docs.anza.xyz/clusters/available#example-solana-validator-command-line-2) -Параметр `--limit-ledger-size` дозволяє вказати, скільки [шредів](/docs/uk/terminology.md#shred) леджера ваша нода зберігатиме на диску. Якщо цей параметр не вказано, валідатор зберігатиме весь леджер, доки не закінчиться місце на диску. Значення за замовчуванням намагається обмежити використання місця на диску леджером до 500 ГБ. За потреби можна змінити це значення, додавши аргумент до параметра `--limit-ledger-size`. Для перегляду значення за замовчуванням, яке використовується параметром `--limit-ledger-size`, виконайте команду `solana-validator --help`. Більше інформації про вибір власного значення обмеження можна знайти [тут](https://github.com/solana-labs/solana/blob/583cec922b6107e0f85c7e14cb5e642bc7dfb340/core/src/ledger_cleanup_service.rs#L15-L26). - -Вказівка одного або кількох параметрів `--known-validator` може захистити вас від запуску з підробленого знімку. +Параметр `--limit-ledger-size` дозволяє вказати, скільки +[шредів](/docs/uk/terminology.md#shred) леджера ваша нода зберігатиме на диску. +Якщо цей параметр не вказано, валідатор зберігатиме весь леджер, доки не +закінчиться місце на диску. Значення за замовчуванням намагається обмежити +використання місця на диску леджером до 500 ГБ. За потреби можна змінити це +значення, додавши аргумент до параметра `--limit-ledger-size`. Для перегляду +значення за замовчуванням, яке використовується параметром +`--limit-ledger-size`, виконайте команду `solana-validator --help`. Більше +інформації про вибір власного значення обмеження можна знайти +[тут](https://github.com/solana-labs/solana/blob/583cec922b6107e0f85c7e14cb5e642bc7dfb340/core/src/ledger_cleanup_service.rs#L15-L26). + +Вказівка одного або кількох параметрів `--known-validator` може захистити вас +від запуску з підробленого знімку. [Більше про цінність запуску з відомими валідаторами](https://docs.anza.xyz/operations/guides/validator-start#known-validators) Додаткові параметри, які варто розглянути: -- `--private-rpc` забороняє публікацію вашого RPC-порту для використання іншими нодами +- `--private-rpc` забороняє публікацію вашого RPC-порту для використання іншими + нодами - `--rpc-bind-address` дозволяє вказати іншу IP-адресу для прив’язки RPC-порту ### Автоматичний Перезапуск та Моніторинг -Ми рекомендуємо налаштувати кожну з ваших нод на автоматичний перезапуск після завершення роботи, щоб мінімізувати втрату даних. Запуск програмного забезпечення Solana як служби systemd є одним із чудових варіантів. +Ми рекомендуємо налаштувати кожну з ваших нод на автоматичний перезапуск після +завершення роботи, щоб мінімізувати втрату даних. Запуск програмного +забезпечення Solana як служби systemd є одним із чудових варіантів. -Для моніторингу ми надаємо інструмент -[`solana-watchtower`](https://github.com/solana-labs/solana/blob/master/watchtower/README.md), -який може моніторити ваш валідатор і визначати, чи є процес `solana-validator` несправним. Він може бути налаштований для сповіщень через Slack, Telegram, Discord або Twilio. Для деталей виконайте команду `solana-watchtower --help`. +Для моніторингу ми надаємо інструмент +[`solana-watchtower`](https://github.com/solana-labs/solana/blob/master/watchtower/README.md), +який може моніторити ваш валідатор і визначати, чи є процес `solana-validator` +несправним. Він може бути налаштований для сповіщень через Slack, Telegram, +Discord або Twilio. Для деталей виконайте команду `solana-watchtower --help`. ```shell solana-watchtower --validator-identity ``` -> Додаткову інформацію про [найкращі практики для Solana Watchtower](https://docs.anza.xyz/operations/best-practices/monitoring#solana-watchtower) можна знайти у документації. + +> Додаткову інформацію про +> [найкращі практики для Solana Watchtower](https://docs.anza.xyz/operations/best-practices/monitoring#solana-watchtower) +> можна знайти у документації. #### Оголошення про Нові Релізи ПЗ -Ми випускаємо нове програмне забезпечення часто (приблизно один реліз на тиждень). Іноді нові версії містять несумісні протокольні зміни, які вимагають своєчасного оновлення ПЗ, щоб уникнути помилок при обробці блоків. +Ми випускаємо нове програмне забезпечення часто (приблизно один реліз на +тиждень). Іноді нові версії містять несумісні протокольні зміни, які вимагають +своєчасного оновлення ПЗ, щоб уникнути помилок при обробці блоків. -Наші офіційні оголошення про всі види релізів (звичайні та пов’язані з безпекою) публікуються в [каналі Discord](https://solana.com/discord) під назвою `#mb-announcement` (`mb` означає `mainnet-beta`). +Наші офіційні оголошення про всі види релізів (звичайні та пов’язані з безпекою) +публікуються в [каналі Discord](https://solana.com/discord) під назвою +`#mb-announcement` (`mb` означає `mainnet-beta`). -Як і для валідаторів зі ставками, ми очікуємо, що валідатори, які обслуговуються біржами, будуть оновлюватися протягом одного-двох робочих днів після оголошення про звичайний реліз. Для релізів, пов’язаних із безпекою, може знадобитися більш термінове реагування. +Як і для валідаторів зі ставками, ми очікуємо, що валідатори, які обслуговуються +біржами, будуть оновлюватися протягом одного-двох робочих днів після оголошення +про звичайний реліз. Для релізів, пов’язаних із безпекою, може знадобитися більш +термінове реагування. ### Цілісність Леджера -За замовчуванням кожна з ваших нод завантажується зі знімку, наданого одним із ваших відомих валідаторів. Цей знімок відображає поточний стан ланцюга, але не містить повного історичного леджера. Якщо одна з ваших нод зупиняється та завантажується з нового знімка, у леджері цієї ноди може з’явитися прогалина. Щоб уникнути цієї проблеми, додайте параметр `--no-snapshot-fetch` до команди `solana-validator`, щоб отримувати історичні дані леджера замість знімка. +За замовчуванням кожна з ваших нод завантажується зі знімку, наданого одним із +ваших відомих валідаторів. Цей знімок відображає поточний стан ланцюга, але не +містить повного історичного леджера. Якщо одна з ваших нод зупиняється та +завантажується з нового знімка, у леджері цієї ноди може з’явитися прогалина. +Щоб уникнути цієї проблеми, додайте параметр `--no-snapshot-fetch` до команди +`solana-validator`, щоб отримувати історичні дані леджера замість знімка. -Не додавайте параметр `--no-snapshot-fetch` під час початкового завантаження, оскільки неможливо завантажити ноду від самого генезис-блоку. Спочатку завантажтеся зі знімка, а потім додайте параметр `--no-snapshot-fetch` для наступних перезавантажень. +Не додавайте параметр `--no-snapshot-fetch` під час початкового завантаження, +оскільки неможливо завантажити ноду від самого генезис-блоку. Спочатку +завантажтеся зі знімка, а потім додайте параметр `--no-snapshot-fetch` для +наступних перезавантажень. -Варто зазначити, що обсяг доступного історичного леджера від інших нод у мережі обмежений. Якщо ваші валідатори зазнають значних простоїв, вони можуть не змогти синхронізуватися з мережею і будуть змушені завантажити новий знімок від відомого валідатора, що створить прогалину в історичному леджері, яку неможливо заповнити. +Варто зазначити, що обсяг доступного історичного леджера від інших нод у мережі +обмежений. Якщо ваші валідатори зазнають значних простоїв, вони можуть не змогти +синхронізуватися з мережею і будуть змушені завантажити новий знімок від +відомого валідатора, що створить прогалину в історичному леджері, яку неможливо +заповнити. ### Мінімізація Доступу до Портів Валідатора -Валідатору необхідно, щоб різні UDP- і TCP-порти були відкриті для вхідного трафіку від усіх інших валідаторів Solana. Хоча це найефективніший режим роботи і настійно рекомендується, можливо обмежити валідатор лише для вхідного трафіку від одного іншого валідатора Solana. - -Спочатку додайте аргумент `--restricted-repair-only-mode`. Це призведе до роботи валідатора в обмеженому режимі, в якому він не отримуватиме push-повідомлення від інших валідаторів і замість цього постійно опитуватиме інші валідатори для отримання блоків. Валідатор буде передавати UDP-пакети іншим валідаторам лише через порти _Gossip_ та _ServeR_ ("serve repair") і отримуватиме UDP-пакети лише через порти _Gossip_ та _Repair_. - -Порт _Gossip_ є двостороннім і дозволяє вашому валідатору підтримувати зв’язок із рештою кластеру. Ваш валідатор передаватиме запити на ремонт через порт _ServeR_, щоб отримувати нові блоки від решти мережі, оскільки Turbine тепер відключено. Ваш валідатор отримуватиме відповіді на запити ремонту через порт _Repair_ від інших валідаторів. - -Щоб додатково обмежити валідатор для запитів блоків лише від одного або кількох валідаторів, спочатку визначте публічний ключ (pubkey) цього валідатора та додайте аргументи `--gossip-pull-validator PUBKEY --repair-validator PUBKEY` для кожного PUBKEY. Це створить навантаження на кожен валідатор, який ви додаєте, тому робіть це обережно і лише після консультації з цільовим валідатором. - -Ваш валідатор тепер повинен спілкуватися лише з чітко вказаними валідаторами і лише через порти _Gossip_, _Repair_ та _ServeR_. +Валідатору необхідно, щоб різні UDP- і TCP-порти були відкриті для вхідного +трафіку від усіх інших валідаторів Solana. Хоча це найефективніший режим роботи +і настійно рекомендується, можливо обмежити валідатор лише для вхідного трафіку +від одного іншого валідатора Solana. + +Спочатку додайте аргумент `--restricted-repair-only-mode`. Це призведе до роботи +валідатора в обмеженому режимі, в якому він не отримуватиме push-повідомлення +від інших валідаторів і замість цього постійно опитуватиме інші валідатори для +отримання блоків. Валідатор буде передавати UDP-пакети іншим валідаторам лише +через порти _Gossip_ та _ServeR_ ("serve repair") і отримуватиме UDP-пакети лише +через порти _Gossip_ та _Repair_. + +Порт _Gossip_ є двостороннім і дозволяє вашому валідатору підтримувати зв’язок +із рештою кластеру. Ваш валідатор передаватиме запити на ремонт через порт +_ServeR_, щоб отримувати нові блоки від решти мережі, оскільки Turbine тепер +відключено. Ваш валідатор отримуватиме відповіді на запити ремонту через порт +_Repair_ від інших валідаторів. + +Щоб додатково обмежити валідатор для запитів блоків лише від одного або кількох +валідаторів, спочатку визначте публічний ключ (pubkey) цього валідатора та +додайте аргументи `--gossip-pull-validator PUBKEY --repair-validator PUBKEY` для +кожного PUBKEY. Це створить навантаження на кожен валідатор, який ви додаєте, +тому робіть це обережно і лише після консультації з цільовим валідатором. + +Ваш валідатор тепер повинен спілкуватися лише з чітко вказаними валідаторами і +лише через порти _Gossip_, _Repair_ та _ServeR_. ## Налаштування Депозитних Акаунтів -Акаунти Solana не потребують жодної ініціалізації в мережі; як тільки вони містять деяку кількість SOL, вони існують. Щоб налаштувати депозитний акаунт для вашої біржі, просто створіть ключову пару Solana за допомогою будь-якого з наших [інструментів для гаманців](https://docs.anza.xyz/cli/wallets). +Акаунти Solana не потребують жодної ініціалізації в мережі; як тільки вони +містять деяку кількість SOL, вони існують. Щоб налаштувати депозитний акаунт для +вашої біржі, просто створіть ключову пару Solana за допомогою будь-якого з наших +[інструментів для гаманців](https://docs.anza.xyz/cli/wallets). -Рекомендуємо використовувати унікальний депозитний акаунт для кожного з ваших користувачів. - -Акаунти Solana мають бути звільнені від оренди, містячи еквівалент 2-річної [оренди](/docs/uk/core/fees.md#rent) у SOL. Щоб визначити мінімальний баланс для звільнення від оренди для ваших депозитних акаунтів, виконайте запит до [ендпоінту `getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx): +Рекомендуємо використовувати унікальний депозитний акаунт для кожного з ваших +користувачів. +Акаунти Solana мають бути звільнені від оренди, містячи еквівалент 2-річної +[оренди](/docs/uk/core/fees.md#rent) у SOL. Щоб визначити мінімальний баланс для +звільнення від оренди для ваших депозитних акаунтів, виконайте запит до +[ендпоінту `getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx): ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -117,33 +187,56 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - ### Офлайн Акаунти -Ви можете залишити ключі для одного або декількох акаунтів колекції офлайн для підвищення безпеки. У цьому випадку вам потрібно буде переміщати SOL до "гарячих" акаунтів за допомогою наших [офлайн-методів](https://docs.anza.xyz/cli/examples/offline-signing). +Ви можете залишити ключі для одного або декількох акаунтів колекції офлайн для +підвищення безпеки. У цьому випадку вам потрібно буде переміщати SOL до +"гарячих" акаунтів за допомогою наших +[офлайн-методів](https://docs.anza.xyz/cli/examples/offline-signing). ## Відстеження Депозитів -Коли користувач хоче внести SOL на вашу біржу, інструктуйте його виконати переказ на відповідну депозитну адресу. +Коли користувач хоче внести SOL на вашу біржу, інструктуйте його виконати +переказ на відповідну депозитну адресу. ### Міграція Транзакцій із Версіями -Коли мережа Mainnet Beta почне обробляти транзакції із версіями, біржі **ЗОБОВ'ЯЗАНІ** внести зміни. Якщо не внести змін, виявлення депозитів працюватиме неправильно, оскільки отримання транзакції з версією або блоку, що містить такі транзакції, призведе до помилки. +Коли мережа Mainnet Beta почне обробляти транзакції із версіями, біржі +**ЗОБОВ'ЯЗАНІ** внести зміни. Якщо не внести змін, виявлення депозитів +працюватиме неправильно, оскільки отримання транзакції з версією або блоку, що +містить такі транзакції, призведе до помилки. - `{"maxSupportedTransactionVersion": 0}` - Параметр `maxSupportedTransactionVersion` потрібно додати до запитів `getBlock` і `getTransaction`, щоб уникнути порушення роботи виявлення депозитів. Остання версія транзакції — `0`, і саме її слід зазначати як максимальну підтримувану версію транзакції. + Параметр `maxSupportedTransactionVersion` потрібно додати до запитів + `getBlock` і `getTransaction`, щоб уникнути порушення роботи виявлення + депозитів. Остання версія транзакції — `0`, і саме її слід зазначати як + максимальну підтримувану версію транзакції. -Важливо розуміти, що транзакції з версіями дозволяють користувачам створювати транзакції, які використовують інший набір ключів акаунтів, завантажених з ончейн таблиць пошуку адрес. +Важливо розуміти, що транзакції з версіями дозволяють користувачам створювати +транзакції, які використовують інший набір ключів акаунтів, завантажених з +ончейн таблиць пошуку адрес. - `{"encoding": "jsonParsed"}` - При отриманні блоків і транзакцій тепер рекомендується використовувати кодування `"jsonParsed"`, оскільки воно включає всі ключі акаунтів транзакції (включаючи ті, що з таблиць пошуку) у список `"accountKeys"` повідомлення. Це спрощує розв'язання змін балансу, описаних у `preBalances` / `postBalances` і `preTokenBalances` / `postTokenBalances`. + При отриманні блоків і транзакцій тепер рекомендується використовувати + кодування `"jsonParsed"`, оскільки воно включає всі ключі акаунтів транзакції + (включаючи ті, що з таблиць пошуку) у список `"accountKeys"` повідомлення. Це + спрощує розв'язання змін балансу, описаних у `preBalances` / `postBalances` і + `preTokenBalances` / `postTokenBalances`. - Якщо використовується кодування `"json"`, записи у `preBalances` / `postBalances` і `preTokenBalances` / `postTokenBalances` можуть посилатися на ключі акаунтів, які **НЕ** входять до списку `"accountKeys"` і потребують розв'язання за допомогою записів `"loadedAddresses"` у метаданих транзакції. + Якщо використовується кодування `"json"`, записи у `preBalances` / + `postBalances` і `preTokenBalances` / `postTokenBalances` можуть посилатися на + ключі акаунтів, які **НЕ** входять до списку `"accountKeys"` і потребують + розв'язання за допомогою записів `"loadedAddresses"` у метаданих транзакції. ### Опитування Блоків -Для відстеження всіх депозитних акаунтів вашої біржі регулярно опитуйте кожен підтверджений блок і перевіряйте адреси, що вас цікавлять, використовуючи JSON-RPC сервіс вашої ноди API Solana. +Для відстеження всіх депозитних акаунтів вашої біржі регулярно опитуйте кожен +підтверджений блок і перевіряйте адреси, що вас цікавлять, використовуючи +JSON-RPC сервіс вашої ноди API Solana. -- Щоб визначити, які блоки доступні, надішліть запит [`getBlocks`](/docs/uk/rpc/http/getBlocks.mdx), передавши останній блок, який ви вже обробили, як параметр start-slot: +- Щоб визначити, які блоки доступні, надішліть запит + [`getBlocks`](/docs/uk/rpc/http/getBlocks.mdx), передавши останній блок, який + ви вже обробили, як параметр start-slot: ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -165,19 +258,25 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - "id": 1 } ``` + Не кожен слот створює блок, тому в послідовності чисел можуть бути прогалини. -- Для кожного блоку запитуйте його вміст за допомогою запиту [`getBlock`](/docs/uk/rpc/http/getBlock.mdx): +- Для кожного блоку запитуйте його вміст за допомогою запиту + [`getBlock`](/docs/uk/rpc/http/getBlock.mdx): ### Поради для Отримання Блоків - `{"rewards": false}` -За замовчуванням отримані блоки містять інформацію про комісії валідаторів за кожен блок і нагороди за стейкінг на межах епох. Якщо ця інформація вам не потрібна, вимкніть її за допомогою параметра `"rewards"`. +За замовчуванням отримані блоки містять інформацію про комісії валідаторів за +кожен блок і нагороди за стейкінг на межах епох. Якщо ця інформація вам не +потрібна, вимкніть її за допомогою параметра `"rewards"`. - `{"transactionDetails": "accounts"}` -За замовчуванням отримані блоки містять багато інформації про транзакції та метадані, які не потрібні для відстеження балансів акаунтів. Встановіть параметр `"transactionDetails"` для прискорення отримання блоків. +За замовчуванням отримані блоки містять багато інформації про транзакції та +метадані, які не потрібні для відстеження балансів акаунтів. Встановіть параметр +`"transactionDetails"` для прискорення отримання блоків. ```shell curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' -d '{ @@ -263,15 +362,29 @@ curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' - } ``` -Поля `preBalances` і `postBalances` дозволяють відстежувати зміни балансу кожного акаунта без необхідності аналізувати всю транзакцію. Вони містять початкові та кінцеві баланси кожного акаунта у [лампортах](/docs/uk/terminology.md#lamport), проіндексовані до списку `accountKeys`. Наприклад, якщо депозитна адреса, яка вас цікавить, — це `G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o`, то ця транзакція представляє переказ 1040000000 - 1030000000 = 10,000,000 лампортів = 0.01 SOL. +Поля `preBalances` і `postBalances` дозволяють відстежувати зміни балансу +кожного акаунта без необхідності аналізувати всю транзакцію. Вони містять +початкові та кінцеві баланси кожного акаунта у +[лампортах](/docs/uk/terminology.md#lamport), проіндексовані до списку +`accountKeys`. Наприклад, якщо депозитна адреса, яка вас цікавить, — це +`G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o`, то ця транзакція представляє +переказ 1040000000 - 1030000000 = 10,000,000 лампортів = 0.01 SOL. -Якщо вам потрібна додаткова інформація про тип транзакції або інші специфічні дані, ви можете запросити блок із RPC у бінарному форматі та проаналізувати його за допомогою нашого [Rust SDK](https://github.com/solana-labs/solana) або [JavaScript SDK](https://github.com/solana-labs/solana-web3.js). +Якщо вам потрібна додаткова інформація про тип транзакції або інші специфічні +дані, ви можете запросити блок із RPC у бінарному форматі та проаналізувати його +за допомогою нашого [Rust SDK](https://github.com/solana-labs/solana) або +[JavaScript SDK](https://github.com/solana-labs/solana-web3.js). ### Історія Адрес -Ви також можете запитати історію транзакцій для певної адреси. Це, як правило, _не_ є життєздатним методом для відстеження всіх ваших депозитних адрес за всіма слотами, але може бути корисним для аналізу кількох акаунтів за певний період часу. +Ви також можете запитати історію транзакцій для певної адреси. Це, як правило, +_не_ є життєздатним методом для відстеження всіх ваших депозитних адрес за всіма +слотами, але може бути корисним для аналізу кількох акаунтів за певний період +часу. -- Надішліть запит [`getSignaturesForAddress`](/docs/uk/rpc/http/getSignaturesForAddress.mdx) до API-ноди: +- Надішліть запит + [`getSignaturesForAddress`](/docs/uk/rpc/http/getSignaturesForAddress.mdx) до + API-ноди: ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -321,7 +434,9 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - "id": 1 } ``` -- Для кожного отриманого підпису отримайте деталі транзакції, надіславши запит [`getTransaction`](/docs/uk/rpc/http/getTransaction.mdx): + +- Для кожного отриманого підпису отримайте деталі транзакції, надіславши запит + [`getTransaction`](/docs/uk/rpc/http/getTransaction.mdx): ```shell curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' -d '{ @@ -420,44 +535,69 @@ curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' - ## Відправлення Виведення -Щоб виконати запит користувача на виведення SOL, ви повинні створити транзакцію переказу Solana та надіслати її на API-ноду для передачі в кластер. +Щоб виконати запит користувача на виведення SOL, ви повинні створити транзакцію +переказу Solana та надіслати її на API-ноду для передачі в кластер. ### Синхронний Переказ -Відправлення синхронного переказу до кластера Solana дозволяє легко переконатися, що переказ успішно завершено та підтверджено кластером. - -Інструмент командного рядка Solana пропонує просту команду `solana transfer` для створення, подання та підтвердження транзакцій переказу. За замовчуванням цей метод чекатиме та відстежуватиме прогрес через stderr, доки транзакція не буде підтверджена кластером. У разі невдачі транзакції буде повідомлено про будь-які помилки. +Відправлення синхронного переказу до кластера Solana дозволяє легко +переконатися, що переказ успішно завершено та підтверджено кластером. +Інструмент командного рядка Solana пропонує просту команду `solana transfer` для +створення, подання та підтвердження транзакцій переказу. За замовчуванням цей +метод чекатиме та відстежуватиме прогрес через stderr, доки транзакція не буде +підтверджена кластером. У разі невдачі транзакції буде повідомлено про будь-які +помилки. ```shell solana transfer --allow-unfunded-recipient --keypair --url http://localhost:8899 ``` -[Solana Javascript SDK](https://github.com/solana-labs/solana-web3.js) пропонує схожий підхід для екосистеми JS. Використовуйте `SystemProgram` для створення транзакції переказу та надсилайте її за допомогою методу `sendAndConfirmTransaction`. +[Solana Javascript SDK](https://github.com/solana-labs/solana-web3.js) пропонує +схожий підхід для екосистеми JS. Використовуйте `SystemProgram` для створення +транзакції переказу та надсилайте її за допомогою методу +`sendAndConfirmTransaction`. ### Асинхронний Переказ -Для більшої гнучкості ви можете надсилати перекази на виведення асинхронно. У цьому випадку саме ви несете відповідальність за перевірку успішності транзакції та її підтвердження кластером. +Для більшої гнучкості ви можете надсилати перекази на виведення асинхронно. У +цьому випадку саме ви несете відповідальність за перевірку успішності транзакції +та її підтвердження кластером. -**Примітка:** Кожна транзакція містить [recent blockhash](/docs/uk/core/transactions.md#recent-blockhash), що вказує на її актуальність. Важливо **дочекатися**, поки цей blockhash не стане недійсним, перш ніж повторювати спробу переказу, який, схоже, не було підтверджено або завершено кластером. Інакше ви ризикуєте створити подвійний витрату. Дивіться більше про [термін дії blockhash](#blockhash-expiration) нижче. +**Примітка:** Кожна транзакція містить +[recent blockhash](/docs/uk/core/transactions.md#recent-blockhash), що вказує на +її актуальність. Важливо **дочекатися**, поки цей blockhash не стане недійсним, +перш ніж повторювати спробу переказу, який, схоже, не було підтверджено або +завершено кластером. Інакше ви ризикуєте створити подвійний витрату. Дивіться +більше про [термін дії blockhash](#blockhash-expiration) нижче. -Спочатку отримайте недавній blockhash за допомогою ендпоінту [`getFees`](/docs/uk/rpc/deprecated/getFees.mdx) або команди CLI: +Спочатку отримайте недавній blockhash за допомогою ендпоінту +[`getFees`](/docs/uk/rpc/deprecated/getFees.mdx) або команди CLI: ```shell solana fees --url http://localhost:8899 ``` -У командному рядку передайте аргумент `--no-wait`, щоб відправити переказ асинхронно, і додайте ваш недавній blockhash за допомогою аргументу `--blockhash`: +У командному рядку передайте аргумент `--no-wait`, щоб відправити переказ +асинхронно, і додайте ваш недавній blockhash за допомогою аргументу +`--blockhash`: ```shell solana transfer --no-wait --allow-unfunded-recipient --blockhash --keypair --url http://localhost:8899 ``` -Ви також можете створити, підписати та серіалізувати транзакцію вручну, а потім надіслати її до кластера за допомогою ендпоінта JSON-RPC [`sendTransaction`](/docs/uk/rpc/http/sendTransaction.mdx). +Ви також можете створити, підписати та серіалізувати транзакцію вручну, а потім +надіслати її до кластера за допомогою ендпоінта JSON-RPC +[`sendTransaction`](/docs/uk/rpc/http/sendTransaction.mdx). #### Підтвердження Транзакцій та Фінальність -Отримайте статус групи транзакцій за допомогою ендпоінта JSON-RPC [`getSignatureStatuses`](/docs/uk/rpc/http/getSignatureStatuses.mdx). Поле `confirmations` вказує, скільки [підтверджених блоків](/docs/uk/terminology.md#confirmed-block) минуло з моменту обробки транзакції. Якщо `confirmations: null`, це означає, що транзакція є [фіналізованою](/docs/uk/terminology.md#finality). +Отримайте статус групи транзакцій за допомогою ендпоінта JSON-RPC +[`getSignatureStatuses`](/docs/uk/rpc/http/getSignatureStatuses.mdx). Поле +`confirmations` вказує, скільки +[підтверджених блоків](/docs/uk/terminology.md#confirmed-block) минуло з моменту +обробки транзакції. Якщо `confirmations: null`, це означає, що транзакція є +[фіналізованою](/docs/uk/terminology.md#finality). ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -507,33 +647,52 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - #### Термін Дії Blockhash -Ви можете перевірити, чи є конкретний blockhash ще дійсним, надіславши запит [`getFeeCalculatorForBlockhash`](/docs/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx) з blockhash як параметром. Якщо значення у відповіді `null`, blockhash недійсний, і транзакція на виведення, яка використовує цей blockhash, не має шансів на успіх. +Ви можете перевірити, чи є конкретний blockhash ще дійсним, надіславши запит +[`getFeeCalculatorForBlockhash`](/docs/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx) +з blockhash як параметром. Якщо значення у відповіді `null`, blockhash +недійсний, і транзакція на виведення, яка використовує цей blockhash, не має +шансів на успіх. ### Перевірка Адрес Акаунтів, Наданих Користувачами, для Виведення -Оскільки транзакції на виведення є незворотними, хорошою практикою може бути перевірка адреси акаунта, наданої користувачем, перед авторизацією виведення, щоб запобігти випадковій втраті коштів користувача. +Оскільки транзакції на виведення є незворотними, хорошою практикою може бути +перевірка адреси акаунта, наданої користувачем, перед авторизацією виведення, +щоб запобігти випадковій втраті коштів користувача. #### Основна Перевірка -Адреси Solana — це 32-байтовий масив, закодований за допомогою алфавіту base58 від Bitcoin. Це призводить до отримання ASCII-рядка, що відповідає наступному регулярному виразу: +Адреси Solana — це 32-байтовий масив, закодований за допомогою алфавіту base58 +від Bitcoin. Це призводить до отримання ASCII-рядка, що відповідає наступному +регулярному виразу: ```text [1-9A-HJ-NP-Za-km-z]{32,44} ``` -Ця перевірка сама по собі є недостатньою, оскільки адреси Solana не мають контрольної суми, тому помилки друку не можуть бути виявлені. Для додаткової перевірки введення користувачем можна декодувати рядок і підтвердити, що довжина отриманого байтового масиву дорівнює 32. Однак існують адреси, які можуть декодуватися у 32 байти, незважаючи на помилки, наприклад, пропущений символ, перестановка символів або ігнорування регістру. +Ця перевірка сама по собі є недостатньою, оскільки адреси Solana не мають +контрольної суми, тому помилки друку не можуть бути виявлені. Для додаткової +перевірки введення користувачем можна декодувати рядок і підтвердити, що довжина +отриманого байтового масиву дорівнює 32. Однак існують адреси, які можуть +декодуватися у 32 байти, незважаючи на помилки, наприклад, пропущений символ, +перестановка символів або ігнорування регістру. #### Розширена Перевірка -Через вразливість до помилок друку, описану вище, рекомендується запитувати баланс для можливих адрес виведення та запитувати у користувача підтвердження, якщо буде виявлено ненульовий баланс. +Через вразливість до помилок друку, описану вище, рекомендується запитувати +баланс для можливих адрес виведення та запитувати у користувача підтвердження, +якщо буде виявлено ненульовий баланс. #### Перевірка Валідного ed25519 Публічного Ключа -Адреса звичайного акаунта в Solana — це Base58-кодований рядок 256-бітного публічного ключа ed25519. Не всі бітові патерни є валідними публічними ключами для кривої ed25519, тому можна забезпечити, що адреси акаунтів, надані користувачем, принаймні є правильними публічними ключами ed25519. +Адреса звичайного акаунта в Solana — це Base58-кодований рядок 256-бітного +публічного ключа ed25519. Не всі бітові патерни є валідними публічними ключами +для кривої ed25519, тому можна забезпечити, що адреси акаунтів, надані +користувачем, принаймні є правильними публічними ключами ed25519. #### Java -Ось приклад на Java для перевірки адреси, наданої користувачем, як валідного публічного ключа ed25519: +Ось приклад на Java для перевірки адреси, наданої користувачем, як валідного +публічного ключа ed25519: Наступний приклад коду передбачає використання Maven. @@ -590,11 +749,13 @@ public class PubkeyValidator ## Мінімальні Суми Депозиту та Виведення -Кожен депозит та виведення SOL повинні бути більшими або дорівнювати мінімальному балансу, звільненому від оренди, для акаунта за адресою гаманця (базовий акаунт SOL, який не містить даних), який наразі складає: **0.000890880 SOL**. +Кожен депозит та виведення SOL повинні бути більшими або дорівнювати +мінімальному балансу, звільненому від оренди, для акаунта за адресою гаманця +(базовий акаунт SOL, який не містить даних), який наразі складає: **0.000890880 +SOL**. Аналогічно, кожен депозитний акаунт повинен містити принаймні цей баланс. - ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ "jsonrpc": "2.0", @@ -612,65 +773,99 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - ## Пріоритетні Комісії та Обчислювальні Одиниці -У періоди високого попиту транзакція може стати недійсною до того, як валідатор включить її до блоку, оскільки були обрані інші транзакції з вищою економічною цінністю. Валідні транзакції в Solana можуть бути затримані або скасовані, якщо Пріоритетні Комісії не впроваджені належним чином. +У періоди високого попиту транзакція може стати недійсною до того, як валідатор +включить її до блоку, оскільки були обрані інші транзакції з вищою економічною +цінністю. Валідні транзакції в Solana можуть бути затримані або скасовані, якщо +Пріоритетні Комісії не впроваджені належним чином. -[Пріоритетні Комісії](/docs/uk/terminology.md#prioritization-fee) — це додаткові комісії, які можна додати до [базової комісії за транзакцію](/docs/uk/core/fees.md#transaction-fees), щоб забезпечити включення транзакцій у блоки і їх доставку. +[Пріоритетні Комісії](/docs/uk/terminology.md#prioritization-fee) — це додаткові +комісії, які можна додати до +[базової комісії за транзакцію](/docs/uk/core/fees.md#transaction-fees), щоб +забезпечити включення транзакцій у блоки і їх доставку. -Ці пріоритетні комісії додаються до транзакції шляхом додавання спеціальної інструкції `Compute Budget`, яка встановлює бажану суму комісії. +Ці пріоритетні комісії додаються до транзакції шляхом додавання спеціальної +інструкції `Compute Budget`, яка встановлює бажану суму комісії. -Якщо ці інструкції не впровадити, це може призвести до збоїв у роботі мережі та скасування транзакцій. Наполегливо рекомендується кожній біржі, що підтримує Solana, використовувати пріоритетні комісії для уникнення збоїв. +Якщо ці інструкції не впровадити, це може призвести до збоїв у роботі мережі та +скасування транзакцій. Наполегливо рекомендується кожній біржі, що підтримує +Solana, використовувати пріоритетні комісії для уникнення збоїв. ### Що таке Пріоритетна Комісія? -Пріоритетні комісії виражаються у мікролампортах за обчислювальну одиницю (наприклад, невеликі суми SOL) і додаються до транзакцій, щоб зробити їх економічно привабливими для валідаторів і забезпечити їх включення до блоків у мережі. +Пріоритетні комісії виражаються у мікролампортах за обчислювальну одиницю +(наприклад, невеликі суми SOL) і додаються до транзакцій, щоб зробити їх +економічно привабливими для валідаторів і забезпечити їх включення до блоків у +мережі. ### Якою має бути Пріоритетна Комісія? -Метод встановлення пріоритетної комісії має включати запити до недавніх значень пріоритетних комісій, щоб встановити розмір комісії, яка буде привабливою для мережі. Використовуючи метод RPC [`getRecentPrioritizationFees`](/docs/uk/rpc/http/getrecentprioritizationfees), можна отримати дані про пріоритетні комісії, необхідні для підтвердження транзакції в недавньому блоці. +Метод встановлення пріоритетної комісії має включати запити до недавніх значень +пріоритетних комісій, щоб встановити розмір комісії, яка буде привабливою для +мережі. Використовуючи метод RPC +[`getRecentPrioritizationFees`](/docs/uk/rpc/http/getrecentprioritizationfees), +можна отримати дані про пріоритетні комісії, необхідні для підтвердження +транзакції в недавньому блоці. -Стратегія ціноутворення пріоритетних комісій залежить від ваших потреб. Універсального підходу не існує. Однією зі стратегій може бути розрахунок рівня успішності ваших транзакцій і коригування пріоритетної комісії відповідно до даних з API про комісії. Ціноутворення на пріоритетні комісії є динамічним і залежить від активності в мережі та ставок інших учасників. +Стратегія ціноутворення пріоритетних комісій залежить від ваших потреб. +Універсального підходу не існує. Однією зі стратегій може бути розрахунок рівня +успішності ваших транзакцій і коригування пріоритетної комісії відповідно до +даних з API про комісії. Ціноутворення на пріоритетні комісії є динамічним і +залежить від активності в мережі та ставок інших учасників. ### Як Впровадити Пріоритетні Комісії -Додавання пріоритетних комісій до транзакції включає додавання двох інструкцій Compute Budget: +Додавання пріоритетних комісій до транзакції включає додавання двох інструкцій +Compute Budget: - для встановлення ціни за обчислювальну одиницю - для встановлення ліміту обчислювальних одиниць -> Детальний [посібник для розробників про використання пріоритетних комісій](/content/guides/advanced/how-to-use-priority-fees.md) доступний для додаткової інформації. +> Детальний +> [посібник для розробників про використання пріоритетних комісій](/content/guides/advanced/how-to-use-priority-fees.md) +> доступний для додаткової інформації. -Створіть інструкцію `setComputeUnitPrice`, щоб додати Пріоритетну Комісію понад Базову Комісію за Транзакцію (5,000 лампортів). +Створіть інструкцію `setComputeUnitPrice`, щоб додати Пріоритетну Комісію понад +Базову Комісію за Транзакцію (5,000 лампортів). ```typescript // import { ComputeBudgetProgram } from "@solana/web3.js" ComputeBudgetProgram.setComputeUnitPrice({ microLamports: number }); ``` -Значення, надане в мікролампортах, буде множитися на обчислювальний бюджет (Compute Unit, CU), щоб визначити Пріоритетну Комісію в лампортах. Наприклад, якщо ваш бюджет CU становить 1M CU, і ви додаєте `1 мікролампорта/CU`, Пріоритетна Комісія становитиме 1 лампорт (1M \* 0.000001). Загальна комісія складе 5001 лампорт. - -Щоб встановити новий обчислювальний бюджет для транзакції, створіть інструкцію `setComputeUnitLimit`. +Значення, надане в мікролампортах, буде множитися на обчислювальний бюджет +(Compute Unit, CU), щоб визначити Пріоритетну Комісію в лампортах. Наприклад, +якщо ваш бюджет CU становить 1M CU, і ви додаєте `1 мікролампорта/CU`, +Пріоритетна Комісія становитиме 1 лампорт (1M \* 0.000001). Загальна комісія +складе 5001 лампорт. +Щоб встановити новий обчислювальний бюджет для транзакції, створіть інструкцію +`setComputeUnitLimit`. ```typescript // import { ComputeBudgetProgram } from "@solana/web3.js" ComputeBudgetProgram.setComputeUnitLimit({ units: number }); ``` -Значення `units`, яке ви надаєте, замінить стандартне значення обчислювального бюджету (Compute Budget) в середовищі виконання Solana. +Значення `units`, яке ви надаєте, замінить стандартне значення обчислювального +бюджету (Compute Budget) в середовищі виконання Solana. -Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць (CU), необхідну для виконання, щоб максимізувати пропускну здатність і мінімізувати загальні комісії. +Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць (CU), +необхідну для виконання, щоб максимізувати пропускну здатність і мінімізувати +загальні комісії. -Ви можете дізнатися, скільки CU споживає транзакція, надіславши її в інший кластер Solana, наприклад, devnet. Наприклад, [простий переказ токенів](https://explorer.solana.com/tx/5scDyuiiEbLxjLUww3APE9X7i8LE3H63unzonUwMG7s2htpoAGG17sgRsNAhR1zVs6NQAnZeRVemVbkAct5myi17) займає 300 CU. +Ви можете дізнатися, скільки CU споживає транзакція, надіславши її в інший +кластер Solana, наприклад, devnet. Наприклад, +[простий переказ токенів](https://explorer.solana.com/tx/5scDyuiiEbLxjLUww3APE9X7i8LE3H63unzonUwMG7s2htpoAGG17sgRsNAhR1zVs6NQAnZeRVemVbkAct5myi17) +займає 300 CU. - ```typescript // import { ... } from "@solana/web3.js" @@ -697,33 +892,55 @@ const transaction = new Transaction() ### Пріоритетні Комісії та Транзакції з Durable Nonces -Якщо у вашій системі використовуються транзакції з Durable Nonces, важливо правильно впровадити Пріоритетні Комісії разом із Durable Transaction Nonces, щоб забезпечити успішне виконання транзакцій. Якщо цього не зробити, заплановані Durable Nonce транзакції не будуть розпізнані належним чином. +Якщо у вашій системі використовуються транзакції з Durable Nonces, важливо +правильно впровадити Пріоритетні Комісії разом із Durable Transaction Nonces, +щоб забезпечити успішне виконання транзакцій. Якщо цього не зробити, заплановані +Durable Nonce транзакції не будуть розпізнані належним чином. -Якщо ви ВИКОРИСТОВУЄТЕ Durable Transaction Nonces, інструкція `AdvanceNonceAccount` МАЄ бути зазначена ПЕРШОЮ у списку інструкцій, навіть якщо використовуються інструкції обчислювального бюджету для встановлення пріоритетних комісій. +Якщо ви ВИКОРИСТОВУЄТЕ Durable Transaction Nonces, інструкція +`AdvanceNonceAccount` МАЄ бути зазначена ПЕРШОЮ у списку інструкцій, навіть якщо +використовуються інструкції обчислювального бюджету для встановлення +пріоритетних комісій. -Специфічний приклад коду, що демонструє використання durable nonces і пріоритетних комісій разом, можна знайти у [керівництві для розробників](/content/guides/advanced/how-to-use-priority-fees.md#special-considerations). +Специфічний приклад коду, що демонструє використання durable nonces і +пріоритетних комісій разом, можна знайти у +[керівництві для розробників](/content/guides/advanced/how-to-use-priority-fees.md#special-considerations). ## Підтримка Стандарту SPL Token -[SPL Token](https://spl.solana.com/token) є стандартом для створення і обміну обгорнутих/синтетичних токенів у блокчейні Solana. +[SPL Token](https://spl.solana.com/token) є стандартом для створення і обміну +обгорнутих/синтетичних токенів у блокчейні Solana. -Робочий процес SPL Token схожий на той, що використовується для нативних SOL токенів, але є кілька відмінностей, які будуть розглянуті в цьому розділі. +Робочий процес SPL Token схожий на той, що використовується для нативних SOL +токенів, але є кілька відмінностей, які будуть розглянуті в цьому розділі. ### Токен Mints -Кожен _тип_ SPL Token декларується шляхом створення акаунта _mint_. Цей акаунт зберігає метадані, які описують характеристики токена, такі як пропозиція, кількість десяткових знаків і різні повноваження з контролю за mint. Кожен акаунт SPL Token посилається на відповідний mint і може взаємодіяти лише з SPL Token цього типу. +Кожен _тип_ SPL Token декларується шляхом створення акаунта _mint_. Цей акаунт +зберігає метадані, які описують характеристики токена, такі як пропозиція, +кількість десяткових знаків і різні повноваження з контролю за mint. Кожен +акаунт SPL Token посилається на відповідний mint і може взаємодіяти лише з SPL +Token цього типу. ### Встановлення CLI Інструменту `spl-token` -Акаунти SPL Token можна запитувати та змінювати за допомогою утиліти командного рядка `spl-token`. Приклади, наведені в цьому розділі, залежать від того, що вона встановлена на вашій локальній системі. +Акаунти SPL Token можна запитувати та змінювати за допомогою утиліти командного +рядка `spl-token`. Приклади, наведені в цьому розділі, залежать від того, що +вона встановлена на вашій локальній системі. -`spl-token` розповсюджується з Rust [crates.io](https://crates.io/crates/spl-token) через утиліту командного рядка Rust `cargo`. Останню версію `cargo` можна встановити за допомогою простого скрипта для вашої платформи на [rustup.rs](https://rustup.rs). Після встановлення `cargo`, утиліту `spl-token` можна отримати за допомогою такої команди: +`spl-token` розповсюджується з Rust +[crates.io](https://crates.io/crates/spl-token) через утиліту командного рядка +Rust `cargo`. Останню версію `cargo` можна встановити за допомогою простого +скрипта для вашої платформи на [rustup.rs](https://rustup.rs). Після +встановлення `cargo`, утиліту `spl-token` можна отримати за допомогою такої +команди: ```shell cargo install spl-token-cli ``` -Після цього ви можете перевірити встановлену версію, щоб переконатися у правильності встановлення: +Після цього ви можете перевірити встановлену версію, щоб переконатися у +правильності встановлення: ```shell spl-token --version @@ -734,12 +951,21 @@ spl-token --version ```text spl-token-cli 2.0.1 ``` + ### Створення Акаунтів -Акаунти SPL Token мають додаткові вимоги, яких не мають нативні акаунти System Program: +Акаунти SPL Token мають додаткові вимоги, яких не мають нативні акаунти System +Program: -1. Акаунти SPL Token мають бути створені до того, як у них можна буде внести токени. Акаунти токенів можна створити явно за допомогою команди `spl-token create-account` або неявно за допомогою команди `spl-token transfer --fund-recipient ...`. -2. Акаунти SPL Token повинні залишатися [звільненими від оренди](/docs/uk/core/fees.md#rent-exempt) протягом усього періоду їх існування, а отже, вимагають внесення невеликої кількості нативних SOL токенів під час створення акаунта. Для акаунтів SPL Token ця сума становить 0.00203928 SOL (2,039,280 лампортів). +1. Акаунти SPL Token мають бути створені до того, як у них можна буде внести + токени. Акаунти токенів можна створити явно за допомогою команди + `spl-token create-account` або неявно за допомогою команди + `spl-token transfer --fund-recipient ...`. +2. Акаунти SPL Token повинні залишатися + [звільненими від оренди](/docs/uk/core/fees.md#rent-exempt) протягом усього + періоду їх існування, а отже, вимагають внесення невеликої кількості нативних + SOL токенів під час створення акаунта. Для акаунтів SPL Token ця сума + становить 0.00203928 SOL (2,039,280 лампортів). #### Командний Рядок @@ -764,6 +990,7 @@ spl-token create-account AkUFCWTXb3w9nY2n6SFJvBV6VwvFUCe4KBMCcgLsa2ir Creating account 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV Signature: 4JsqZEPra2eDTHtHpB4FMWSfk3UgcCVmkKkP7zESZeMrKmFFkDkNd91pKP3vPVVZZPiu5XxyJwS73Vi5WsZL88D7 ``` + Або щоб створити акаунт SPL Token з конкретною ключовою парою: ```shell @@ -778,6 +1005,7 @@ spl-token create-account AkUFCWTXb3w9nY2n6SFJvBV6VwvFUCe4KBMCcgLsa2ir token-acco Creating account 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV Signature: 4JsqZEPra2eDTHtHpB4FMWSfk3UgcCVmkKkP7zESZeMrKmFFkDkNd91pKP3vPVVZZPiu5XxyJwS73Vi5WsZL88D7 ``` + ### Перевірка Балансу Акаунта #### Командний Рядок @@ -799,11 +1027,15 @@ solana balance 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV ``` 0 ``` + ### Переказ Токенів -Вихідним акаунтом для переказу є фактичний акаунт токенів, який містить необхідну суму. +Вихідним акаунтом для переказу є фактичний акаунт токенів, який містить +необхідну суму. -Однак адресою отримувача може бути звичайний гаманець. Якщо асоційований токен акаунт для вказаного mint ще не існує для цього гаманця, переказ створить його, якщо буде вказаний аргумент `--fund-recipient`. +Однак адресою отримувача може бути звичайний гаманець. Якщо асоційований токен +акаунт для вказаного mint ще не існує для цього гаманця, переказ створить його, +якщо буде вказаний аргумент `--fund-recipient`. #### Командний Рядок @@ -831,19 +1063,43 @@ Signature: 3R6tsog17QM8KfzbcbdP4aoMfwgo6hBggJDVy7dZPVmH2xbCWjEj31JKD53NzMrf25ChF ### Депозити -Оскільки кожна пара `(гаманець, mint)` потребує окремого акаунта в ончейні, рекомендується, щоб адреси для цих акаунтів були отримані з гаманців для депозиту SOL за допомогою схеми [Associated Token Account (ATA)](https://spl.solana.com/associated-token-account), і приймалися _лише_ депозити з ATA адрес. +Оскільки кожна пара `(гаманець, mint)` потребує окремого акаунта в ончейні, +рекомендується, щоб адреси для цих акаунтів були отримані з гаманців для +депозиту SOL за допомогою схеми +[Associated Token Account (ATA)](https://spl.solana.com/associated-token-account), +і приймалися _лише_ депозити з ATA адрес. -Відстеження транзакцій депозиту має використовувати метод [опитування блоків](#poll-for-blocks), описаний вище. Кожен новий блок слід сканувати на наявність успішних транзакцій, що посилаються на адреси акаунтів, отриманих для користувачів. Поля `preTokenBalance` і `postTokenBalance` з метаданих транзакцій необхідно використовувати для визначення ефективної зміни балансу. Ці поля ідентифікують mint токена та власника акаунта (основну адресу гаманця) відповідного акаунта. +Відстеження транзакцій депозиту має використовувати метод +[опитування блоків](#poll-for-blocks), описаний вище. Кожен новий блок слід +сканувати на наявність успішних транзакцій, що посилаються на адреси акаунтів, +отриманих для користувачів. Поля `preTokenBalance` і `postTokenBalance` з +метаданих транзакцій необхідно використовувати для визначення ефективної зміни +балансу. Ці поля ідентифікують mint токена та власника акаунта (основну адресу +гаманця) відповідного акаунта. -Зауважте, що якщо акаунт для отримання створюється під час транзакції, у нього не буде запису `preTokenBalance`, оскільки стан акаунта раніше не існував. У цьому випадку початковий баланс можна вважати нульовим. +Зауважте, що якщо акаунт для отримання створюється під час транзакції, у нього +не буде запису `preTokenBalance`, оскільки стан акаунта раніше не існував. У +цьому випадку початковий баланс можна вважати нульовим. ### Виведення Адреса для виведення, надана користувачем, має бути адресою їх SOL гаманця. -Перед виконанням [переказу](#token-transfers) для виведення біржа повинна перевірити адресу, як це [описано вище](#validating-user-supplied-account-addresses-for-withdrawals). Крім того, ця адреса має належати System Program і не мати даних акаунта. Якщо на цій адресі відсутній баланс SOL, перед виконанням виведення слід отримати підтвердження користувача. Усі інші адреси для виведення повинні бути відхилені. - -З адреси для виведення [Associated Token Account (ATA)](https://spl.solana.com/associated-token-account) для відповідного mint отримується, і переказ виконується на цей акаунт за допомогою інструкції [TransferChecked](https://github.com/solana-labs/solana-program-library/blob/fc0d6a2db79bd6499f04b9be7ead0c400283845e/token/program/src/instruction.rs#L268). Зауважте, що ATA адреса може ще не існувати, у цьому випадку біржа повинна профінансувати акаунт від імені користувача. Для акаунтів SPL Token фінансування акаунта для виведення потребує 0.00203928 SOL (2,039,280 лампортів). +Перед виконанням [переказу](#token-transfers) для виведення біржа повинна +перевірити адресу, як це +[описано вище](#validating-user-supplied-account-addresses-for-withdrawals). +Крім того, ця адреса має належати System Program і не мати даних акаунта. Якщо +на цій адресі відсутній баланс SOL, перед виконанням виведення слід отримати +підтвердження користувача. Усі інші адреси для виведення повинні бути відхилені. + +З адреси для виведення +[Associated Token Account (ATA)](https://spl.solana.com/associated-token-account) +для відповідного mint отримується, і переказ виконується на цей акаунт за +допомогою інструкції +[TransferChecked](https://github.com/solana-labs/solana-program-library/blob/fc0d6a2db79bd6499f04b9be7ead0c400283845e/token/program/src/instruction.rs#L268). +Зауважте, що ATA адреса може ще не існувати, у цьому випадку біржа повинна +профінансувати акаунт від імені користувача. Для акаунтів SPL Token фінансування +акаунта для виведення потребує 0.00203928 SOL (2,039,280 лампортів). Шаблон команди `spl-token transfer` для виведення: @@ -855,31 +1111,54 @@ spl-token transfer --fund-recipient #### Freeze Authority (Замороження Акаунтів) -Для дотримання регуляторних вимог емітент токенів SPL може опціонально мати "Freeze Authority" (повноваження замороження) для всіх акаунтів, створених у зв'язку з його mint. Це дозволяє йому [заморожувати](https://spl.solana.com/token#freezing-accounts) активи в певному акаунті за бажанням, роблячи акаунт недоступним до моменту його розморожування. Якщо ця функція використовується, публічний ключ freeze authority буде зареєстрований у акаунті mint токену SPL. +Для дотримання регуляторних вимог емітент токенів SPL може опціонально мати +"Freeze Authority" (повноваження замороження) для всіх акаунтів, створених у +зв'язку з його mint. Це дозволяє йому +[заморожувати](https://spl.solana.com/token#freezing-accounts) активи в певному +акаунті за бажанням, роблячи акаунт недоступним до моменту його розморожування. +Якщо ця функція використовується, публічний ключ freeze authority буде +зареєстрований у акаунті mint токену SPL. ### Основна Підтримка Стандарту SPL Token-2022 (Token-Extensions) -[SPL Token-2022](https://spl.solana.com/token-2022) є новим стандартом для створення й обміну обгорнутих/синтетичних токенів у блокчейні Solana. +[SPL Token-2022](https://spl.solana.com/token-2022) є новим стандартом для +створення й обміну обгорнутих/синтетичних токенів у блокчейні Solana. -Відомий також як "Token Extensions", цей стандарт включає багато нових функцій, які можуть бути опціонально увімкнені творцями токенів та власниками акаунтів. До таких функцій належать конфіденційні перекази, комісії за переказ, закриття mint, метадані, постійні делегати, незмінна власність тощо. Більше інформації дивіться в [керівництві з розширень](https://spl.solana.com/token-2022/extensions). +Відомий також як "Token Extensions", цей стандарт включає багато нових функцій, +які можуть бути опціонально увімкнені творцями токенів та власниками акаунтів. +До таких функцій належать конфіденційні перекази, комісії за переказ, закриття +mint, метадані, постійні делегати, незмінна власність тощо. Більше інформації +дивіться в +[керівництві з розширень](https://spl.solana.com/token-2022/extensions). -Якщо ваша біржа підтримує SPL Token, багато додаткових зусиль для підтримки SPL Token-2022 не знадобиться: +Якщо ваша біржа підтримує SPL Token, багато додаткових зусиль для підтримки SPL +Token-2022 не знадобиться: -- CLI інструмент безпроблемно працює з обома програмами, починаючи з версії 3.0.0. -- Поля `preTokenBalances` та `postTokenBalances` включають баланси SPL Token-2022. -- RPC індексує акаунти SPL Token-2022, але їх потрібно запитувати окремо за програмним ідентифікатором `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`. +- CLI інструмент безпроблемно працює з обома програмами, починаючи з версії + 3.0.0. +- Поля `preTokenBalances` та `postTokenBalances` включають баланси SPL + Token-2022. +- RPC індексує акаунти SPL Token-2022, але їх потрібно запитувати окремо за + програмним ідентифікатором `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`. -Програма Associated Token Account працює так само, і правильно розраховує необхідну суму депозиту SOL для нового акаунта. +Програма Associated Token Account працює так само, і правильно розраховує +необхідну суму депозиту SOL для нового акаунта. -Однак через розширення акаунти можуть бути більшими за 165 байтів, тому вони можуть потребувати більше ніж 0.00203928 SOL для фінансування. +Однак через розширення акаунти можуть бути більшими за 165 байтів, тому вони +можуть потребувати більше ніж 0.00203928 SOL для фінансування. -Наприклад, програма Associated Token Account завжди включає розширення "immutable owner", тому акаунти займають мінімум 170 байтів, що вимагає 0.00207408 SOL. +Наприклад, програма Associated Token Account завжди включає розширення +"immutable owner", тому акаунти займають мінімум 170 байтів, що вимагає +0.00207408 SOL. ### Міркування Щодо Розширень -Попередній розділ описує базову підтримку SPL Token-2022. Оскільки розширення змінюють поведінку токенів, біржам, можливо, доведеться змінити, як вони обробляють токени. +Попередній розділ описує базову підтримку SPL Token-2022. Оскільки розширення +змінюють поведінку токенів, біржам, можливо, доведеться змінити, як вони +обробляють токени. -Можливо побачити всі розширення на mint або токен акаунті за допомогою наступної команди: +Можливо побачити всі розширення на mint або токен акаунті за допомогою наступної +команди: ```shell spl-token display @@ -887,9 +1166,11 @@ spl-token display #### Комісія за Переказ -Токен може бути налаштований з комісією за переказ, при якій частина переданих токенів утримується на адресі отримувача для подальшого стягнення. +Токен може бути налаштований з комісією за переказ, при якій частина переданих +токенів утримується на адресі отримувача для подальшого стягнення. -Якщо ваша біржа здійснює переказ цих токенів, зверніть увагу, що не всі токени можуть надійти на адресу отримувача через утриману суму. +Якщо ваша біржа здійснює переказ цих токенів, зверніть увагу, що не всі токени +можуть надійти на адресу отримувача через утриману суму. Під час переказу можна вказати очікувану комісію, щоб уникнути несподіванок: @@ -899,9 +1180,11 @@ spl-token transfer --expected-fee --fund-recipient #### Конфіденційні Перекази -Mint може бути налаштований для конфіденційних переказів, при яких суми токенів шифруються, але власники акаунтів залишаються публічними. +Mint може бути налаштований для конфіденційних переказів, при яких суми токенів +шифруються, але власники акаунтів залишаються публічними. -Біржі можуть налаштувати токен акаунти для відправлення та отримання конфіденційних переказів, щоб приховати суми користувачів. Увімкнення конфіденційних переказів для токен акаунтів не є обов’язковим, тому біржі можуть змусити користувачів надсилати токени неконфіденційно. +Біржі можуть налаштувати токен акаунти для відправлення та отримання +конфіденційних переказів, щоб приховати суми користувачів. Увімкнення +конфіденційних переказів для токен акаунтів не є обов’язковим, тому біржі можуть +змусити користувачів надсилати токени неконфіденційно. -Щоб увімкнути конфіденційні перекази, акаунт має бути налаштований відповідним чином: +Щоб увімкнути конфіденційні перекази, акаунт має бути налаштований відповідним +чином: ```shell spl-token configure-confidential-transfer-account --address @@ -927,7 +1215,9 @@ spl-token configure-confidential-transfer-account --address spl-token transfer --confidential ``` -Під час конфіденційного переказу поля `preTokenBalance` та `postTokenBalance` не показуватимуть змін. Щоб виконати операцію з депозитними акаунтами, необхідно розшифрувати новий баланс, щоб вивести токени: +Під час конфіденційного переказу поля `preTokenBalance` та `postTokenBalance` не +показуватимуть змін. Щоб виконати операцію з депозитними акаунтами, необхідно +розшифрувати новий баланс, щоб вивести токени: ```shell spl-token apply-pending-balance --address @@ -936,7 +1226,9 @@ spl-token withdraw-confidential-tokens --address --transfer-hook-account ... ``` + #### Обов'язкова Нотатка (Memo) при Переказі -Користувачі можуть налаштувати свої токен акаунти так, щоб перекази вимагали нотатку (memo). +Користувачі можуть налаштувати свої токен акаунти так, щоб перекази вимагали +нотатку (memo). -Біржі можуть додавати інструкцію нотатки перед тим, як переказати токени користувачам, або вимагати, щоб користувачі додавали нотатку перед відправкою токенів на біржу: +Біржі можуть додавати інструкцію нотатки перед тим, як переказати токени +користувачам, або вимагати, щоб користувачі додавали нотатку перед відправкою +токенів на біржу: ```shell spl-token transfer --with-memo ``` -## Тестування Інтеграції -Обов'язково протестуйте весь свій робочий процес у кластерах Solana devnet та testnet [clusters](/docs/uk/core/clusters.md) перед переходом до продакшну на mainnet-beta. Devnet є найбільш відкритим і гнучким, і ідеально підходить для початкової розробки, тоді як testnet пропонує більш реалістичну конфігурацію кластера. Обидва кластери devnet та testnet підтримують faucet. Використовуйте команду `solana airdrop 1`, щоб отримати трохи SOL для devnet або testnet для розробки та тестування. +## Тестування Інтеграції +Обов'язково протестуйте весь свій робочий процес у кластерах Solana devnet та +testnet [clusters](/docs/uk/core/clusters.md) перед переходом до продакшну на +mainnet-beta. Devnet є найбільш відкритим і гнучким, і ідеально підходить для +початкової розробки, тоді як testnet пропонує більш реалістичну конфігурацію +кластера. Обидва кластери devnet та testnet підтримують faucet. Використовуйте +команду `solana airdrop 1`, щоб отримати трохи SOL для devnet або testnet для +розробки та тестування. diff --git a/docs/locales/uk/programs/anchor/client-typescript.md b/docs/locales/uk/programs/anchor/client-typescript.md index 42be6e41c..d53d54e12 100644 --- a/docs/locales/uk/programs/anchor/client-typescript.md +++ b/docs/locales/uk/programs/anchor/client-typescript.md @@ -1,15 +1,16 @@ --- title: JS/TS Client description: - Дізнайтеся, як використовувати клієнтську бібліотеку TypeScript для взаємодії з Solana + Дізнайтеся, як використовувати клієнтську бібліотеку TypeScript для взаємодії + з Solana sidebarLabel: JS/TS Client sidebarSortOrder: 3 --- Anchor надає бібліотеку клієнта TypeScript ([@coral-xyz/anchor](https://github.com/coral-xyz/anchor/tree/v0.30.1/ts/packages/anchor)) -Це спрощує процес взаємодії з програмами Solana від клієнта -у JavaScript або TypeScript. +Це спрощує процес взаємодії з програмами Solana від клієнта у JavaScript або +TypeScript. ## Клієнтська програма @@ -22,15 +23,15 @@ Anchor надає бібліотеку клієнта TypeScript `AnchorProvider` - це абстракція, яка поєднує дві речі: - `Підключення ' - з'єднання з [кластером Solana] (/docs/core/clusters.md) -(тобто localhost, devnet, mainnet) -- `Wallet` - (необов’язково) Гаманець за замовчуванням, який використовується для оплати та підписання транзакцій - - - + (тобто localhost, devnet, mainnet) +- `Wallet` - (необов’язково) Гаманець за замовчуванням, який використовується + для оплати та підписання транзакцій + + -При інтеграції з фронтендом за допомогою -[Адаптер гаманця] (https://solana.com/developers/guides/wallets/add-solana-wallet-adapter-to-nextjs), -Вам потрібно буде налаштувати `AnchorProvider` та `Program`. +При інтеграції з фронтендом за допомогою [Адаптер гаманця] +(https://solana.com/developers/guides/wallets/add-solana-wallet-adapter-to-nextjs), +Вам потрібно буде налаштувати `AnchorProvider` та `Program`. ```ts {9-10, 12-14} import { Program, AnchorProvider, setProvider } from "@coral-xyz/anchor"; @@ -52,13 +53,13 @@ export const program = new Program(idl as HelloAnchor, { У фрагменті коду вище: - `idl.json` - це файл IDL, створений якір, знайдено на -`/target/idl/ .json` в якорі. + `/target/idl/ .json` в якорі. - `idltype.ts` - це тип IDL (для використання з TS), знайдено в -`/target/type/ .ts` в якорі. + `/target/type/ .ts` в якорі. -Крім того, ви можете створити екземпляр, використовуючи лише IDL -і підключення до кластеру солани.Це означає, що немає за замовчуванням -`Wallet`, але дозволяє використовувати` Програму 'для отримання облікових записів або побудувати +Крім того, ви можете створити екземпляр, використовуючи лише IDL і підключення +до кластеру солани.Це означає, що немає за замовчуванням `Wallet`, але дозволяє +використовувати` Програму 'для отримання облікових записів або побудувати Інструкції без підключеного гаманця. ```ts {8-10} @@ -77,9 +78,10 @@ export const program = new Program(idl as HelloAnchor, { -Якір автоматично налаштовує екземпляр `Program` у тестовому файлі за замовчуванням -нові проекти.Однак ця установка відрізняється від того, як ви ініціалізуєте програму -Поза робочою областю якоря, наприклад, у програмах React або Node.js. +Якір автоматично налаштовує екземпляр `Program` у тестовому файлі за +замовчуванням нові проекти.Однак ця установка відрізняється від того, як ви +ініціалізуєте програму Поза робочою областю якоря, наприклад, у програмах React +або Node.js. ```typescript import * as anchor from "@coral-xyz/anchor"; @@ -105,20 +107,23 @@ describe("hello_anchor", () => { ## Виклик інструкцій -Після того як `Program` налаштовано за допомогою програмного IDL, ви можете використовувати якір +Після того як `Program` налаштовано за допомогою програмного IDL, ви можете +використовувати якір [`MethodsBuilder`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L155) для: + - Створіть окремі інструкції - Будуйте транзакції - Будуйте та надсилайте транзакції Основний формат виглядає як наступне: + -`program.methods` - Це API Builder для створення інструкційних дзвінків з -IDL програми +`program.methods` - Це API Builder для створення інструкційних дзвінків з IDL +програми ```ts /methods/ {1} await program.methods @@ -131,7 +136,8 @@ await program.methods -У розділі `.methods` вказуйте назву інструкції з IDL програми, передаючи будь-які необхідні аргументи як значення, розділені комами. +У розділі `.methods` вказуйте назву інструкції з IDL програми, передаючи +будь-які необхідні аргументи як значення, розділені комами. ```ts /instructionName/ /instructionData1/ /instructionData2/ {2} await program.methods @@ -144,7 +150,8 @@ await program.methods -`.accounts` - Вказуйте адресу облікових записів, необхідних для інструкції, як це зазначено в IDL. +`.accounts` - Вказуйте адресу облікових записів, необхідних для інструкції, як +це зазначено в IDL. ```ts /accounts/ {3} await program.methods @@ -153,7 +160,9 @@ await program.methods .signers([]) .rpc(); ``` -Зверніть увагу, що деякі адреси облікових записів не потрібно вказувати явно, оскільки клієнт Anchor може автоматично їх визначити. Це зазвичай стосується: + +Зверніть увагу, що деякі адреси облікових записів не потрібно вказувати явно, +оскільки клієнт Anchor може автоматично їх визначити. Це зазвичай стосується: - Загальних облікових записів (наприклад, Програма Системи) - Облікових записів, де адреса є PDA (Програма-Походження Адреси) @@ -161,7 +170,10 @@ await program.methods -`.signers` - Необов'язково передайте масив ключових пар, які потрібні як додаткові підписанти для інструкції. Це зазвичай використовується при створенні нових облікових записів, де адреса облікового запису є публічним ключем нещодавно згенерованої ключової пари. +`.signers` - Необов'язково передайте масив ключових пар, які потрібні як +додаткові підписанти для інструкції. Це зазвичай використовується при створенні +нових облікових записів, де адреса облікового запису є публічним ключем +нещодавно згенерованої ключової пари. ```ts /signers/ {4} await program.methods @@ -171,7 +183,9 @@ await program.methods .rpc(); ``` -Зверніть увагу, що `.signers` слід використовувати тільки при використанні `.rpc()`. Коли ви використовуєте `.transaction()` або `.instruction()`, підписанти повинні бути додані до транзакції перед її відправкою. +Зверніть увагу, що `.signers` слід використовувати тільки при використанні +`.rpc()`. Коли ви використовуєте `.transaction()` або `.instruction()`, +підписанти повинні бути додані до транзакції перед її відправкою. @@ -182,11 +196,13 @@ Anchor надає кілька методів для створення інст -Метод [`rpc()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L283) +Метод +[`rpc()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L283) [відправляє підписану транзакцію](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/rpc.ts#L29) з вказаною інструкцією та повертає `TransactionSignature`. -При використанні `.rpc` гаманець з `Provider` автоматично додається як підписант. +При використанні `.rpc` гаманець з `Provider` автоматично додається як +підписант. ```ts {13} // Generate keypair for the new account @@ -207,7 +223,8 @@ const transactionSignature = await program.methods -Метод [`transaction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L382) +Метод +[`transaction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L382) [створює `Transaction`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/transaction.ts#L18-L26) з вказаною інструкцією без відправки транзакції. @@ -234,9 +251,11 @@ const transactionSignature = await connection.sendTransaction(transaction, [ -Метод [`instruction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L348) +Метод +[`instruction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L348) [створює `TransactionInstruction`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/instruction.ts#L57-L61) -з вказаною інструкцією. Це корисно, якщо ви хочете вручну додати інструкцію до транзакції та поєднати її з іншими інструкціями. +з вказаною інструкцією. Це корисно, якщо ви хочете вручну додати інструкцію до +транзакції та поєднати її з іншими інструкціями. ```ts {12} /instruction()/ // Generate keypair for the new account @@ -265,16 +284,20 @@ const transactionSignature = await connection.sendTransaction(transaction, [ ## Отримання облікових записів -Клієнт `Program` спрощує процес отримання та десеріалізації облікових записів, створених вашою програмою Anchor. +Клієнт `Program` спрощує процес отримання та десеріалізації облікових записів, +створених вашою програмою Anchor. -Використовуйте `program.account`, за яким слідує назва типу облікового запису, визначеного в IDL. Anchor надає кілька методів для отримання облікових записів. +Використовуйте `program.account`, за яким слідує назва типу облікового запису, +визначеного в IDL. Anchor надає кілька методів для отримання облікових записів. -Використовуйте [`all()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L251) -для отримання всіх існуючих облікових записів для конкретного типу облікового запису. +Використовуйте +[`all()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L251) +для отримання всіх існуючих облікових записів для конкретного типу облікового +запису. ```ts /all/ const accounts = await program.account.newAccount.all(); @@ -283,9 +306,13 @@ const accounts = await program.account.newAccount.all(); -Використовуйте `memcmp` (порівняння пам'яті) для фільтрації облікових записів, дані яких відповідають конкретному значенню на вказаному зсуві. Для використання `memcmp` необхідно розуміти байтову структуру поля даних для типу облікового запису, який ви отримуєте. +Використовуйте `memcmp` (порівняння пам'яті) для фільтрації облікових записів, +дані яких відповідають конкретному значенню на вказаному зсуві. Для використання +`memcmp` необхідно розуміти байтову структуру поля даних для типу облікового +запису, який ви отримуєте. -При обчисленні зсуву пам'ятайте, що перші 8 байтів у облікових записах, створених програмою Anchor, зарезервовані для дискримінатора облікового запису. +При обчисленні зсуву пам'ятайте, що перші 8 байтів у облікових записах, +створених програмою Anchor, зарезервовані для дискримінатора облікового запису. ```ts /memcmp/ const accounts = await program.account.newAccount.all([ @@ -301,7 +328,8 @@ const accounts = await program.account.newAccount.all([ -Використовуйте [`fetch()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L165) +Використовуйте +[`fetch()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L165) для отримання даних облікового запису для одного облікового запису. ```ts /fetch/ @@ -311,8 +339,10 @@ const account = await program.account.newAccount.fetch(ACCOUNT_ADDRESS); -Використовуйте [`fetchMultiple()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L200) -для отримання даних облікових записів для кількох облікових записів, передавши масив адрес облікових записів. +Використовуйте +[`fetchMultiple()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L200) +для отримання даних облікових записів для кількох облікових записів, передавши +масив адрес облікових записів. ```ts /fetchMultiple/ const accounts = await program.account.newAccount.fetchMultiple([ diff --git a/docs/locales/uk/programs/anchor/cpi.md b/docs/locales/uk/programs/anchor/cpi.md index 4e725d555..311a1444f 100644 --- a/docs/locales/uk/programs/anchor/cpi.md +++ b/docs/locales/uk/programs/anchor/cpi.md @@ -1,29 +1,30 @@ --- title: CPIs з Anchor description: - Дізнайтеся, як реалізувати Cross Program Invocations (CPI) в програмах на Anchor, - що дозволяє взаємодіяти між різними програмами на Solana + Дізнайтеся, як реалізувати Cross Program Invocations (CPI) в програмах на + Anchor, що дозволяє взаємодіяти між різними програмами на Solana sidebarLabel: CPIs з Anchor sidebarSortOrder: 5 --- [Cross Program Invocations (CPI)](/docs/core/cpi.md) означають процес, коли одна -програма викликає інструкції іншої програми, що дозволяє здійснювати композицію програм на Solana. +програма викликає інструкції іншої програми, що дозволяє здійснювати композицію +програм на Solana. -Цей розділ охоплює основи реалізації CPIs в програмі Anchor, -використовуючи інструкцію простого переказу SOL як практичний приклад. Після того, як ви -зрозумієте основи реалізації CPI, ви зможете застосувати ці ж концепції -для будь-якої інструкції. +Цей розділ охоплює основи реалізації CPIs в програмі Anchor, використовуючи +інструкцію простого переказу SOL як практичний приклад. Після того, як ви +зрозумієте основи реалізації CPI, ви зможете застосувати ці ж концепції для +будь-якої інструкції. ## Cross Program Invocations -Розглянемо програму, яка реалізує CPI для інструкції переказу в System Program. Ось приклад програми на +Розглянемо програму, яка реалізує CPI для інструкції переказу в System Program. +Ось приклад програми на [Solana Playground](https://beta.solpg.io/66df2751cffcf4b13384d35a). Файл `lib.rs` містить одну інструкцію `sol_transfer`. Коли інструкція -`sol_transfer` в програмі Anchor викликається, програма -внутрішньо викликає інструкцію переказу з System Program. - +`sol_transfer` в програмі Anchor викликається, програма внутрішньо викликає +інструкцію переказу з System Program. ```rs filename="lib.rs" /sol_transfer/ /transfer/ {23} use anchor_lang::prelude::*; @@ -63,8 +64,8 @@ pub struct SolTransfer<'info> { } ``` -Файл `cpi.test.ts` показує, як викликати інструкцію `sol_transfer` програми Anchor і реєструє посилання на деталі транзакції на SolanaFM. - +Файл `cpi.test.ts` показує, як викликати інструкцію `sol_transfer` програми +Anchor і реєструє посилання на деталі транзакції на SolanaFM. ```ts filename="cpi.test.ts" it("SOL Transfer Anchor", async () => { @@ -83,29 +84,30 @@ it("SOL Transfer Anchor", async () => { }); ``` -Ви можете побудувати, розгорнути та запустити тест для цього прикладу на Playground, щоб переглянути -деталі транзакції на [SolanaFM explorer](https://solana.fm/). +Ви можете побудувати, розгорнути та запустити тест для цього прикладу на +Playground, щоб переглянути деталі транзакції на +[SolanaFM explorer](https://solana.fm/). Деталі транзакції покажуть, що спочатку була викликана програма Anchor -(інструкція 1), яка потім викликає System Program (інструкція 1.1), -що призводить до успішного переказу SOL. +(інструкція 1), яка потім викликає System Program (інструкція 1.1), що +призводить до успішного переказу SOL. ![Деталі транзакції](/assets/docs/core/cpi/transaction-details.png) ### Пояснення прикладу 1 -Реалізація CPI слідує такому ж шаблону, як і створення інструкції для додавання в -транзакцію. Коли реалізуємо CPI, потрібно вказати ID програми, -рахунки та дані інструкції для викликаної інструкції. +Реалізація CPI слідує такому ж шаблону, як і створення інструкції для додавання +в транзакцію. Коли реалізуємо CPI, потрібно вказати ID програми, рахунки та дані +інструкції для викликаної інструкції. Інструкція переказу в System Program вимагає два рахунки: - `from`: Рахунок, що надсилає SOL. - `to`: Рахунок, що отримує SOL. -У прикладній програмі структура `SolTransfer` вказує рахунки, необхідні -для інструкції переказу. System Program також включена, оскільки CPI -викликає System Program. +У прикладній програмі структура `SolTransfer` вказує рахунки, необхідні для +інструкції переказу. System Program також включена, оскільки CPI викликає System +Program. ```rust /sender/ /recipient/ /system_program/ #[derive(Accounts)] @@ -127,13 +129,13 @@ CPI. -Інструкція `sol_transfer`, включена в прикладний код, показує типовий -підхід до побудови CPIs за допомогою фреймворку Anchor. +Інструкція `sol_transfer`, включена в прикладний код, показує типовий підхід до +побудови CPIs за допомогою фреймворку Anchor. Цей підхід передбачає створення [`CpiContext`](https://docs.rs/anchor-lang/latest/anchor_lang/context/struct.CpiContext.html), -який містить `program_id` та рахунки, необхідні для викликаної інструкції, а також допоміжну функцію (`transfer`) для виклику конкретної -інструкції. +який містить `program_id` та рахунки, необхідні для викликаної інструкції, а +також допоміжну функцію (`transfer`) для виклику конкретної інструкції. ```rust use anchor_lang::system_program::{transfer, Transfer}; @@ -158,8 +160,8 @@ pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { } ``` -Змінна `cpi_context` вказує ID програми (System Program) та -рахунки (відправник і отримувач), необхідні для інструкції переказу. +Змінна `cpi_context` вказує ID програми (System Program) та рахунки (відправник +і отримувач), необхідні для інструкції переказу. ```rust /program_id/ /from_pubkey/ /to_pubkey/ let cpi_context = CpiContext::new( @@ -171,8 +173,8 @@ let cpi_context = CpiContext::new( ); ``` -Змінні `cpi_context` та `amount` передаються в функцію `transfer` для -виконання CPI, що викликає інструкцію переказу з System Program. +Змінні `cpi_context` та `amount` передаються в функцію `transfer` для виконання +CPI, що викликає інструкцію переказу з System Program. ```rust transfer(cpi_context, amount)?; @@ -181,12 +183,13 @@ transfer(cpi_context, amount)?; -Цей приклад показує інший підхід до реалізації CPI за допомогою функції `invoke` та +Цей приклад показує інший підхід до реалізації CPI за допомогою функції `invoke` +та [`system_instruction::transfer`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L881), що зазвичай використовується в рідних програмах на Rust. -Під капотом попередній приклад є абстракцією цієї реалізації. -Нижче наведений приклад є функціонально еквівалентним попередньому. +Під капотом попередній приклад є абстракцією цієї реалізації. Нижче наведений +приклад є функціонально еквівалентним попередньому. ```rust use anchor_lang::solana_program::{program::invoke, system_instruction}; @@ -209,11 +212,13 @@ pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { -Ви також можете вручну створити інструкцію для передачі в функцію `invoke()`. -Це корисно, коли немає доступної бібліотеки, що допомагає побудувати -інструкцію, яку ви хочете викликати. Цей підхід вимагає вказати `AccountMeta` для інструкції та правильно створити буфер даних інструкції. +Ви також можете вручну створити інструкцію для передачі в функцію `invoke()`. Це +корисно, коли немає доступної бібліотеки, що допомагає побудувати інструкцію, +яку ви хочете викликати. Цей підхід вимагає вказати `AccountMeta` для інструкції +та правильно створити буфер даних інструкції. -Інструкція `sol_transfer` нижче є вручну реалізованим CPI для інструкції переказу в System Program. +Інструкція `sol_transfer` нижче є вручну реалізованим CPI для інструкції +переказу в System Program. ```rust /instruction/10,13 {28} pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { @@ -249,13 +254,13 @@ pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { ``` Інструкція `sol_transfer` вище повторює цей -[приклад](/docs/core/transactions.md#manual-sol-transfer) вручну побудованої інструкції переказу SOL. Вона слідує тому ж шаблону, що і створення +[приклад](/docs/core/transactions.md#manual-sol-transfer) вручну побудованої +інструкції переказу SOL. Вона слідує тому ж шаблону, що і створення [інструкції](/docs/core/transactions.md#instruction) для додавання в транзакцію. При створенні інструкції на Rust використовуйте наступний синтаксис для вказівки `AccountMeta` для кожного рахунку: - ```rust AccountMeta::new(account1_pubkey, true), // writable, signer AccountMeta::new(account2_pubkey, false), // writable, not signer @@ -272,12 +277,13 @@ AccountMeta::new_readonly(account4_pubkey, true), // writable, signer ## Cross Program Invocations з PDA підписами -Далі розглянемо програму, яка реалізує CPI для інструкції переказу в System Program, де відправником є Програма Походження Адреси (PDA), для якої програма повинна "підписати" транзакцію. Ось приклад програми на +Далі розглянемо програму, яка реалізує CPI для інструкції переказу в System +Program, де відправником є Програма Походження Адреси (PDA), для якої програма +повинна "підписати" транзакцію. Ось приклад програми на [Solana Playground](https://beta.solpg.io/66df2bd2cffcf4b13384d35b). Файл `lib.rs` містить наступну програму з єдиною інструкцією `sol_transfer`. - ```rust filename="lib.rs" use anchor_lang::prelude::*; use anchor_lang::system_program::{transfer, Transfer}; @@ -325,11 +331,11 @@ pub struct SolTransfer<'info> { } ``` -Файл `cpi.test.ts` показує, як викликати інструкцію `sol_transfer` програми Anchor і реєструє посилання на деталі транзакції на SolanaFM. +Файл `cpi.test.ts` показує, як викликати інструкцію `sol_transfer` програми +Anchor і реєструє посилання на деталі транзакції на SolanaFM. Він показує, як отримати PDA за допомогою насіння, вказаного в програмі: - ```ts /pda/ /wallet.publicKey/ const [PDA] = PublicKey.findProgramAddressSync( [Buffer.from("pda"), wallet.publicKey.toBuffer()], @@ -337,8 +343,8 @@ const [PDA] = PublicKey.findProgramAddressSync( ); ``` -Першим кроком у цьому прикладі є фінансування рахунку PDA за допомогою простого переказу SOL з гаманця Playground. - +Першим кроком у цьому прикладі є фінансування рахунку PDA за допомогою простого +переказу SOL з гаманця Playground. ```ts filename="cpi.test.ts" it("Fund PDA with SOL", async () => { @@ -364,8 +370,8 @@ it("Fund PDA with SOL", async () => { ``` Коли PDA буде фінансовано SOL, викликається інструкція `sol_transfer`. Ця -інструкція переказує SOL з рахунку PDA назад на рахунок `wallet` через -CPI до System Program, що "підписується" програмою. +інструкція переказує SOL з рахунку PDA назад на рахунок `wallet` через CPI до +System Program, що "підписується" програмою. ```ts it("SOL Transfer with PDA signer", async () => { @@ -383,12 +389,12 @@ it("SOL Transfer with PDA signer", async () => { }); ``` -Ви можете побудувати, розгорнути та запустити тест, щоб переглянути деталі транзакції на -[SolanaFM explorer](https://solana.fm/). +Ви можете побудувати, розгорнути та запустити тест, щоб переглянути деталі +транзакції на [SolanaFM explorer](https://solana.fm/). Деталі транзакції покажуть, що спочатку була викликана користувацька програма -(інструкція 1), яка потім викликає System Program (інструкція 1.1), -що призводить до успішного переказу SOL. +(інструкція 1), яка потім викликає System Program (інструкція 1.1), що +призводить до успішного переказу SOL. ![Деталі транзакції](/assets/docs/core/cpi/transaction-details-pda.png) @@ -397,10 +403,10 @@ it("SOL Transfer with PDA signer", async () => { У прикладному коді структура `SolTransfer` вказує рахунки, необхідні для інструкції переказу. -Відправником є PDA, для якого програма повинна підписати транзакцію. `seeds`, які використовуються для отримання -адреси для `pda_account`, включають зашитий рядок "pda" та адресу -рахунку `recipient`. Це означає, що адреса для `pda_account` є -унікальною для кожного `recipient`. +Відправником є PDA, для якого програма повинна підписати транзакцію. `seeds`, +які використовуються для отримання адреси для `pda_account`, включають зашитий +рядок "pda" та адресу рахунку `recipient`. Це означає, що адреса для +`pda_account` є унікальною для кожного `recipient`. ```rust /pda_account/ /recipient/2 /system_program/ #[derive(Accounts)] @@ -425,6 +431,7 @@ const [PDA] = PublicKey.findProgramAddressSync( program.programId, ); ``` + Наступні вкладки представляють два підходи до реалізації Cross Program Invocations (CPI), кожен з яких має різний рівень абстракції. Обидва приклади є функціонально еквівалентними. Основною метою є ілюстрація деталей реалізації @@ -434,13 +441,13 @@ CPI. -Інструкція `sol_transfer`, включена в прикладний код, показує типовий -підхід до побудови CPIs за допомогою фреймворку Anchor. +Інструкція `sol_transfer`, включена в прикладний код, показує типовий підхід до +побудови CPIs за допомогою фреймворку Anchor. Цей підхід передбачає створення [`CpiContext`](https://docs.rs/anchor-lang/latest/anchor_lang/context/struct.CpiContext.html), -який містить `program_id` та рахунки, необхідні для викликаної інструкції, а також допоміжну функцію (`transfer`) для виклику конкретної -інструкції. +який містить `program_id` та рахунки, необхідні для викликаної інструкції, а +також допоміжну функцію (`transfer`) для виклику конкретної інструкції. ```rust /cpi_context/ {19} pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { @@ -485,9 +492,8 @@ let cpi_context = CpiContext::new( .with_signer(signer_seeds); ``` -Змінні `cpi_context` та `amount` передаються в функцію `transfer` для -виконання CPI. - +Змінні `cpi_context` та `amount` передаються в функцію `transfer` для виконання +CPI. ```rust transfer(cpi_context, amount)?; @@ -495,19 +501,19 @@ transfer(cpi_context, amount)?; Коли обробляється CPI, середовище виконання Solana перевіряє, чи правильно наведені насіння та ID програми викликача для отримання дійсного PDA. Потім PDA -додається як підписант під час виклику. Цей механізм дозволяє програмам підписувати PDA, -які отримані з їхнього ID програми. +додається як підписант під час виклику. Цей механізм дозволяє програмам +підписувати PDA, які отримані з їхнього ID програми. -Під капотом попередній приклад є обгорткою для функції `invoke_signed()`, -яка використовує +Під капотом попередній приклад є обгорткою для функції `invoke_signed()`, яка +використовує [`system_instruction::transfer`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L881) для побудови інструкції. -Цей приклад показує, як використовувати функцію `invoke_signed()`, щоб зробити CPI -підписаним PDA. +Цей приклад показує, як використовувати функцію `invoke_signed()`, щоб зробити +CPI підписаним PDA. ```rust use anchor_lang::solana_program::{program::invoke_signed, system_instruction}; @@ -530,8 +536,9 @@ pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { Ok(()) } ``` -Ця реалізація функціонально еквівалентна попередньому прикладу. -`signer_seeds` передаються в функцію `invoke_signed`. + +Ця реалізація функціонально еквівалентна попередньому прикладу. `signer_seeds` +передаються в функцію `invoke_signed`. diff --git a/docs/locales/uk/programs/anchor/idl.md b/docs/locales/uk/programs/anchor/idl.md index 1f4024f89..080f030d6 100644 --- a/docs/locales/uk/programs/anchor/idl.md +++ b/docs/locales/uk/programs/anchor/idl.md @@ -7,19 +7,22 @@ sidebarLabel: Файл IDL sidebarSortOrder: 2 --- -Файл Interface Definition Language (IDL) надає стандартизований JSON-файл, -який описує інструкції та рахунки програми. Цей файл спрощує процес інтеграції -вашої програми на блокчейні з клієнтськими додатками. +Файл Interface Definition Language (IDL) надає стандартизований JSON-файл, який +описує інструкції та рахунки програми. Цей файл спрощує процес інтеграції вашої +програми на блокчейні з клієнтськими додатками. Основні переваги IDL: -- Стандартизація: Надає послідовний формат для опису інструкцій та рахунків програми -- Генерація клієнта: Використовується для генерації коду клієнта для взаємодії з програмою +- Стандартизація: Надає послідовний формат для опису інструкцій та рахунків + програми +- Генерація клієнта: Використовується для генерації коду клієнта для взаємодії з + програмою Команда `anchor build` генерує файл IDL, який знаходиться за адресою `/target/idl/.json`. -Нижче наведені фрагменти коду, що показують, як програма, IDL та клієнт взаємопов'язані. +Нижче наведені фрагменти коду, що показують, як програма, IDL та клієнт +взаємопов'язані. ## Інструкції програми @@ -31,8 +34,8 @@ sidebarSortOrder: 2 -Наведена програма включає інструкцію `initialize`, що вказує на рахунки -та параметри, які вона потребує. +Наведена програма включає інструкцію `initialize`, що вказує на рахунки та +параметри, які вона потребує. ```rust {8-12, 15-22} use anchor_lang::prelude::*; @@ -181,17 +184,16 @@ describe("hello_anchor", () => { ## Рахунки програми -Масив `accounts` у файлі IDL відповідає структурам у програмі, -позначеним макросом `#[account]`. Ці структури визначають дані, які зберігаються в +Масив `accounts` у файлі IDL відповідає структурам у програмі, позначеним +макросом `#[account]`. Ці структури визначають дані, які зберігаються в рахунках, створених програмою. -Наведена програма визначає структуру `NewAccount` з одним полем `data` -типу `u64`. - +Наведена програма визначає структуру `NewAccount` з одним полем `data` типу +`u64`. ```rust {24-27} use anchor_lang::prelude::*; @@ -229,7 +231,6 @@ pub struct NewAccount { Згенерований файл IDL включає рахунок у стандартизованому форматі JSON, включаючи його ім'я, дискримінатор та поля. - ```json filename="JSON" {39-40, 45-54} { "address": "BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd", @@ -341,23 +342,27 @@ describe("hello_anchor", () => { ## Дискримінатори -Anchor призначає унікальний 8-байтовий дискримінатор для кожної інструкції та типу рахунку в програмі. Ці дискримінатори служать як ідентифікатори для відрізнення різних інструкцій або типів рахунків. +Anchor призначає унікальний 8-байтовий дискримінатор для кожної інструкції та +типу рахунку в програмі. Ці дискримінатори служать як ідентифікатори для +відрізнення різних інструкцій або типів рахунків. -Дискримінатор генерується за допомогою перших 8 байтів хешу Sha256 префікса, поєднаного з ім'ям інструкції або рахунку. Починаючи з версії Anchor v0.30, ці дискримінатори включені в файл IDL. +Дискримінатор генерується за допомогою перших 8 байтів хешу Sha256 префікса, +поєднаного з ім'ям інструкції або рахунку. Починаючи з версії Anchor v0.30, ці +дискримінатори включені в файл IDL. Зверніть увагу, що при роботі з Anchor, вам зазвичай не потрібно взаємодіяти -безпосередньо з цими дискримінаторами. Цей розділ надає контекст щодо того, -як генерується і використовується дискримінатор. +безпосередньо з цими дискримінаторами. Цей розділ надає контекст щодо того, як +генерується і використовується дискримінатор. -Дискримінатор інструкції використовується програмою для визначення, яку конкретну -інструкцію виконати при виклику. +Дискримінатор інструкції використовується програмою для визначення, яку +конкретну інструкцію виконати при виклику. -Коли інструкція програми Anchor викликається, дискримінатор включається як -перші 8 байтів даних інструкції. Це робиться автоматично клієнтом Anchor. +Коли інструкція програми Anchor викликається, дискримінатор включається як перші +8 байтів даних інструкції. Це робиться автоматично клієнтом Anchor. ```json filename="IDL" {4} "instructions": [ @@ -369,7 +374,8 @@ Anchor призначає унікальний 8-байтовий дискрим ] ``` -Дискримінатор для інструкції — це перші 8 байтів хешу Sha256 префікса `global` плюс ім'я інструкції. +Дискримінатор для інструкції — це перші 8 байтів хешу Sha256 префікса `global` +плюс ім'я інструкції. Наприклад: @@ -404,8 +410,9 @@ ed = 237 -Дискримінатор рахунку використовується для ідентифікації конкретного типу рахунку при -десеріалізації даних з ланцюга та встановлюється при створенні рахунку. +Дискримінатор рахунку використовується для ідентифікації конкретного типу +рахунку при десеріалізації даних з ланцюга та встановлюється при створенні +рахунку. ```json filename="IDL" {4} "accounts": [ @@ -416,11 +423,11 @@ ed = 237 ] ``` -Дискримінатор для рахунку — це перші 8 байтів хешу Sha256 префікса `account` плюс ім'я рахунку. +Дискримінатор для рахунку — це перші 8 байтів хешу Sha256 префікса `account` +плюс ім'я рахунку. Наприклад: - ``` sha256("account:NewAccount") ``` @@ -447,13 +454,16 @@ e8 = 232 Реалізацію генерації дискримінатора ви можете знайти в кодовій базі Anchor [тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L101-L117). -Зверніть увагу, що різні програми, які використовують однакові імена рахунків, генеруватимуть той самий дискримінатор. При десеріалізації даних рахунків програми Anchor також перевірятимуть, що рахунок належить очікуваній програмі для заданого типу рахунку. +Зверніть увагу, що різні програми, які використовують однакові імена рахунків, +генеруватимуть той самий дискримінатор. При десеріалізації даних рахунків +програми Anchor також перевірятимуть, що рахунок належить очікуваній програмі +для заданого типу рахунку. -Дискримінатор події використовується для ідентифікації конкретного типу події при -десеріалізації даних з ланцюга при емісії події. +Дискримінатор події використовується для ідентифікації конкретного типу події +при десеріалізації даних з ланцюга при емісії події. ```json filename="IDL" {4} "events": [ @@ -464,7 +474,8 @@ e8 = 232 ] ``` -Дискримінатор для події — це перші 8 байтів хешу Sha256 префікса `event` плюс ім'я події. +Дискримінатор для події — це перші 8 байтів хешу Sha256 префікса `event` плюс +ім'я події. Наприклад: @@ -496,9 +507,10 @@ c9 = 201 Реалізацію генерації дискримінатора ви можете знайти в кодовій базі Anchor [тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/event/src/lib.rs#L23-L27). -Зверніть увагу, що різні програми, які використовують однакові імена подій, генеруватимуть той самий -дискримінатор. При десеріалізації даних подій програми Anchor також перевірятимуть, що -подія належить очікуваній програмі для заданого типу події. +Зверніть увагу, що різні програми, які використовують однакові імена подій, +генеруватимуть той самий дискримінатор. При десеріалізації даних подій програми +Anchor також перевірятимуть, що подія належить очікуваній програмі для заданого +типу події. - \ No newline at end of file + diff --git a/docs/locales/uk/programs/anchor/index.md b/docs/locales/uk/programs/anchor/index.md index 35be0c546..169686979 100644 --- a/docs/locales/uk/programs/anchor/index.md +++ b/docs/locales/uk/programs/anchor/index.md @@ -1,8 +1,9 @@ --- title: Початок роботи з Anchor description: - Дізнайтесь, як будувати програми для Solana за допомогою фреймворку Anchor. Цей - детальний посібник охоплює створення, збірку, тестування та розгортання смарт-контрактів Solana з використанням Anchor. + Дізнайтесь, як будувати програми для Solana за допомогою фреймворку Anchor. + Цей детальний посібник охоплює створення, збірку, тестування та розгортання + смарт-контрактів Solana з використанням Anchor. sidebarLabel: Фреймворк Anchor sidebarSortOrder: 0 altRoutes: @@ -11,9 +12,9 @@ altRoutes: - /docs/programs/overview --- -Фреймворк Anchor — це інструмент, який спрощує процес створення програм для Solana. -Неважливо, чи ви новачок у блокчейн-розробці, чи досвідчений програміст, Anchor спрощує процес написання, тестування та розгортання -програм для Solana. +Фреймворк Anchor — це інструмент, який спрощує процес створення програм для +Solana. Неважливо, чи ви новачок у блокчейн-розробці, чи досвідчений програміст, +Anchor спрощує процес написання, тестування та розгортання програм для Solana. У цьому розділі ми розглянемо: @@ -35,7 +36,6 @@ altRoutes: Щоб перевірити встановлення Anchor CLI, відкрийте термінал і виконайте: - ```shell filename="Terminal" anchor --version ``` @@ -48,13 +48,16 @@ anchor-cli 0.30.1 ## Початок роботи -Цей розділ охоплює основні кроки для створення, зборки та тестування вашої першої локальної програми на Anchor. +Цей розділ охоплює основні кроки для створення, зборки та тестування вашої +першої локальної програми на Anchor. ### Створення нового проекту -Щоб почати новий проект, використовуйте команду `anchor init`, після якої вкажіть назву вашого проекту. Ця команда створює нову директорію з вказаним ім'ям і налаштовує стандартну програму та тестовий файл. +Щоб почати новий проект, використовуйте команду `anchor init`, після якої +вкажіть назву вашого проекту. Ця команда створює нову директорію з вказаним +ім'ям і налаштовує стандартну програму та тестовий файл. ```shell filename="Terminal" anchor init my-project @@ -66,7 +69,8 @@ anchor init my-project cd my-project ``` -Стандартна програма Anchor знаходиться за адресою `programs/my-project/src/lib.rs`. +Стандартна програма Anchor знаходиться за адресою +`programs/my-project/src/lib.rs`. @@ -99,13 +103,14 @@ pub struct Initialize {} -Стандартний тестовий файл TypeScript знаходиться за адресою `/tests/my-project.ts`. +Стандартний тестовий файл TypeScript знаходиться за адресою +`/tests/my-project.ts`. -Цей файл демонструє, як викликати інструкцію `initialize` стандартної програми в TypeScript. - +Цей файл демонструє, як викликати інструкцію `initialize` стандартної програми в +TypeScript. ```ts filename="my-project.ts" import * as anchor from "@coral-xyz/anchor"; @@ -129,8 +134,8 @@ describe("my-project", () => { -Якщо ви віддаєте перевагу Rust для тестування, ініціалізуйте свій проект за допомогою прапорця -`--test-template rust`. +Якщо ви віддаєте перевагу Rust для тестування, ініціалізуйте свій проект за +допомогою прапорця `--test-template rust`. ```shell anchor init --test-template rust my-project @@ -183,9 +188,9 @@ fn test_initialize() { anchor build ``` -Зкомпільована програма буде знаходитися за адресою `/target/deploy/my_project.so`. Вміст -цього файлу буде збережено в мережі Solana (як виконуваний акаунт) -під час розгортання вашої програми. +Зкомпільована програма буде знаходитися за адресою +`/target/deploy/my_project.so`. Вміст цього файлу буде збережено в мережі Solana +(як виконуваний акаунт) під час розгортання вашої програми. ### Тестування програми @@ -195,24 +200,31 @@ anchor build anchor test ``` -За замовчуванням конфігураційний файл `Anchor.toml` вказує на кластер `localnet`. При розробці на `localnet`, команда `anchor test` автоматично: +За замовчуванням конфігураційний файл `Anchor.toml` вказує на кластер +`localnet`. При розробці на `localnet`, команда `anchor test` автоматично: 1. Запускає локальний валідатор Solana 2. Створює та розгортає вашу програму на локальному кластері 3. Виконує тести з папки `tests` 4. Зупиняє локальний валідатор Solana -Альтернативно, ви можете вручну запустити локальний валідатор Solana та виконувати тести проти нього. Це корисно, якщо ви хочете, щоб валідатор працював, поки ви працюєте над програмою. Це дозволяє вам перевіряти акаунти та журнали транзакцій на [Solana Explorer](https://explorer.solana.com/?cluster=custom) під час розробки локально. +Альтернативно, ви можете вручну запустити локальний валідатор Solana та +виконувати тести проти нього. Це корисно, якщо ви хочете, щоб валідатор +працював, поки ви працюєте над програмою. Це дозволяє вам перевіряти акаунти та +журнали транзакцій на +[Solana Explorer](https://explorer.solana.com/?cluster=custom) під час розробки +локально. -Відкрийте новий термінал і запустіть локальний валідатор Solana, виконуючи команду -`solana-test-validator`. +Відкрийте новий термінал і запустіть локальний валідатор Solana, виконуючи +команду `solana-test-validator`. ```shell filename="Terminal" copy solana-test-validator ``` -У окремому терміналі виконайте тести проти локального кластера. Використовуйте прапорець -`--skip-local-validator`, щоб пропустити запуск локального валідатора, оскільки він уже працює. +У окремому терміналі виконайте тести проти локального кластера. Використовуйте +прапорець `--skip-local-validator`, щоб пропустити запуск локального валідатора, +оскільки він уже працює. ```shell filename="Terminal" copy anchor test --skip-local-validator @@ -220,7 +232,8 @@ anchor test --skip-local-validator ### Розгортання на Devnet -За замовчуванням конфігураційний файл `Anchor.toml` у проекті Anchor вказує на кластер localnet. +За замовчуванням конфігураційний файл `Anchor.toml` у проекті Anchor вказує на +кластер localnet. ```toml filename="Anchor.toml" {14} [toolchain] @@ -243,7 +256,9 @@ wallet = "~/.config/solana/id.json" test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" ``` -Щоб розгорнути вашу програму на devnet, змініть значення `cluster` на `Devnet`. Зверніть увагу, що для цього ваш гаманець повинен мати достатньо SOL на Devnet для покриття вартості розгортання. +Щоб розгорнути вашу програму на devnet, змініть значення `cluster` на `Devnet`. +Зверніть увагу, що для цього ваш гаманець повинен мати достатньо SOL на Devnet +для покриття вартості розгортання. ```diff -cluster = "Localnet" @@ -256,13 +271,16 @@ cluster = "Devnet" wallet = "~/.config/solana/id.json" ``` -Тепер, коли ви виконаєте команду `anchor deploy`, ваша програма буде розгорнута на кластері devnet. Команда `anchor test` також використовуватиме кластер, вказаний у файлі `Anchor.toml`. +Тепер, коли ви виконаєте команду `anchor deploy`, ваша програма буде розгорнута +на кластері devnet. Команда `anchor test` також використовуватиме кластер, +вказаний у файлі `Anchor.toml`. ```shell anchor deploy ``` -Щоб розгорнути на mainnet, просто оновіть файл `Anchor.toml`, вказавши кластер mainnet. +Щоб розгорнути на mainnet, просто оновіть файл `Anchor.toml`, вказавши кластер +mainnet. ```toml filename="Anchor.toml" [provider] @@ -272,17 +290,18 @@ wallet = "~/.config/solana/id.json" ### Оновлення програми -Програми Solana можна оновити, повторно розгорнувши програму з тим самим ID програми. - -Щоб оновити програму, просто внесіть зміни в код вашої програми і виконайте команду -`anchor build` для генерації оновленого файлу `.so`. +Програми Solana можна оновити, повторно розгорнувши програму з тим самим ID +програми. +Щоб оновити програму, просто внесіть зміни в код вашої програми і виконайте +команду `anchor build` для генерації оновленого файлу `.so`. ```shell anchor build ``` -Потім виконайте команду `anchor deploy`, щоб повторно розгорнути оновлену програму. +Потім виконайте команду `anchor deploy`, щоб повторно розгорнути оновлену +програму. ```shell anchor deploy @@ -290,15 +309,18 @@ anchor deploy ### Закриття програми -Щоб повернути SOL, виділені на акаунт програми, ви можете закрити вашу програму Solana. +Щоб повернути SOL, виділені на акаунт програми, ви можете закрити вашу програму +Solana. -Для закриття програми використовуйте команду `solana program close `. Наприклад: +Для закриття програми використовуйте команду +`solana program close `. Наприклад: ```shell solana program close 3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg --bypass-warning ``` -Зверніть увагу, що після закриття програми, ID програми не можна буде використовувати для розгортання нової програми. +Зверніть увагу, що після закриття програми, ID програми не можна буде +використовувати для розгортання нової програми. @@ -334,11 +356,13 @@ solana program close 3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg --bypass-warni ### Папка Programs -Папка `/programs` містить програми Anchor вашого проекту. Один робочий простір може містити кілька програм. +Папка `/programs` містить програми Anchor вашого проекту. Один робочий простір +може містити кілька програм. ### Папка Tests -Папка `/tests` містить тестові файли для вашого проекту. Стандартний тестовий файл створюється автоматично під час створення вашого проекту. +Папка `/tests` містить тестові файли для вашого проекту. Стандартний тестовий +файл створюється автоматично під час створення вашого проекту. ### Папка Target @@ -354,8 +378,10 @@ solana program close 3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg --bypass-warni ### Папка .anchor -Містить файл `program-logs`, що містить журнали транзакцій з останнього виконання тестових файлів. +Містить файл `program-logs`, що містить журнали транзакцій з останнього +виконання тестових файлів. ### Папка App -Папка `/app` є порожньою і може бути опційно використана для вашого фронтенд-коду. \ No newline at end of file +Папка `/app` є порожньою і може бути опційно використана для вашого +фронтенд-коду. diff --git a/docs/locales/uk/programs/anchor/pda.md b/docs/locales/uk/programs/anchor/pda.md index 505698c82..5b80e71a7 100644 --- a/docs/locales/uk/programs/anchor/pda.md +++ b/docs/locales/uk/programs/anchor/pda.md @@ -1,50 +1,55 @@ --- title: PDAs з Anchor description: - Дізнайтеся, як використовувати Program Derived Addresses (PDA) в програмах Anchor, використовуючи - обмеження та реалізуючи поширені шаблони PDA + Дізнайтеся, як використовувати Program Derived Addresses (PDA) в програмах + Anchor, використовуючи обмеження та реалізуючи поширені шаблони PDA sidebarLabel: PDAs з Anchor sidebarSortOrder: 4 --- -[Program Derived Addresses (PDA)](/docs/core/pda) — це функція розробки на Solana, -яка дозволяє створювати унікальну адресу, що отримується детерміновано -з попередньо визначених вхідних значень (насіння) та ID програми. +[Program Derived Addresses (PDA)](/docs/core/pda) — це функція розробки на +Solana, яка дозволяє створювати унікальну адресу, що отримується детерміновано з +попередньо визначених вхідних значень (насіння) та ID програми. Цей розділ охоплює базові приклади використання PDA в програмі Anchor. ## Обмеження Anchor для PDA -При використанні PDA в програмі Anchor, зазвичай використовуються обмеження акаунтів Anchor -для визначення насіння, що використовуються для отримання PDA. Ці обмеження служать -як перевірки безпеки, щоб переконатися, що правильна адреса була отримана. +При використанні PDA в програмі Anchor, зазвичай використовуються обмеження +акаунтів Anchor для визначення насіння, що використовуються для отримання PDA. +Ці обмеження служать як перевірки безпеки, щоб переконатися, що правильна адреса +була отримана. Обмеження, які використовуються для визначення насіння PDA, включають: -- `seeds`: Масив необов'язкових насінь, що використовуються для отримання PDA. Насіння можуть бути - статичними значеннями або динамічними посиланнями на дані акаунтів. -- `bump`: Bump seed, що використовується для отримання PDA. Використовується для забезпечення того, - щоб адреса не потрапляла на криву Ed25519 і була дійсним PDA. -- `seeds::program` - (Необов'язково) ID програми, що використовується для отримання адреси PDA. - Це обмеження використовується лише для отримання PDA, де ID програми не є - поточною програмою. +- `seeds`: Масив необов'язкових насінь, що використовуються для отримання PDA. + Насіння можуть бути статичними значеннями або динамічними посиланнями на дані + акаунтів. +- `bump`: Bump seed, що використовується для отримання PDA. Використовується для + забезпечення того, щоб адреса не потрапляла на криву Ed25519 і була дійсним + PDA. +- `seeds::program` - (Необов'язково) ID програми, що використовується для + отримання адреси PDA. Це обмеження використовується лише для отримання PDA, де + ID програми не є поточною програмою. Обмеження `seeds` та `bump` повинні використовуватися разом. ### Приклади використання -Нижче наведені приклади, що демонструють, як використовувати обмеження PDA в програмі Anchor. +Нижче наведені приклади, що демонструють, як використовувати обмеження PDA в +програмі Anchor. -Обмеження `seeds` визначає необов'язкові значення, що використовуються для отримання PDA. +Обмеження `seeds` визначає необов'язкові значення, що використовуються для +отримання PDA. #### Без необов'язкових сідів -- Використовуйте порожній масив `[]`, щоб визначити PDA без необов'язкових насінь. - +- Використовуйте порожній масив `[]`, щоб визначити PDA без необов'язкових + насінь. ```rs #[derive(Accounts)] @@ -74,8 +79,8 @@ pub struct InstructionAccounts<'info> { #### Кілька насінь та посилань на акаунти -- Можна вказати кілька насінь в обмеженні `seeds`. Обмеження `seeds` - також може посилатися на інші адреси акаунтів або дані акаунтів. +- Можна вказати кілька насінь в обмеженні `seeds`. Обмеження `seeds` також може + посилатися на інші адреси акаунтів або дані акаунтів. ```rs #[derive(Accounts)] @@ -89,8 +94,8 @@ pub struct InstructionAccounts<'info> { } ``` -Приклад вище використовує як статичне насіння (`b"hello_world"`), так і динамічне насіння -(публічний ключ підписанта). +Приклад вище використовує як статичне насіння (`b"hello_world"`), так і +динамічне насіння (публічний ключ підписанта). @@ -115,7 +120,9 @@ pub struct InstructionAccounts<'info> { #### Вказати значення Bump -Ви можете явно вказати значення bump, що корисно для оптимізації використання обчислювальних одиниць. Це передбачає, що акаунт PDA вже був створений і bump seed зберігається як поле в існуючому акаунті. +Ви можете явно вказати значення bump, що корисно для оптимізації використання +обчислювальних одиниць. Це передбачає, що акаунт PDA вже був створений і bump +seed зберігається як поле в існуючому акаунті. ```rs #[derive(Accounts)] @@ -133,16 +140,19 @@ pub struct CustomAccount { } ``` -Зберігаючи значення bump у даних акаунту, програма не потребує його повторного обчислення, що дозволяє заощадити обчислювальні одиниці. Збережене значення bump може бути збережено в самому акаунті або в іншому акаунті. +Зберігаючи значення bump у даних акаунту, програма не потребує його повторного +обчислення, що дозволяє заощадити обчислювальні одиниці. Збережене значення bump +може бути збережено в самому акаунті або в іншому акаунті. -Обмеження `seeds::program` визначає ID програми, що використовується для отримання PDA. -Це обмеження використовується лише при отриманні PDA з іншої програми. +Обмеження `seeds::program` визначає ID програми, що використовується для +отримання PDA. Це обмеження використовується лише при отриманні PDA з іншої +програми. -Використовуйте це обмеження, коли ваша інструкція повинна взаємодіяти з акаунтами PDA, -створеними іншою програмою. +Використовуйте це обмеження, коли ваша інструкція повинна взаємодіяти з +акаунтами PDA, створеними іншою програмою. ```rs #[derive(Accounts)] @@ -160,8 +170,8 @@ pub struct InstructionAccounts<'info> { -Обмеження `init` зазвичай використовується разом з `seeds` та `bump` для створення нового -акаунту з адресою, яка є PDA. Під капотом обмеження `init` +Обмеження `init` зазвичай використовується разом з `seeds` та `bump` для +створення нового акаунту з адресою, яка є PDA. Під капотом обмеження `init` викликає System Program для створення акаунту. ```rs @@ -191,7 +201,9 @@ pub struct CustomAccount { ## Насіння PDA в IDL -Насіння Program Derived Address (PDA), визначені в обмеженні `seeds`, включені в IDL файл програми. Це дозволяє клієнту Anchor автоматично вирішувати акаунти, використовуючи ці насіння під час побудови інструкцій. +Насіння Program Derived Address (PDA), визначені в обмеженні `seeds`, включені в +IDL файл програми. Це дозволяє клієнту Anchor автоматично вирішувати акаунти, +використовуючи ці насіння під час побудови інструкцій. Наведений нижче приклад показує взаємозв'язок між програмою, IDL та клієнтом. @@ -199,8 +211,8 @@ pub struct CustomAccount { -Програма нижче визначає `pda_account`, використовуючи статичне насіння (`b"hello_world"`) -та публічний ключ підписанта як динамічне насіння. +Програма нижче визначає `pda_account`, використовуючи статичне насіння +(`b"hello_world"`) та публічний ключ підписанта як динамічне насіння. ```rs {18} /signer/ use anchor_lang::prelude::*; @@ -280,7 +292,10 @@ IDL файл програми включає насіння PDA, визначе Клієнт Anchor може автоматично визначити адресу PDA, використовуючи IDL файл. -У наведеному нижче прикладі Anchor автоматично визначає адресу PDA, використовуючи гаманець постачальника як підписанта, а його публічний ключ як динамічне насіння для отримання PDA. Це усуває необхідність явного отримання PDA під час побудови інструкції. +У наведеному нижче прикладі Anchor автоматично визначає адресу PDA, +використовуючи гаманець постачальника як підписанта, а його публічний ключ як +динамічне насіння для отримання PDA. Це усуває необхідність явного отримання PDA +під час побудови інструкції. ```ts {13} import * as anchor from "@coral-xyz/anchor"; @@ -301,7 +316,8 @@ describe("hello_anchor", () => { }); ``` -Коли інструкція викликається, PDA виводиться в журнали програми, як це визначено в інструкції програми. +Коли інструкція викликається, PDA виводиться в журнали програми, як це визначено +в інструкції програми. ```{3} Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 invoke [1] diff --git a/docs/locales/uk/programs/anchor/program-structure.md b/docs/locales/uk/programs/anchor/program-structure.md index 3fc534b6c..e37a5eac7 100644 --- a/docs/locales/uk/programs/anchor/program-structure.md +++ b/docs/locales/uk/programs/anchor/program-structure.md @@ -1,8 +1,8 @@ --- title: Структура програми Anchor description: - Дізнайтеся про структуру програм Anchor, включаючи основні макроси та їх - роль у спрощенні розробки програм для Solana + Дізнайтеся про структуру програм Anchor, включаючи основні макроси та їх роль + у спрощенні розробки програм для Solana sidebarLabel: Структура програми sidebarSortOrder: 1 --- @@ -15,16 +15,17 @@ sidebarSortOrder: 1 Основні макроси, які використовуються в програмі Anchor, включають: - [`declare_id`](#declare-id-macro): Визначає on-chain адресу програми -- [`#[program]`](#program-macro): Визначає модуль, що містить логіку інструкцій програми -- [`#[derive(Accounts)]`](#derive-accounts-macro): Застосовується до структур для - вказівки списку акаунтів, необхідних для інструкції +- [`#[program]`](#program-macro): Визначає модуль, що містить логіку інструкцій + програми +- [`#[derive(Accounts)]`](#derive-accounts-macro): Застосовується до структур + для вказівки списку акаунтів, необхідних для інструкції - [`#[account]`](#account-macro): Застосовується до структур для створення користувацьких типів акаунтів для програми ## Приклад програми -Давайте розглянемо просту програму, яка демонструє використання вищезгаданих макросів, -щоб зрозуміти основну структуру програми Anchor. +Давайте розглянемо просту програму, яка демонструє використання вищезгаданих +макросів, щоб зрозуміти основну структуру програми Anchor. Наведена нижче програма створює новий акаунт (`NewAccount`), який зберігає значення `u64`, передане в інструкцію `initialize`. @@ -71,8 +72,8 @@ use anchor_lang::prelude::*; declare_id!("11111111111111111111111111111111"); ``` -За замовчуванням, ID програми — це публічний ключ ключової пари, згенерованої за адресою -`/target/deploy/your_program_name.json`. +За замовчуванням, ID програми — це публічний ключ ключової пари, згенерованої за +адресою `/target/deploy/your_program_name.json`. Щоб оновити значення ID програми в макросі `declare_id` за допомогою публічного ключа ключової пари з файлу `/target/deploy/your_program_name.json`, виконайте @@ -83,15 +84,16 @@ anchor keys sync ``` Команда `anchor keys sync` корисна для виконання при клонуванні репозиторію, де -значення ID програми в макросі `declare_id` клонованого репозиторію не буде співпадати -з тим, що генерується при виконанні команди `anchor build` локально. +значення ID програми в макросі `declare_id` клонованого репозиторію не буде +співпадати з тим, що генерується при виконанні команди `anchor build` локально. ## Макрос `#[program]` Макрос [`#[program]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/lib.rs#L12) -визначає модуль, що містить усі обробники інструкцій для вашої програми. Кожна публічна функція -в межах цього модуля відповідає інструкції, яку можна викликати. +визначає модуль, що містить усі обробники інструкцій для вашої програми. Кожна +публічна функція в межах цього модуля відповідає інструкції, яку можна +викликати. ```rust filename="lib.rs" {5, 8-12} use anchor_lang::prelude::*; @@ -125,7 +127,10 @@ pub struct NewAccount { ### Контекст інструкції -Обробники інструкцій — це функції, які визначають логіку, що виконується, коли інструкція викликається. Перший параметр кожного обробника має тип `Context`, де `T` — це структура, яка реалізує трейд `Accounts` і вказує на акаунти, які потрібні для інструкції. +Обробники інструкцій — це функції, які визначають логіку, що виконується, коли +інструкція викликається. Перший параметр кожного обробника має тип `Context`, +де `T` — це структура, яка реалізує трейд `Accounts` і вказує на акаунти, які +потрібні для інструкції. Тип [`Context`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/context.rs#L24) @@ -151,12 +156,14 @@ pub struct Context<'a, 'b, 'c, 'info, T> { - `ctx.accounts`: Акаунти, необхідні для інструкції - `ctx.program_id`: Публічний ключ програми (адреса) -- `ctx.remaining_accounts`: Додаткові акаунти, які не вказані в структурі `Accounts`. +- `ctx.remaining_accounts`: Додаткові акаунти, які не вказані в структурі + `Accounts`. - `ctx.bumps`: Bump seed для будь-яких акаунтів [Program Derived Address (PDA)](/docs/core/pda.md), вказаних у структурі `Accounts` -Додаткові параметри є необов'язковими та можуть бути включені для вказівки аргументів, які повинні бути надані при виклику інструкції. +Додаткові параметри є необов'язковими та можуть бути включені для вказівки +аргументів, які повинні бути надані при виклику інструкції. ```rust filename="lib.rs" /Context/ /data/1 pub fn initialize(ctx: Context, data: u64) -> Result<()> { @@ -166,8 +173,8 @@ pub fn initialize(ctx: Context, data: u64) -> Result<()> { } ``` -У цьому прикладі структура `Initialize` реалізує трейд `Accounts`, де -кожне поле в структурі представляє акаунт, необхідний для інструкції `initialize`. +У цьому прикладі структура `Initialize` реалізує трейд `Accounts`, де кожне поле +в структурі представляє акаунт, необхідний для інструкції `initialize`. ```rust filename="lib.rs" /Initialize/ /Accounts/ #[program] @@ -194,9 +201,11 @@ pub struct Initialize<'info> { Макрос [`#[derive(Accounts)]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/derive/accounts/src/lib.rs#L630) -застосовується до структури для вказівки акаунтів, які повинні бути надані під час виклику інструкції. Цей макрос реалізує трейд +застосовується до структури для вказівки акаунтів, які повинні бути надані під +час виклику інструкції. Цей макрос реалізує трейд [`Accounts`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/lib.rs#L105), -що спрощує перевірку акаунтів, а також серіалізацію та десеріалізацію даних акаунтів. +що спрощує перевірку акаунтів, а також серіалізацію та десеріалізацію даних +акаунтів. ```rust /Accounts/ {1} #[derive(Accounts)] @@ -209,7 +218,9 @@ pub struct Initialize<'info> { } ``` -Кожне поле в структурі представляє акаунт, необхідний для інструкції. Іменування кожного поля є довільним, але рекомендується використовувати описове ім'я, яке вказує на призначення акаунту. +Кожне поле в структурі представляє акаунт, необхідний для інструкції. Іменування +кожного поля є довільним, але рекомендується використовувати описове ім'я, яке +вказує на призначення акаунту. ```rust /signer/2 /new_account/ /system_program/ #[derive(Accounts)] @@ -224,10 +235,15 @@ pub struct Initialize<'info> { ### Перевірка акаунтів -Для запобігання вразливостям безпеки важливо перевіряти, що акаунти, надані інструкції, є очікуваними. Акаунти перевіряються в програмах Anchor двома способами, які зазвичай використовуються разом: +Для запобігання вразливостям безпеки важливо перевіряти, що акаунти, надані +інструкції, є очікуваними. Акаунти перевіряються в програмах Anchor двома +способами, які зазвичай використовуються разом: - [Обмеження акаунтів](https://www.anchor-lang.com/docs/account-constraints): - Обмеження визначають додаткові умови, які акаунт повинен задовольняти, щоб вважатися дійсним для інструкції. Обмеження застосовуються за допомогою атрибута `#[account(..)]`, який розміщується над полем у структурі, що реалізує трейд `Accounts`. + Обмеження визначають додаткові умови, які акаунт повинен задовольняти, щоб + вважатися дійсним для інструкції. Обмеження застосовуються за допомогою + атрибута `#[account(..)]`, який розміщується над полем у структурі, що + реалізує трейд `Accounts`. Реалізацію обмежень можна знайти [тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/parser/accounts/constraints.rs). @@ -243,8 +259,9 @@ pub struct Initialize<'info> { } ``` -- [Типи акаунтів](https://www.anchor-lang.com/docs/account-types): Anchor - надає різні типи акаунтів, щоб допомогти гарантувати, що акаунт, наданий клієнтом, відповідає тому, що очікує програма. +- [Типи акаунтів](https://www.anchor-lang.com/docs/account-types): Anchor надає + різні типи акаунтів, щоб допомогти гарантувати, що акаунт, наданий клієнтом, + відповідає тому, що очікує програма. Реалізацію типів акаунтів можна знайти [тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/accounts). @@ -261,7 +278,8 @@ pub struct Initialize<'info> { ``` Коли інструкція в програмі Anchor викликається, програма спочатку перевіряє -надані акаунти перед виконанням логіки інструкції. Після перевірки ці акаунти можна отримати в інструкції за допомогою синтаксису `ctx.accounts`. +надані акаунти перед виконанням логіки інструкції. Після перевірки ці акаунти +можна отримати в інструкції за допомогою синтаксису `ctx.accounts`. ```rust filename="lib.rs" /ctx.accounts.new_account/ /new_account/ /Initialize/ use anchor_lang::prelude::*; @@ -297,8 +315,8 @@ pub struct NewAccount { Макрос [`#[account]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L66) -застосовується до структур, які визначають дані, що зберігаються в користувацьких акаунтах, -створених вашою програмою. +застосовується до структур, які визначають дані, що зберігаються в +користувацьких акаунтах, створених вашою програмою. ```rust #[account] @@ -319,8 +337,8 @@ pub struct NewAccount { перші 8 байтів даних акаунту під час його ініціалізації. Це допомагає відрізняти типи акаунтів і використовується для перевірки акаунтів. - [Серіалізація та десеріалізація даних](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L202-L246): - Дані акаунту автоматично серіалізуються та десеріалізуються відповідно до типу акаунту. - + Дані акаунту автоматично серіалізуються та десеріалізуються відповідно до типу + акаунту. ```rust filename="lib.rs" /data/2,6 /NewAccount/ {24-27} use anchor_lang::prelude::*; @@ -356,9 +374,11 @@ pub struct NewAccount { Дискримінатор акаунту в програмі Anchor — це 8-байтовий ідентифікатор, унікальний для кожного типу акаунту. Він отримується з перших 8 байтів SHA256 -хешу рядка `account:`. Цей дискримінатор зберігається як перші 8 байтів даних акаунту під час його створення. +хешу рядка `account:`. Цей дискримінатор зберігається як перші 8 +байтів даних акаунту під час його створення. -При створенні акаунту в програмі Anchor для дискримінатора повинно бути виділено 8 байтів. +При створенні акаунту в програмі Anchor для дискримінатора повинно бути виділено +8 байтів. ```rust /8/1 #[account(init, payer = signer, space = 8 + 8)] @@ -367,7 +387,11 @@ pub new_account: Account<'info, NewAccount>, Дискримінатор використовується в наступних двох сценаріях: -- Ініціалізація: Коли акаунт створюється, дискримінатор встановлюється як перші 8 байтів даних акаунту. -- Десеріалізація: Коли дані акаунту десеріалізуються, перші 8 байтів даних акаунту перевіряються на відповідність дискримінатору очікуваного типу акаунту. +- Ініціалізація: Коли акаунт створюється, дискримінатор встановлюється як перші + 8 байтів даних акаунту. +- Десеріалізація: Коли дані акаунту десеріалізуються, перші 8 байтів даних + акаунту перевіряються на відповідність дискримінатору очікуваного типу + акаунту. -Якщо є невідповідність, це вказує на те, що клієнт надав неочікуваний акаунт. Цей механізм служить перевіркою валідності акаунтів у програмах Anchor. +Якщо є невідповідність, це вказує на те, що клієнт надав неочікуваний акаунт. +Цей механізм служить перевіркою валідності акаунтів у програмах Anchor. diff --git a/docs/locales/uk/programs/deploying.md b/docs/locales/uk/programs/deploying.md index 7486f9866..c4b2bd845 100644 --- a/docs/locales/uk/programs/deploying.md +++ b/docs/locales/uk/programs/deploying.md @@ -1,19 +1,20 @@ --- title: "Розгортання програм" description: - Розгортання програм на ланцюгу можна здійснити за допомогою Solana CLI, використовуючи - Upgradable BPF loader для завантаження скомпільованого байт-коду на блокчейн Solana. + Розгортання програм на ланцюгу можна здійснити за допомогою Solana CLI, + використовуючи Upgradable BPF loader для завантаження скомпільованого + байт-коду на блокчейн Solana. sidebarSortOrder: 2 --- -Програми Solana зберігаються в "виконуваних" акаунтах в мережі. Ці -акаунти містять скомпільований байт-код програми, який визначає інструкції, -які користувачі викликають для взаємодії з програмою. +Програми Solana зберігаються в "виконуваних" акаунтах в мережі. Ці акаунти +містять скомпільований байт-код програми, який визначає інструкції, які +користувачі викликають для взаємодії з програмою. ## Команди CLI -Цей розділ призначений як довідник для базових команд CLI для створення -та розгортання програм Solana. Для покрокового посібника зі створення вашої першої +Цей розділ призначений як довідник для базових команд CLI для створення та +розгортання програм Solana. Для покрокового посібника зі створення вашої першої програми почніть з [Розробки програм на Rust](/docs/programs/rust). ### Збірка програми @@ -28,30 +29,47 @@ cargo build-sbf 1. Скомпілює вашу програму 2. Створить директорію `target/deploy` -3. Згенерує файл `.so`, де `` відповідає імені вашої програми у файлі `Cargo.toml` +3. Згенерує файл `.so`, де `` відповідає імені вашої + програми у файлі `Cargo.toml` -Вивантажений файл `.so` містить скомпільований байт-код вашої програми, який буде -збережено в акаунті Solana під час розгортання вашої програми. +Вивантажений файл `.so` містить скомпільований байт-код вашої програми, який +буде збережено в акаунті Solana під час розгортання вашої програми. ### Розгортання програми -Щоб розгорнути вашу програму, використовуйте команду `solana program deploy`, вказавши шлях до файлу `.so`, який був створений командою `cargo build-sbf`. +Щоб розгорнути вашу програму, використовуйте команду `solana program deploy`, +вказавши шлях до файлу `.so`, який був створений командою `cargo build-sbf`. ```shell solana program deploy ./target/deploy/your_program.so ``` -Під час періодів завантаження є кілька додаткових прапорців, які можна використовувати для полегшення розгортання програми. - -- `--with-compute-unit-price`: Встановіть ціну за обчислювальні одиниці для транзакції, в increments 0.000001 лампортів (мікро-лампорти) за обчислювальну одиницю. -- `--max-sign-attempts`: Максимальна кількість спроб підписати або повторно підписати транзакції після закінчення терміну дії blockhash. Якщо будь-які транзакції, надіслані під час розгортання програми, залишаються непідтвердженими після закінчення терміну дії початково вибраного останнього blockhash, ці транзакції будуть повторно підписані з новим blockhash і відправлені знову. Використовуйте цей параметр для налаштування максимальної кількості спроб підписання транзакцій. Кожен blockhash є дійсним близько 60 секунд, що означає, що використання значення за замовчуванням 5 призведе до надсилання транзакцій щонайменше 5 хвилин або до тих пір, поки всі транзакції не будуть підтверджені, залежно від того, що відбудеться раніше. [за замовчуванням: 5] -- `--use-rpc`: Надсилайте транзакції запису до налаштованого RPC замість TPU валідатора. Цей прапорець вимагає RPC з урахуванням ставки. +Під час періодів завантаження є кілька додаткових прапорців, які можна +використовувати для полегшення розгортання програми. + +- `--with-compute-unit-price`: Встановіть ціну за обчислювальні одиниці для + транзакції, в increments 0.000001 лампортів (мікро-лампорти) за обчислювальну + одиницю. +- `--max-sign-attempts`: Максимальна кількість спроб підписати або повторно + підписати транзакції після закінчення терміну дії blockhash. Якщо будь-які + транзакції, надіслані під час розгортання програми, залишаються + непідтвердженими після закінчення терміну дії початково вибраного останнього + blockhash, ці транзакції будуть повторно підписані з новим blockhash і + відправлені знову. Використовуйте цей параметр для налаштування максимальної + кількості спроб підписання транзакцій. Кожен blockhash є дійсним близько 60 + секунд, що означає, що використання значення за замовчуванням 5 призведе до + надсилання транзакцій щонайменше 5 хвилин або до тих пір, поки всі транзакції + не будуть підтверджені, залежно від того, що відбудеться раніше. [за + замовчуванням: 5] +- `--use-rpc`: Надсилайте транзакції запису до налаштованого RPC замість TPU + валідатора. Цей прапорець вимагає RPC з урахуванням ставки. Ви можете використовувати ці прапорці окремо або поєднувати їх разом. Наприклад: ```shell solana program deploy ./target/deploy/your_program.so --with-compute-unit-price 10000 --max-sign-attempts 1000 --use-rpc ``` + - Використовуйте [Priority Fee API від Helius](https://docs.helius.dev/guides/priority-fee-api) для отримання оцінки пріоритетної плати, яку потрібно встановити за допомогою @@ -59,18 +77,19 @@ solana program deploy ./target/deploy/your_program.so --with-compute-unit-price - Отримайте [RPC з урахуванням ставки](https://solana.com/developers/guides/advanced/stake-weighted-qos) - від [Helius](https://www.helius.dev/) або - [Triton](https://triton.one/) для використання з прапорцем `--use-rpc`. Прапорець - `--use-rpc` повинен використовуватись тільки з RPC з урахуванням ставки. + від [Helius](https://www.helius.dev/) або [Triton](https://triton.one/) для + використання з прапорцем `--use-rpc`. Прапорець `--use-rpc` повинен + використовуватись тільки з RPC з урахуванням ставки. -Щоб оновити ваш за умовчанням RPC URL за допомогою власної точки доступу RPC, використовуйте команду -`solana config set`. +Щоб оновити ваш за умовчанням RPC URL за допомогою власної точки доступу RPC, +використовуйте команду `solana config set`. ```shell solana config set --url ``` -Ви можете переглянути список програм, які ви розгорнули, використовуючи підкоманду `program show`: +Ви можете переглянути список програм, які ви розгорнули, використовуючи +підкоманду `program show`: ```shell solana program show --programs @@ -85,18 +104,18 @@ Program Id | Slot | Authority ### Оновлення програми -Авторизація на оновлення програми може змінювати існуючу програму Solana, розгортаючи -новий файл `.so` на той самий ID програми. +Авторизація на оновлення програми може змінювати існуючу програму Solana, +розгортаючи новий файл `.so` на той самий ID програми. Щоб оновити існуючу програму Solana: - Змініть вихідний код вашої програми - Виконайте команду `cargo build-sbf`, щоб згенерувати оновлений файл `.so` -- Виконайте команду `solana program deploy ./target/deploy/your_program.so`, щоб розгорнути - оновлений файл `.so` +- Виконайте команду `solana program deploy ./target/deploy/your_program.so`, щоб + розгорнути оновлений файл `.so` -Авторизацію на оновлення можна змінити за допомогою підкоманди `set-upgrade-authority` -наступним чином: +Авторизацію на оновлення можна змінити за допомогою підкоманди +`set-upgrade-authority` наступним чином: ```shell solana program set-upgrade-authority --new-upgrade-authority @@ -104,14 +123,15 @@ solana program set-upgrade-authority --new-upgrade-authority < ### Незмінна програма -Програму можна зробити незмінною, видаливши її авторизацію на оновлення. Це незворотна дія. +Програму можна зробити незмінною, видаливши її авторизацію на оновлення. Це +незворотна дія. ```shell solana program set-upgrade-authority --final ``` -Ви можете вказати, що програма має бути незмінною при розгортанні, встановивши прапорець -`--final` під час розгортання програми. +Ви можете вказати, що програма має бути незмінною при розгортанні, встановивши +прапорець `--final` під час розгортання програми. ```shell solana program deploy ./target/deploy/your_program.so --final @@ -135,15 +155,18 @@ Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOL reclaimed ``` -Зверніть увагу, що після закриття програми її ID програми не можна буде використовувати знову. Спроба розгорнути програму з раніше закритим ID програми призведе до помилки. +Зверніть увагу, що після закриття програми її ID програми не можна буде +використовувати знову. Спроба розгорнути програму з раніше закритим ID програми +призведе до помилки. ``` Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, use a new Program Id ``` -Якщо вам потрібно повторно розгорнути програму після її закриття, ви повинні згенерувати новий -ID програми. Щоб згенерувати нову ключову пару для програми, виконайте наступну команду: +Якщо вам потрібно повторно розгорнути програму після її закриття, ви повинні +згенерувати новий ID програми. Щоб згенерувати нову ключову пару для програми, +виконайте наступну команду: ```shell filename="Terminal" solana-keygen new -o ./target/deploy/your_program-keypair.json --force @@ -154,8 +177,9 @@ solana-keygen new -o ./target/deploy/your_program-keypair.json --force ### Акаунти буфера програми -Розгортання програми вимагає кількох транзакцій через обмеження в 1232 байти -для транзакцій на Solana. Проміжним кроком процесу розгортання є запис байт-коду програми в тимчасовий "акаунт буфера". +Розгортання програми вимагає кількох транзакцій через обмеження в 1232 байти для +транзакцій на Solana. Проміжним кроком процесу розгортання є запис байт-коду +програми в тимчасовий "акаунт буфера". Цей акаунт буфера автоматично закривається після успішного розгортання програми. Однак, якщо розгортання не вдалося, акаунт буфера залишається, і ви можете: @@ -163,7 +187,8 @@ solana-keygen new -o ./target/deploy/your_program-keypair.json --force - Продовжити розгортання, використовуючи існуючий акаунт буфера - Закрити акаунт буфера, щоб повернути виділений SOL (оренду) -Ви можете перевірити, чи є відкриті акаунти буфера, використовуючи підкоманду `program show`, наступним чином: +Ви можете перевірити, чи є відкриті акаунти буфера, використовуючи підкоманду +`program show`, наступним чином: ```shell solana program show --buffers @@ -176,7 +201,8 @@ Buffer Address | Authority 5TRm1DxYcXLbSEbbxWcQbEUCce7L4tVgaC6e2V4G82pM | 4kh6HxYZiAebF8HWLsUWod2EaQQ6iWHpHYCz8UcmFbM1 | 0.57821592 SOL ``` -Ви можете продовжити до розгортання за допомогою підкоманди `program deploy` наступним чином: +Ви можете продовжити до розгортання за допомогою підкоманди `program deploy` +наступним чином: ```shell solana program deploy --buffer 5TRm1DxYcXLbSEbbxWcQbEUCce7L4tVgaC6e2V4G82pM @@ -198,11 +224,13 @@ solana program close --buffers ### ELF Dump -Внутрішні дані SBF shared object можна вивести в текстовий файл, щоб отримати більше -інформації про склад програми та те, що вона може виконувати під час виконання. Вивантаження -містить як ELF інформацію, так і список всіх символів та інструкцій, що їх реалізують. Деякі з повідомлень журналу помилок BPF loader -будуть посилатися на конкретні номери інструкцій, де сталася помилка. -Ці посилання можна знайти у вивантаженні ELF, щоб ідентифікувати помилкову інструкцію та її контекст. +Внутрішні дані SBF shared object можна вивести в текстовий файл, щоб отримати +більше інформації про склад програми та те, що вона може виконувати під час +виконання. Вивантаження містить як ELF інформацію, так і список всіх символів та +інструкцій, що їх реалізують. Деякі з повідомлень журналу помилок BPF loader +будуть посилатися на конкретні номери інструкцій, де сталася помилка. Ці +посилання можна знайти у вивантаженні ELF, щоб ідентифікувати помилкову +інструкцію та її контекст. ```shell cargo build-bpf --dump @@ -213,14 +241,17 @@ cargo build-bpf --dump ## Процес розгортання програми Розгортання програми на Solana вимагає кількох транзакцій через максимальний -ліміт розміру транзакцій у 1232 байти. Solana CLI надсилає ці транзакції за допомогою підкоманди `solana program deploy`. Процес можна розділити на наступні 3 фази: +ліміт розміру транзакцій у 1232 байти. Solana CLI надсилає ці транзакції за +допомогою підкоманди `solana program deploy`. Процес можна розділити на наступні +3 фази: 1. [Ініціалізація буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2113): Спочатку CLI надсилає транзакцію, яка [створює акаунт буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1903) достатнього розміру для байт-коду, що розгортається. Також викликається [інструкція ініціалізації буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L320), - щоб встановити право власності на буфер і обмежити записи на вибрану адресу розробника. + щоб встановити право власності на буфер і обмежити записи на вибрану адресу + розробника. 2. [Запис буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2129): Після ініціалізації акаунту буфера CLI [розбиває байт-код програми](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1940) @@ -228,7 +259,9 @@ cargo build-bpf --dump [відправляє транзакції зі швидкістю 100 транзакцій за секунду](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/client/src/tpu_client.rs#L133), щоб записати кожен шматок за допомогою [інструкції запису буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L334). - Ці транзакції надсилаються безпосередньо до порту обробки транзакцій (TPU) поточного лідера і обробляються паралельно. Після того, як всі транзакції будуть надіслані, CLI + Ці транзакції надсилаються безпосередньо до порту обробки транзакцій (TPU) + поточного лідера і обробляються паралельно. Після того, як всі транзакції + будуть надіслані, CLI [опитує RPC API партіями підписів транзакцій](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/client/src/tpu_client.rs#L216), щоб переконатися, що кожен запис був успішним і підтвердженим. 3. [Фіналізація](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1807): @@ -238,8 +271,8 @@ cargo build-bpf --dump [розгорнути нову програму](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L362) або [оновити існуючу програму](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L513). - В будь-якому випадку байт-код, записаний в акаунт буфера, буде скопійовано - в акаунт даних програми і перевірено. + В будь-якому випадку байт-код, записаний в акаунт буфера, буде скопійовано в + акаунт даних програми і перевірено. ## Оновлювана програма BPF Loader @@ -252,48 +285,49 @@ Solana. Коли ви розгортаєте програму, власник а Оновлювана програма BPF loader підтримує три різні типи акаунтів стану: 1. [Акаунт програми](https://github.com/solana-labs/solana/blob/master/sdk/program/src/bpf_loader_upgradeable.rs#L34): - Це основний акаунт програми на ланцюгу, і його адреса зазвичай - називається "ID програми". ID програми — це те, на що посилаються інструкції транзакцій - для виклику програми. Акаунти програми незмінні після розгортання, тому ви можете вважати їх проксі-акаунтами для байт-коду та - стану, що зберігаються в інших акаунтах. + Це основний акаунт програми на ланцюгу, і його адреса зазвичай називається + "ID програми". ID програми — це те, на що посилаються інструкції транзакцій + для виклику програми. Акаунти програми незмінні після розгортання, тому ви + можете вважати їх проксі-акаунтами для байт-коду та стану, що зберігаються в + інших акаунтах. 2. [Акаунт даних програми](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/bpf_loader_upgradeable.rs#L39): - Цей акаунт зберігає виконуваний байт-код програми на ланцюгу. - Коли програма оновлюється, дані цього акаунту оновлюються новим - байт-кодом. Крім байт-коду, акаунти даних програми також - відповідають за зберігання слоту, коли вони були востаннє змінені, та адреси - єдиного акаунту, авторизованого для зміни акаунту (ця адреса може бути - очищена, щоб зробити програму незмінною). + Цей акаунт зберігає виконуваний байт-код програми на ланцюгу. Коли програма + оновлюється, дані цього акаунту оновлюються новим байт-кодом. Крім байт-коду, + акаунти даних програми також відповідають за зберігання слоту, коли вони були + востаннє змінені, та адреси єдиного акаунту, авторизованого для зміни акаунту + (ця адреса може бути очищена, щоб зробити програму незмінною). 3. [Акаунти буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/bpf_loader_upgradeable.rs#L27): - Ці акаунти тимчасово зберігають байт-код під час активного - розгортання програми через серію транзакцій. Вони також зберігають адресу - єдиного акаунту, який авторизований для виконання записів. + Ці акаунти тимчасово зберігають байт-код під час активного розгортання + програми через серію транзакцій. Вони також зберігають адресу єдиного + акаунту, який авторизований для виконання записів. ### Інструкції -Акаунти стану, перераховані вище, можуть бути змінені лише за допомогою однієї з наступних -інструкцій, що підтримуються програмою Upgradeable BPF Loader: +Акаунти стану, перераховані вище, можуть бути змінені лише за допомогою однієї з +наступних інструкцій, що підтримуються програмою Upgradeable BPF Loader: 1. [Ініціалізація буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L21): - Створює акаунт буфера і зберігає адресу авторизації, яка дозволена - змінювати буфер. + Створює акаунт буфера і зберігає адресу авторизації, яка дозволена змінювати + буфер. 2. [Запис](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L28): Записує байт-код на вказаний байтовий офсет в акаунті буфера. Записи обробляються маленькими шматками через обмеження транзакцій Solana, максимальний розмір яких складає 1232 байти. 3. [Розгортання](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L77): - Створює акаунт програми та акаунт даних програми. Він заповнює - акаунт даних програми, копіюючи байт-код, що зберігається в акаунті буфера. Якщо - байт-код є дійсним, акаунт програми буде встановлений як виконуваний, - дозволяючи його викликати. Якщо байт-код недійсний, інструкція не вдасться, і всі зміни будуть скасовані. + Створює акаунт програми та акаунт даних програми. Він заповнює акаунт даних + програми, копіюючи байт-код, що зберігається в акаунті буфера. Якщо байт-код + є дійсним, акаунт програми буде встановлений як виконуваний, дозволяючи його + викликати. Якщо байт-код недійсний, інструкція не вдасться, і всі зміни + будуть скасовані. 4. [Оновлення](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L102): - Заповнює існуючий акаунт даних програми, копіюючи виконуваний байт-код з акаунта - буфера. Подібно до інструкції розгортання, вона буде успішною лише в тому випадку, якщо - байт-код є дійсним. + Заповнює існуючий акаунт даних програми, копіюючи виконуваний байт-код з + акаунта буфера. Подібно до інструкції розгортання, вона буде успішною лише в + тому випадку, якщо байт-код є дійсним. 5. [Встановлення авторизації](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L114): Оновлює авторизацію акаунта даних програми або акаунта буфера, якщо поточний - власник акаунту підписав транзакцію, що обробляється. Якщо авторизація буде видалена без заміни, - її можна буде встановити лише один раз і акаунт більше не можна буде закрити. + власник акаунту підписав транзакцію, що обробляється. Якщо авторизація буде + видалена без заміни, її можна буде встановити лише один раз і акаунт більше + не можна буде закрити. 6. [Закриття](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L127): - Очищає дані акаунта програми або акаунта буфера та повертає SOL, - використані для депозиту звільнення від оренди. - + Очищає дані акаунта програми або акаунта буфера та повертає SOL, використані + для депозиту звільнення від оренди. diff --git a/docs/locales/uk/programs/examples.md b/docs/locales/uk/programs/examples.md index be25a95dd..e20f39553 100644 --- a/docs/locales/uk/programs/examples.md +++ b/docs/locales/uk/programs/examples.md @@ -1,8 +1,9 @@ --- title: "Приклади програм" description: - "Список прикладів програм для Solana на різних мовах і фреймворках, - які можуть допомогти вам вивчити та використовувати їх як посилання для ваших власних проектів." + "Список прикладів програм для Solana на різних мовах і фреймворках, які можуть + допомогти вам вивчити та використовувати їх як посилання для ваших власних + проектів." tags: - quickstart - program @@ -28,19 +29,19 @@ sidebarSortOrder: 3 Репозиторій [Solana Program Examples](https://github.com/solana-developers/program-examples) -на GitHub пропонує кілька підпапок, кожна з яких містить приклади коду -для різних парадигм програмування Solana та мов, створених, щоб допомогти +на GitHub пропонує кілька підпапок, кожна з яких містить приклади коду для +різних парадигм програмування Solana та мов, створених, щоб допомогти розробникам вивчати та експериментувати з розробкою на блокчейні Solana. Ви можете знайти приклади в репозиторії `solana-developers/program-examples` разом з файлами README, що пояснюють, як запускати різні приклади. Більшість прикладів є самодостатніми та доступні на рідному Rust (тобто без використання -фреймворку) та [Anchor](https://www.anchor-lang.com/docs/installation). Також -є список прикладів, які ми з радістю б +фреймворку) та [Anchor](https://www.anchor-lang.com/docs/installation). Також є +список прикладів, які ми з радістю б [побачили як внески](https://github.com/solana-developers/program-examples?tab=readme-ov-file#examples-wed-love-to-see). -У репозиторії ви знайдете наступну підпапку, кожну з яких з різними -прикладами програм: +У репозиторії ви знайдете наступну підпапку, кожну з яких з різними прикладами +програм: - [Основи](#basics) - [Стиснення](#compression) @@ -52,26 +53,26 @@ sidebarSortOrder: 3 ## Основи -Містить серію прикладів, які демонструють основні кроки для -створення програм Solana, використовуючи рідні бібліотеки Rust. Ці приклади -призначені для того, щоб допомогти розробникам зрозуміти основні концепції програмування Solana. - -| Назва прикладу | Опис | Мова | -| ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------ | -| [Дані акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/account-data) | Збереження адреси з ім'ям, номером будинку, вулицею та містом в акаунті. | Native, Anchor | -| [Перевірка акаунтів](https://github.com/solana-developers/program-examples/tree/main/basics/checking-accounts) | Уроки безпеки, що показують, як виконувати перевірки акаунтів | Native, Anchor | -| [Закриття акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/close-account) | Показує, як закривати акаунти, щоб повернути оренду. | Native, Anchor | -| [Лічильник](https://github.com/solana-developers/program-examples/tree/main/basics/counter) | Простий програмний лічильник на всіх різних архітектурах. | Native, Anchor, mpl-stack| -| [Створення акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/create-account) | Як створити системний акаунт в межах програми. | Native, Anchor | -| [Перехресний виклик програми](https://github.com/solana-developers/program-examples/tree/main/basics/cross-program-invocation) | Використовуючи аналогію з рукою та важелем, показує, як викликати іншу програму з програми. | Native, Anchor | -| [Hello Solana](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana) | Приклад "Hello world", який просто виводить hello world у журналах транзакцій. | Native, Anchor | -| [Pda Rent payer](https://github.com/solana-developers/program-examples/tree/main/basics/pda-rent-payer) | Показує, як можна використовувати лампорти з PDA для оплати нового акаунта. | Native, Anchor | -| [Обробка інструкцій](https://github.com/solana-developers/program-examples/tree/main/basics/processing-instructions) | Показує, як обробляти рядкові дані інструкцій та u32. | Native, Anchor | -| [Програма з похідними адресами](https://github.com/solana-developers/program-examples/tree/main/basics/program-derived-addresses) | Показує, як використовувати насіння для посилання на PDA та збереження даних в ньому. | Native, Anchor | -| [Перерозподіл](https://github.com/solana-developers/program-examples/tree/main/basics/realloc) | Показує, як збільшувати та зменшувати розмір існуючого акаунта. | Native, Anchor | -| [Оренда](https://github.com/solana-developers/program-examples/tree/main/basics/rent) | Тут ви дізнаєтесь, як обчислювати вимоги оренди в межах програми. | Native, Anchor | -| [Розташування репозиторію](https://github.com/solana-developers/program-examples/tree/main/basics/repository-layout) | Рекомендації щодо структурування вашого макету програми. | Native, Anchor | -| [Передача SOL](https://github.com/solana-developers/program-examples/tree/main/basics/transfer-sol) | Різні методи передачі SOL для системних акаунтів та PDA. | Native, Anchor, Seahorse | +Містить серію прикладів, які демонструють основні кроки для створення програм +Solana, використовуючи рідні бібліотеки Rust. Ці приклади призначені для того, +щоб допомогти розробникам зрозуміти основні концепції програмування Solana. + +| Назва прикладу | Опис | Мова | +| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------- | +| [Дані акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/account-data) | Збереження адреси з ім'ям, номером будинку, вулицею та містом в акаунті. | Native, Anchor | +| [Перевірка акаунтів](https://github.com/solana-developers/program-examples/tree/main/basics/checking-accounts) | Уроки безпеки, що показують, як виконувати перевірки акаунтів | Native, Anchor | +| [Закриття акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/close-account) | Показує, як закривати акаунти, щоб повернути оренду. | Native, Anchor | +| [Лічильник](https://github.com/solana-developers/program-examples/tree/main/basics/counter) | Простий програмний лічильник на всіх різних архітектурах. | Native, Anchor, mpl-stack | +| [Створення акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/create-account) | Як створити системний акаунт в межах програми. | Native, Anchor | +| [Перехресний виклик програми](https://github.com/solana-developers/program-examples/tree/main/basics/cross-program-invocation) | Використовуючи аналогію з рукою та важелем, показує, як викликати іншу програму з програми. | Native, Anchor | +| [Hello Solana](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana) | Приклад "Hello world", який просто виводить hello world у журналах транзакцій. | Native, Anchor | +| [Pda Rent payer](https://github.com/solana-developers/program-examples/tree/main/basics/pda-rent-payer) | Показує, як можна використовувати лампорти з PDA для оплати нового акаунта. | Native, Anchor | +| [Обробка інструкцій](https://github.com/solana-developers/program-examples/tree/main/basics/processing-instructions) | Показує, як обробляти рядкові дані інструкцій та u32. | Native, Anchor | +| [Програма з похідними адресами](https://github.com/solana-developers/program-examples/tree/main/basics/program-derived-addresses) | Показує, як використовувати насіння для посилання на PDA та збереження даних в ньому. | Native, Anchor | +| [Перерозподіл](https://github.com/solana-developers/program-examples/tree/main/basics/realloc) | Показує, як збільшувати та зменшувати розмір існуючого акаунта. | Native, Anchor | +| [Оренда](https://github.com/solana-developers/program-examples/tree/main/basics/rent) | Тут ви дізнаєтесь, як обчислювати вимоги оренди в межах програми. | Native, Anchor | +| [Розташування репозиторію](https://github.com/solana-developers/program-examples/tree/main/basics/repository-layout) | Рекомендації щодо структурування вашого макету програми. | Native, Anchor | +| [Передача SOL](https://github.com/solana-developers/program-examples/tree/main/basics/transfer-sol) | Різні методи передачі SOL для системних акаунтів та PDA. | Native, Anchor, Seahorse | ## Стиснення @@ -79,62 +80,67 @@ sidebarSortOrder: 3 [стиснення стану](/docs/advanced/state-compression.md) на Solana. Головним чином фокусується на стиснених NFT (cNFT). -| Назва прикладу | Опис | Мова | -| -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------- | -| [cNFT-burn](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-burn) | Для знищення cNFT він може бути спалений. Цей приклад показує, як це зробити в програмі. | Anchor | -| [cNFT-Vault](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-vault/anchor) | Як зберігати cNFT в програмі та відправляти його знову. | Anchor | -| [cutils](https://github.com/solana-developers/program-examples/tree/main/compression/cutils) | Набір утиліт для, наприклад, мінтування та перевірки cNFT в програмі. | Anchor | +| Назва прикладу | Опис | Мова | +| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------ | +| [cNFT-burn](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-burn) | Для знищення cNFT він може бути спалений. Цей приклад показує, як це зробити в програмі. | Anchor | +| [cNFT-Vault](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-vault/anchor) | Як зберігати cNFT в програмі та відправляти його знову. | Anchor | +| [cutils](https://github.com/solana-developers/program-examples/tree/main/compression/cutils) | Набір утиліт для, наприклад, мінтування та перевірки cNFT в програмі. | Anchor | ## Оракули Оракули дозволяють використовувати дані поза ланцюгом в програмах. -| Назва прикладу | Опис | Мова | -| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------ | -| [Pyth](https://github.com/solana-developers/program-examples/tree/main/oracles/pyth) | Pyth надає дані про ціни токенів для використання в програмах на ланцюгу. | Anchor | +| Назва прикладу | Опис | Мова | +| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- | ------ | +| [Pyth](https://github.com/solana-developers/program-examples/tree/main/oracles/pyth) | Pyth надає дані про ціни токенів для використання в програмах на ланцюгу. | Anchor | ## Токени -Більшість токенів на Solana використовують стандарт токенів Solana Program Library (SPL). Тут -ви знайдете багато прикладів, як створювати, передавати, спалювати токени та навіть як взаємодіяти з ними в програмах. +Більшість токенів на Solana використовують стандарт токенів Solana Program +Library (SPL). Тут ви знайдете багато прикладів, як створювати, передавати, +спалювати токени та навіть як взаємодіяти з ними в програмах. -| Назва прикладу | Опис | Мова | -| --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------ | -| [Створення токена](https://github.com/solana-developers/program-examples/tree/main/tokens/create-token) | Як створити токен та додати метадані метаплекса до нього. | Anchor, Native | -| [NFT Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/nft-minter) | Мінтування тільки однієї кількості токену, а потім видалення права на мінтинг. | Anchor, Native | -| [PDA Mint Authority](https://github.com/solana-developers/program-examples/tree/main/tokens/pda-mint-authority) | Показує, як змінити право на мінтинг токенів через PDA. | Anchor, Native | -| [SPL Token Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/spl-token-minter) | Пояснює, як використовувати Associated Token Accounts для відслідковування токен акаунтів. | Anchor, Native | -| [Token Swap](https://github.com/solana-developers/program-examples/tree/main/tokens/token-swap) | Розширений приклад, який показує, як побудувати AMM (автоматизований маркет-мейкер) пул для SPL токенів. | Anchor | -| [Передача токенів](https://github.com/solana-developers/program-examples/tree/main/tokens/transfer-tokens) | Показує, як передавати SPL токени за допомогою CPIs у програму токенів. | Anchor, Native | -| [Token-2022](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022) | Див. Token 2022 (Розширення токенів). | Anchor, Native | +| Назва прикладу | Опис | Мова | +| --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -------------- | +| [Створення токена](https://github.com/solana-developers/program-examples/tree/main/tokens/create-token) | Як створити токен та додати метадані метаплекса до нього. | Anchor, Native | +| [NFT Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/nft-minter) | Мінтування тільки однієї кількості токену, а потім видалення права на мінтинг. | Anchor, Native | +| [PDA Mint Authority](https://github.com/solana-developers/program-examples/tree/main/tokens/pda-mint-authority) | Показує, як змінити право на мінтинг токенів через PDA. | Anchor, Native | +| [SPL Token Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/spl-token-minter) | Пояснює, як використовувати Associated Token Accounts для відслідковування токен акаунтів. | Anchor, Native | +| [Token Swap](https://github.com/solana-developers/program-examples/tree/main/tokens/token-swap) | Розширений приклад, який показує, як побудувати AMM (автоматизований маркет-мейкер) пул для SPL токенів. | Anchor | +| [Передача токенів](https://github.com/solana-developers/program-examples/tree/main/tokens/transfer-tokens) | Показує, як передавати SPL токени за допомогою CPIs у програму токенів. | Anchor, Native | +| [Token-2022](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022) | Див. Token 2022 (Розширення токенів). | Anchor, Native | ## Token 2022 (Розширення токенів) -Token 2022 — це новий стандарт для токенів на Solana. Це більш гнучкий стандарт, який -дозволяє додавати до токену 16 різних розширень для додавання більшої функціональності. - -| Назва прикладу | Опис | Мова | -| ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------ | -| [Основи](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/basics/anchor) | Як створити токен, мінтувати та передавати його. | Anchor | -| [Стандартний стан акаунта](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/default-account-state/native) | Це розширення дозволяє створювати акаунти токенів з певним станом, наприклад замороженими. | Native | -| [Право закриття мінта](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/mint-close-authority) | З старою програмою токенів не було можливості закривати мінт. Тепер це можливо. | Native | -| [Багато розширень](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/multiple-extensions) | Показує, як додавати кілька розширень до одного мінта | Native | -| [Вказівник метаданих NFT](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/nft-meta-data-pointer) | Можна використовувати розширення метаданих для створення NFT та додавання динамічних метаданих на ланцюг. | Anchor | -| [Не передаваємий](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/non-transferable/native) | Корисно, наприклад, для досягнень, програм рефералів або будь-яких токенів, які не можна передавати. | Native | -| [Плата за передачу](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-fees) | Кожна передача токенів утримує певну кількість токенів у акаунті токена, яку потім можна забрати. | Native | -| [Transfer Hook](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-hook) | Чотири приклади для додавання додаткової функціональності до вашого токена за допомогою CPI з програми токенів. | Anchor | +Token 2022 — це новий стандарт для токенів на Solana. Це більш гнучкий стандарт, +який дозволяє додавати до токену 16 різних розширень для додавання більшої +функціональності. + +| Назва прикладу | Опис | Мова | +| ------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- | ------ | +| [Основи](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/basics/anchor) | Як створити токен, мінтувати та передавати його. | Anchor | +| [Стандартний стан акаунта](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/default-account-state/native) | Це розширення дозволяє створювати акаунти токенів з певним станом, наприклад замороженими. | Native | +| [Право закриття мінта](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/mint-close-authority) | З старою програмою токенів не було можливості закривати мінт. Тепер це можливо. | Native | +| [Багато розширень](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/multiple-extensions) | Показує, як додавати кілька розширень до одного мінта | Native | +| [Вказівник метаданих NFT](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/nft-meta-data-pointer) | Можна використовувати розширення метаданих для створення NFT та додавання динамічних метаданих на ланцюг. | Anchor | +| [Не передаваємий](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/non-transferable/native) | Корисно, наприклад, для досягнень, програм рефералів або будь-яких токенів, які не можна передавати. | Native | +| [Плата за передачу](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-fees) | Кожна передача токенів утримує певну кількість токенів у акаунті токена, яку потім можна забрати. | Native | +| [Transfer Hook](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-hook) | Чотири приклади для додавання додаткової функціональності до вашого токена за допомогою CPI з програми токенів. | Anchor | ## Break -[Break](https://break.solana.com/) — це додаток на React, який дає користувачам можливість -відчути, наскільки швидко і ефективно працює мережа Solana. Чи зможете ви _зламати_ блокчейн Solana? Протягом 15 секунд кожне натискання кнопки або клавіші -відправляє нову транзакцію в кластер. Ударте по клавіатурі так швидко, як можете, і дивіться, -як ваші транзакції підтверджуються в реальному часі, поки мережа справляється з усім! +[Break](https://break.solana.com/) — це додаток на React, який дає користувачам +можливість відчути, наскільки швидко і ефективно працює мережа Solana. Чи +зможете ви _зламати_ блокчейн Solana? Протягом 15 секунд кожне натискання кнопки +або клавіші відправляє нову транзакцію в кластер. Ударте по клавіатурі так +швидко, як можете, і дивіться, як ваші транзакції підтверджуються в реальному +часі, поки мережа справляється з усім! -Break можна грати на наших мережах Devnet, Testnet та Mainnet Beta. Ігри безкоштовні на Devnet і Testnet, -де сесія фінансується мережевим фонтаном. На Mainnet Beta користувачі платять 0,08 SOL за гру. Сесійний акаунт можна -фінансувати через локальний гаманець keystore або скануючи QR-код з Trust Wallet для -переміщення токенів. +Break можна грати на наших мережах Devnet, Testnet та Mainnet Beta. Ігри +безкоштовні на Devnet і Testnet, де сесія фінансується мережевим фонтаном. На +Mainnet Beta користувачі платять 0,08 SOL за гру. Сесійний акаунт можна +фінансувати через локальний гаманець keystore або скануючи QR-код з Trust Wallet +для переміщення токенів. [Клацніть тут, щоб зіграти в Break](https://break.solana.com/) @@ -142,10 +148,10 @@ Break можна грати на наших мережах Devnet, Testnet та Спочатку отримайте останню версію прикладів коду: - ```shell git clone https://github.com/solana-labs/break.git cd break ``` -Дотримуйтесь кроків у файлі [README](https://github.com/solana-labs/break/blob/main/README.md) репозиторію. +Дотримуйтесь кроків у файлі +[README](https://github.com/solana-labs/break/blob/main/README.md) репозиторію. diff --git a/docs/locales/uk/programs/faq.md b/docs/locales/uk/programs/faq.md index d11a5f914..7514d785e 100644 --- a/docs/locales/uk/programs/faq.md +++ b/docs/locales/uk/programs/faq.md @@ -15,65 +15,68 @@ sidebarSortOrder: 7 [Berkeley Packet Filter (BPF)](https://en.wikipedia.org/wiki/Berkeley_Packet_Filter) байткоду. -Оскільки Solana використовує інфраструктуру компілятора LLVM, програму можна написати -на будь-якій мові програмування, яка підтримує компіляцію в BPF бекенд LLVM. +Оскільки Solana використовує інфраструктуру компілятора LLVM, програму можна +написати на будь-якій мові програмування, яка підтримує компіляцію в BPF бекенд +LLVM. BPF надає ефективний [набір інструкцій](https://github.com/iovisor/bpf-docs/blob/master/eBPF.md), -який можна виконувати в інтерпретованій віртуальній машині або як ефективно згенеровані -нативні інструкції за допомогою just-in-time компіляції. +який можна виконувати в інтерпретованій віртуальній машині або як ефективно +згенеровані нативні інструкції за допомогою just-in-time компіляції. ## Карта пам'яті -Віртуальна адресна карта пам'яті, яку використовують програми Solana SBF, є фіксованою -та має наступне розташування: +Віртуальна адресна карта пам'яті, яку використовують програми Solana SBF, є +фіксованою та має наступне розташування: - Код програми починається з адреси 0x100000000 - Дані стека починаються з адреси 0x200000000 - Дані купи починаються з адреси 0x300000000 - Вхідні параметри програми починаються з адреси 0x400000000 -Вищезазначені віртуальні адреси є початковими адресами, але програми отримують доступ до -підмножини карти пам'яті. Програма викликає паніку, якщо вона намагається читати або -записувати в віртуальну адресу, до якої не було надано доступу, і повертається помилка -`AccessViolation`, яка містить адресу та розмір спроби порушення. +Вищезазначені віртуальні адреси є початковими адресами, але програми отримують +доступ до підмножини карти пам'яті. Програма викликає паніку, якщо вона +намагається читати або записувати в віртуальну адресу, до якої не було надано +доступу, і повертається помилка `AccessViolation`, яка містить адресу та розмір +спроби порушення. ## InvalidAccountData Ця помилка програми може статися з багатьох причин. Зазвичай це викликано передачею акаунта в програму, якого програма не очікує, або через неправильне -положення акаунта в інструкції або акаунт, який не сумісний з виконуваною інструкцією. +положення акаунта в інструкції або акаунт, який не сумісний з виконуваною +інструкцією. -Реалізація програми може також спричинити цю помилку при виконанні -перехресної інструкції між програмами, якщо забули надати акаунт для програми, -яку ви викликаєте. +Реалізація програми може також спричинити цю помилку при виконанні перехресної +інструкції між програмами, якщо забули надати акаунт для програми, яку ви +викликаєте. ## InvalidInstructionData -Ця помилка програми може статися при спробі десеріалізувати інструкцію, перевірте, -чи структура, передана в інструкцію, точно відповідає вимогам програми. Між полями -може бути деяке додаткове заповнення. Якщо програма реалізує трейти Rust `Pack`, спробуйте -упакувати і розпакувати тип інструкції `T`, щоб визначити точне кодування, -яке програма очікує. +Ця помилка програми може статися при спробі десеріалізувати інструкцію, +перевірте, чи структура, передана в інструкцію, точно відповідає вимогам +програми. Між полями може бути деяке додаткове заповнення. Якщо програма +реалізує трейти Rust `Pack`, спробуйте упакувати і розпакувати тип інструкції +`T`, щоб визначити точне кодування, яке програма очікує. ## MissingRequiredSignature -Деякі інструкції вимагають, щоб акаунт був підписантом; ця помилка повертається, якщо -очікується підпис акаунта, але він відсутній. +Деякі інструкції вимагають, щоб акаунт був підписантом; ця помилка повертається, +якщо очікується підпис акаунта, але він відсутній. Реалізація програми може також викликати цю помилку при виконанні -[перехресного виклику програми](/docs/core/cpi.md), який вимагає підписаного адреси програми, -але передані насіння підписувача до `invoke_signed` не збігаються з -насіннями підписувача, що використовуються для створення адреси програми -[`create_program_address`](/docs/core/pda.md#createprogramaddress). +[перехресного виклику програми](/docs/core/cpi.md), який вимагає підписаного +адреси програми, але передані насіння підписувача до `invoke_signed` не +збігаються з насіннями підписувача, що використовуються для створення адреси +програми [`create_program_address`](/docs/core/pda.md#createprogramaddress). ## Стек -SBF використовує стекові кадри замість змінного покажчика стеку. Кожен стековий кадр -має розмір 4 КБ. +SBF використовує стекові кадри замість змінного покажчика стеку. Кожен стековий +кадр має розмір 4 КБ. -Якщо програма порушує розмір цього стекового кадру, компілятор повідомить -про перевищення розміру як попередження. +Якщо програма порушує розмір цього стекового кадру, компілятор повідомить про +перевищення розміру як попередження. Наприклад: @@ -81,82 +84,92 @@ SBF використовує стекові кадри замість змінн Error: Function _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E Stack offset of -30728 exceeded max offset of -4096 by 26632 bytes, please minimize large stack variables ``` -Повідомлення вказує, який символ перевищує розмір свого стекового кадру, але ім'я може бути змінене. +Повідомлення вказує, який символ перевищує розмір свого стекового кадру, але +ім'я може бути змінене. -> Щоб деманглювати символ Rust, використовуйте [rustfilt](https://github.com/luser/rustfilt). - -Вищезазначене попередження походить від програми на Rust, тому демангльоване ім'я символу: +> Щоб деманглювати символ Rust, використовуйте +> [rustfilt](https://github.com/luser/rustfilt). +Вищезазначене попередження походить від програми на Rust, тому демангльоване +ім'я символу: ```shell rustfilt _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E curve25519_dalek::edwards::EdwardsBasepointTable::create ``` -Причина того, що виводиться попередження, а не помилка, полягає в тому, що деякі залежні -пакети можуть містити функціональність, яка порушує обмеження розміру стекового кадру, навіть -якщо програма не використовує цю функціональність. Якщо програма порушить розмір стеку під час виконання, -то буде виведено помилку `AccessViolation`. -Стекові кадри SBF займають діапазон віртуальних адрес, починаючи з `0x200000000`. +Причина того, що виводиться попередження, а не помилка, полягає в тому, що деякі +залежні пакети можуть містити функціональність, яка порушує обмеження розміру +стекового кадру, навіть якщо програма не використовує цю функціональність. Якщо +програма порушить розмір стеку під час виконання, то буде виведено помилку +`AccessViolation`. + +Стекові кадри SBF займають діапазон віртуальних адрес, починаючи з +`0x200000000`. ## Розмір купи Програми мають доступ до купи часу виконання через API Rust `alloc`. Для -швидкого виділення пам'яті використовується проста купа на 32 КБ. Куча не підтримує -`free` або `realloc`. +швидкого виділення пам'яті використовується проста купа на 32 КБ. Куча не +підтримує `free` або `realloc`. -Програми мають доступ до пам'яті об'ємом 32 КБ, починаючи з віртуальної -адреси 0x300000000, і можуть реалізувати власну купу на основі специфічних потреб програми. +Програми мають доступ до пам'яті об'ємом 32 КБ, починаючи з віртуальної адреси +0x300000000, і можуть реалізувати власну купу на основі специфічних потреб +програми. Програми на Rust реалізують купу безпосередньо, визначаючи власний [`global_allocator`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/entrypoint.rs#L72) ## Завантажувачі -Програми розгортаються і виконуються через завантажувачі часу виконання, наразі підтримуються -два завантажувачі: +Програми розгортаються і виконуються через завантажувачі часу виконання, наразі +підтримуються два завантажувачі: + - [BPF Loader](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader.rs#L17) - [BPF loader (deprecated)](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader_deprecated.rs#L14) -Завантажувачі можуть підтримувати різні інтерфейси бінарних додатків, тому розробники повинні -пишуть свої програми для одного завантажувача і розгортають їх на тому ж завантажувачі. Якщо програма, -написана для одного завантажувача, буде розгорнута на іншому, це зазвичай призведе до -помилки `AccessViolation` через невідповідність десеріалізації вхідних параметрів програми. +Завантажувачі можуть підтримувати різні інтерфейси бінарних додатків, тому +розробники повинні пишуть свої програми для одного завантажувача і розгортають +їх на тому ж завантажувачі. Якщо програма, написана для одного завантажувача, +буде розгорнута на іншому, це зазвичай призведе до помилки `AccessViolation` +через невідповідність десеріалізації вхідних параметрів програми. -Для практичних цілей програми завжди повинні бути написані для останнього -BPF завантажувача, і останній завантажувач є за умовчанням для інтерфейсу командного рядка -та JavaScript API. +Для практичних цілей програми завжди повинні бути написані для останнього BPF +завантажувача, і останній завантажувач є за умовчанням для інтерфейсу командного +рядка та JavaScript API. - [Точки входу програми Rust](/docs/programs/lang-rust.md#program-entrypoint) ### Розгортання -Розгортання програми SBF — це процес завантаження спільного об'єкта BPF в -дані акаунта програми та позначення акаунта як виконуваного. Клієнт розбиває -спільний об'єкт SBF на менші частини і надсилає їх як дані інструкцій +Розгортання програми SBF — це процес завантаження спільного об'єкта BPF в дані +акаунта програми та позначення акаунта як виконуваного. Клієнт розбиває спільний +об'єкт SBF на менші частини і надсилає їх як дані інструкцій [`Write`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/loader_instruction.rs#L13) -до завантажувача, де завантажувач записує ці дані в акаунт програми. -Якщо всі частини отримані, клієнт надсилає +до завантажувача, де завантажувач записує ці дані в акаунт програми. Якщо всі +частини отримані, клієнт надсилає [`Finalize`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/loader_instruction.rs#L30) -інструкцію до завантажувача, завантажувач потім перевіряє, чи є дані SBF дійсними -і позначає акаунт програми як _виконуваний_. Після того, як акаунт програми -буде позначено як виконуваний, подальші транзакції можуть видавати інструкції для цієї -програми для обробки. +інструкцію до завантажувача, завантажувач потім перевіряє, чи є дані SBF +дійсними і позначає акаунт програми як _виконуваний_. Після того, як акаунт +програми буде позначено як виконуваний, подальші транзакції можуть видавати +інструкції для цієї програми для обробки. -Коли інструкція спрямована до виконуваної програми SBF, завантажувач -конфігурує середовище виконання програми, серіалізує вхідні параметри програми, -викликає точку входу програми і повідомляє про будь-які помилки. +Коли інструкція спрямована до виконуваної програми SBF, завантажувач конфігурує +середовище виконання програми, серіалізує вхідні параметри програми, викликає +точку входу програми і повідомляє про будь-які помилки. -Додаткову інформацію див. в розділі [розгортання програм](/docs/programs/deploying.md). +Додаткову інформацію див. в розділі +[розгортання програм](/docs/programs/deploying.md). ### Серіалізація вхідних параметрів -Завантажувачі SBF серіалізують вхідні параметри програми в масив байтів, який потім передається -в точку входу програми, де програма відповідає за їх десеріалізацію на ланцюгу. Одна з змін між -депрецованим завантажувачем і поточним полягає в тому, що вхідні параметри серіалізуються так, -що різні параметри потрапляють на вирівняні офсети в межах вирівняного байтового -масиву. Це дозволяє реалізаціям десеріалізації безпосередньо посилатися на -байтовий масив і надавати вирівняні вказівники до програми. +Завантажувачі SBF серіалізують вхідні параметри програми в масив байтів, який +потім передається в точку входу програми, де програма відповідає за їх +десеріалізацію на ланцюгу. Одна з змін між депрецованим завантажувачем і +поточним полягає в тому, що вхідні параметри серіалізуються так, що різні +параметри потрапляють на вирівняні офсети в межах вирівняного байтового масиву. +Це дозволяє реалізаціям десеріалізації безпосередньо посилатися на байтовий +масив і надавати вирівняні вказівники до програми. - [Десеріалізація параметрів програми на Rust](/docs/programs/lang-rust.md#parameter-deserialization) @@ -165,8 +178,8 @@ BPF завантажувача, і останній завантажувач є - 8 байт беззнакового числа акаунтів - Для кожного акаунта: - - 1 байт, що вказує, чи є цей акаунт дублікатом, якщо ні — значення 0xff, - в іншому випадку значення — це індекс акаунта, з яким він є дублікатом. + - 1 байт, що вказує, чи є цей акаунт дублікатом, якщо ні — значення 0xff, в + іншому випадку значення — це індекс акаунта, з яким він є дублікатом. - Якщо дублікати: 7 байт заповнювальної пам'яті - Якщо не дублікати: - 1 байт булевого типу, true, якщо акаунт є підписантом diff --git a/docs/locales/uk/programs/limitations.md b/docs/locales/uk/programs/limitations.md index a2e33411f..955549850 100644 --- a/docs/locales/uk/programs/limitations.md +++ b/docs/locales/uk/programs/limitations.md @@ -3,15 +3,20 @@ title: "Обмеження" sidebarSortOrder: 6 --- -Розробка програм на блокчейні Solana має деякі вроджені обмеження. Нижче наведено список поширених обмежень, з якими ви можете зіткнутися. +Розробка програм на блокчейні Solana має деякі вроджені обмеження. Нижче +наведено список поширених обмежень, з якими ви можете зіткнутися. ## Бібліотеки Rust -Оскільки програми Rust на блокчейні повинні бути детермінованими і виконуватись у середовищі з обмеженими ресурсами та одночасною обробкою, вони мають деякі обмеження щодо використання бібліотек. +Оскільки програми Rust на блокчейні повинні бути детермінованими і виконуватись +у середовищі з обмеженими ресурсами та одночасною обробкою, вони мають деякі +обмеження щодо використання бібліотек. -Програми Rust на блокчейні підтримують більшість бібліотек Rust, таких як libstd, libcore, liballoc, а також багато сторонніх бібліотек. +Програми Rust на блокчейні підтримують більшість бібліотек Rust, таких як +libstd, libcore, liballoc, а також багато сторонніх бібліотек. -Проте існують певні обмеження через обмежені ресурси середовища та необхідність детермінованості: +Проте існують певні обмеження через обмежені ресурси середовища та необхідність +детермінованості: - Немає доступу до: - `rand` @@ -28,41 +33,62 @@ sidebarSortOrder: 6 - `std::os` - Використання Bincode є дуже ресурсомістким і його слід уникати. - Форматування рядків також є ресурсомістким і повинно бути мінімізоване. -- Відсутня підтримка для `println!` та `print!`, замість цього використовуйте макрос +- Відсутня підтримка для `println!` та `print!`, замість цього використовуйте + макрос [`msg!`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/log.rs#L33). -- Під час виконання встановлено обмеження на кількість інструкцій, які програма може виконати під час обробки однієї інструкції. Дивіться [бюджет обчислень](/docs/core/fees.md#compute-budget) для більш детальної інформації. +- Під час виконання встановлено обмеження на кількість інструкцій, які програма + може виконати під час обробки однієї інструкції. Дивіться + [бюджет обчислень](/docs/core/fees.md#compute-budget) для більш детальної + інформації. ## Бюджет обчислень -Для запобігання зловживанню обчислювальними ресурсами блокчейну кожна транзакція отримує [бюджет обчислень](/docs/terminology.md#compute-budget). Перевищення цього бюджету призведе до провалу транзакції. +Для запобігання зловживанню обчислювальними ресурсами блокчейну кожна транзакція +отримує [бюджет обчислень](/docs/terminology.md#compute-budget). Перевищення +цього бюджету призведе до провалу транзакції. -Дивіться документацію про [обмеження обчислень](/docs/core/fees.md#compute-budget) для більш детальної інформації. +Дивіться документацію про +[обмеження обчислень](/docs/core/fees.md#compute-budget) для більш детальної +інформації. ## Глибина стеку викликів — помилка `CallDepthExceeded` Програми Solana мають обмежену глибину стеку викликів до **64 кадрів**. -Якщо програма перевищує дозволену глибину стеку викликів, вона отримує помилку `CallDepthExceeded`. +Якщо програма перевищує дозволену глибину стеку викликів, вона отримує помилку +`CallDepthExceeded`. ## Глибина викликів CPI — помилка `CallDepth` -Перехресні виклики між програмами дозволяють програмам викликати інші програми безпосередньо, але наразі глибина обмежена до `4`. +Перехресні виклики між програмами дозволяють програмам викликати інші програми +безпосередньо, але наразі глибина обмежена до `4`. -Якщо програма перевищує дозволену [глибину викликів між програмами](/docs/core/cpi.md), вона отримує помилку `CallDepth`. +Якщо програма перевищує дозволену +[глибину викликів між програмами](/docs/core/cpi.md), вона отримує помилку +`CallDepth`. ## Підтримка типів float у Rust -Програми підтримують обмежений набір операцій із типами float у Rust. Якщо програма намагається використовувати операцію із float, яка не підтримується, виконання викликає помилку про нерозв’язаний символ. +Програми підтримують обмежений набір операцій із типами float у Rust. Якщо +програма намагається використовувати операцію із float, яка не підтримується, +виконання викликає помилку про нерозв’язаний символ. -Операції із float виконуються через програмні бібліотеки (LLVM's float built-ins) і споживають більше обчислювальних одиниць, ніж операції з цілими числами. Загалом рекомендується використовувати фіксовану точку там, де це можливо. +Операції із float виконуються через програмні бібліотеки (LLVM's float +built-ins) і споживають більше обчислювальних одиниць, ніж операції з цілими +числами. Загалом рекомендується використовувати фіксовану точку там, де це +можливо. -[Математичні тести Solana Program Library](https://github.com/solana-labs/solana-program-library/tree/master/libraries/math) демонструють продуктивність деяких математичних операцій. Для запуску тесту синхронізуйте репозиторій і виконайте: +[Математичні тести Solana Program Library](https://github.com/solana-labs/solana-program-library/tree/master/libraries/math) +демонструють продуктивність деяких математичних операцій. Для запуску тесту +синхронізуйте репозиторій і виконайте: ```shell cargo test-sbf -- --nocapture --test-threads=1 ``` -Недавні результати показують, що операції із float споживають більше інструкцій порівняно з еквівалентами для цілих чисел. Реалізації з фіксованою точкою також будуть менш ресурсомісткими, ніж float: +Недавні результати показують, що операції із float споживають більше інструкцій +порівняно з еквівалентами для цілих чисел. Реалізації з фіксованою точкою також +будуть менш ресурсомісткими, ніж float: ```text u64 f32 @@ -72,7 +98,11 @@ Divide 9 219 ## Статичні змінні, які можна змінювати -Спільні об’єкти програм не підтримують змінювані спільні дані. Програми спільно використовують один і той самий код та дані лише для читання, що означає, що розробники не повинні включати статичні змінювані або глобальні змінні в програми. У майбутньому може бути додано механізм копіювання при записі для підтримки змінюваних даних. +Спільні об’єкти програм не підтримують змінювані спільні дані. Програми спільно +використовують один і той самий код та дані лише для читання, що означає, що +розробники не повинні включати статичні змінювані або глобальні змінні в +програми. У майбутньому може бути додано механізм копіювання при записі для +підтримки змінюваних даних. ## Ділення зі знаком diff --git a/docs/locales/uk/programs/rust/index.md b/docs/locales/uk/programs/rust/index.md index bfc459af9..16c3c79c3 100644 --- a/docs/locales/uk/programs/rust/index.md +++ b/docs/locales/uk/programs/rust/index.md @@ -1,28 +1,31 @@ --- title: Розробка програм на Rust description: - Дізнайтеся, як розробляти програми для Solana, використовуючи Rust, включаючи покрокові - інструкції для створення, збірки, тестування та розгортання смарт-контрактів на - блокчейні Solana. + Дізнайтеся, як розробляти програми для Solana, використовуючи Rust, включаючи + покрокові інструкції для створення, збірки, тестування та розгортання + смарт-контрактів на блокчейні Solana. sidebarLabel: Програми на Rust sidebarSortOrder: 1 altRoutes: - /docs/programs/lang-rust --- -Програми для Solana в основному розробляються за допомогою мови програмування Rust. -Ця сторінка зосереджена на написанні програм для Solana на Rust без використання фреймворку Anchor, -метод, який часто називають написанням "рідних програм на Rust". +Програми для Solana в основному розробляються за допомогою мови програмування +Rust. Ця сторінка зосереджена на написанні програм для Solana на Rust без +використання фреймворку Anchor, метод, який часто називають написанням "рідних +програм на Rust". Розробка рідних програм на Rust дає розробникам повний контроль над їхніми програмами для Solana. Однак цей підхід вимагає більше ручної налаштування та -шаблонного коду порівняно з використанням фреймворку Anchor. Цей метод рекомендований для розробників, які: +шаблонного коду порівняно з використанням фреймворку Anchor. Цей метод +рекомендований для розробників, які: - Шукають детальний контроль над логікою програми та оптимізаціями -- Хочуть зрозуміти основні концепції, перш ніж переходити до фреймворків вищого рівня +- Хочуть зрозуміти основні концепції, перш ніж переходити до фреймворків вищого + рівня -Для початківців ми рекомендуємо почати з фреймворку Anchor. Для отримання додаткової інформації див. розділ -[Anchor](/docs/programs/anchor). +Для початківців ми рекомендуємо почати з фреймворку Anchor. Для отримання +додаткової інформації див. розділ [Anchor](/docs/programs/anchor). ## Попередні вимоги @@ -36,37 +39,38 @@ altRoutes: ## Початок роботи -Наведений приклад охоплює основні кроки для створення вашої першої програми для Solana, -написаної на Rust. Ми створимо мінімальну програму, яка виводить "Hello, world!" в -журнали програми. +Наведений приклад охоплює основні кроки для створення вашої першої програми для +Solana, написаної на Rust. Ми створимо мінімальну програму, яка виводить "Hello, +world!" в журнали програми. ### Створення нової програми -Спочатку створіть новий проект на Rust, використовуючи стандартну команду `cargo init` з -прапорцем `--lib`. +Спочатку створіть новий проект на Rust, використовуючи стандартну команду +`cargo init` з прапорцем `--lib`. ```shell filename="Terminal" cargo init hello_world --lib ``` -Перейдіть до директорії проекту. Ви повинні побачити стандартні файли `src/lib.rs` та -`Cargo.toml`. +Перейдіть до директорії проекту. Ви повинні побачити стандартні файли +`src/lib.rs` та `Cargo.toml`. ```shell filename="Terminal" cd hello_world ``` -Далі додайте залежність `solana-program`. Це мінімальна залежність, -необхідна для побудови програми Solana. +Далі додайте залежність `solana-program`. Це мінімальна залежність, необхідна +для побудови програми Solana. ```shell filename="Terminal" cargo add solana-program@1.18.26 ``` Далі додайте наступний фрагмент до файлу `Cargo.toml`. Якщо ви не включите цю -конфігурацію, директорія `target/deploy` не буде згенерована під час збірки програми. +конфігурацію, директорія `target/deploy` не буде згенерована під час збірки +програми. ```toml filename="Cargo.toml" [lib] @@ -88,9 +92,12 @@ crate-type = ["cdylib", "lib"] solana-program = "1.18.26" ``` -Далі замініть вміст файлу `src/lib.rs` на наступний код. Це мінімальна програма для Solana, яка виводить "Hello, world!" в журнал програми, коли програма викликається. +Далі замініть вміст файлу `src/lib.rs` на наступний код. Це мінімальна програма +для Solana, яка виводить "Hello, world!" в журнал програми, коли програма +викликається. -Макрос `msg!` використовується в програмах Solana для виведення повідомлення в журнал програми. +Макрос `msg!` використовується в програмах Solana для виведення повідомлення в +журнал програми. ```rs filename="lib.rs" use solana_program::{ @@ -121,11 +128,11 @@ cargo build-sbf 1. Файл `.so` (наприклад, `hello_world.so`): Це зкомпільована програма Solana, яка буде розгорнута в мережі як "смарт-контракт". -2. Файл ключової пари (наприклад, `hello_world-keypair.json`): Публічний ключ цієї - ключової пари використовується як ID програми при розгортанні програми. +2. Файл ключової пари (наприклад, `hello_world-keypair.json`): Публічний ключ + цієї ключової пари використовується як ID програми при розгортанні програми. -Щоб переглянути ID програми, виконайте наступну команду у вашому терміналі. Ця команда -виводить публічний ключ ключової пари за вказаним шляхом до файлу: +Щоб переглянути ID програми, виконайте наступну команду у вашому терміналі. Ця +команда виводить публічний ключ ключової пари за вказаним шляхом до файлу: ```shell filename="Terminal" solana address -k ./target/deploy/hello_world-keypair.json @@ -139,8 +146,8 @@ Example output: ### Тестування програми -Далі протестуйте програму за допомогою crate `solana-program-test`. Додайте наступні -залежності до файлу `Cargo.toml`. +Далі протестуйте програму за допомогою crate `solana-program-test`. Додайте +наступні залежності до файлу `Cargo.toml`. ```shell filename="Terminal" cargo add solana-program-test@1.18.26 --dev @@ -181,8 +188,8 @@ mod test { } ``` -Запустіть тест за допомогою команди `cargo test-sbf`. У журналі програми буде виведено -"Hello, world!". +Запустіть тест за допомогою команди `cargo test-sbf`. У журналі програми буде +виведено "Hello, world!". ```shell filename="Terminal" cargo test-sbf @@ -223,8 +230,8 @@ Keypair Path: /.config/solana/id.json Commitment: confirmed ``` -Відкрийте новий термінал і виконайте команду `solana-test-validator`, щоб запустити -локальний валідатор. +Відкрийте новий термінал і виконайте команду `solana-test-validator`, щоб +запустити локальний валідатор. ```shell filename="Terminal" solana-test-validator @@ -247,8 +254,9 @@ Signature: Ви можете перевірити ID програми та підпис транзакції на [Solana Explorer](https://explorer.solana.com/?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899). -Зверніть увагу, що кластер на Solana Explorer також повинен бути localhost. Опція "Custom RPC -URL" на Solana Explorer за замовчуванням встановлюється на `http://localhost:8899`. +Зверніть увагу, що кластер на Solana Explorer також повинен бути localhost. +Опція "Custom RPC URL" на Solana Explorer за замовчуванням встановлюється на +`http://localhost:8899`. ### Виклик програми @@ -276,7 +284,8 @@ cargo add solana-client@1.18.26 --dev ``` Додайте наступний код до файлу `examples/client.rs`. Це Rust клієнтський скрипт, -який фінансує нову ключову пару для оплати зборів за транзакцію і потім викликає програму hello world. +який фінансує нову ключову пару для оплати зборів за транзакцію і потім викликає +програму hello world. ```rs filename="example/client.rs" use solana_client::rpc_client::RpcClient; @@ -334,7 +343,8 @@ async fn main() { } ``` -Перед виконанням скрипту замініть ID програми в наведеному коді на той, що відповідає вашій програмі. +Перед виконанням скрипту замініть ID програми в наведеному коді на той, що +відповідає вашій програмі. Ви можете отримати свій ID програми, виконавши наступну команду. @@ -369,8 +379,9 @@ Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77b ### Оновлення програми -Програми Solana можна оновити, повторно розгорнувши їх на той самий ID програми. Оновіть -програму в `src/lib.rs`, щоб виводити "Hello, Solana!" замість "Hello, world!". +Програми Solana можна оновити, повторно розгорнувши їх на той самий ID програми. +Оновіть програму в `src/lib.rs`, щоб виводити "Hello, Solana!" замість "Hello, +world!". ```diff filename="lib.rs" pub fn process_instruction( @@ -428,7 +439,8 @@ cargo run --example client Ви можете закрити свою програму Solana, щоб повернути SOL, виділені для акаунту. Закриття програми є незворотним, тому це слід робити обережно. -Щоб закрити програму, використовуйте команду `solana program close `. Наприклад: +Щоб закрити програму, використовуйте команду +`solana program close `. Наприклад: ```shell filename="Terminal" solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz @@ -442,21 +454,25 @@ Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOL reclaimed ``` -Зверніть увагу, що після закриття програми її ID програми не можна буде використовувати знову. Спроба розгорнути програму з раніше закритим ID програми призведе до помилки. +Зверніть увагу, що після закриття програми її ID програми не можна буде +використовувати знову. Спроба розгорнути програму з раніше закритим ID програми +призведе до помилки. ``` Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, use a new Program Id ``` -Якщо вам потрібно повторно розгорнути програму з тим самим вихідним кодом після закриття програми, ви повинні згенерувати новий ID програми. Щоб згенерувати нову ключову пару для програми, виконайте наступну команду: +Якщо вам потрібно повторно розгорнути програму з тим самим вихідним кодом після +закриття програми, ви повинні згенерувати новий ID програми. Щоб згенерувати +нову ключову пару для програми, виконайте наступну команду: ```shell filename="Terminal" solana-keygen new -o ./target/deploy/hello_world-keypair.json --force ``` Альтернативно, ви можете видалити існуючий файл ключової пари (наприклад, -`./target/deploy/hello_world-keypair.json`) і знову виконати команду `cargo build-sbf`, -що згенерує новий файл ключової пари. +`./target/deploy/hello_world-keypair.json`) і знову виконати команду +`cargo build-sbf`, що згенерує новий файл ключової пари. diff --git a/docs/locales/uk/programs/rust/program-structure.md b/docs/locales/uk/programs/rust/program-structure.md index 96955bdbf..e8d172094 100644 --- a/docs/locales/uk/programs/rust/program-structure.md +++ b/docs/locales/uk/programs/rust/program-structure.md @@ -2,14 +2,14 @@ title: Структура програми на Rust sidebarLabel: Структура програми description: - Дізнайтесь, як структуровані програми Solana на Rust, включаючи точки входу, управління станом, - обробку інструкцій та тестування. + Дізнайтесь, як структуровані програми Solana на Rust, включаючи точки входу, + управління станом, обробку інструкцій та тестування. sidebarSortOrder: 1 --- Програми Solana, написані на Rust, мають мінімальні вимоги до структури, що дає -гнучкість у тому, як організовувати код. Єдина вимога — програма повинна мати `entrypoint`, -який визначає точку початку виконання програми. +гнучкість у тому, як організовувати код. Єдина вимога — програма повинна мати +`entrypoint`, який визначає точку початку виконання програми. ## Структура програми @@ -28,14 +28,16 @@ sidebarSortOrder: 1 ## Приклад програми -Щоб продемонструвати, як побудувати рідну програму на Rust з кількома інструкціями, -ми розглянемо просту програму лічильника, яка реалізує дві інструкції: +Щоб продемонструвати, як побудувати рідну програму на Rust з кількома +інструкціями, ми розглянемо просту програму лічильника, яка реалізує дві +інструкції: -1. `InitializeCounter`: Створює і ініціалізує новий акаунт з початковим значенням. +1. `InitializeCounter`: Створює і ініціалізує новий акаунт з початковим + значенням. 2. `IncrementCounter`: Збільшує значення, що зберігається в існуючому акаунті. -Для простоти програма буде реалізована в одному файлі `lib.rs`, -хоча на практиці вам, можливо, захочеться розділити більші програми на кілька файлів. +Для простоти програма буде реалізована в одному файлі `lib.rs`, хоча на практиці +вам, можливо, захочеться розділити більші програми на кілька файлів. @@ -315,28 +317,30 @@ tokio = "1.41.0" ### Створення нової програми -Спочатку створіть новий проект на Rust, використовуючи стандартну команду `cargo init` з прапорцем `--lib`. +Спочатку створіть новий проект на Rust, використовуючи стандартну команду +`cargo init` з прапорцем `--lib`. ```shell filename="Terminal" cargo init counter_program --lib ``` -Перейдіть до директорії проекту. Ви повинні побачити стандартні файли `src/lib.rs` та -`Cargo.toml`. +Перейдіть до директорії проекту. Ви повинні побачити стандартні файли +`src/lib.rs` та `Cargo.toml`. ```shell filename="Terminal" cd counter_program ``` -Далі додайте залежність `solana-program`. Це мінімальна залежність, -необхідна для побудови програми Solana. +Далі додайте залежність `solana-program`. Це мінімальна залежність, необхідна +для побудови програми Solana. ```shell filename="Terminal" cargo add solana-program@1.18.26 ``` Далі додайте наступний фрагмент до файлу `Cargo.toml`. Якщо ви не включите цю -конфігурацію, директорія `target/deploy` не буде згенерована під час збірки програми. +конфігурацію, директорія `target/deploy` не буде згенерована під час збірки +програми. ```toml filename="Cargo.toml" [lib] @@ -361,8 +365,8 @@ solana-program = "1.18.26" ### Точка входу програми Точка входу програми Solana — це функція, яка викликається, коли програма -активується. Точка входу має наступне сире визначення, і розробники можуть створювати власну -реалізацію функції точки входу. +активується. Точка входу має наступне сире визначення, і розробники можуть +створювати власну реалізацію функції точки входу. Для простоти використовуйте макрос [`entrypoint!`](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L124-L140) @@ -422,24 +426,32 @@ pub type ProcessInstruction = - `program_id`: Публічний ключ викликаної програми (поточна програма) - `accounts`: `AccountInfo` для акаунтів, необхідних для викликаної інструкції -- `instruction_data`: Додаткові дані, передані програмі, які вказують інструкцію для виконання та її необхідні аргументи +- `instruction_data`: Додаткові дані, передані програмі, які вказують інструкцію + для виконання та її необхідні аргументи Ці три параметри безпосередньо відповідають даним, які клієнти повинні надати при побудові інструкції для виклику програми. ### Визначення стану програми -При створенні програми Solana зазвичай починають з визначення стану програми — даних, які будуть зберігатися в акаунтах, створених і належних вашій програмі. +При створенні програми Solana зазвичай починають з визначення стану програми — +даних, які будуть зберігатися в акаунтах, створених і належних вашій програмі. -Стан програми визначається за допомогою структур Rust, які представляють макет даних акаунтів програми. Ви можете визначити кілька структур для представлення різних типів акаунтів вашої програми. +Стан програми визначається за допомогою структур Rust, які представляють макет +даних акаунтів програми. Ви можете визначити кілька структур для представлення +різних типів акаунтів вашої програми. -При роботі з акаунтами вам потрібен спосіб перетворювати типи даних вашої програми в і з сирих байтів, що зберігаються в полі даних акаунту: +При роботі з акаунтами вам потрібен спосіб перетворювати типи даних вашої +програми в і з сирих байтів, що зберігаються в полі даних акаунту: -- Серіалізація: Перетворення ваших типів даних у байти для збереження в полі даних акаунту -- Десеріалізація: Перетворення байтів, збережених в акаунті, назад у ваші типи даних +- Серіалізація: Перетворення ваших типів даних у байти для збереження в полі + даних акаунту +- Десеріалізація: Перетворення байтів, збережених в акаунті, назад у ваші типи + даних -Хоча ви можете використовувати будь-який формат серіалізації для розробки програм Solana, -[Borsh](https://borsh.io/) є загальноприйнятим. Щоб використовувати Borsh у вашій програмі Solana: +Хоча ви можете використовувати будь-який формат серіалізації для розробки +програм Solana, [Borsh](https://borsh.io/) є загальноприйнятим. Щоб +використовувати Borsh у вашій програмі Solana: 1. Додайте crate `borsh` як залежність до вашого `Cargo.toml`: @@ -447,8 +459,8 @@ pub type ProcessInstruction = cargo add borsh ``` -2. Імпортуйте трейди Borsh і використовуйте макрос `derive`, щоб реалізувати трейди для - ваших структур: +2. Імпортуйте трейди Borsh і використовуйте макрос `derive`, щоб реалізувати + трейди для ваших структур: ```rust use borsh::{BorshSerialize, BorshDeserialize}; @@ -460,8 +472,9 @@ pub struct CounterAccount { } ``` -Додайте структуру `CounterAccount` до файлу `lib.rs` для визначення стану програми. Ця -структура буде використовуватися як в інструкції ініціалізації, так і в інструкції збільшення. +Додайте структуру `CounterAccount` до файлу `lib.rs` для визначення стану +програми. Ця структура буде використовуватися як в інструкції ініціалізації, так +і в інструкції збільшення. ```rs filename="lib.rs" {12} {25-29} use solana_program::{ @@ -496,7 +509,9 @@ pub struct CounterAccount { ### Визначення інструкцій -Інструкції позначають різні операції, які ваша програма Solana може виконувати. Вважайте їх публічними API вашої програми — вони визначають, які дії користувачі можуть виконувати при взаємодії з вашою програмою. +Інструкції позначають різні операції, які ваша програма Solana може виконувати. +Вважайте їх публічними API вашої програми — вони визначають, які дії користувачі +можуть виконувати при взаємодії з вашою програмою. Інструкції зазвичай визначаються за допомогою enum на Rust, де: @@ -515,12 +530,14 @@ pub enum CounterInstruction { } ``` -Коли клієнт викликає вашу програму, він повинен надати дані інструкції (як буфер байтів), де: +Коли клієнт викликає вашу програму, він повинен надати дані інструкції (як буфер +байтів), де: - Перший байт вказує, який варіант інструкції потрібно виконати (0, 1 і т.д.) - Решта байтів містить серіалізовані параметри інструкції (якщо це необхідно) -Для перетворення даних інструкції (байтів) у варіант enum зазвичай реалізують допоміжний метод. Цей метод: +Для перетворення даних інструкції (байтів) у варіант enum зазвичай реалізують +допоміжний метод. Цей метод: 1. Розділяє перший байт, щоб отримати варіант інструкції 2. Зіставляє варіант і парсить будь-які додаткові параметри з решти байтів @@ -553,7 +570,8 @@ impl CounterInstruction { } ``` -Додайте наступний код до файлу `lib.rs` для визначення інструкцій для програми лічильника. +Додайте наступний код до файлу `lib.rs` для визначення інструкцій для програми +лічильника. ```rs filename="lib.rs" {18-46} use borsh::{BorshDeserialize, BorshSerialize}; @@ -605,12 +623,14 @@ impl CounterInstruction { ### Обробники інструкцій -Обробники інструкцій — це функції, які містять бізнес-логіку для кожної інструкції. Зазвичай функції обробників називаються як -`process_`, але ви вільні вибрати будь-яку конвенцію найменувань. +Обробники інструкцій — це функції, які містять бізнес-логіку для кожної +інструкції. Зазвичай функції обробників називаються як +`process_`, але ви вільні вибрати будь-яку конвенцію +найменувань. -Додайте наступний код до файлу `lib.rs`. Цей код використовує enum `CounterInstruction` -та метод `unpack`, визначений на попередньому кроці, для маршрутизації вхідних інструкцій -до відповідних функцій обробників: +Додайте наступний код до файлу `lib.rs`. Цей код використовує enum +`CounterInstruction` та метод `unpack`, визначений на попередньому кроці, для +маршрутизації вхідних інструкцій до відповідних функцій обробників: ```rs filename="lib.rs" {8-17} {20-32} /process_initialize_counter/1 /process_increment_counter/1 entrypoint!(process_instruction); @@ -647,8 +667,8 @@ fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> P } ``` -Далі додайте реалізацію функції `process_initialize_counter`. Цей -обробник інструкції: +Далі додайте реалізацію функції `process_initialize_counter`. Цей обробник +інструкції: 1. Створює і виділяє місце для нового акаунту для збереження даних лічильника 2. Ініціалізує дані акаунту з `initial_value`, переданим в інструкцію @@ -663,13 +683,13 @@ fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> P 3. System Program, який ми викликаємо для створення нового акаунту Для визначення акаунтів, необхідних для інструкції, ми створюємо ітератор по -масиву `accounts` та використовуємо функцію `next_account_info`, щоб отримати кожен -акаунт. Кількість акаунтів, яку ви визначаєте, є кількістю акаунтів, необхідних для -інструкції. +масиву `accounts` та використовуємо функцію `next_account_info`, щоб отримати +кожен акаунт. Кількість акаунтів, яку ви визначаєте, є кількістю акаунтів, +необхідних для інструкції. Порядок акаунтів має значення — при побудові інструкції на стороні клієнта, -акаунти повинні надаватися в тому ж порядку, в якому вони визначені в -програмі, щоб інструкція виконалася успішно. +акаунти повинні надаватися в тому ж порядку, в якому вони визначені в програмі, +щоб інструкція виконалася успішно. Хоча змінні імена акаунтів не впливають на функціональність програми, рекомендується використовувати описові імена. @@ -692,9 +712,12 @@ fn process_initialize_counter( Перед створенням акаунту нам потрібно: -1. Вказати простір (у байтах), який потрібно виділити для поля даних акаунту. Оскільки ми зберігаємо значення типу u64 (`count`), нам потрібно 8 байтів. +1. Вказати простір (у байтах), який потрібно виділити для поля даних акаунту. + Оскільки ми зберігаємо значення типу u64 (`count`), нам потрібно 8 байтів. -2. Обчислити мінімальний баланс "ренту", необхідний для акаунту. На Solana акаунти повинні підтримувати мінімальний баланс лампортів (ренту), що залежить від кількості даних, що зберігаються в акаунті. +2. Обчислити мінімальний баланс "ренту", необхідний для акаунту. На Solana + акаунти повинні підтримувати мінімальний баланс лампортів (ренту), що + залежить від кількості даних, що зберігаються в акаунті. ```rs filename="lib.rs" {12-17} fn process_initialize_counter( @@ -722,22 +745,23 @@ fn process_initialize_counter( Після того, як простір визначено і рент обчислений, створіть акаунт, викликавши інструкцію `create_account` з System Program. -На Solana нові акаунти можуть бути створені тільки через System Program. При створенні -акаунту ми вказуємо кількість байтів для виділення та програму-власника -нового акаунту. System Program: +На Solana нові акаунти можуть бути створені тільки через System Program. При +створенні акаунту ми вказуємо кількість байтів для виділення та +програму-власника нового акаунту. System Program: 1. Створює новий акаунт 2. Виділяє вказаний простір для поля даних акаунту 3. Передає право власності на вказану програму -Цей перехід права власності важливий, оскільки тільки власник акаунту може змінювати -дані акаунту. У цьому випадку ми встановлюємо нашу програму як власника, що дозволить нам змінювати -дані акаунту для збереження значення лічильника. +Цей перехід права власності важливий, оскільки тільки власник акаунту може +змінювати дані акаунту. У цьому випадку ми встановлюємо нашу програму як +власника, що дозволить нам змінювати дані акаунту для збереження значення +лічильника. Щоб викликати System Program з інструкції нашої програми, ми робимо Cross Program Invocation (CPI) через функцію `invoke`. CPI дозволяє одній програмі -викликати інструкції інших програм — в цьому випадку інструкцію `create_account` з System Program. - +викликати інструкції інших програм — в цьому випадку інструкцію `create_account` +з System Program. ```rs filename="lib.rs" {19-33} fn process_initialize_counter( @@ -780,10 +804,11 @@ fn process_initialize_counter( Після того, як акаунт створено, ми ініціалізуємо дані акаунту за допомогою: -1. Створення нової структури `CounterAccount` з переданим значенням `initial_value`. +1. Створення нової структури `CounterAccount` з переданим значенням + `initial_value`. 2. Отримання змінної посилання на поле даних нового акаунту. -3. Серіалізації структури `CounterAccount` в поле даних акаунту, - що ефективно зберігає значення `initial_value` в акаунті. +3. Серіалізації структури `CounterAccount` в поле даних акаунту, що ефективно + зберігає значення `initial_value` в акаунті. ```rs filename="lib.rs" {35-44} /initial_value/ fn process_initialize_counter( @@ -893,22 +918,24 @@ fn process_initialize_counter( } ``` -Далі додайте реалізацію функції `process_increment_counter`. Ця -інструкція збільшує значення існуючого акаунту лічильника. +Далі додайте реалізацію функції `process_increment_counter`. Ця інструкція +збільшує значення існуючого акаунту лічильника. -Так само, як і в функції `process_initialize_counter`, ми починаємо з створення ітератора -по акаунтах. У цьому випадку ми очікуємо лише один акаунт, який є акаунтом, що має бути оновлений. +Так само, як і в функції `process_initialize_counter`, ми починаємо з створення +ітератора по акаунтах. У цьому випадку ми очікуємо лише один акаунт, який є +акаунтом, що має бути оновлений. -Зверніть увагу, що на практиці розробник повинен реалізувати різні перевірки безпеки для -валідності акаунтів, переданих до програми. Оскільки всі акаунти надаються викликачем інструкції, -немає гарантії, що надані акаунти — це саме ті акаунти, які програма очікує. Відсутність перевірок -валідності акаунтів є поширеним джерелом вразливостей програми. +Зверніть увагу, що на практиці розробник повинен реалізувати різні перевірки +безпеки для валідності акаунтів, переданих до програми. Оскільки всі акаунти +надаються викликачем інструкції, немає гарантії, що надані акаунти — це саме ті +акаунти, які програма очікує. Відсутність перевірок валідності акаунтів є +поширеним джерелом вразливостей програми. -Наведений приклад містить перевірку для того, щоб переконатися, що акаунт, на який ми посилаємось як -`counter_account`, належить виконуючій програмі. +Наведений приклад містить перевірку для того, щоб переконатися, що акаунт, на +який ми посилаємось як `counter_account`, належить виконуючій програмі. ```rs filename="lib.rs" {6-9} // Update an existing counter's value @@ -999,8 +1026,8 @@ fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> P ### Тестування інструкцій -Для тестування інструкцій програми додайте наступні залежності до -файлу `Cargo.toml`. +Для тестування інструкцій програми додайте наступні залежності до файлу +`Cargo.toml`. ```shell filename="Terminal" cargo add solana-program-test@1.18.26 --dev @@ -1008,9 +1035,9 @@ cargo add solana-sdk@1.18.26 --dev cargo add tokio --dev ``` -Далі додайте наступний тестовий модуль до файлу `lib.rs` і виконайте команду `cargo test-sbf` для -запуску тестів. За бажанням, використовуйте прапорець `--nocapture`, щоб побачити -виведені дані в результатах. +Далі додайте наступний тестовий модуль до файлу `lib.rs` і виконайте команду +`cargo test-sbf` для запуску тестів. За бажанням, використовуйте прапорець +`--nocapture`, щоб побачити виведені дані в результатах. ```shell filename="Термінал" cargo test-sbf -- --nocapture @@ -1040,9 +1067,9 @@ mod test { } ``` -Далі налаштуйте тест за допомогою `ProgramTest`. Потім створіть нову ключову пару, яку будемо використовувати як -адресу для акаунту лічильника, який ми ініціалізуємо, і визначте початкове значення, -яке встановимо для лічильника. +Далі налаштуйте тест за допомогою `ProgramTest`. Потім створіть нову ключову +пару, яку будемо використовувати як адресу для акаунту лічильника, який ми +ініціалізуємо, і визначте початкове значення, яке встановимо для лічильника. ```rs filename="lib.rs" #[cfg(test)] @@ -1091,7 +1118,8 @@ AccountMeta::new_readonly(account4_pubkey, true), // writable, signer Для тестування інструкції ініціалізації: -- Створіть дані інструкції з варіантом 0 (`InitializeCounter`) та початковим значенням +- Створіть дані інструкції з варіантом 0 (`InitializeCounter`) та початковим + значенням - Побудуйте інструкцію з ID програми, даними інструкції та необхідними акаунтами - Відправте транзакцію з інструкцією ініціалізації - Перевірте, що акаунт був створений з правильним початковим значенням @@ -1160,8 +1188,8 @@ AccountMeta::new_readonly(account4_pubkey, true), // writable, signer - Перевірте, що акаунт був збільшений до правильного значення Зверніть увагу, що дані інструкції для інструкції збільшення — це `[1]`, що -відповідає варіанту 1 (`IncrementCounter`). Оскільки інструкція збільшення не має додаткових -параметрів, дані — це просто варіант інструкції. +відповідає варіанту 1 (`IncrementCounter`). Оскільки інструкція збільшення не +має додаткових параметрів, дані — це просто варіант інструкції. ```rs filename="lib.rs" {55-82} #[tokio::test] diff --git a/docs/locales/uk/programs/testing.md b/docs/locales/uk/programs/testing.md index 663653121..2ec9784b0 100644 --- a/docs/locales/uk/programs/testing.md +++ b/docs/locales/uk/programs/testing.md @@ -1,48 +1,76 @@ --- title: "Тестування з NodeJS" -description: "Тестування нативних solana programs написаних Rust використовуючи NodeJS" +description: + "Тестування нативних solana programs написаних Rust використовуючи NodeJS" sidebarSortOrder: 5 --- ## Тестування з NodeJS -Коли ви розробляєте програми на Solana, важливо забезпечити їхню правильність і надійність. До цього часу розробники використовували `solana-test-validator` для тестування. Цей документ описує тестування вашої програми Solana за допомогою Node.js і бібліотеки `solana-bankrun`. +Коли ви розробляєте програми на Solana, важливо забезпечити їхню правильність і +надійність. До цього часу розробники використовували `solana-test-validator` для +тестування. Цей документ описує тестування вашої програми Solana за допомогою +Node.js і бібліотеки `solana-bankrun`. ## Огляд Є два способи тестування програм на Solana: -1. [solana-test-validator](https://docs.anza.xyz/cli/examples/test-validator): Локальний емулятор блокчейна Solana, який обробляє транзакції, що надсилаються на валідацію. -2. Різні фреймворки для тестування програм SBF (Solana Bytecode Format) на базі BanksClient: - - `Bankrun` — це фреймворк, що імітує роботу Solana bank, дозволяючи розробникам розгортати програми, взаємодіяти з ними та оцінювати їх поведінку у тестових умовах, що нагадують mainnet. - - Підтримуються фреймворки як [solana-program-test](https://docs.rs/solana-program-test) (Rust), [solana-bankrun](https://github.com/kevinheavey/solana-bankrun) (Rust, JavaScript), [anchor-bankrun](https://www.npmjs.com/package/anchor-bankrun) (Anchor, JavaScript), [solders.bankrun](https://kevinheavey.github.io/solders/api_reference/bankrun.html) (Python). +1. [solana-test-validator](https://docs.anza.xyz/cli/examples/test-validator): + Локальний емулятор блокчейна Solana, який обробляє транзакції, що + надсилаються на валідацію. +2. Різні фреймворки для тестування програм SBF (Solana Bytecode Format) на базі + BanksClient: + - `Bankrun` — це фреймворк, що імітує роботу Solana bank, дозволяючи + розробникам розгортати програми, взаємодіяти з ними та оцінювати їх + поведінку у тестових умовах, що нагадують mainnet. + - Підтримуються фреймворки як + [solana-program-test](https://docs.rs/solana-program-test) (Rust), + [solana-bankrun](https://github.com/kevinheavey/solana-bankrun) (Rust, + JavaScript), [anchor-bankrun](https://www.npmjs.com/package/anchor-bankrun) + (Anchor, JavaScript), + [solders.bankrun](https://kevinheavey.github.io/solders/api_reference/bankrun.html) + (Python). > [`pnpm create solana-program`](https://github.com/solana-program/create-solana-program) -> може допомогти створити клієнти для JS і Rust, включаючи тести. Anchor ще не підтримується. +> може +> допомогти створити клієнти для JS і Rust, включаючи тести. Anchor ще не +> підтримується. У цьому керівництві ми використовуємо `Solana Bankrun`. -`Bankrun` — це дуже швидкий, потужний та легкий фреймворк для тестування програм Solana у Node.js. +`Bankrun` — це дуже швидкий, потужний та легкий фреймворк для тестування програм +Solana у Node.js. -- Основна перевага використання `Solana Bankrun` полягає в тому, що вам не потрібно налаштовувати середовище для тестування програм, як це потрібно при використанні `solana-test-validator`. Це можна зробити за допомогою коду всередині тестів. -- `Bankrun` динамічно встановлює час та дані акаунтів, що неможливо при використанні `solana-test-validator`. +- Основна перевага використання `Solana Bankrun` полягає в тому, що вам не + потрібно налаштовувати середовище для тестування програм, як це потрібно при + використанні `solana-test-validator`. Це можна зробити за допомогою коду + всередині тестів. +- `Bankrun` динамічно встановлює час та дані акаунтів, що неможливо при + використанні `solana-test-validator`. ## Інсталяція -Додайте `solana-bankrun` як dev-залежність до вашого Node.js проекту. Якщо ваша Solana програма ще не є Node.js проектом, ви можете ініціалізувати її за допомогою команди `npm init`: +Додайте `solana-bankrun` як dev-залежність до вашого Node.js проекту. Якщо ваша +Solana програма ще не є Node.js проектом, ви можете ініціалізувати її за +допомогою команди `npm init`: ```bash npm i -D solana-bankrun ``` + ## Використання ### Директорія для Програми -Перш за все, `.so` файл вашої програми повинен бути присутнім в одній із наступних директорій: +Перш за все, `.so` файл вашої програми повинен бути присутнім в одній із +наступних директорій: - `./tests/fixtures` (створіть цю директорію, якщо її ще не існує). - Ваша поточна робоча директорія. -- Директорія, яку ви визначите в змінних середовища `BPF_OUT_DIR` або `SBF_OUT_DIR`. - Наприклад: +- Директорія, яку ви визначите в змінних середовища `BPF_OUT_DIR` або + `SBF_OUT_DIR`. + Наприклад: + ```json { "scripts": { @@ -50,9 +78,12 @@ npm i -D solana-bankrun } } ``` + ### Початок Роботи -Функція `start` з бібліотеки `solana-bankrun` запускає `BanksServer` і `BanksClient`, розгортає програми та додає акаунти відповідно до ваших інструкцій. +Функція `start` з бібліотеки `solana-bankrun` запускає `BanksServer` і +`BanksClient`, розгортає програми та додає акаунти відповідно до ваших +інструкцій. Приклад використання: @@ -69,12 +100,22 @@ test("testing program instruction", async () => { // write tests }); ``` + ### `context` у Bankrun -- Ми отримуємо доступ до `context` з функції `start`. `context` містить `BanksClient`, останній blockhash та профінансовану keypair для підпису транзакцій. -- У `context` є `payer`, який є профінансованою парою ключів і може використовуватися для підпису транзакцій. -- `context` також містить `context.lastBlockhash` або `context.getLatestBlockhash`, що спрощує отримання [Blockhash](https://solana.com/docs/terminology#blockhash) під час тестів. -- `context.banksClient` використовується для надсилання транзакцій і отримання даних акаунтів зі стану реєстру. Наприклад, іноді потрібна [оренда (Rent)](https://solana.com/docs/terminology#rent) (в лампортах) для створення транзакції, наприклад, при використанні інструкції `createAccount()` з `SystemProgram`. Це можна зробити за допомогою `BanksClient`: +- Ми отримуємо доступ до `context` з функції `start`. `context` містить + `BanksClient`, останній blockhash та профінансовану keypair для підпису + транзакцій. +- У `context` є `payer`, який є профінансованою парою ключів і може + використовуватися для підпису транзакцій. +- `context` також містить `context.lastBlockhash` або + `context.getLatestBlockhash`, що спрощує отримання + [Blockhash](https://solana.com/docs/terminology#blockhash) під час тестів. +- `context.banksClient` використовується для надсилання транзакцій і отримання + даних акаунтів зі стану реєстру. Наприклад, іноді потрібна + [оренда (Rent)](https://solana.com/docs/terminology#rent) (в лампортах) для + створення транзакції, наприклад, при використанні інструкції `createAccount()` + з `SystemProgram`. Це можна зробити за допомогою `BanksClient`: ```typescript const rent = await client.getRent(); @@ -85,7 +126,9 @@ test("testing program instruction", async () => { //.... }); ``` -- Ви можете зчитувати дані акаунта з `BanksClient`, використовуючи функцію `getAccount`. + +- Ви можете зчитувати дані акаунта з `BanksClient`, використовуючи функцію + `getAccount`. ```typescript AccountInfo = await client.getAccount(counter); @@ -93,17 +136,19 @@ test("testing program instruction", async () => { ### Обробка Транзакції -Функція `processTransaction()` виконує транзакцію з використанням завантажених програм і акаунтів, отриманих із функції `start`. Вона повертає результат виконаної транзакції. +Функція `processTransaction()` виконує транзакцію з використанням завантажених +програм і акаунтів, отриманих із функції `start`. Вона повертає результат +виконаної транзакції. ```typescript let transaction = await client.processTransaction(tx); ``` + ## Приклад Ось приклад тесту для програми [hello world](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/native): - ```typescript import { PublicKey, @@ -158,6 +203,7 @@ describe("hello-solana", async () => { }); }); ``` + Ось як виглядає результат після запуску тестів для [hello world програми](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/native): diff --git a/docs/locales/uk/rpc.md b/docs/locales/uk/rpc.md index e8e6582a6..d63508930 100644 --- a/docs/locales/uk/rpc.md +++ b/docs/locales/uk/rpc.md @@ -4,7 +4,7 @@ sidebarSortOrder: 1 isSkippedInNav: true --- -Цей файл не повинен редагуватися, оскільки він не призначений для відображення. Він існує лише для створення посилання в головній бічній панелі документації. +Цей файл не повинен редагуватися, оскільки він не призначений для відображення. +Він існує лише для створення посилання в головній бічній панелі документації. -Документація JSON RPC для Solana доступна в -[`rpc` каталозі](./rpc/) +Документація JSON RPC для Solana доступна в [`rpc` каталозі](./rpc/) diff --git a/docs/locales/uk/terminology.md b/docs/locales/uk/terminology.md index 39d74a750..5a06d576d 100644 --- a/docs/locales/uk/terminology.md +++ b/docs/locales/uk/terminology.md @@ -11,23 +11,28 @@ keywords: isSkippedInNav: true --- -Наведені нижче терміни використовуються в документації Solana та екосистемі розробки. +Наведені нижче терміни використовуються в документації Solana та екосистемі +розробки. ## Обліковий запис (account) Запис у реєстрі Solana, який або зберігає дані, або є виконуваною програмою. -Як і обліковий запис у традиційному банку, обліковий запис Solana може зберігати кошти, які називаються [лампортами](#lamport). Як файл у Linux, він адресується ключем, часто згадуваним як [публічний ключ](#public-key-pubkey) або pubkey. +Як і обліковий запис у традиційному банку, обліковий запис Solana може зберігати +кошти, які називаються [лампортами](#lamport). Як файл у Linux, він адресується +ключем, часто згадуваним як [публічний ключ](#public-key-pubkey) або pubkey. Ключ може бути одним із таких: - Публічний ключ ed25519 -- Адреса облікового запису, отримана програмно (32-байтне значення поза кривою ed25519) +- Адреса облікового запису, отримана програмно (32-байтне значення поза кривою + ed25519) - Хеш публічного ключа ed25519 із рядком із 32 символів ## Власник облікового запису (account owner) -Адреса програми, якій належить обліковий запис. Тільки програма-власник може змінювати обліковий запис. +Адреса програми, якій належить обліковий запис. Тільки програма-власник може +змінювати обліковий запис. Див. також [Повноваження](#authority). @@ -41,28 +46,39 @@ isSkippedInNav: true Наприклад: -- Можливість карбування нових токенів надається обліковому запису, який є "владою карбування" токена. -- Можливість оновлювати програму надається обліковому запису, який є "владою оновлення" програми. +- Можливість карбування нових токенів надається обліковому запису, який є + "владою карбування" токена. +- Можливість оновлювати програму надається обліковому запису, який є "владою + оновлення" програми. ## Стан банку (bank state) -Результат виконання всіх програм у реєстрі на певній [висоті тікання](#tick-height). Він включає щонайменше набір усіх [облікових записів](#account), які зберігають ненульові [нативні токени](#native-token). +Результат виконання всіх програм у реєстрі на певній +[висоті тікання](#tick-height). Він включає щонайменше набір усіх +[облікових записів](#account), які зберігають ненульові +[нативні токени](#native-token). ## Блок (block) -Неперервний набір [записів](#entry) у реєстрі, підтверджений [голосуванням](#ledger-vote). [Лідер](#leader) створює не більше одного блоку за [слот](#slot). +Неперервний набір [записів](#entry) у реєстрі, підтверджений +[голосуванням](#ledger-vote). [Лідер](#leader) створює не більше одного блоку за +[слот](#slot). ## Блокхеш (blockhash) -Унікальне значення ([хеш](#hash)), яке ідентифікує запис (блок). Solana обчислює блокхеш із останнього [ідентифікатора запису](#entry-id) блоку. +Унікальне значення ([хеш](#hash)), яке ідентифікує запис (блок). Solana обчислює +блокхеш із останнього [ідентифікатора запису](#entry-id) блоку. ## Висота блоку (block height) -Кількість [блоків](#block) під поточним блоком. Перший блок після [генезис-блоку](#genesis-block) має висоту один. +Кількість [блоків](#block) під поточним блоком. Перший блок після +[генезис-блоку](#genesis-block) має висоту один. ## Завантажувач BPF (BPF loader) -Програма Solana, яка завантажує [програми на основі BPF](/docs/uk/core/programs#berkeley-packet-filter-bpf) в [блокчейн](#onchain-program), дозволяючи їм взаємодіяти з середовищем виконання. +Програма Solana, яка завантажує +[програми на основі BPF](/docs/uk/core/programs#berkeley-packet-filter-bpf) в +[блокчейн](#onchain-program), дозволяючи їм взаємодіяти з середовищем виконання. ## Клієнт (client) @@ -78,7 +94,8 @@ isSkippedInNav: true ## Бюджет обчислень (compute budget) -Максимальна кількість [обчислювальних одиниць](#compute-units), спожитих за транзакцію. +Максимальна кількість [обчислювальних одиниць](#compute-units), спожитих за +транзакцію. ## Обчислювальні одиниці (compute units) @@ -86,11 +103,13 @@ isSkippedInNav: true ## Час підтвердження (confirmation time) -Час, який пройшов між створенням [тікового запису](#tick) [лідером](#leader) та створенням [підтвердженого блоку](#confirmed-block). +Час, який пройшов між створенням [тікового запису](#tick) [лідером](#leader) та +створенням [підтвердженого блоку](#confirmed-block). ## Підтверджений блок (confirmed block) -[Блок](#block), який отримав [супербільшість](#supermajority) [голосів реєстру](#ledger-vote). +[Блок](#block), який отримав [супербільшість](#supermajority) +[голосів реєстру](#ledger-vote). ## Площина керування (control plane) @@ -98,7 +117,9 @@ isSkippedInNav: true ## Період охолодження (cooldown period) -Декілька [епох](#epoch) після деактивації [ставки](#stake), протягом яких вона поступово стає доступною для зняття. Під час цього періоду ставка вважається "деактивованою". Докладніше: +Декілька [епох](#epoch) після деактивації [ставки](#stake), протягом яких вона +поступово стає доступною для зняття. Під час цього періоду ставка вважається +"деактивованою". Докладніше: [періоди прогріву та охолодження](https://docs.anza.xyz/implemented-proposals/staking-rewards#stake-warmup-cooldown-withdrawal). ## Кредит (credit) @@ -107,23 +128,28 @@ isSkippedInNav: true ## Виклик між програмами (CPI) -Виклик однієї [програми на блокчейні](#onchain-program) до іншої. Докладніше див. [Виклик між програмами](/docs/uk/core/cpi.md). +Виклик однієї [програми на блокчейні](#onchain-program) до іншої. Докладніше +див. [Виклик між програмами](/docs/uk/core/cpi.md). ## Площина даних (data plane) -Мультикаст-мережа, яка використовується для ефективної перевірки [записів](#entry) і досягнення консенсусу. +Мультикаст-мережа, яка використовується для ефективної перевірки +[записів](#entry) і досягнення консенсусу. ## Дрон (drone) -Зовнішній сервіс, який виступає в ролі хранителя приватного ключа користувача. Зазвичай використовується для перевірки та підпису транзакцій. +Зовнішній сервіс, який виступає в ролі хранителя приватного ключа користувача. +Зазвичай використовується для перевірки та підпису транзакцій. ## Запис (entry) -Запис у [реєстрі](#ledger), який може бути або [тіком](#tick), або [записом транзакції](#transactions-entry). +Запис у [реєстрі](#ledger), який може бути або [тіком](#tick), або +[записом транзакції](#transactions-entry). ## Ідентифікатор запису (entry id) -Хеш ([hash](#hash)), стійкий до попереднього зображення, який є унікальним ідентифікатором [запису](#entry). Хеш слугує доказом: +Хеш ([hash](#hash)), стійкий до попереднього зображення, який є унікальним +ідентифікатором [запису](#entry). Хеш слугує доказом: - Генерації запису після певного проміжку часу - Включення зазначених [транзакцій](#transaction) у запис @@ -133,19 +159,25 @@ isSkippedInNav: true ## Епоха (epoch) -Проміжок часу, визначений кількістю [слотів](#slot), протягом яких діє [розклад лідерів](#leader-schedule). +Проміжок часу, визначений кількістю [слотів](#slot), протягом яких діє +[розклад лідерів](#leader-schedule). ## Обліковий запис для комісій (fee account) -Обліковий запис у транзакції, який оплачує вартість включення транзакції до реєстру. Це перший обліковий запис у транзакції. Він має бути оголошений як читально-записуваний (writable), оскільки оплата транзакції зменшує баланс облікового запису. +Обліковий запис у транзакції, який оплачує вартість включення транзакції до +реєстру. Це перший обліковий запис у транзакції. Він має бути оголошений як +читально-записуваний (writable), оскільки оплата транзакції зменшує баланс +облікового запису. ## Фінальність (finality) -Стан, коли вузли, що представляють 2/3 [ставки](#stake), мають спільний [корінь](#root). +Стан, коли вузли, що представляють 2/3 [ставки](#stake), мають спільний +[корінь](#root). ## Форк (fork) -[Реєстр](#ledger), створений на основі загальних записів, але який розійшовся у своєму розвитку. +[Реєстр](#ledger), створений на основі загальних записів, але який розійшовся у +своєму розвитку. ## Генезис-блок (genesis block) @@ -153,7 +185,8 @@ isSkippedInNav: true ## Генезис-конфігурація (genesis config) -Файл конфігурації, який підготовлює [реєстр](#ledger) для [генезис-блоку](#genesis-block). +Файл конфігурації, який підготовлює [реєстр](#ledger) для +[генезис-блоку](#genesis-block). ## Хеш (hash) @@ -161,7 +194,8 @@ isSkippedInNav: true ## Інфляція (inflation) -Збільшення кількості токенів із часом, яке використовується для фінансування винагород за валідацію та подальшого розвитку Solana. +Збільшення кількості токенів із часом, яке використовується для фінансування +винагород за валідацію та подальшого розвитку Solana. ## Внутрішня інструкція (inner instruction) @@ -169,66 +203,96 @@ isSkippedInNav: true ## Інструкція (instruction) -Виклик для запуску конкретного [обробника інструкцій](#instruction-handler) у [програмі](#program). Інструкція також вказує, які облікові записи потрібно прочитати або змінити, та додаткові дані, які слугують допоміжним вхідним параметром для [обробника інструкцій](#instruction-handler). Кожна [транзакція](#transaction) має містити принаймні одну інструкцію. +Виклик для запуску конкретного [обробника інструкцій](#instruction-handler) у +[програмі](#program). Інструкція також вказує, які облікові записи потрібно +прочитати або змінити, та додаткові дані, які слугують допоміжним вхідним +параметром для [обробника інструкцій](#instruction-handler). Кожна +[транзакція](#transaction) має містити принаймні одну інструкцію. ## Обробник інструкцій (instruction handler) -Функції [програм](#program), які обробляють [інструкції](#instruction) із [транзакцій](#transaction). Обробник інструкцій може містити одну або кілька [викликів між програмами](#cross-program-invocation-cpi). +Функції [програм](#program), які обробляють [інструкції](#instruction) із +[транзакцій](#transaction). Обробник інструкцій може містити одну або кілька +[викликів між програмами](#cross-program-invocation-cpi). ## Пара ключів (keypair) -[Публічний ключ](#public-key-pubkey) і відповідний [приватний ключ](#private-key), які використовуються для доступу до облікового запису. +[Публічний ключ](#public-key-pubkey) і відповідний +[приватний ключ](#private-key), які використовуються для доступу до облікового +запису. ## Лампорти (lamport) -Дробова одиниця [нативного токена](#native-token) із вартістю 0.000000001 [SOL](#sol). +Дробова одиниця [нативного токена](#native-token) із вартістю 0.000000001 +[SOL](#sol). > У межах бюджету обчислень використовується кількість -> _[мікролампортів](https://github.com/solana-labs/solana/blob/ced8f6a512c61e0dd5308095ae8457add4a39e94/program-runtime/src/prioritization_fee.rs#L1-L2)_ для розрахунку [пріоритетної комісії](#prioritization-fee). +> _[мікролампортів](https://github.com/solana-labs/solana/blob/ced8f6a512c61e0dd5308095ae8457add4a39e94/program-runtime/src/prioritization_fee.rs#L1-L2)_ +> для розрахунку [пріоритетної комісії](#prioritization-fee). ## Лідер (leader) -Роль [валідатора](#validator), який додає [записи](#entry) до [реєстру](#ledger). +Роль [валідатора](#validator), який додає [записи](#entry) до +[реєстру](#ledger). ## Розклад лідерів (leader schedule) -Послідовність [публічних ключів](#public-key-pubkey) [валідаторів](#validator), пов’язаних із [слотами](#slot). Кластер використовує цей розклад, щоб визначити, який валідатор є [лідером](#leader) у певний момент часу. +Послідовність [публічних ключів](#public-key-pubkey) [валідаторів](#validator), +пов’язаних із [слотами](#slot). Кластер використовує цей розклад, щоб визначити, +який валідатор є [лідером](#leader) у певний момент часу. ## Реєстр (ledger) -Список [записів](#entry), що містять [транзакції](#transaction), підписані [клієнтами](#client). Концептуально це можна простежити до [генезис-блоку](#genesis-block), але реєстр конкретного [валідатора](#validator) може містити лише новіші [блоки](#block), щоб зменшити обсяг зберігання, оскільки старіші блоки не потрібні для перевірки майбутніх блоків за задумом. +Список [записів](#entry), що містять [транзакції](#transaction), підписані +[клієнтами](#client). Концептуально це можна простежити до +[генезис-блоку](#genesis-block), але реєстр конкретного [валідатора](#validator) +може містити лише новіші [блоки](#block), щоб зменшити обсяг зберігання, +оскільки старіші блоки не потрібні для перевірки майбутніх блоків за задумом. ## Голос у реєстрі (ledger vote) -[Хеш](#hash) стану [валідатора](#validator) на певній [висоті тікання](#tick-height). Він включає підтвердження валідатора, що [блок](#block), який він отримав, був перевірений, а також обіцянку не голосувати за конфліктуючий [блок](#block) (тобто [форк](#fork)) протягом певного часу, відомого як період [блокування](#lockout). +[Хеш](#hash) стану [валідатора](#validator) на певній +[висоті тікання](#tick-height). Він включає підтвердження валідатора, що +[блок](#block), який він отримав, був перевірений, а також обіцянку не +голосувати за конфліктуючий [блок](#block) (тобто [форк](#fork)) протягом +певного часу, відомого як період [блокування](#lockout). ## Легкий клієнт (light client) -Тип [клієнта](#client), який може перевірити, що він підключений до валідного [кластеру](#cluster). Він виконує більше перевірок реєстру, ніж [тонкий клієнт](#thin-client), але менше, ніж [валідатор](#validator). +Тип [клієнта](#client), який може перевірити, що він підключений до валідного +[кластеру](#cluster). Він виконує більше перевірок реєстру, ніж +[тонкий клієнт](#thin-client), але менше, ніж [валідатор](#validator). ## Завантажувач (loader) -[Програма](#program) із можливістю інтерпретувати двійкове кодування інших програм на блокчейні. +[Програма](#program) із можливістю інтерпретувати двійкове кодування інших +програм на блокчейні. ## Блокування (lockout) -Тривалість часу, протягом якої [валідатор](#validator) не може [голосувати](#ledger-vote) за інший [форк](#fork). +Тривалість часу, протягом якої [валідатор](#validator) не може +[голосувати](#ledger-vote) за інший [форк](#fork). ## Повідомлення (message) -Структурований вміст [транзакції](#transaction), зазвичай містить заголовок, масив адрес облікових записів, недавній [блокхеш](#blockhash) та масив [інструкцій](#instruction). +Структурований вміст [транзакції](#transaction), зазвичай містить заголовок, +масив адрес облікових записів, недавній [блокхеш](#blockhash) та масив +[інструкцій](#instruction). Докладніше про [форматування повідомлень у транзакціях](/docs/uk/core/transactions.md#message-header). ## Коефіцієнт Накамото (Nakamoto coefficient) -Міра децентралізації, яка визначає найменшу кількість незалежних суб’єктів, що можуть колективно зупинити блокчейн. Термін запропонований Балажі С. Срінівасаном і Леландом Лі у статті +Міра децентралізації, яка визначає найменшу кількість незалежних суб’єктів, що +можуть колективно зупинити блокчейн. Термін запропонований Балажі С. +Срінівасаном і Леландом Лі у статті [Quantifying Decentralization](https://news.earn.com/quantifying-decentralization-e39db233c28e). ## Нативний токен (native token) -[Токен](#token), що використовується для відстеження роботи [вузлів](#node) у кластері. +[Токен](#token), що використовується для відстеження роботи [вузлів](#node) у +кластері. ## Вузол (node) @@ -240,7 +304,10 @@ isSkippedInNav: true ## Програма на блокчейні (onchain program) -Виконуваний код у блокчейні Solana, який інтерпретує [інструкції](#instruction), надіслані в кожній [транзакції](#transaction), щоб читати та змінювати облікові записи, якими він управляє. Ці програми часто називають "[розумними контрактами](/docs/uk/core/programs.md)" на інших блокчейнах. +Виконуваний код у блокчейні Solana, який інтерпретує [інструкції](#instruction), +надіслані в кожній [транзакції](#transaction), щоб читати та змінювати облікові +записи, якими він управляє. Ці програми часто називають +"[розумними контрактами](/docs/uk/core/programs.md)" на інших блокчейнах. ## PoH (Proof of History) @@ -248,7 +315,10 @@ isSkippedInNav: true ## Окуляр (point) -Зважений [кредит](#credit) у системі винагород. У системі [винагород валідатора](https://docs.anza.xyz/consensus/stake-delegation-and-rewards) кількість очок, що належить [ставці](#stake), є добутком [голосових кредитів](#vote-credit) і кількості лампортів, що були поставлені. +Зважений [кредит](#credit) у системі винагород. У системі +[винагород валідатора](https://docs.anza.xyz/consensus/stake-delegation-and-rewards) +кількість очок, що належить [ставці](#stake), є добутком +[голосових кредитів](#vote-credit) і кількості лампортів, що були поставлені. ## Програма (program) @@ -256,7 +326,8 @@ isSkippedInNav: true ## Програмно отриманий обліковий запис (PDA) -Обліковий запис, підписуючою владою якого є програма, і тому він не контролюється приватним ключем, як інші облікові записи. +Обліковий запис, підписуючою владою якого є програма, і тому він не +контролюється приватним ключем, як інші облікові записи. ## Ідентифікатор програми (program id) @@ -264,15 +335,22 @@ isSkippedInNav: true ## Доказ історії (Proof of History, PoH) -Стек доказів, кожен із яких підтверджує, що певні дані існували до моменту створення доказу і що пройшов точний проміжок часу до попереднього доказу. Як і [перевірювана функція затримки (VDF)](#verifiable-delay-function-vdf), Proof of History може бути перевірений швидше, ніж його створення. +Стек доказів, кожен із яких підтверджує, що певні дані існували до моменту +створення доказу і що пройшов точний проміжок часу до попереднього доказу. Як і +[перевірювана функція затримки (VDF)](#verifiable-delay-function-vdf), Proof of +History може бути перевірений швидше, ніж його створення. ## Пріоритетна комісія (prioritization fee) -Додаткова комісія, яку користувач може вказати в інструкції бюджету обчислень, щоб пріоритизувати свої [транзакції](#transaction). +Додаткова комісія, яку користувач може вказати в інструкції бюджету обчислень, +щоб пріоритизувати свої [транзакції](#transaction). -Пріоритетна комісія розраховується шляхом множення запитаного максимуму обчислювальних одиниць на ціну обчислювальної одиниці (вказується в інтервалах 0.000001 лампорта за одиницю), округлену до найближчого лампорта. +Пріоритетна комісія розраховується шляхом множення запитаного максимуму +обчислювальних одиниць на ціну обчислювальної одиниці (вказується в інтервалах +0.000001 лампорта за одиницю), округлену до найближчого лампорта. -Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць, необхідних для виконання, щоб зменшити комісію. +Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць, +необхідних для виконання, щоб зменшити комісію. ## Публічний ключ (public key, pubkey) @@ -280,49 +358,80 @@ isSkippedInNav: true ## Оренда (rent) -Комісія, яку сплачують [облікові записи](#account) і [програми](#program) за зберігання даних у блокчейні. Якщо на рахунку недостатньо балансу для оплати оренди, він може бути видалений. +Комісія, яку сплачують [облікові записи](#account) і [програми](#program) за +зберігання даних у блокчейні. Якщо на рахунку недостатньо балансу для оплати +оренди, він може бути видалений. -Див. також [звільнення від оренди](#rent-exempt). Докладніше про оренду: [Що таке оренда?](/docs/uk/intro/rent.md). +Див. також [звільнення від оренди](#rent-exempt). Докладніше про оренду: +[Що таке оренда?](/docs/uk/intro/rent.md). ## Звільнення від оренди (rent exempt) -Облікові записи, які підтримують мінімальний баланс лампортів, пропорційний кількості даних, що зберігаються в обліковому записі. Усі нові облікові записи зберігаються на блокчейні постійно, доки обліковий запис не буде закрито. Неможливо створити обліковий запис, який не відповідає порогу звільнення від оренди. +Облікові записи, які підтримують мінімальний баланс лампортів, пропорційний +кількості даних, що зберігаються в обліковому записі. Усі нові облікові записи +зберігаються на блокчейні постійно, доки обліковий запис не буде закрито. +Неможливо створити обліковий запис, який не відповідає порогу звільнення від +оренди. ## Корінь (root) -[Блок](#block) або [слот](#slot), який досяг максимального [блокування](#lockout) у [валідатора](#validator). Корінь є найвищим блоком, який є предком усіх активних форків у валідатора. Усі предкові блоки кореня також транзитивно є коренями. Блоки, які не є предками чи нащадками кореня, виключаються з розгляду для консенсусу і можуть бути відкинуті. +[Блок](#block) або [слот](#slot), який досяг максимального +[блокування](#lockout) у [валідатора](#validator). Корінь є найвищим блоком, +який є предком усіх активних форків у валідатора. Усі предкові блоки кореня +також транзитивно є коренями. Блоки, які не є предками чи нащадками кореня, +виключаються з розгляду для консенсусу і можуть бути відкинуті. ## Середовище виконання (runtime) -Компонент [валідатора](#validator), відповідальний за виконання [програм](#program). +Компонент [валідатора](#validator), відповідальний за виконання +[програм](#program). ## Sealevel -Паралельне середовище виконання Solana для [програм на блокчейні](#onchain-program). +Паралельне середовище виконання Solana для +[програм на блокчейні](#onchain-program). ## Шред (shred) -Фрагмент [блоку](#block); найменша одиниця, яка передається між [валідаторами](#validator). +Фрагмент [блоку](#block); найменша одиниця, яка передається між +[валідаторами](#validator). ## Підпис (signature) -64-байтний підпис ed25519, що складається з R (32 байти) і S (32 байти). Цей підпис забезпечує відсутність можливості модифікації (мальованості). Кожна транзакція повинна мати щонайменше один підпис для [облікового запису комісій](#fee-account). Таким чином, перший підпис у транзакції може використовуватися як [ідентифікатор транзакції](#transaction-id). +64-байтний підпис ed25519, що складається з R (32 байти) і S (32 байти). Цей +підпис забезпечує відсутність можливості модифікації (мальованості). Кожна +транзакція повинна мати щонайменше один підпис для +[облікового запису комісій](#fee-account). Таким чином, перший підпис у +транзакції може використовуватися як +[ідентифікатор транзакції](#transaction-id). ## Рівень пропуску (skip rate) -Відсоток [пропущених слотів](#skipped-slot) від загальної кількості слотів лідера в поточній епосі. Ця метрика може бути оманливою через високу варіативність після межі епохи, коли вибірка невелика, а також для валідаторів із малою кількістю слотів лідера. Однак вона може бути корисною для виявлення неправильних конфігурацій вузлів. +Відсоток [пропущених слотів](#skipped-slot) від загальної кількості слотів +лідера в поточній епосі. Ця метрика може бути оманливою через високу +варіативність після межі епохи, коли вибірка невелика, а також для валідаторів +із малою кількістю слотів лідера. Однак вона може бути корисною для виявлення +неправильних конфігурацій вузлів. ## Пропущений слот (skipped slot) -Минулий [слот](#slot), у якому не було створено [блоку](#block), тому що лідер був офлайн або [форк](#fork), що містить цей слот, був залишений на користь кращого варіанту за консенсусом кластера. Пропущений слот не з’явиться як предок для блоків у наступних слотах, не збільшить [висоту блоку](#block-height) і не призведе до прострочення найстарішого `recent_blockhash`. +Минулий [слот](#slot), у якому не було створено [блоку](#block), тому що лідер +був офлайн або [форк](#fork), що містить цей слот, був залишений на користь +кращого варіанту за консенсусом кластера. Пропущений слот не з’явиться як предок +для блоків у наступних слотах, не збільшить [висоту блоку](#block-height) і не +призведе до прострочення найстарішого `recent_blockhash`. -Чи було пропущено слот, можна визначити лише тоді, коли він стає старішим за останній [корінний](#root) (а отже, не пропущений) слот. +Чи було пропущено слот, можна визначити лише тоді, коли він стає старішим за +останній [корінний](#root) (а отже, не пропущений) слот. ## Слот (slot) -Проміжок часу, протягом якого кожен [лідер](#leader) приймає транзакції та створює [блок](#block). +Проміжок часу, протягом якого кожен [лідер](#leader) приймає транзакції та +створює [блок](#block). -Колективно слоти створюють логічний годинник. Слоти упорядковані послідовно та не перекриваються, охоплюючи приблизно однакові інтервали реального часу відповідно до [PoH](#proof-of-history-poh). +Колективно слоти створюють логічний годинник. Слоти упорядковані послідовно та +не перекриваються, охоплюючи приблизно однакові інтервали реального часу +відповідно до [PoH](#proof-of-history-poh). ## Розумний контракт (smart contract) @@ -334,15 +443,18 @@ isSkippedInNav: true ## Бібліотека програм Solana (SPL) -[Бібліотека програм](https://spl.solana.com/) на Solana, таких як spl-token, що сприяють виконанню завдань, як-от створення та використання токенів. +[Бібліотека програм](https://spl.solana.com/) на Solana, таких як spl-token, що +сприяють виконанню завдань, як-от створення та використання токенів. ## Ставка (stake) -Токени, які можуть бути конфісковані [кластером](#cluster), якщо буде доведено зловмисну поведінку [валідатора](#validator). +Токени, які можуть бути конфісковані [кластером](#cluster), якщо буде доведено +зловмисну поведінку [валідатора](#validator). ## Якість обслуговування з урахуванням ставки (stake-weighted quality of service, SWQoS) -SWQoS дозволяє [надавати перевагу транзакціям, які надходять від валідаторів із поставленими токенами](https://solana.com/developers/guides/advanced/stake-weighted-qos). +SWQoS дозволяє +[надавати перевагу транзакціям, які надходять від валідаторів із поставленими токенами](https://solana.com/developers/guides/advanced/stake-weighted-qos). ## Супербільшість (supermajority) @@ -350,11 +462,16 @@ SWQoS дозволяє [надавати перевагу транзакціям ## Системна змінна (sysvar) -Системний [обліковий запис](#account). [Системні змінні (Sysvars)](https://docs.anza.xyz/runtime/sysvars) надають інформацію про стан кластера, наприклад поточну висоту тіку, значення винагород [очок](#point) тощо. Програми можуть отримати доступ до системних змінних через обліковий запис Sysvar (публічний ключ) або запитати через системний виклик. +Системний [обліковий запис](#account). +[Системні змінні (Sysvars)](https://docs.anza.xyz/runtime/sysvars) надають +інформацію про стан кластера, наприклад поточну висоту тіку, значення винагород +[очок](#point) тощо. Програми можуть отримати доступ до системних змінних через +обліковий запис Sysvar (публічний ключ) або запитати через системний виклик. ## Тонкий клієнт (thin client) -Тип [клієнта](#client), який довіряє, що він підключений до дійсного [кластеру](#cluster). +Тип [клієнта](#client), який довіряє, що він підключений до дійсного +[кластеру](#cluster). ## Тік (tick) @@ -370,15 +487,21 @@ N-тий [тік](#tick) у [реєстрі](#ledger). ## Програма розширення токенів (Token Extensions Program) -[Програма розширення токенів](https://spl.solana.com/token-2022) має ідентифікатор `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` і включає всі ті самі функції, що й [Програма токенів](#token-program), але додає розширення, як-от конфіденційні перекази, кастомна логіка переказу, розширені метадані тощо. +[Програма розширення токенів](https://spl.solana.com/token-2022) має +ідентифікатор `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` і включає всі ті +самі функції, що й [Програма токенів](#token-program), але додає розширення, +як-от конфіденційні перекази, кастомна логіка переказу, розширені метадані тощо. ## Карбування токенів (token mint) -Обліковий запис, який може створювати токени. Різні токени відрізняються за унікальними адресами карбування токенів. +Обліковий запис, який може створювати токени. Різні токени відрізняються за +унікальними адресами карбування токенів. ## Програма токенів (Token Program) -[Програма токенів](https://spl.solana.com/token) має ідентифікатор `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` і надає базові можливості передачі, заморожування та карбування токенів. +[Програма токенів](https://spl.solana.com/token) має ідентифікатор +`TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` і надає базові можливості +передачі, заморожування та карбування токенів. ## TPS @@ -390,15 +513,21 @@ N-тий [тік](#tick) у [реєстрі](#ledger). ## Транзакція (transaction) -Одна або кілька [інструкцій](#instruction), підписаних [клієнтом](#client) за допомогою однієї або кількох [пар ключів](#keypair), виконуються атомарно з двома можливими результатами: успіх або невдача. +Одна або кілька [інструкцій](#instruction), підписаних [клієнтом](#client) за +допомогою однієї або кількох [пар ключів](#keypair), виконуються атомарно з +двома можливими результатами: успіх або невдача. ## Ідентифікатор транзакції (transaction id) -Перший [підпис](#signature) у [транзакції](#transaction), який можна використовувати для унікальної ідентифікації транзакції у повному [реєстрі](#ledger). +Перший [підпис](#signature) у [транзакції](#transaction), який можна +використовувати для унікальної ідентифікації транзакції у повному +[реєстрі](#ledger). ## Підтвердження транзакції (transaction confirmations) -Кількість [підтверджених блоків](#confirmed-block) з моменту прийняття транзакції до [реєстру](#ledger). Транзакція завершується, коли її блок стає [коренем](#root). +Кількість [підтверджених блоків](#confirmed-block) з моменту прийняття +транзакції до [реєстру](#ledger). Транзакція завершується, коли її блок стає +[коренем](#root). ## Запис транзакцій (transactions entry) @@ -410,7 +539,8 @@ N-тий [тік](#tick) у [реєстрі](#ledger). ## Валідатор (validator) -Повноцінний учасник мережі Solana, який створює нові [блоки](#block). Валідатор перевіряє транзакції, додані до [реєстру](#ledger). +Повноцінний учасник мережі Solana, який створює нові [блоки](#block). Валідатор +перевіряє транзакції, додані до [реєстру](#ledger). ## VDF @@ -418,7 +548,9 @@ N-тий [тік](#tick) у [реєстрі](#ledger). ## Перевірювана функція затримки (VDF) -Функція, яка займає фіксований проміжок часу для виконання та генерує доказ, що вона виконалася. Цей доказ можна перевірити швидше, ніж час, необхідний для його створення. +Функція, яка займає фіксований проміжок часу для виконання та генерує доказ, що +вона виконалася. Цей доказ можна перевірити швидше, ніж час, необхідний для його +створення. ## Голос (vote) @@ -426,13 +558,18 @@ N-тий [тік](#tick) у [реєстрі](#ledger). ## Кредит голосування (vote credit) -Нарахування винагороди для [валідаторів](#validator). Кредит голосування присуджується валідатору на його рахунок голосування, коли він досягає [кореня](#root). +Нарахування винагороди для [валідаторів](#validator). Кредит голосування +присуджується валідатору на його рахунок голосування, коли він досягає +[кореня](#root). ## Гаманець (wallet) -Набір [пар ключів](#keypair), який дозволяє користувачам керувати своїми коштами. +Набір [пар ключів](#keypair), який дозволяє користувачам керувати своїми +коштами. ## Період прогріву (warmup period) -Декілька [епох](#epoch) після делегування [ставки](#stake), протягом яких вона поступово стає активною. Під час цього періоду ставка вважається "активованою". Докладніше: +Декілька [епох](#epoch) після делегування [ставки](#stake), протягом яких вона +поступово стає активною. Під час цього періоду ставка вважається "активованою". +Докладніше: [періоди прогріву та охолодження](https://docs.anza.xyz/consensus/stake-delegation-and-rewards#stake-warmup-cooldown-withdrawal). From 2f631148bd0a28f699609a25a4599ca0ce95a2ea Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Wed, 15 Jan 2025 21:15:10 +0200 Subject: [PATCH 13/14] prettier fixes --- docs/locales/uk/advanced/actions.md | 626 ++++++++++++------ docs/locales/uk/advanced/confirmation.md | 337 +++++++--- docs/locales/uk/advanced/lookup-tables.md | 91 ++- docs/locales/uk/advanced/retry.md | 115 +++- docs/locales/uk/advanced/state-compression.md | 166 +++-- docs/locales/uk/advanced/versions.md | 54 +- .../uk/clients/javascript-reference.md | 130 +++- docs/locales/uk/clients/javascript.md | 117 +++- docs/locales/uk/clients/rust.md | 24 +- docs/locales/uk/core/accounts.md | 160 +++-- docs/locales/uk/core/clusters.md | 45 +- docs/locales/uk/core/cpi.md | 39 +- docs/locales/uk/core/fees.md | 411 +++++++++--- docs/locales/uk/core/index.md | 84 ++- docs/locales/uk/core/pda.md | 125 ++-- docs/locales/uk/core/programs.md | 104 +-- docs/locales/uk/core/tokens.md | 308 +++++---- docs/locales/uk/core/transactions.md | 193 ++++-- docs/locales/uk/economics/index.md | 43 +- .../inflation/_adjusted_staking_yield.md | 45 +- .../economics/inflation/inflation-schedule.md | 69 +- .../uk/economics/inflation/terminology.md | 76 ++- docs/locales/uk/economics/staking/index.md | 103 +-- .../uk/economics/staking/stake-accounts.md | 57 +- .../uk/economics/staking/stake-programming.md | 24 +- docs/locales/uk/index.md | 88 ++- docs/locales/uk/intro/dev.md | 150 +++-- docs/locales/uk/intro/installation.md | 201 ++++-- .../quick-start/cross-program-invocation.md | 153 +++-- .../intro/quick-start/deploying-programs.md | 115 ++-- docs/locales/uk/intro/quick-start/index.md | 61 +- .../quick-start/program-derived-address.md | 227 ++++--- .../intro/quick-start/reading-from-network.md | 153 +++-- .../intro/quick-start/writing-to-network.md | 59 +- docs/locales/uk/intro/wallets.md | 53 +- docs/locales/uk/more/exchange.md | 586 ++++++++++++---- .../uk/programs/anchor/client-typescript.md | 112 ++-- docs/locales/uk/programs/anchor/cpi.md | 149 +++-- docs/locales/uk/programs/anchor/idl.md | 82 ++- docs/locales/uk/programs/anchor/index.md | 104 +-- docs/locales/uk/programs/anchor/pda.md | 88 ++- .../uk/programs/anchor/program-structure.md | 94 ++- docs/locales/uk/programs/deploying.md | 188 +++--- docs/locales/uk/programs/examples.md | 146 ++-- docs/locales/uk/programs/faq.md | 157 +++-- docs/locales/uk/programs/limitations.md | 62 +- docs/locales/uk/programs/rust/index.md | 102 +-- .../uk/programs/rust/program-structure.md | 186 +++--- docs/locales/uk/programs/testing.md | 87 ++- docs/locales/uk/rpc.md | 6 +- docs/locales/uk/terminology.md | 291 +++++--- 51 files changed, 4873 insertions(+), 2373 deletions(-) diff --git a/docs/locales/uk/advanced/actions.md b/docs/locales/uk/advanced/actions.md index 0debc4c69..22a93fa1f 100644 --- a/docs/locales/uk/advanced/actions.md +++ b/docs/locales/uk/advanced/actions.md @@ -4,8 +4,8 @@ title: "Дії та Блінки" seoTitle: "Дії та Блінки" description: "Дії Solana — це API, які повертають транзакції для попереднього перегляду і - підпису користувачами. Посилання на блокчейн — або блінки — перетворюють дії - в зручні, багаті на метадані посилання для спільного використання." + підпису користувачами. Посилання на блокчейн — або блінки — перетворюють дії в + зручні, багаті на метадані посилання для спільного використання." altRoutes: - /docs/actions - /docs/blinks @@ -16,16 +16,16 @@ altRoutes: транзакції в блокчейні Solana для попереднього перегляду, підпису та відправки. Вони можуть використовуватися в різних контекстах, таких як QR-коди, кнопки, віджети та вебсайти. Дії дозволяють розробникам легко інтегрувати функціонал -екосистеми Solana у свій додаток, дозволяючи виконувати блокчейн-транзакції -без необхідності переходу на інші сторінки або додатки. +екосистеми Solana у свій додаток, дозволяючи виконувати блокчейн-транзакції без +необхідності переходу на інші сторінки або додатки. [Посилання на блокчейн](#blinks) — або блінки — перетворюють будь-яку дію Solana в зручне посилання, багате метаданими. Блінки дозволяють клієнтам, які підтримують їх, (таким як гаманці або боти) відображати додаткові функціональні можливості. Наприклад, на вебсайті блінк може негайно відкрити попередній перегляд транзакції у гаманці, а в Discord бот може перетворити блінк на -інтерактивні кнопки. Це забезпечує взаємодію з блокчейном на будь-якій платформі, -що підтримує URL. +інтерактивні кнопки. Це забезпечує взаємодію з блокчейном на будь-якій +платформі, що підтримує URL. ## Початок роботи @@ -35,15 +35,16 @@ altRoutes: npm install @solana/actions ``` -- встановіть [Solana Actions SDK](https://www.npmjs.com/package/@solana/actions) у вашому додатку +- встановіть [Solana Actions SDK](https://www.npmjs.com/package/@solana/actions) + у вашому додатку - створіть API-ендпойнт для [GET-запиту](#get-request), який повертає метадані про вашу дію - створіть API-ендпойнт для [POST-запиту](#post-request), який повертає транзакцію для підпису користувачем > Перегляньте цей відеоурок про -> [створення дії Solana](https://www.youtube.com/watch?v=kCht01Ycif0) за допомогою -> `@solana/actions` SDK. +> [створення дії Solana](https://www.youtube.com/watch?v=kCht01Ycif0) за +> допомогою `@solana/actions` SDK. > > Ви також можете знайти > [вихідний код дії](https://github.com/solana-developers/solana-actions/blob/main/examples/next-js/src/app/api/actions/transfer-sol/route.ts), @@ -68,22 +69,21 @@ npm install @solana/actions ## Дії Специфікація дій Solana використовує набір стандартних API для передачі -транзакцій (та, зрештою, повідомлень) для підпису безпосередньо користувачам. -Ці API доступні за публічними URL, які можуть взаємодіяти з будь-якими клієнтами. +транзакцій (та, зрештою, повідомлень) для підпису безпосередньо користувачам. Ці +API доступні за публічними URL, які можуть взаємодіяти з будь-якими клієнтами. -> Дії можна уявити як API-ендпойнт, який повертає метадані та об'єкт для -> підпису користувачем (транзакцію або повідомлення для аутентифікації) за -> допомогою їх блокчейн-гаманця. +> Дії можна уявити як API-ендпойнт, який повертає метадані та об'єкт для підпису +> користувачем (транзакцію або повідомлення для аутентифікації) за допомогою їх +> блокчейн-гаманця. API дій складається з простих `GET` і `POST` запитів до URL-ендпойнтів дій та обробки відповідей, які відповідають інтерфейсу дій. -1. [GET-запит](#get-request) повертає метадані, які надають клієнту - інформацію про доступні дії за цим URL, а також список пов’язаних дій (за - бажанням). -2. [POST-запит](#post-request) повертає транзакцію або повідомлення для - підпису, які клієнт відображає в гаманці користувача для підпису та виконання - у блокчейні або іншому офчейн-сервісі. +1. [GET-запит](#get-request) повертає метадані, які надають клієнту інформацію + про доступні дії за цим URL, а також список пов’язаних дій (за бажанням). +2. [POST-запит](#post-request) повертає транзакцію або повідомлення для підпису, + які клієнт відображає в гаманці користувача для підпису та виконання у + блокчейні або іншому офчейн-сервісі. ### Виконання дії та життєвий цикл @@ -116,16 +116,16 @@ API дій складається з простих `GET` і `POST` запиті ## Блінки -Блінки (посилання на блокчейн) — це клієнтські програми, які аналізують API -дій і створюють інтерфейси користувача для взаємодії з діями та їх виконання. +Блінки (посилання на блокчейн) — це клієнтські програми, які аналізують API дій +і створюють інтерфейси користувача для взаємодії з діями та їх виконання. Клієнтські програми, що підтримують блінки, виявляють URL, сумісні з діями, аналізують їх і дозволяють користувачам взаємодіяти з ними у стандартизованих інтерфейсах. > Будь-яка клієнтська програма, яка повністю аналізує API дій для створення -> повноцінного інтерфейсу, є _блінком_. Отже, не всі клієнти, які -> використовують API дій, є блінками. +> повноцінного інтерфейсу, є _блінком_. Отже, не всі клієнти, які використовують +> API дій, є блінками. ### Специфікація URL блінків @@ -141,7 +141,8 @@ https://example.domain/?action= - URL блінка повинен містити параметр запиту `action`, значення якого має бути [URL-кодованим](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) - [URL дії](#url-scheme). Це значення має бути закодоване, щоб уникнути конфліктів з іншими параметрами протоколу. + [URL дії](#url-scheme). Це значення має бути закодоване, щоб уникнути + конфліктів з іншими параметрами протоколу. - Клієнтська програма повинна [декодувати URL](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent) @@ -149,8 +150,9 @@ https://example.domain/?action= [Схему URL дії](#url-scheme)). - Клієнт повинен відобразити багатий інтерфейс користувача, який дозволяє - завершити повний [життєвий цикл виконання дії](#action-execution-and-lifecycle), - включаючи підписання у гаманці. + завершити повний + [життєвий цикл виконання дії](#action-execution-and-lifecycle), включаючи + підписання у гаманці. > Не всі клієнтські програми-блінки (наприклад, вебсайти або децентралізовані > додатки) підтримуватимуть усі дії. Розробники додатків можуть обирати, які дії @@ -167,8 +169,7 @@ https://example.domain/?action=solana-action%3Ahttps%3A%2F%2Factions.alice.com%2 Блінки можуть бути пов’язані з діями щонайменше трьома способами: -1. Поширення явного URL дії: - `solana-action:https://actions.alice.com/donate` +1. Поширення явного URL дії: `solana-action:https://actions.alice.com/donate` У цьому випадку лише клієнти, які підтримують блінки, можуть відобразити блінк. Не буде доступного попереднього перегляду посилання або сайту, який @@ -178,9 +179,9 @@ https://example.domain/?action=solana-action%3Ahttps%3A%2F%2Factions.alice.com%2 [`actions.json`](#actionsjson) у кореневій директорії домену вебсайту. Наприклад, `https://alice.com/actions.json` зіставляє - `https://alice.com/donate`, URL вебсайту, на якому користувачі можуть - зробити пожертву для Alice, з API URL `https://actions.alice.com/donate`, на - якому хостяться дії для пожертвування Alice. + `https://alice.com/donate`, URL вебсайту, на якому користувачі можуть зробити + пожертву для Alice, з API URL `https://actions.alice.com/donate`, на якому + хостяться дії для пожертвування Alice. 3. Вбудовування URL дії у "перехідний" URL сайту, який розуміє, як аналізувати дії. @@ -211,8 +212,8 @@ https://example.domain/?action=solana-action%3Ahttps%3A%2F%2Factions.alice.com%2 > всі введення для кожної з ваших пов'язаних дій. Кожен клієнтський додаток або гаманець може мати різні вимоги щодо того, які -ендпойнти дій будуть автоматично розгортатися й негайно відображатися користувачам -на платформах соціальних мереж. +ендпойнти дій будуть автоматично розгортатися й негайно відображатися +користувачам на платформах соціальних мереж. Наприклад, деякі клієнти можуть працювати за підходом "список дозволених" і вимагати верифікації перед розгортанням дії для користувачів, як це робить @@ -223,16 +224,16 @@ https://example.domain/?action=solana-action%3Ahttps%3A%2F%2Factions.alice.com%2 ### Реєстр дій Dialect -Як загальне благо для екосистеми Solana, [Dialect](https://dialect.to) -підтримує публічний реєстр — разом із допомогою Solana Foundation та інших -членів спільноти — для посилань на блокчейн, які попередньо перевірені й -походять із відомих джерел. На момент запуску лише дії, зареєстровані в реєстрі -Dialect, будуть автоматично розгортатися у Twitter, коли їх публікують. +Як загальне благо для екосистеми Solana, [Dialect](https://dialect.to) підтримує +публічний реєстр — разом із допомогою Solana Foundation та інших членів +спільноти — для посилань на блокчейн, які попередньо перевірені й походять із +відомих джерел. На момент запуску лише дії, зареєстровані в реєстрі Dialect, +будуть автоматично розгортатися у Twitter, коли їх публікують. Клієнтські програми та гаманці можуть вільно використовувати цей публічний -реєстр або інші рішення, щоб забезпечити безпеку користувачів. Якщо посилання -на блокчейн не верифіковане через реєстр Dialect, воно не оброблятиметься -клієнтом блінків і буде відображатися як звичайне URL. +реєстр або інші рішення, щоб забезпечити безпеку користувачів. Якщо посилання на +блокчейн не верифіковане через реєстр Dialect, воно не оброблятиметься клієнтом +блінків і буде відображатися як звичайне URL. Розробники можуть подати заявку на верифікацію у Dialect тут: [dial.to/register](https://dial.to/register) @@ -243,16 +244,17 @@ Dialect, будуть автоматично розгортатися у Twitter процесу взаємодії запит/відповідь: - Схема URL [Solana Action](#url-scheme), яка надає URL дії -- [OPTIONS-відповідь](#options-response) на URL дії для відповідності вимогам CORS +- [OPTIONS-відповідь](#options-response) на URL дії для відповідності вимогам + CORS - [GET-запит](#get-request) до URL дії - [GET-відповідь](#get-response) із сервера - [POST-запит](#post-request) до URL дії - [POST-відповідь](#post-response) із сервера -Кожен із цих запитів надсилається _клієнтом дій_ (наприклад, гаманець, розширення -для браузера, децентралізований додаток, вебсайт тощо) для збору специфічних -метаданих для багатого інтерфейсу користувача та забезпечення вводу користувачем -до API дій. +Кожен із цих запитів надсилається _клієнтом дій_ (наприклад, гаманець, +розширення для браузера, децентралізований додаток, вебсайт тощо) для збору +специфічних метаданих для багатого інтерфейсу користувача та забезпечення вводу +користувачем до API дій. Кожна з відповідей створюється додатком (наприклад, вебсайтом, серверним додатком тощо) і повертається _клієнту дій_. Зрештою, це забезпечує транзакцію @@ -263,7 +265,8 @@ Dialect, будуть автоматично розгортатися у Twitter > полегшення читання. > > Для кращої безпеки типів і покращеного досвіду розробників пакет -> `@solana/actions-spec` містить більш складні визначення типів. Ви можете знайти +> `@solana/actions-spec` містить більш складні визначення типів. Ви можете +> знайти > [вихідний код тут](https://github.com/solana-developers/solana-actions/blob/main/packages/actions-spec/index.d.ts). ### Схема URL @@ -299,8 +302,8 @@ solana-action: ### OPTIONS-відповідь Для забезпечення крос-доменного доступу (CORS) у клієнтах дій (включаючи -блінки), усі ендпойнти дій повинні відповідати на HTTP-запити методу `OPTIONS` -з дійсними заголовками, які дозволять клієнтам проходити CORS-перевірки для всіх +блінки), усі ендпойнти дій повинні відповідати на HTTP-запити методу `OPTIONS` з +дійсними заголовками, які дозволять клієнтам проходити CORS-перевірки для всіх подальших запитів із їхнього домену. Клієнт дій може виконувати @@ -347,7 +350,8 @@ HTTP `GET` JSON-запит до URL-ендпойнта дії. ### GET-відповідь URL-ендпойнт дії (наприклад, додаток або серверний бекенд) повинен відповідати -HTTP `OK` JSON-відповіддю (з дійсним вмістом у тілі) або відповідною помилкою HTTP. +HTTP `OK` JSON-відповіддю (з дійсним вмістом у тілі) або відповідною помилкою +HTTP. - Клієнт повинен обробляти HTTP [помилки клієнта](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses), @@ -401,28 +405,56 @@ export interface Action { } ``` -- `type` - Тип дії, що надається користувачеві. За замовчуванням встановлено значення `action`. Початковий `ActionGetResponse` повинен мати тип `action`. - - - `action` - Стандартна дія, яка дозволяє користувачеві взаємодіяти з будь-якими `LinkedActions`. - - `completed` - Використовується для позначення стану "завершено" у ланцюжку дій. - -- `icon` - Значення має бути абсолютним HTTP або HTTPS URL іконки. Файл повинен бути формату SVG, PNG або WebP, інакше клієнт/гаманець повинен відхилити його як **пошкоджений**. - -- `title` - Значення має бути рядком UTF-8, що представляє джерело запиту дії. Наприклад, це може бути назва бренду, магазину, програми або особи, яка робить запит. - -- `description` - Значення має бути рядком UTF-8, що надає інформацію про дію. Опис повинен бути відображений користувачеві. - -- `label` - Значення має бути рядком UTF-8, який буде відображено на кнопці для натискання користувачем. Усі мітки не повинні перевищувати 5 слів і повинні починатися з дієслова, щоб закріпити дію, яку ви хочете, щоб користувач виконав. Наприклад, "Mint NFT", "Vote Yes" або "Stake 1 SOL". - -- `disabled` - Значення має бути логічним (boolean), щоб представляти стан вимкнення кнопки (яка відображає рядок `label`). Якщо значення не надано, `disabled` має за замовчуванням бути `false` (тобто увімкнено). Наприклад, якщо кінцева точка дії використовується для голосування, яке вже закрите, встановіть `disabled=true`, а мітка може бути "Vote Closed". - -- `error` - Необов'язковий індикатор помилки для нефатальних помилок. Якщо присутній, клієнт повинен відобразити це користувачеві. Якщо встановлено, це не повинно заважати клієнту інтерпретувати дію або відображати її користувачеві (див. [Помилки дій](#action-errors)). Наприклад, помилка може використовуватися разом із `disabled`, щоб показати причину, як-от бізнес-обмеження, авторизація, стан або помилка зовнішнього ресурсу. - -- `links.actions` - Необов'язковий масив пов'язаних дій для кінцевої точки. Користувачам повинен бути відображений інтерфейс для кожної зі вказаних дій, і очікується, що вони виконають лише одну. Наприклад, кінцева точка дії для голосування в управлінні DAO може повернути три варіанти для користувача: "Vote Yes", "Vote No" і "Abstain from Vote". - - - Якщо `links.actions` не надано, клієнт повинен відобразити одну кнопку, використовуючи кореневий рядок `label`, і виконати POST-запит до тієї самої кінцевої точки URL дії, що й початковий GET-запит. - - - Якщо будь-які `links.actions` надані, клієнт повинен відображати лише кнопки та поля введення на основі елементів, перелічених у полі `links.actions`. Клієнт не повинен відображати кнопку для вмісту кореневого `label`. +- `type` - Тип дії, що надається користувачеві. За замовчуванням встановлено + значення `action`. Початковий `ActionGetResponse` повинен мати тип `action`. + + - `action` - Стандартна дія, яка дозволяє користувачеві взаємодіяти з + будь-якими `LinkedActions`. + - `completed` - Використовується для позначення стану "завершено" у ланцюжку + дій. + +- `icon` - Значення має бути абсолютним HTTP або HTTPS URL іконки. Файл повинен + бути формату SVG, PNG або WebP, інакше клієнт/гаманець повинен відхилити його + як **пошкоджений**. + +- `title` - Значення має бути рядком UTF-8, що представляє джерело запиту дії. + Наприклад, це може бути назва бренду, магазину, програми або особи, яка робить + запит. + +- `description` - Значення має бути рядком UTF-8, що надає інформацію про дію. + Опис повинен бути відображений користувачеві. + +- `label` - Значення має бути рядком UTF-8, який буде відображено на кнопці для + натискання користувачем. Усі мітки не повинні перевищувати 5 слів і повинні + починатися з дієслова, щоб закріпити дію, яку ви хочете, щоб користувач + виконав. Наприклад, "Mint NFT", "Vote Yes" або "Stake 1 SOL". + +- `disabled` - Значення має бути логічним (boolean), щоб представляти стан + вимкнення кнопки (яка відображає рядок `label`). Якщо значення не надано, + `disabled` має за замовчуванням бути `false` (тобто увімкнено). Наприклад, + якщо кінцева точка дії використовується для голосування, яке вже закрите, + встановіть `disabled=true`, а мітка може бути "Vote Closed". + +- `error` - Необов'язковий індикатор помилки для нефатальних помилок. Якщо + присутній, клієнт повинен відобразити це користувачеві. Якщо встановлено, це + не повинно заважати клієнту інтерпретувати дію або відображати її + користувачеві (див. [Помилки дій](#action-errors)). Наприклад, помилка може + використовуватися разом із `disabled`, щоб показати причину, як-от + бізнес-обмеження, авторизація, стан або помилка зовнішнього ресурсу. + +- `links.actions` - Необов'язковий масив пов'язаних дій для кінцевої точки. + Користувачам повинен бути відображений інтерфейс для кожної зі вказаних дій, і + очікується, що вони виконають лише одну. Наприклад, кінцева точка дії для + голосування в управлінні DAO може повернути три варіанти для користувача: + "Vote Yes", "Vote No" і "Abstain from Vote". + + - Якщо `links.actions` не надано, клієнт повинен відобразити одну кнопку, + використовуючи кореневий рядок `label`, і виконати POST-запит до тієї самої + кінцевої точки URL дії, що й початковий GET-запит. + + - Якщо будь-які `links.actions` надані, клієнт повинен відображати лише кнопки + та поля введення на основі елементів, перелічених у полі `links.actions`. + Клієнт не повинен відображати кнопку для вмісту кореневого `label`. ```ts filename="LinkedAction" export interface LinkedAction { @@ -439,7 +471,8 @@ export interface LinkedAction { } ``` -`ActionParameter` дозволяє визначити, яке саме введення API дій запитує у користувача: +`ActionParameter` дозволяє визначити, яке саме введення API дій запитує у +користувача: ```ts filename="ActionParameter" /** @@ -466,15 +499,30 @@ export interface ActionParameter { } ``` -`pattern` повинен бути рядком, еквівалентним дійсному регулярному виразу. Цей регулярний вираз має використовуватися клієнтами-блінками для перевірки введення користувача перед виконанням POST-запиту. Якщо `pattern` не є дійсним регулярним виразом, клієнт повинен його ігнорувати. - -`patternDescription` — це опис, зрозумілий для людини, який пояснює очікуване введення користувача. Якщо надано `pattern`, то `patternDescription` також обов’язково має бути надано. - -Значення `min` та `max` дозволяють встановити нижню та/або верхню межу введення, запитуваного у користувача (наприклад, мінімальне/максимальне число або мінімальну/максимальну довжину рядка). Вони повинні використовуватися для клієнтської валідації. Для типів введення `date` або `datetime-local` ці значення мають бути рядками, що представляють дати. Для інших типів введення на основі рядків значення повинні бути числами, що представляють їх мінімальну/максимальну довжину символів. - -Якщо введене значення користувача не відповідає `pattern`, користувач має отримати повідомлення про помилку на стороні клієнта, що вказує на недійсність поля введення, і відображати рядок `patternDescription`. - -Поле `type` дозволяє API дій визначати більш конкретні поля введення користувача, забезпечуючи кращу валідацію на стороні клієнта та покращуючи користувацький досвід. У багатьох випадках цей тип буде подібний до стандартного +`pattern` повинен бути рядком, еквівалентним дійсному регулярному виразу. Цей +регулярний вираз має використовуватися клієнтами-блінками для перевірки введення +користувача перед виконанням POST-запиту. Якщо `pattern` не є дійсним регулярним +виразом, клієнт повинен його ігнорувати. + +`patternDescription` — це опис, зрозумілий для людини, який пояснює очікуване +введення користувача. Якщо надано `pattern`, то `patternDescription` також +обов’язково має бути надано. + +Значення `min` та `max` дозволяють встановити нижню та/або верхню межу введення, +запитуваного у користувача (наприклад, мінімальне/максимальне число або +мінімальну/максимальну довжину рядка). Вони повинні використовуватися для +клієнтської валідації. Для типів введення `date` або `datetime-local` ці +значення мають бути рядками, що представляють дати. Для інших типів введення на +основі рядків значення повинні бути числами, що представляють їх +мінімальну/максимальну довжину символів. + +Якщо введене значення користувача не відповідає `pattern`, користувач має +отримати повідомлення про помилку на стороні клієнта, що вказує на недійсність +поля введення, і відображати рядок `patternDescription`. + +Поле `type` дозволяє API дій визначати більш конкретні поля введення +користувача, забезпечуючи кращу валідацію на стороні клієнта та покращуючи +користувацький досвід. У багатьох випадках цей тип буде подібний до стандартного [елемента введення HTML](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). Тип `ActionParameterType` можна спростити до такого формату: @@ -497,7 +545,10 @@ export type ActionParameterType = | "select"; ``` -Кожне зі значень `type` зазвичай має відповідати полю введення користувача, яке нагадує стандартний HTML-елемент `input` відповідного типу (наприклад, ``), щоб забезпечити кращу валідацію на стороні клієнта та покращити користувацький досвід: +Кожне зі значень `type` зазвичай має відповідати полю введення користувача, яке +нагадує стандартний HTML-елемент `input` відповідного типу (наприклад, +``), щоб забезпечити кращу валідацію на стороні клієнта та +покращити користувацький досвід: - `text` - еквівалент HTML [елемента введення типу "text"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/text) @@ -513,22 +564,31 @@ export type ActionParameterType = [елемента введення типу "datetime-local"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local) - `checkbox` - еквівалент групи стандартних HTML [елементів введення типу "checkbox"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox). - API дій має повертати `options`, як описано нижче. Користувач повинен мати змогу вибрати кілька запропонованих варіантів. + API дій має повертати `options`, як описано нижче. Користувач повинен мати + змогу вибрати кілька запропонованих варіантів. - `radio` - еквівалент групи стандартних HTML [елементів введення типу "radio"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio). - API дій має повертати `options`, як описано нижче. Користувач повинен мати змогу вибрати лише один із запропонованих варіантів. -- Інші еквіваленти HTML-типів введення, не зазначені вище (`hidden`, `button`, `submit`, `file` тощо), наразі не підтримуються. + API дій має повертати `options`, як описано нижче. Користувач повинен мати + змогу вибрати лише один із запропонованих варіантів. +- Інші еквіваленти HTML-типів введення, не зазначені вище (`hidden`, `button`, + `submit`, `file` тощо), наразі не підтримуються. -Окрім елементів, схожих на HTML-типи введення, також підтримуються наступні елементи введення користувача: +Окрім елементів, схожих на HTML-типи введення, також підтримуються наступні +елементи введення користувача: - `textarea` - еквівалент HTML [елемента "textarea"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea), що дозволяє користувачеві вводити багаторядковий текст. - `select` - еквівалент HTML [елемента "select"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select), - що надає користувачеві досвід вибору з випадаючого списку. API дій має повертати `options`, як описано нижче. + що надає користувачеві досвід вибору з випадаючого списку. API дій має + повертати `options`, як описано нижче. -Коли `type` встановлено як `select`, `checkbox` або `radio`, API дій має включати масив `options`, кожен із яких надає `label` та `value` принаймні. Кожна опція також може мати значення `selected`, яке інформує клієнт-блінк, яка опція має бути обрана за замовчуванням для користувача (див. відмінності для `checkbox` і `radio`). +Коли `type` встановлено як `select`, `checkbox` або `radio`, API дій має +включати масив `options`, кожен із яких надає `label` та `value` принаймні. +Кожна опція також може мати значення `selected`, яке інформує клієнт-блінк, яка +опція має бути обрана за замовчуванням для користувача (див. відмінності для +`checkbox` і `radio`). Цей `ActionParameterSelectable` можна спростити до такого визначення типу: @@ -548,15 +608,23 @@ interface ActionParameterSelectable extends ActionParameter { } ``` -Якщо `type` не встановлено або задано невідоме/непідтримуване значення, клієнти-блінки мають за замовчуванням використовувати `text` і відображати просте текстове поле введення. +Якщо `type` не встановлено або задано невідоме/непідтримуване значення, +клієнти-блінки мають за замовчуванням використовувати `text` і відображати +просте текстове поле введення. -API дій все одно відповідає за валідацію та санітизацію всіх даних, отриманих від параметрів введення користувача, забезпечуючи виконання всіх обов’язкових ("required") полів введення за необхідності. +API дій все одно відповідає за валідацію та санітизацію всіх даних, отриманих +від параметрів введення користувача, забезпечуючи виконання всіх обов’язкових +("required") полів введення за необхідності. -Для платформ, які не базуються на HTML/веб (наприклад, для нативних мобільних додатків), слід використовувати еквівалентні нативні компоненти введення, щоб забезпечити аналогічний досвід та валідацію на стороні клієнта, як описано для HTML/веб. +Для платформ, які не базуються на HTML/веб (наприклад, для нативних мобільних +додатків), слід використовувати еквівалентні нативні компоненти введення, щоб +забезпечити аналогічний досвід та валідацію на стороні клієнта, як описано для +HTML/веб. #### Приклад відповіді на GET-запит -Наступний приклад відповіді забезпечує єдину "кореневу" дію, яка очікує, що користувачеві буде представлена одна кнопка з міткою "Отримати токен доступу": +Наступний приклад відповіді забезпечує єдину "кореневу" дію, яка очікує, що +користувачеві буде представлена одна кнопка з міткою "Отримати токен доступу": ```json { @@ -567,7 +635,9 @@ API дій все одно відповідає за валідацію та с } ``` -Наступний приклад відповіді забезпечує 3 пов’язані посилання на дії, що дозволяють користувачеві натиснути одну з трьох кнопок для голосування за пропозицію DAO: +Наступний приклад відповіді забезпечує 3 пов’язані посилання на дії, що +дозволяють користувачеві натиснути одну з трьох кнопок для голосування за +пропозицію DAO: ```json { @@ -596,9 +666,14 @@ API дій все одно відповідає за валідацію та с #### Приклад відповіді на GET-запит з параметрами -Наступні приклади відповіді демонструють, як приймати текстове введення від користувача (через `parameters`) і включати це введення у кінцеву кінцеву точку запиту `POST` (через поле `href` у `LinkedAction`): +Наступні приклади відповіді демонструють, як приймати текстове введення від +користувача (через `parameters`) і включати це введення у кінцеву кінцеву точку +запиту `POST` (через поле `href` у `LinkedAction`): -Наступний приклад відповіді забезпечує користувачеві 3 пов’язані дії для стейкінгу SOL: кнопку з міткою "Stake 1 SOL", іншу кнопку з міткою "Stake 5 SOL" та текстове поле введення, яке дозволяє користувачеві ввести конкретне значення "amount", що буде надіслано до API дій: +Наступний приклад відповіді забезпечує користувачеві 3 пов’язані дії для +стейкінгу SOL: кнопку з міткою "Stake 1 SOL", іншу кнопку з міткою "Stake 5 SOL" +та текстове поле введення, яке дозволяє користувачеві ввести конкретне значення +"amount", що буде надіслано до API дій: ```json { @@ -633,7 +708,9 @@ API дій все одно відповідає за валідацію та с } ``` -Наступний приклад відповіді забезпечує одне поле введення для користувача, щоб ввести `amount`, яке буде надіслано з запитом `POST` (може бути використано як параметр запиту або як підшлях): +Наступний приклад відповіді забезпечує одне поле введення для користувача, щоб +ввести `amount`, яке буде надіслано з запитом `POST` (може бути використано як +параметр запиту або як підшлях): ```json { @@ -661,7 +738,9 @@ API дій все одно відповідає за валідацію та с ### POST Запит -Наступний приклад відповіді забезпечує одне поле введення для користувача, щоб ввести `amount`, яке буде надіслано з запитом `POST` (може бути використано як параметр запиту або як підшлях): +Наступний приклад відповіді забезпечує одне поле введення для користувача, щоб +ввести `amount`, яке буде надіслано з запитом `POST` (може бути використано як +параметр запиту або як підшлях): ```json { @@ -669,35 +748,42 @@ API дій все одно відповідає за валідацію та с } ``` -- `account` - Значення повинно бути відкритим ключем облікового запису у форматі base58, який може підписувати транзакцію. +- `account` - Значення повинно бути відкритим ключем облікового запису у форматі + base58, який може підписувати транзакцію. -Клієнт має виконати запит із заголовком -[Accept-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding), -а застосунок може відповісти заголовком -[Content-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding) +Клієнт має виконати запит із заголовком +[Accept-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding), +а застосунок може відповісти заголовком +[Content-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding) для HTTP-компресії. -Клієнт повинен відобразити домен URL дії під час виконання запиту. Якщо був виконаний `GET`-запит, клієнт також повинен відобразити `title` та відрендерити зображення `icon` з відповіді GET. +Клієнт повинен відобразити домен URL дії під час виконання запиту. Якщо був +виконаний `GET`-запит, клієнт також повинен відобразити `title` та відрендерити +зображення `icon` з відповіді GET. ### Відповідь на POST-запит -Кінцева точка `POST` для дії повинна відповідати HTTP-відповіддю `OK` у форматі JSON (з дійсним тілом відповіді) або відповідною HTTP-помилкою. +Кінцева точка `POST` для дії повинна відповідати HTTP-відповіддю `OK` у форматі +JSON (з дійсним тілом відповіді) або відповідною HTTP-помилкою. -- Клієнт повинен обробляти +- Клієнт повинен обробляти [помилки клієнта](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses), - [помилки сервера](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses), - та + [помилки сервера](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses), + та [відповіді-перенаправлення](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). -- Кінцева точка повинна відповідати з - заголовком [`Content-Type`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) +- Кінцева точка повинна відповідати з заголовком + [`Content-Type`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) значенням `application/json`. -Помилкові відповіді (тобто HTTP-коди стану 4xx і 5xx) повинні повертати JSON-відповідь, що відповідає структурі `ActionError`, для відображення корисного повідомлення про помилку користувачам. Див. [Помилки дій](#action-errors). +Помилкові відповіді (тобто HTTP-коди стану 4xx і 5xx) повинні повертати +JSON-відповідь, що відповідає структурі `ActionError`, для відображення +корисного повідомлення про помилку користувачам. Див. +[Помилки дій](#action-errors). #### Тіло відповіді на POST-запит -Відповідь `POST` з HTTP-відповіддю `OK` у форматі JSON повинна включати тіло відповіді наступного вигляду: - +Відповідь `POST` з HTTP-відповіддю `OK` у форматі JSON повинна включати тіло +відповіді наступного вигляду: ```ts filename="ActionPostResponse" /** @@ -717,23 +803,25 @@ export interface ActionPostResponse { }; } ``` -- `transaction` - Значення повинно бути серіалізованою транзакцією, закодованою в base64 + +- `transaction` - Значення повинно бути серіалізованою транзакцією, закодованою + в base64 ([документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#serialize)). Клієнт повинен декодувати транзакцію з base64 і [десеріалізувати її](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#from). -- `message` - Значення повинно бути рядком у форматі UTF-8, який описує суть транзакції, - включеної у відповідь. Клієнт повинен відобразити це значення користувачу. - Наприклад, це може бути назва товару, який купується, застосована знижка, - або подяка. +- `message` - Значення повинно бути рядком у форматі UTF-8, який описує суть + транзакції, включеної у відповідь. Клієнт повинен відобразити це значення + користувачу. Наприклад, це може бути назва товару, який купується, застосована + знижка, або подяка. -- `links.next` - Необов'язкове значення, яке використовується для "зчеплення" кількох дій - у послідовності. Після підтвердження включеної `transaction` у блокчейні - клієнт може отримати та відобразити наступну дію. Дивіться +- `links.next` - Необов'язкове значення, яке використовується для "зчеплення" + кількох дій у послідовності. Після підтвердження включеної `transaction` у + блокчейні клієнт може отримати та відобразити наступну дію. Дивіться [Зчеплення дій](#action-chaining) для отримання додаткової інформації. -- Клієнт та застосунок повинні дозволяти додаткові поля у тілі запиту - та відповіді, які можуть бути додані у майбутніх оновленнях специфікацій. +- Клієнт та застосунок повинні дозволяти додаткові поля у тілі запиту та + відповіді, які можуть бути додані у майбутніх оновленнях специфікацій. > Застосунок може відповідати частково або повністю підписаною транзакцією. > Клієнт та гаманець повинні перевіряти транзакцію як **ненадійну**. @@ -751,8 +839,9 @@ export interface ActionPostResponse { [`recentBlockhash`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html#recentBlockhash) у транзакції та встановити `recentBlockhash` на [останній blockhash](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getLatestBlockhash). -- Клієнт повинен серіалізувати та десеріалізувати транзакцію перед її підписанням. - Це забезпечує послідовний порядок ключів облікових записів як рішення для +- Клієнт повинен серіалізувати та десеріалізувати транзакцію перед її + підписанням. Це забезпечує послідовний порядок ключів облікових записів як + рішення для [цієї проблеми](https://github.com/solana-labs/solana/issues/21722). Якщо транзакція вже частково підписана: @@ -765,18 +854,17 @@ export interface ActionPostResponse { - Клієнт повинен перевірити існуючі підписи, і якщо будь-який з них недійсний, клієнт повинен відхилити транзакцію як **пошкоджену**. -Клієнт повинен підписати транзакцію лише за допомогою `account`, зазначеного у запиті, -і зробити це лише у випадку, якщо очікується підпис для цього `account`. +Клієнт повинен підписати транзакцію лише за допомогою `account`, зазначеного у +запиті, і зробити це лише у випадку, якщо очікується підпис для цього `account`. -Якщо очікується будь-який підпис, окрім підпису для `account` у запиті, -клієнт повинен відхилити транзакцію як **шкідливу**. +Якщо очікується будь-який підпис, окрім підпису для `account` у запиті, клієнт +повинен відхилити транзакцію як **шкідливу**. ### Помилки дій API для дій повинні повертати помилки у форматі `ActionError`, щоб надати -корисні повідомлення про помилки для користувачів. Залежно від контексту, ця помилка -може бути фатальною або нефатальною. - +корисні повідомлення про помилки для користувачів. Залежно від контексту, ця +помилка може бути фатальною або нефатальною. ```ts filename="ActionError" export interface ActionError { @@ -784,26 +872,43 @@ export interface ActionError { message: string; } ``` -Коли API для дій відповідає HTTP-кодом помилки (тобто 4xx і 5xx), тіло відповіді має бути JSON-навантаженням, яке відповідає формату `ActionError`. Помилка вважається фатальною, і повідомлення, яке міститься в ній, має бути представлене користувачеві. -Для відповідей API, які підтримують необов'язковий атрибут `error` (наприклад, [`ActionGetResponse`](#get-response)), помилка вважається нефатальною, і повідомлення, яке міститься в ній, також має бути представлене користувачеві. +Коли API для дій відповідає HTTP-кодом помилки (тобто 4xx і 5xx), тіло відповіді +має бути JSON-навантаженням, яке відповідає формату `ActionError`. Помилка +вважається фатальною, і повідомлення, яке міститься в ній, має бути представлене +користувачеві. + +Для відповідей API, які підтримують необов'язковий атрибут `error` (наприклад, +[`ActionGetResponse`](#get-response)), помилка вважається нефатальною, і +повідомлення, яке міститься в ній, також має бути представлене користувачеві. ## Зчеплення дій -Дії Solana можуть бути "зчеплені" разом у послідовну серію. Після підтвердження транзакції дії у блокчейні можна отримати наступну дію та представити її користувачеві. +Дії Solana можуть бути "зчеплені" разом у послідовну серію. Після підтвердження +транзакції дії у блокчейні можна отримати наступну дію та представити її +користувачеві. -Зчеплення дій дозволяє розробникам створювати більш складний і динамічний досвід у рамках blinks, включаючи: +Зчеплення дій дозволяє розробникам створювати більш складний і динамічний досвід +у рамках blinks, включаючи: -- надання декількох транзакцій (і в майбутньому повідомлень для підпису) користувачу; +- надання декількох транзакцій (і в майбутньому повідомлень для підпису) + користувачу; - налаштування метаданих дії залежно від адреси гаманця користувача; - оновлення метаданих blink після успішної транзакції; -- отримання API-зворотного виклику з підписом транзакції для додаткової перевірки та логіки на сервері API для дій; -- налаштовані повідомлення про успіх, шляхом оновлення відображуваних метаданих (наприклад, нове зображення або опис). +- отримання API-зворотного виклику з підписом транзакції для додаткової + перевірки та логіки на сервері API для дій; +- налаштовані повідомлення про успіх, шляхом оновлення відображуваних метаданих + (наприклад, нове зображення або опис). -Для зчеплення кількох дій разом, у будь-якому `ActionPostResponse` включіть `links.next` одного з наступних типів: +Для зчеплення кількох дій разом, у будь-якому `ActionPostResponse` включіть +`links.next` одного з наступних типів: -- `PostNextActionLink` — Посилання POST-запиту з URL зворотного виклику того самого походження для отримання `signature` і `account` користувача у тілі. Цей URL зворотного виклику повинен відповідати `NextAction`. -- `InlineNextActionLink` — Вбудовані метадані для наступної дії, які мають бути представлені користувачеві негайно після підтвердження транзакції. Ніякий зворотний виклик не буде виконано. +- `PostNextActionLink` — Посилання POST-запиту з URL зворотного виклику того + самого походження для отримання `signature` і `account` користувача у тілі. + Цей URL зворотного виклику повинен відповідати `NextAction`. +- `InlineNextActionLink` — Вбудовані метадані для наступної дії, які мають бути + представлені користувачеві негайно після підтвердження транзакції. Ніякий + зворотний виклик не буде виконано. ```ts export type NextActionLink = PostNextActionLink | InlineNextActionLink; @@ -826,15 +931,20 @@ export interface InlineNextActionLink { action: NextAction; } ``` -### NextAction -Після того як транзакція, включена в `ActionPostResponse`, підписана користувачем і підтверджена у блокчейні, blink-клієнт повинен або: +### NextAction -- виконати запит зворотного виклику, щоб отримати і відобразити `NextAction`, або -- якщо `NextAction` вже надана через `links.next`, blink-клієнт повинен оновити відображувані метадані і не робити запит зворотного виклику. +Після того як транзакція, включена в `ActionPostResponse`, підписана +користувачем і підтверджена у блокчейні, blink-клієнт повинен або: -Якщо URL зворотного виклику не має того ж походження, що і початковий POST-запит, запит зворотного виклику не повинен виконуватися. Blink-клієнти повинні відобразити помилку, що повідомляє користувача. +- виконати запит зворотного виклику, щоб отримати і відобразити `NextAction`, + або +- якщо `NextAction` вже надана через `links.next`, blink-клієнт повинен оновити + відображувані метадані і не робити запит зворотного виклику. +Якщо URL зворотного виклику не має того ж походження, що і початковий +POST-запит, запит зворотного виклику не повинен виконуватися. Blink-клієнти +повинні відобразити помилку, що повідомляє користувача. ```ts filename="NextAction" /** The next action to be performed */ @@ -846,31 +956,47 @@ export type CompletedAction = Omit, "links">; ### Відповідно до `type`, наступна дія повинна бути представлена користувачеві через blink-клієнти одним із наступних способів: -- `action` - (за замовчуванням) Стандартна дія, яка дозволяє користувачеві переглядати включені метадані Action, взаємодіяти з наданими `LinkedActions` і продовжувати виконувати будь-які наступні дії в ланцюжку. +- `action` - (за замовчуванням) Стандартна дія, яка дозволяє користувачеві + переглядати включені метадані Action, взаємодіяти з наданими `LinkedActions` і + продовжувати виконувати будь-які наступні дії в ланцюжку. -- `completed` - Завершальний стан ланцюжка дій, який може оновлювати інтерфейс blink із включеними метаданими Action, але не дозволяє користувачеві виконувати подальші дії. +- `completed` - Завершальний стан ланцюжка дій, який може оновлювати інтерфейс + blink із включеними метаданими Action, але не дозволяє користувачеві + виконувати подальші дії. -Якщо `links.next` не надано, blink-клієнти повинні припустити, що поточна дія є фінальною у ланцюжку, і представити свій інтерфейс "завершеної" дії після підтвердження транзакції. +Якщо `links.next` не надано, blink-клієнти повинні припустити, що поточна дія є +фінальною у ланцюжку, і представити свій інтерфейс "завершеної" дії після +підтвердження транзакції. ## actions.json -Файл [`actions.json`](#actionsjson) використовується для того, щоб додаток міг інструктувати клієнтів про те, які URL-адреси вебсайту підтримують Solana Actions, і надавати мапінг, який може бути використаний для виконання [GET запитів](#get-request) до серверу API дій. +Файл [`actions.json`](#actionsjson) використовується для того, щоб додаток міг +інструктувати клієнтів про те, які URL-адреси вебсайту підтримують Solana +Actions, і надавати мапінг, який може бути використаний для виконання +[GET запитів](#get-request) до серверу API дій. -Відповідь файлу `actions.json` також повинна повертати дійсні заголовки Cross-Origin для запитів `GET` і `OPTIONS`, зокрема заголовок `Access-Control-Allow-Origin` із значенням `*`. +Відповідь файлу `actions.json` також повинна повертати дійсні заголовки +Cross-Origin для запитів `GET` і `OPTIONS`, зокрема заголовок +`Access-Control-Allow-Origin` із значенням `*`. Детальніше див. у розділі [OPTIONS response](#options-response) вище. -Файл `actions.json` повинен бути збережений і загальнодоступний у кореневій директорії домену. +Файл `actions.json` повинен бути збережений і загальнодоступний у кореневій +директорії домену. -Наприклад, якщо ваш вебдодаток розгорнуто на `my-site.com`, тоді файл `actions.json` має бути доступний за адресою `https://my-site.com/actions.json`. Цей файл також має бути доступний через будь-який браузер за допомогою заголовка `Access-Control-Allow-Origin` із значенням `*`. +Наприклад, якщо ваш вебдодаток розгорнуто на `my-site.com`, тоді файл +`actions.json` має бути доступний за адресою `https://my-site.com/actions.json`. +Цей файл також має бути доступний через будь-який браузер за допомогою заголовка +`Access-Control-Allow-Origin` із значенням `*`. ### Правила -Поле `rules` дозволяє додатку мапувати набір відносних маршрутів вебсайту на інші шляхи. +Поле `rules` дозволяє додатку мапувати набір відносних маршрутів вебсайту на +інші шляхи. **Тип:** `Array` з `ActionRuleObject`. @@ -882,28 +1008,39 @@ interface ActionRuleObject { apiPath: string; } ``` -- [`pathPattern`](#rules-pathpattern) - Шаблон, який відповідає кожному вхідному шляху. -- [`apiPath`](#rules-apipath) - Місце призначення, визначене як абсолютний шлях або зовнішній URL. +- [`pathPattern`](#rules-pathpattern) - Шаблон, який відповідає кожному вхідному + шляху. + +- [`apiPath`](#rules-apipath) - Місце призначення, визначене як абсолютний шлях + або зовнішній URL. #### Правила - pathPattern -Шаблон, який відповідає кожному вхідному шляху. Це може бути абсолютний або відносний шлях, який підтримує наступні формати: +Шаблон, який відповідає кожному вхідному шляху. Це може бути абсолютний або +відносний шлях, який підтримує наступні формати: - **Точне співпадіння**: Відповідає точному URL-шляху. - Приклад: `/exact-path` - Приклад: `https://website.com/exact-path` -- **Співпадіння з використанням шаблону**: Використовує символи підстановки для відповідності будь-якій послідовності символів у шляху URL. Це може відповідати одному (за допомогою `*`) або кільком сегментам (за допомогою `**`). (Див. [Path Matching](#rules-path-matching) нижче). +- **Співпадіння з використанням шаблону**: Використовує символи підстановки для + відповідності будь-якій послідовності символів у шляху URL. Це може + відповідати одному (за допомогою `*`) або кільком сегментам (за допомогою + `**`). (Див. [Path Matching](#rules-path-matching) нижче). - - Приклад: `/trade/*` відповідатиме `/trade/123` і `/trade/abc`, захоплюючи лише перший сегмент після `/trade/`. - - Приклад: `/category/*/item/**` відповідатиме `/category/123/item/456` і `/category/abc/item/def`. - - Приклад: `/api/actions/trade/*/confirm` відповідатиме `/api/actions/trade/123/confirm`. + - Приклад: `/trade/*` відповідатиме `/trade/123` і `/trade/abc`, захоплюючи + лише перший сегмент після `/trade/`. + - Приклад: `/category/*/item/**` відповідатиме `/category/123/item/456` і + `/category/abc/item/def`. + - Приклад: `/api/actions/trade/*/confirm` відповідатиме + `/api/actions/trade/123/confirm`. #### Правила - apiPath -Шлях призначення для запиту дії. Він може бути визначений як абсолютний шлях або зовнішній URL. +Шлях призначення для запиту дії. Він може бути визначений як абсолютний шлях або +зовнішній URL. - Приклад: `/api/exact-path` - Приклад: `https://api.example.com/v1/donate/*` @@ -912,21 +1049,24 @@ interface ActionRuleObject { #### Правила - Query Parameters -Параметри запиту з оригінального URL завжди зберігаються та додаються до мапованого URL. +Параметри запиту з оригінального URL завжди зберігаються та додаються до +мапованого URL. #### Правила - Path Matching Наступна таблиця описує синтаксис для шаблонів відповідності шляхів: -| Оператор | Відповідає | -| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `*` | Один сегмент шляху, що не включає оточуючі символи розділювача шляху `/`. | +| Оператор | Відповідає | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `*` | Один сегмент шляху, що не включає оточуючі символи розділювача шляху `/`. | | `**` | Відповідає нулю або більшій кількості символів, включаючи будь-які символи розділювача шляху `/` між декількома сегментами шляху. Якщо включені інші оператори, оператор `**` повинен бути останнім. | -| `?` | Непідтримуваний шаблон. | +| `?` | Непідтримуваний шаблон. | ### Приклади Правил -Наступний приклад демонструє правило точного співпадіння для мапування запитів до `/buy` з кореня вашого сайту на точний шлях `/api/buy`, відносно кореня вашого сайту: +Наступний приклад демонструє правило точного співпадіння для мапування запитів +до `/buy` з кореня вашого сайту на точний шлях `/api/buy`, відносно кореня +вашого сайту: ```json filename="actions.json" { @@ -939,7 +1079,10 @@ interface ActionRuleObject { } ``` -Наступний приклад використовує шаблонне співставлення шляху для відображення запитів до будь-якого шляху (за винятком підкаталогів) під `/actions/` від кореня вашого сайту до відповідного шляху під `/api/actions/`, відносно кореня вашого сайту: +Наступний приклад використовує шаблонне співставлення шляху для відображення +запитів до будь-якого шляху (за винятком підкаталогів) під `/actions/` від +кореня вашого сайту до відповідного шляху під `/api/actions/`, відносно кореня +вашого сайту: ```json filename="actions.json" { @@ -952,7 +1095,10 @@ interface ActionRuleObject { } ``` -Наступний приклад використовує зіставлення шляхів із використанням символів підстановки для перенаправлення запитів до будь-якого шляху (за винятком підкаталогів) під `/donate/` у кореневій директорії вашого сайту до відповідного абсолютного шляху `https://api.dialect.com/api/v1/donate/` на зовнішньому сайті: +Наступний приклад використовує зіставлення шляхів із використанням символів +підстановки для перенаправлення запитів до будь-якого шляху (за винятком +підкаталогів) під `/donate/` у кореневій директорії вашого сайту до відповідного +абсолютного шляху `https://api.dialect.com/api/v1/donate/` на зовнішньому сайті: ```json filename="actions.json" { @@ -965,9 +1111,13 @@ interface ActionRuleObject { } ``` -Наступний приклад використовує зіставлення шляхів із використанням символів підстановки для ідемпотентного правила, щоб перенаправляти запити до будь-якого шляху (включаючи підкаталоги) під `/api/actions/` у кореневій директорії вашого сайту до самого себе: +Наступний приклад використовує зіставлення шляхів із використанням символів +підстановки для ідемпотентного правила, щоб перенаправляти запити до будь-якого +шляху (включаючи підкаталоги) під `/api/actions/` у кореневій директорії вашого +сайту до самого себе: -> Ідемпотентні правила дозволяють клієнтам blink легше визначати, чи підтримує даний шлях запити API дій, без необхідності: +> Ідемпотентні правила дозволяють клієнтам blink легше визначати, чи підтримує +> даний шлях запити API дій, без необхідності: > > - додавання префіксу `solana-action:` URI, > - виконання додаткового тестування відповіді, @@ -986,53 +1136,107 @@ interface ActionRuleObject { ## Ідентифікація Дії (Action Identity) -Кінцеві точки дій (Action endpoints) можуть включати _Ідентифікацію Дії_ у транзакціях, які повертаються у [POST-відповіді](#post-response) для підпису користувачем. Це дозволяє індексаторам та аналітичним платформам легко та достовірно приписувати активність у блокчейні конкретному провайдеру дій (тобто сервісу). - -[Ідентифікація Дії](#action-identity) — це пара ключів (keypair), яка використовується для підпису спеціально форматованого повідомлення, що включається до транзакції за допомогою інструкції Memo. Це _Повідомлення Ідентифікатора_ (_Identifier Message_) може бути достовірно приписане до конкретної Ідентифікації Дії, а отже, до конкретного провайдера дій. - -Пара ключів не вимагається для підписання самої транзакції. Це дозволяє гаманцям та додаткам покращити доставку транзакції, якщо у транзакції, поверненій користувачу, немає інших підписів (див. [POST-відповідь транзакції](#post-response-transaction)). - -Якщо сценарій використання провайдера дій вимагає, щоб їх бекенд-сервіси попередньо підписували транзакцію перед тим, як це зробить користувач, вони мають використовувати цю пару ключів як Ідентифікацію Дії. Це дозволить зменшити кількість облікових записів у транзакції, скоротивши її загальний розмір на 32 байти. +Кінцеві точки дій (Action endpoints) можуть включати _Ідентифікацію Дії_ у +транзакціях, які повертаються у [POST-відповіді](#post-response) для підпису +користувачем. Це дозволяє індексаторам та аналітичним платформам легко та +достовірно приписувати активність у блокчейні конкретному провайдеру дій (тобто +сервісу). + +[Ідентифікація Дії](#action-identity) — це пара ключів (keypair), яка +використовується для підпису спеціально форматованого повідомлення, що +включається до транзакції за допомогою інструкції Memo. Це _Повідомлення +Ідентифікатора_ (_Identifier Message_) може бути достовірно приписане до +конкретної Ідентифікації Дії, а отже, до конкретного провайдера дій. + +Пара ключів не вимагається для підписання самої транзакції. Це дозволяє гаманцям +та додаткам покращити доставку транзакції, якщо у транзакції, поверненій +користувачу, немає інших підписів (див. +[POST-відповідь транзакції](#post-response-transaction)). + +Якщо сценарій використання провайдера дій вимагає, щоб їх бекенд-сервіси +попередньо підписували транзакцію перед тим, як це зробить користувач, вони +мають використовувати цю пару ключів як Ідентифікацію Дії. Це дозволить зменшити +кількість облікових записів у транзакції, скоротивши її загальний розмір на 32 +байти. ### Повідомлення Ідентифікатора Дії (Action Identifier Message) -Повідомлення Ідентифікатора Дії — це UTF-8 рядок, розділений двокрапками, який включається до транзакції за допомогою однієї [інструкції SPL Memo](https://spl.solana.com/memo). +Повідомлення Ідентифікатора Дії — це UTF-8 рядок, розділений двокрапками, який +включається до транзакції за допомогою однієї +[інструкції SPL Memo](https://spl.solana.com/memo). ```shell protocol:identity:reference:signature ``` -- `protocol` - Значення протоколу, який використовується (встановлено як `solana-action` відповідно до [URL-схеми](#url-scheme) вище). -- `identity` - Значення має бути публічним ключем у форматі base58, який відповідає парі ключів Ідентифікації Дії. -- `reference` - Значення має бути масивом байтів довжиною 32 у форматі base58. Це можуть бути як публічні ключі, так і інші дані, які можуть або не можуть відповідати обліковим записам у Solana. -- `signature` - Підпис у форматі base58, створений парою ключів Ідентифікації Дії, що підписує лише значення `reference`. - -Значення `reference` має використовуватися тільки один раз і в одній транзакції. Для приписування транзакцій провайдеру дій, лише перше використання значення `reference` вважається дійсним. -Транзакції можуть містити кілька інструкцій Memo. Під час виконання [`getSignaturesForAddress`](https://solana.com/docs/rpc/http/getsignaturesforaddress) поле `memo` у результатах повертає повідомлення кожної інструкції Memo як єдиний рядок, розділений крапкою з комою. - -Жодні інші дані не повинні включатися до інструкції Memo Повідомлення Ідентифікатора. - -Облікові записи `identity` та `reference` повинні бути включені як доступні тільки для читання, але без можливості підпису ([ключі](https://solana-labs.github.io/solana-web3.js/v1.x/classes/TransactionInstruction.html#keys)) у транзакції в інструкції, яка не є Інструкцією Memo Повідомлення Ідентифікатора. - -Інструкція Memo Повідомлення Ідентифікатора не повинна містити жодних облікових записів. Якщо облікові записи надаються, програма Memo вимагає, щоб ці облікові записи були дійсними підписувачами. Це обмежує гнучкість і може погіршити досвід користувача, тому це вважається антипатерном і має бути уникнуто. +- `protocol` - Значення протоколу, який використовується (встановлено як + `solana-action` відповідно до [URL-схеми](#url-scheme) вище). +- `identity` - Значення має бути публічним ключем у форматі base58, який + відповідає парі ключів Ідентифікації Дії. +- `reference` - Значення має бути масивом байтів довжиною 32 у форматі base58. + Це можуть бути як публічні ключі, так і інші дані, які можуть або не можуть + відповідати обліковим записам у Solana. +- `signature` - Підпис у форматі base58, створений парою ключів Ідентифікації + Дії, що підписує лише значення `reference`. + +Значення `reference` має використовуватися тільки один раз і в одній транзакції. +Для приписування транзакцій провайдеру дій, лише перше використання значення +`reference` вважається дійсним. + +Транзакції можуть містити кілька інструкцій Memo. Під час виконання +[`getSignaturesForAddress`](https://solana.com/docs/rpc/http/getsignaturesforaddress) +поле `memo` у результатах повертає повідомлення кожної інструкції Memo як єдиний +рядок, розділений крапкою з комою. + +Жодні інші дані не повинні включатися до інструкції Memo Повідомлення +Ідентифікатора. + +Облікові записи `identity` та `reference` повинні бути включені як доступні +тільки для читання, але без можливості підпису +([ключі](https://solana-labs.github.io/solana-web3.js/v1.x/classes/TransactionInstruction.html#keys)) +у транзакції в інструкції, яка не є Інструкцією Memo Повідомлення +Ідентифікатора. + +Інструкція Memo Повідомлення Ідентифікатора не повинна містити жодних облікових +записів. Якщо облікові записи надаються, програма Memo вимагає, щоб ці облікові +записи були дійсними підписувачами. Це обмежує гнучкість і може погіршити досвід +користувача, тому це вважається антипатерном і має бути уникнуто. ### Перевірка Ідентифікації Дії (Action Identity Verification) -Будь-яка транзакція, що включає обліковий запис `identity`, може бути достовірно пов'язана з провайдером дій за допомогою багатоступінчастого процесу: +Будь-яка транзакція, що включає обліковий запис `identity`, може бути достовірно +пов'язана з провайдером дій за допомогою багатоступінчастого процесу: 1. Отримайте всі транзакції для заданого `identity`. -2. Розберіть і перевірте рядок memo кожної транзакції, переконавшись, що підпис `signature` дійсний для збереженого значення `reference`. -3. Перевірте, чи є ця транзакція першим випадком використання `reference` у блокчейні: - - Якщо ця транзакція є першим випадком, вона вважається підтвердженою і може бути достовірно приписана провайдеру дій. - - Якщо ця транзакція НЕ є першим випадком, вона вважається недійсною і, відповідно, не може бути приписана провайдеру дій. - -Оскільки валідатори Solana індексують транзакції за обліковими записами, метод RPC [`getSignaturesForAddress`](https://solana.com/docs/rpc/http/getsignaturesforaddress) може бути використаний для визначення всіх транзакцій, що включають обліковий запис `identity`. - -Відповідь цього методу RPC включає всі дані Memo у полі `memo`. Якщо в транзакції було використано кілька інструкцій Memo, кожне повідомлення Memo буде включено в це поле `memo` і має бути відповідним чином розібране перевіряючою стороною для отримання _Повідомлення Ідентифікації_. - -Ці транзакції спочатку мають вважатися **НЕПЕРЕВІРЕНИМИ**. Це пов'язано з тим, що `identity` не вимагається для підписання транзакції, що дозволяє будь-якій транзакції включати цей обліковий запис як не-підписувач. Це потенційно може штучно збільшити статистику приписування та використання. - -Повідомлення Ідентифікації має бути перевірене для забезпечення того, що `signature` було створено `identity`, підписуючи `reference`. Якщо ця перевірка підпису не вдається, транзакція вважається недійсною. - -Якщо перевірка підпису успішна, перевіряюча сторона має забезпечити, що ця транзакція є першим випадком використання `reference`. Якщо це не так, транзакція вважається недійсною. - +2. Розберіть і перевірте рядок memo кожної транзакції, переконавшись, що підпис + `signature` дійсний для збереженого значення `reference`. +3. Перевірте, чи є ця транзакція першим випадком використання `reference` у + блокчейні: + - Якщо ця транзакція є першим випадком, вона вважається підтвердженою і може + бути достовірно приписана провайдеру дій. + - Якщо ця транзакція НЕ є першим випадком, вона вважається недійсною і, + відповідно, не може бути приписана провайдеру дій. + +Оскільки валідатори Solana індексують транзакції за обліковими записами, метод +RPC +[`getSignaturesForAddress`](https://solana.com/docs/rpc/http/getsignaturesforaddress) +може бути використаний для визначення всіх транзакцій, що включають обліковий +запис `identity`. + +Відповідь цього методу RPC включає всі дані Memo у полі `memo`. Якщо в +транзакції було використано кілька інструкцій Memo, кожне повідомлення Memo буде +включено в це поле `memo` і має бути відповідним чином розібране перевіряючою +стороною для отримання _Повідомлення Ідентифікації_. + +Ці транзакції спочатку мають вважатися **НЕПЕРЕВІРЕНИМИ**. Це пов'язано з тим, +що `identity` не вимагається для підписання транзакції, що дозволяє будь-якій +транзакції включати цей обліковий запис як не-підписувач. Це потенційно може +штучно збільшити статистику приписування та використання. + +Повідомлення Ідентифікації має бути перевірене для забезпечення того, що +`signature` було створено `identity`, підписуючи `reference`. Якщо ця перевірка +підпису не вдається, транзакція вважається недійсною. + +Якщо перевірка підпису успішна, перевіряюча сторона має забезпечити, що ця +транзакція є першим випадком використання `reference`. Якщо це не так, +транзакція вважається недійсною. diff --git a/docs/locales/uk/advanced/confirmation.md b/docs/locales/uk/advanced/confirmation.md index 7134d5313..08621dfb1 100644 --- a/docs/locales/uk/advanced/confirmation.md +++ b/docs/locales/uk/advanced/confirmation.md @@ -4,96 +4,126 @@ sidebarLabel: "Підтвердження та закінчення строку title: "Підтвердження транзакції та закінчення строку дії" seoTitle: "Підтвердження транзакції та закінчення строку дії" description: - "Дізнайтеся, як працює підтвердження транзакцій у Solana і коли транзакція завершує дію - (включаючи перевірку останніх blockhash)." + "Дізнайтеся, як працює підтвердження транзакцій у Solana і коли транзакція + завершує дію (включаючи перевірку останніх blockhash)." altRoutes: - /docs/uk/advanced - /docs/uk/core/transactions/confirmation --- -Проблеми, пов'язані з -[підтвердженням транзакції](/docs/uk/terminology.md#transaction-confirmations), -є поширеними серед нових розробників під час створення застосунків. Ця стаття має на меті підвищити загальне розуміння механізму підтвердження, який використовується в блокчейні Solana, включаючи деякі рекомендовані найкращі практики. +Проблеми, пов'язані з +[підтвердженням транзакції](/docs/uk/terminology.md#transaction-confirmations), +є поширеними серед нових розробників під час створення застосунків. Ця стаття +має на меті підвищити загальне розуміння механізму підтвердження, який +використовується в блокчейні Solana, включаючи деякі рекомендовані найкращі +практики. ## Короткий вступ до транзакцій -Перед тим як розглянути, як працює підтвердження та закінчення строку дії транзакцій у Solana, давайте коротко розглянемо кілька основ: +Перед тим як розглянути, як працює підтвердження та закінчення строку дії +транзакцій у Solana, давайте коротко розглянемо кілька основ: - що таке транзакція, - життєвий цикл транзакції, - що таке blockhash, -- і коротке ознайомлення з Proof of History (PoH) і тим, як це стосується blockhash. +- і коротке ознайомлення з Proof of History (PoH) і тим, як це стосується + blockhash. ### Що таке транзакція? -Транзакції складаються з двох компонентів: -[повідомлення](/docs/uk/terminology.md#message) -і -[списку підписів](/docs/uk/terminology.md#signature). -Повідомлення транзакції містить основну інформацію та складається з чотирьох компонентів: +Транзакції складаються з двох компонентів: +[повідомлення](/docs/uk/terminology.md#message) і +[списку підписів](/docs/uk/terminology.md#signature). Повідомлення транзакції +містить основну інформацію та складається з чотирьох компонентів: - **заголовок** з метаданими про транзакцію, - **список інструкцій** для виконання, - **список акаунтів**, які потрібно завантажити, - та **“недавній blockhash”**. -У цій статті ми зосередимося на -[недавньому blockhash](/docs/uk/terminology.md#blockhash), -оскільки він відіграє важливу роль у підтвердженні транзакції. +У цій статті ми зосередимося на +[недавньому blockhash](/docs/uk/terminology.md#blockhash), оскільки він відіграє +важливу роль у підтвердженні транзакції. ### Життєвий цикл транзакції -Нижче наведено основні етапи життєвого циклу транзакції. У цій статті розглядаються всі етапи, крім 1 і 4. +Нижче наведено основні етапи життєвого циклу транзакції. У цій статті +розглядаються всі етапи, крім 1 і 4. -1. Створення заголовка та списку інструкцій разом із переліком акаунтів, які потрібно прочитати або записати. -2. Отримання недавнього blockhash та його використання для підготовки повідомлення транзакції. +1. Створення заголовка та списку інструкцій разом із переліком акаунтів, які + потрібно прочитати або записати. +2. Отримання недавнього blockhash та його використання для підготовки + повідомлення транзакції. 3. Симуляція транзакції, щоб переконатися, що вона поводиться очікувано. -4. Запит користувача на підписання підготовленого повідомлення транзакції за допомогою його приватного ключа. -5. Відправка транзакції до RPC-вузла, який намагається передати її поточному виробнику блоків. +4. Запит користувача на підписання підготовленого повідомлення транзакції за + допомогою його приватного ключа. +5. Відправка транзакції до RPC-вузла, який намагається передати її поточному + виробнику блоків. 6. Очікування, що виробник блоку перевірить і додасть транзакцію до свого блоку. -7. Підтвердження того, що транзакція або була включена в блок, або закінчився її термін дії. +7. Підтвердження того, що транзакція або була включена в блок, або закінчився її + термін дії. ### Що таке Blockhash? -[“Blockhash”](/docs/uk/terminology.md#blockhash) -означає останній Proof of History (PoH) хеш для -[“слота”](/docs/uk/terminology.md#slot) -(опис нижче). Оскільки Solana використовує PoH як довірений годинник, недавній blockhash транзакції можна розглядати як **мітку часу**. +[“Blockhash”](/docs/uk/terminology.md#blockhash) означає останній Proof of +History (PoH) хеш для [“слота”](/docs/uk/terminology.md#slot) (опис нижче). +Оскільки Solana використовує PoH як довірений годинник, недавній blockhash +транзакції можна розглядати як **мітку часу**. ### Коротке нагадування про Proof of History -Механізм Proof of History у Solana використовує довгий ланцюг рекурсивних хешів SHA-256 для створення довіреного годинника. Назва “історія” походить від того, що виробники блоків додають хеш ідентифікаторів транзакцій у потік, щоб зафіксувати, які транзакції були оброблені в їхньому блоці. +Механізм Proof of History у Solana використовує довгий ланцюг рекурсивних хешів +SHA-256 для створення довіреного годинника. Назва “історія” походить від того, +що виробники блоків додають хеш ідентифікаторів транзакцій у потік, щоб +зафіксувати, які транзакції були оброблені в їхньому блоці. -[Обчислення PoH-хешу](https://github.com/anza-xyz/agave/blob/aa0922d6845e119ba466f88497e8209d1c82febc/entry/src/poh.rs#L79): +[Обчислення PoH-хешу](https://github.com/anza-xyz/agave/blob/aa0922d6845e119ba466f88497e8209d1c82febc/entry/src/poh.rs#L79): `next_hash = hash(prev_hash, hash(transaction_ids))`. -PoH може використовуватися як довірений годинник, оскільки кожен хеш має бути створений послідовно. Кожен згенерований блок містить blockhash і список контрольних точок хешів, званих “ticks,” які дозволяють валідаторам перевіряти весь ланцюг хешів паралельно та доводити, що певний час дійсно минув. +PoH може використовуватися як довірений годинник, оскільки кожен хеш має бути +створений послідовно. Кожен згенерований блок містить blockhash і список +контрольних точок хешів, званих “ticks,” які дозволяють валідаторам перевіряти +весь ланцюг хешів паралельно та доводити, що певний час дійсно минув. ## Закінчення строку дії транзакції -За замовчуванням усі транзакції Solana закінчують строк дії, якщо їх не включено в блок протягом певного періоду часу. **Переважна більшість** проблем із підтвердженням транзакцій пов'язана з тим, як RPC-вузли та валідатори виявляють і обробляють **прострочені** транзакції. Чітке розуміння механізму закінчення строку дії транзакції допоможе вам діагностувати більшість проблем із підтвердженням транзакцій. +За замовчуванням усі транзакції Solana закінчують строк дії, якщо їх не включено +в блок протягом певного періоду часу. **Переважна більшість** проблем із +підтвердженням транзакцій пов'язана з тим, як RPC-вузли та валідатори виявляють +і обробляють **прострочені** транзакції. Чітке розуміння механізму закінчення +строку дії транзакції допоможе вам діагностувати більшість проблем із +підтвердженням транзакцій. ### Як працює закінчення строку дії транзакції? -Кожна транзакція містить “недавній blockhash,” який використовується як часовий штамп PoH і закінчується, коли цей blockhash більше не вважається “достатньо недавнім.” - -Коли кожен блок завершується (тобто досягається максимальна висота тиків, -[визначена](https://github.com/anza-xyz/agave/blob/0588ecc6121ba026c65600d117066dbdfaf63444/runtime/src/bank.rs#L3269-L3271), -до "кордону блоку"), фінальний хеш блоку додається до `BlockhashQueue`, яка зберігає максимум -[300 найновіших blockhash](https://github.com/anza-xyz/agave/blob/e0b0bcc80380da34bb63364cc393801af1e1057f/sdk/program/src/clock.rs#L123-L126). -Під час обробки транзакцій валідатори Solana перевіряють, чи зберігається недавній blockhash транзакції серед останніх 151 записаних хешів (так званий "максимальний вік обробки"). Якщо недавній blockhash транзакції -[старший за цей вік](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/runtime/src/bank.rs#L3570-L3571), +Кожна транзакція містить “недавній blockhash,” який використовується як часовий +штамп PoH і закінчується, коли цей blockhash більше не вважається “достатньо +недавнім.” + +Коли кожен блок завершується (тобто досягається максимальна висота тиків, +[визначена](https://github.com/anza-xyz/agave/blob/0588ecc6121ba026c65600d117066dbdfaf63444/runtime/src/bank.rs#L3269-L3271), +до "кордону блоку"), фінальний хеш блоку додається до `BlockhashQueue`, яка +зберігає максимум +[300 найновіших blockhash](https://github.com/anza-xyz/agave/blob/e0b0bcc80380da34bb63364cc393801af1e1057f/sdk/program/src/clock.rs#L123-L126). +Під час обробки транзакцій валідатори Solana перевіряють, чи зберігається +недавній blockhash транзакції серед останніх 151 записаних хешів (так званий +"максимальний вік обробки"). Якщо недавній blockhash транзакції +[старший за цей вік](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/runtime/src/bank.rs#L3570-L3571), транзакція не обробляється. -> Завдяки поточному -> [максимальному віку обробки, що становить 150](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L129-L131) -> і тому, що "вік" blockhash у черзі є -> [нульовим індексом](https://github.com/anza-xyz/agave/blob/992a398fe8ea29ec4f04d081ceef7664960206f4/accounts-db/src/blockhash_queue.rs#L248-L274), -> фактично є 151 blockhash, які вважаються "достатньо недавніми" і дійсними для обробки. +> Завдяки поточному +> [максимальному віку обробки, що становить 150](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L129-L131) +> і тому, що "вік" blockhash у черзі є +> [нульовим індексом](https://github.com/anza-xyz/agave/blob/992a398fe8ea29ec4f04d081ceef7664960206f4/accounts-db/src/blockhash_queue.rs#L248-L274), +> фактично є 151 blockhash, які вважаються "достатньо недавніми" і дійсними для +> обробки. -Оскільки [слоти](/docs/uk/terminology.md#slot) (тобто періоди часу, протягом яких валідатор може створити блок) налаштовані на тривалість близько -[400 мс](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L107-L109), -але можуть коливатися між 400 мс і 600 мс, певний blockhash можна використовувати в транзакціях приблизно протягом 60–90 секунд, перш ніж він вважатиметься простроченим у середовищі виконання. +Оскільки [слоти](/docs/uk/terminology.md#slot) (тобто періоди часу, протягом +яких валідатор може створити блок) налаштовані на тривалість близько +[400 мс](https://github.com/anza-xyz/agave/blob/cb2fd2b632f16a43eff0c27af7458e4e97512e31/sdk/program/src/clock.rs#L107-L109), +але можуть коливатися між 400 мс і 600 мс, певний blockhash можна +використовувати в транзакціях приблизно протягом 60–90 секунд, перш ніж він +вважатиметься простроченим у середовищі виконання. ### Приклад закінчення строку дії транзакції @@ -101,16 +131,26 @@ PoH може використовуватися як довірений годи 1. Валідатор активно створює новий блок для поточного слота. 2. Валідатор отримує транзакцію від користувача з недавнім blockhash `abcd...`. -3. Валідатор перевіряє цей blockhash `abcd...` у списку недавніх blockhash у `BlockhashQueue` і виявляє, що він був створений 151 блок тому. -4. Оскільки йому рівно 151 блок, транзакція ще не прострочена та може бути оброблена. -5. Але зачекайте: перед обробкою транзакції валідатор завершує створення наступного блоку та додає його до `BlockhashQueue`. Потім валідатор починає створювати блок для наступного слота (валідатори можуть створювати блоки протягом 4 послідовних слотів). -6. Валідатор перевіряє ту ж транзакцію ще раз і виявляє, що їй тепер 152 блоки. Вона відхиляється, оскільки занадто стара. :( +3. Валідатор перевіряє цей blockhash `abcd...` у списку недавніх blockhash у + `BlockhashQueue` і виявляє, що він був створений 151 блок тому. +4. Оскільки йому рівно 151 блок, транзакція ще не прострочена та може бути + оброблена. +5. Але зачекайте: перед обробкою транзакції валідатор завершує створення + наступного блоку та додає його до `BlockhashQueue`. Потім валідатор починає + створювати блок для наступного слота (валідатори можуть створювати блоки + протягом 4 послідовних слотів). +6. Валідатор перевіряє ту ж транзакцію ще раз і виявляє, що їй тепер 152 блоки. + Вона відхиляється, оскільки занадто стара. :( ## Чому транзакції закінчують строк дії? -Це робиться для того, щоб валідатори могли уникнути повторної обробки тієї ж транзакції. +Це робиться для того, щоб валідатори могли уникнути повторної обробки тієї ж +транзакції. -Наївний підхід для запобігання повторній обробці полягав би в перевірці кожної нової транзакції з усією історією транзакцій блокчейна. Але завдяки тому, що транзакції закінчують строк дії за короткий період часу, валідаторам потрібно перевіряти лише відносно невеликий набір **недавніх** транзакцій. +Наївний підхід для запобігання повторній обробці полягав би в перевірці кожної +нової транзакції з усією історією транзакцій блокчейна. Але завдяки тому, що +транзакції закінчують строк дії за короткий період часу, валідаторам потрібно +перевіряти лише відносно невеликий набір **недавніх** транзакцій. ### Other blockchains @@ -126,124 +166,229 @@ processing. ### Інші блокчейни -Підхід Solana до запобігання повторній обробці транзакцій значно відрізняється від інших блокчейнів. Наприклад, Ethereum використовує лічильник (nonce) для кожного відправника транзакцій і обробляє лише транзакції, які використовують наступний дійсний nonce. +Підхід Solana до запобігання повторній обробці транзакцій значно відрізняється +від інших блокчейнів. Наприклад, Ethereum використовує лічильник (nonce) для +кожного відправника транзакцій і обробляє лише транзакції, які використовують +наступний дійсний nonce. -Підхід Ethereum є простим для реалізації валідаторами, але може викликати проблеми для користувачів. Багато хто стикався із ситуаціями, коли їхні транзакції Ethereum залишалися в стані **очікування** протягом тривалого часу, а всі подальші транзакції з більшими значеннями nonce блокувалися. +Підхід Ethereum є простим для реалізації валідаторами, але може викликати +проблеми для користувачів. Багато хто стикався із ситуаціями, коли їхні +транзакції Ethereum залишалися в стані **очікування** протягом тривалого часу, а +всі подальші транзакції з більшими значеннями nonce блокувалися. ### Переваги на Solana Solana має кілька переваг у цьому підході: -1. Один платник комісії може надсилати кілька транзакцій одночасно, які можуть оброблятися в будь-якому порядку. Це може статися, якщо ви використовуєте кілька додатків одночасно. -2. Якщо транзакція не була додана до блоку та закінчила строк дії, користувачі можуть спробувати знову, знаючи, що їхня попередня транзакція **ніколи** не буде оброблена. +1. Один платник комісії може надсилати кілька транзакцій одночасно, які можуть + оброблятися в будь-якому порядку. Це може статися, якщо ви використовуєте + кілька додатків одночасно. +2. Якщо транзакція не була додана до блоку та закінчила строк дії, користувачі + можуть спробувати знову, знаючи, що їхня попередня транзакція **ніколи** не + буде оброблена. -Відсутність використання лічильників робить досвід роботи з Solana більш зрозумілим для користувачів, оскільки вони швидше отримують результат — успіх, невдачу або закінчення строку дії — та уникають тривалого стану очікування. +Відсутність використання лічильників робить досвід роботи з Solana більш +зрозумілим для користувачів, оскільки вони швидше отримують результат — успіх, +невдачу або закінчення строку дії — та уникають тривалого стану очікування. ### Недоліки на Solana Звісно, є й недоліки: -1. Валідатори повинні активно відстежувати набір усіх оброблених ідентифікаторів транзакцій, щоб запобігти їх повторній обробці. -2. Якщо час закінчення строку дії надто короткий, користувачі можуть не встигнути надіслати свої транзакції до того, як вони стануть недійсними. +1. Валідатори повинні активно відстежувати набір усіх оброблених ідентифікаторів + транзакцій, щоб запобігти їх повторній обробці. +2. Якщо час закінчення строку дії надто короткий, користувачі можуть не + встигнути надіслати свої транзакції до того, як вони стануть недійсними. -Ці недоліки показують компроміс у тому, як налаштовано строк дії транзакцій. Якщо збільшити час закінчення строку дії, валідаторам доведеться використовувати більше пам’яті для відстеження транзакцій. Якщо ж скоротити строк дії, користувачам буде важче встигнути надіслати свої транзакції. +Ці недоліки показують компроміс у тому, як налаштовано строк дії транзакцій. +Якщо збільшити час закінчення строку дії, валідаторам доведеться використовувати +більше пам’яті для відстеження транзакцій. Якщо ж скоротити строк дії, +користувачам буде важче встигнути надіслати свої транзакції. -Наразі кластери Solana вимагають, щоб транзакції використовували blockhash, який не старший за 151 блок. +Наразі кластери Solana вимагають, щоб транзакції використовували blockhash, який +не старший за 151 блок. -> У цьому [питанні GitHub](https://github.com/solana-labs/solana/issues/23582) надані розрахунки, які оцінюють, що валідаторам mainnet-beta потрібно близько 150 МБ пам’яті для відстеження транзакцій. У майбутньому це можна оптимізувати, не скорочуючи строк дії транзакцій, як зазначено в цьому обговоренні. +> У цьому [питанні GitHub](https://github.com/solana-labs/solana/issues/23582) +> надані розрахунки, які оцінюють, що валідаторам mainnet-beta потрібно близько +> 150 МБ пам’яті для відстеження транзакцій. У майбутньому це можна +> оптимізувати, не скорочуючи строк дії транзакцій, як зазначено в цьому +> обговоренні. ## Поради щодо підтвердження транзакцій -Як зазначалося раніше, blockhash закінчують строк дії через період, який може тривати всього **одну хвилину**, коли слоти обробляються з цільовим часом 400 мс. +Як зазначалося раніше, blockhash закінчують строк дії через період, який може +тривати всього **одну хвилину**, коли слоти обробляються з цільовим часом 400 +мс. -Одна хвилина — це не багато, враховуючи, що клієнту потрібно отримати недавній blockhash, дочекатися підписання транзакції користувачем, а потім сподіватися, що надіслана транзакція досягне лідера, який погодиться її обробити. Розглянемо кілька порад, які допоможуть уникнути невдач підтвердження через закінчення строку дії транзакцій. +Одна хвилина — це не багато, враховуючи, що клієнту потрібно отримати недавній +blockhash, дочекатися підписання транзакції користувачем, а потім сподіватися, +що надіслана транзакція досягне лідера, який погодиться її обробити. Розглянемо +кілька порад, які допоможуть уникнути невдач підтвердження через закінчення +строку дії транзакцій. ### Отримуйте blockhash із відповідним рівнем підтвердження -З огляду на короткий період закінчення строку дії, клієнти та додатки повинні допомагати користувачам створювати транзакції з blockhash, який є максимально недавнім. +З огляду на короткий період закінчення строку дії, клієнти та додатки повинні +допомагати користувачам створювати транзакції з blockhash, який є максимально +недавнім. -Коли ви отримуєте blockhash, рекомендованим RPC API є [`getLatestBlockhash`](/docs/uk/rpc/http/getLatestBlockhash.mdx). За замовчуванням цей API використовує рівень підтвердження `finalized`, щоб повернути blockhash останнього фіналізованого блоку. Проте ви можете змінити цю поведінку, встановивши параметр `commitment` на інший рівень підтвердження. +Коли ви отримуєте blockhash, рекомендованим RPC API є +[`getLatestBlockhash`](/docs/uk/rpc/http/getLatestBlockhash.mdx). За +замовчуванням цей API використовує рівень підтвердження `finalized`, щоб +повернути blockhash останнього фіналізованого блоку. Проте ви можете змінити цю +поведінку, встановивши параметр `commitment` на інший рівень підтвердження. **Рекомендація** -Рівень підтвердження `confirmed` майже завжди слід використовувати для запитів RPC, оскільки він зазвичай лише на кілька слотів відстає від рівня `processed` і має дуже низьку ймовірність належати до відхиленого [форку](https://docs.anza.xyz/consensus/fork-generation). +Рівень підтвердження `confirmed` майже завжди слід використовувати для запитів +RPC, оскільки він зазвичай лише на кілька слотів відстає від рівня `processed` і +має дуже низьку ймовірність належати до відхиленого +[форку](https://docs.anza.xyz/consensus/fork-generation). Але ви також можете розглянути інші варіанти: -- Вибір `processed` дозволяє отримати найбільш недавній blockhash порівняно з іншими рівнями підтвердження, що дає більше часу на підготовку і обробку транзакції. Однак через поширеність форків у блокчейні Solana близько 5% блоків не потрапляють у фіналізований кластер, що створює ризик того, що ваша транзакція використовує blockhash, що належить до відкинутого форку. Транзакції з такими blockhash ніколи не будуть вважатися недавніми у фіналізованому блокчейні. -- Використання [рівня підтвердження за замовчуванням](/docs/uk/rpc#default-commitment) `finalized` виключає ризик того, що вибраний blockhash належатиме до відкинутого форку. Однак це має компроміс: зазвичай є щонайменше 32 слоти різниці між найбільш недавнім підтвердженим блоком і найбільш недавнім фіналізованим блоком. Це значно зменшує строк дії ваших транзакцій приблизно на 13 секунд, що може бути ще більш суттєвим за нестабільних умов кластеру. +- Вибір `processed` дозволяє отримати найбільш недавній blockhash порівняно з + іншими рівнями підтвердження, що дає більше часу на підготовку і обробку + транзакції. Однак через поширеність форків у блокчейні Solana близько 5% + блоків не потрапляють у фіналізований кластер, що створює ризик того, що ваша + транзакція використовує blockhash, що належить до відкинутого форку. + Транзакції з такими blockhash ніколи не будуть вважатися недавніми у + фіналізованому блокчейні. +- Використання + [рівня підтвердження за замовчуванням](/docs/uk/rpc#default-commitment) + `finalized` виключає ризик того, що вибраний blockhash належатиме до + відкинутого форку. Однак це має компроміс: зазвичай є щонайменше 32 слоти + різниці між найбільш недавнім підтвердженим блоком і найбільш недавнім + фіналізованим блоком. Це значно зменшує строк дії ваших транзакцій приблизно + на 13 секунд, що може бути ще більш суттєвим за нестабільних умов кластеру. ### Використовуйте відповідний рівень підтвердження для preflight -Якщо ваша транзакція використовує blockhash, отриманий з одного RPC-вузла, але надсилається або симулюється на іншому, можуть виникнути проблеми через затримку одного з вузлів. +Якщо ваша транзакція використовує blockhash, отриманий з одного RPC-вузла, але +надсилається або симулюється на іншому, можуть виникнути проблеми через затримку +одного з вузлів. -Коли RPC-вузли отримують запит `sendTransaction`, вони намагаються визначити строк дії транзакції, використовуючи найбільш недавній фіналізований блок або блок, вибраний параметром `preflightCommitment`. **Дуже поширена проблема** виникає, якщо blockhash транзакції створений після блоку, який використовується для обчислення строку дії. У такому випадку RPC-вузол лише один раз пересилає транзакцію, а потім **видаляє** її. +Коли RPC-вузли отримують запит `sendTransaction`, вони намагаються визначити +строк дії транзакції, використовуючи найбільш недавній фіналізований блок або +блок, вибраний параметром `preflightCommitment`. **Дуже поширена проблема** +виникає, якщо blockhash транзакції створений після блоку, який використовується +для обчислення строку дії. У такому випадку RPC-вузол лише один раз пересилає +транзакцію, а потім **видаляє** її. -Аналогічно, при отриманні запиту `simulateTransaction` RPC-вузли симулюють транзакцію, використовуючи найбільш недавній фіналізований блок або блок, вибраний параметром `preflightCommitment`. Якщо вибраний блок для симуляції старіший за blockhash транзакції, симуляція завершиться помилкою “blockhash not found”. +Аналогічно, при отриманні запиту `simulateTransaction` RPC-вузли симулюють +транзакцію, використовуючи найбільш недавній фіналізований блок або блок, +вибраний параметром `preflightCommitment`. Якщо вибраний блок для симуляції +старіший за blockhash транзакції, симуляція завершиться помилкою “blockhash not +found”. **Рекомендація** -Навіть якщо ви використовуєте `skipPreflight`, **завжди** встановлюйте параметр `preflightCommitment` на той самий рівень підтвердження, який використовувався для отримання blockhash транзакції, як для запитів `sendTransaction`, так і `simulateTransaction`. +Навіть якщо ви використовуєте `skipPreflight`, **завжди** встановлюйте параметр +`preflightCommitment` на той самий рівень підтвердження, який використовувався +для отримання blockhash транзакції, як для запитів `sendTransaction`, так і +`simulateTransaction`. ### Уникайте відставання RPC-вузлів під час надсилання транзакцій -Якщо ваш додаток використовує сервіс пулу RPC або якщо кінцева точка RPC відрізняється між створенням транзакції та її надсиланням, будьте обережні зі сценаріями, коли один RPC-вузол відстає від іншого. Наприклад, якщо blockhash транзакції отримано з одного RPC-вузла, а транзакція надсилається на інший для обробки або симуляції, другий RPC-вузол може відставати. +Якщо ваш додаток використовує сервіс пулу RPC або якщо кінцева точка RPC +відрізняється між створенням транзакції та її надсиланням, будьте обережні зі +сценаріями, коли один RPC-вузол відстає від іншого. Наприклад, якщо blockhash +транзакції отримано з одного RPC-вузла, а транзакція надсилається на інший для +обробки або симуляції, другий RPC-вузол може відставати. **Рекомендація** -Для запитів `sendTransaction` клієнти повинні повторно надсилати транзакцію до RPC-вузла на частих інтервалах, щоб у випадку, якщо RPC-вузол трохи відстає від кластеру, він врешті-решт виявив транзакцію та її строк дії. +Для запитів `sendTransaction` клієнти повинні повторно надсилати транзакцію до +RPC-вузла на частих інтервалах, щоб у випадку, якщо RPC-вузол трохи відстає від +кластеру, він врешті-решт виявив транзакцію та її строк дії. -Для запитів `simulateTransaction` клієнти повинні використовувати параметр -[`replaceRecentBlockhash`](/docs/uk/rpc/http/simulateTransaction.mdx), щоб інструктувати RPC-вузол замінювати blockhash симульованої транзакції на blockhash, який завжди буде дійсним для симуляції. +Для запитів `simulateTransaction` клієнти повинні використовувати параметр +[`replaceRecentBlockhash`](/docs/uk/rpc/http/simulateTransaction.mdx), щоб +інструктувати RPC-вузол замінювати blockhash симульованої транзакції на +blockhash, який завжди буде дійсним для симуляції. ### Уникайте повторного використання застарілих blockhash -Навіть якщо ваш додаток отримав дуже недавній blockhash, переконайтеся, що ви не використовуєте його надто довго. Ідеальний сценарій — отримати свіжий blockhash безпосередньо перед підписанням транзакції. +Навіть якщо ваш додаток отримав дуже недавній blockhash, переконайтеся, що ви не +використовуєте його надто довго. Ідеальний сценарій — отримати свіжий blockhash +безпосередньо перед підписанням транзакції. **Рекомендація для додатків** -Часто запитуйте нові blockhash, щоб забезпечити готовність вашого додатка до створення транзакції, коли користувач виконує дію. +Часто запитуйте нові blockhash, щоб забезпечити готовність вашого додатка до +створення транзакції, коли користувач виконує дію. **Рекомендація для гаманців** -Часто запитуйте нові blockhash та оновлюйте blockhash транзакції перед підписанням, щоб забезпечити її актуальність. +Часто запитуйте нові blockhash та оновлюйте blockhash транзакції перед +підписанням, щоб забезпечити її актуальність. ### Використовуйте надійні RPC-вузли для отримання blockhash -RPC-вузли можуть відставати від кластеру через навантаження або інші причини, повертаючи blockhash, який майже вичерпав строк дії. +RPC-вузли можуть відставати від кластеру через навантаження або інші причини, +повертаючи blockhash, який майже вичерпав строк дії. **Рекомендація** Моніторте стан RPC-вузлів, використовуючи такі методи: -1. Викликайте API - [`getSlot`](/docs/uk/rpc/http/getSlot.mdx) з рівнем підтвердження `processed` для отримання останнього обробленого слота вузла та порівняйте його з - [`getMaxShredInsertSlot`](/docs/uk/rpc/http/getMaxShredInsertSlot.mdx), щоб оцінити відставання вузла. -2. Використовуйте RPC API `getLatestBlockhash` з рівнем підтвердження `confirmed` на кількох різних RPC-вузлах та обирайте blockhash від вузла, який повертає найвищий слот для свого [контекстного слоту](/docs/uk/rpc/index.mdx#rpcresponse-structure). +1. Викликайте API [`getSlot`](/docs/uk/rpc/http/getSlot.mdx) з рівнем + підтвердження `processed` для отримання останнього обробленого слота вузла та + порівняйте його з + [`getMaxShredInsertSlot`](/docs/uk/rpc/http/getMaxShredInsertSlot.mdx), щоб + оцінити відставання вузла. +2. Використовуйте RPC API `getLatestBlockhash` з рівнем підтвердження + `confirmed` на кількох різних RPC-вузлах та обирайте blockhash від вузла, + який повертає найвищий слот для свого + [контекстного слоту](/docs/uk/rpc/index.mdx#rpcresponse-structure). ### Зачекайте достатньо довго перед закінченням терміну дії **Рекомендація** -При виклику RPC API [`getLatestBlockhash`](/docs/uk/rpc/http/getLatestBlockhash.mdx) для отримання останнього blockhash вашої транзакції зверніть увагу на `lastValidBlockHeight` у відповіді. +При виклику RPC API +[`getLatestBlockhash`](/docs/uk/rpc/http/getLatestBlockhash.mdx) для отримання +останнього blockhash вашої транзакції зверніть увагу на `lastValidBlockHeight` у +відповіді. -Потім викликайте RPC API [`getBlockHeight`](/docs/uk/rpc/http/getBlockHeight.mdx) з рівнем підтвердження `confirmed`, поки він не поверне висоту блоку, більшу за попередньо отриманий `lastValidBlockHeight`. +Потім викликайте RPC API +[`getBlockHeight`](/docs/uk/rpc/http/getBlockHeight.mdx) з рівнем підтвердження +`confirmed`, поки він не поверне висоту блоку, більшу за попередньо отриманий +`lastValidBlockHeight`. ### Розгляньте використання "довготривалих" транзакцій -Іноді уникнути проблем із закінченням терміну дії транзакції дуже важко (наприклад, при офлайн-підписанні або нестабільності кластера). Якщо попередні поради не підходять для вашого випадку використання, ви можете перейти на використання довготривалих транзакцій (вони вимагають трохи налаштувань). +Іноді уникнути проблем із закінченням терміну дії транзакції дуже важко +(наприклад, при офлайн-підписанні або нестабільності кластера). Якщо попередні +поради не підходять для вашого випадку використання, ви можете перейти на +використання довготривалих транзакцій (вони вимагають трохи налаштувань). -Щоб почати використовувати довготривалі транзакції, користувач спочатку повинен подати транзакцію, яка -[викликає інструкції для створення спеціального "nonce" облікового запису на блокчейні](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.create_nonce_account.html) і зберігає в ньому "довготривалий blockhash". У будь-який момент у майбутньому (доки nonce-аккаунт ще не використаний) користувач може створити довготривалу транзакцію, дотримуючись двох правил: +Щоб почати використовувати довготривалі транзакції, користувач спочатку повинен +подати транзакцію, яка +[викликає інструкції для створення спеціального "nonce" облікового запису на блокчейні](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.create_nonce_account.html) +і зберігає в ньому "довготривалий blockhash". У будь-який момент у майбутньому +(доки nonce-аккаунт ще не використаний) користувач може створити довготривалу +транзакцію, дотримуючись двох правил: -1. Список інструкцій повинен починатися з [системної інструкції "advance nonce"](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.advance_nonce_account.html), яка завантажує їх nonce-аккаунт. -2. Blockhash транзакції повинен дорівнювати довготривалому blockhash, збереженому nonce-аккаунтом на блокчейні. +1. Список інструкцій повинен починатися з + [системної інструкції "advance nonce"](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.advance_nonce_account.html), + яка завантажує їх nonce-аккаунт. +2. Blockhash транзакції повинен дорівнювати довготривалому blockhash, + збереженому nonce-аккаунтом на блокчейні. Ось як Solana обробляє ці довготривалі транзакції: -1. Якщо blockhash транзакції більше не є "недавнім", система перевіряє, чи починається список інструкцій транзакції з інструкції "advance nonce". +1. Якщо blockhash транзакції більше не є "недавнім", система перевіряє, чи + починається список інструкцій транзакції з інструкції "advance nonce". 2. Якщо так, система завантажує nonce-аккаунт, вказаний у цій інструкції. -3. Потім перевіряє, чи збережений довготривалий blockhash відповідає blockhash транзакції. -4. Нарешті, система оновлює blockhash nonce-аккаунту до останнього недавнього blockhash, щоб гарантувати, що ця ж транзакція не може бути оброблена повторно. - -Детальніше про роботу цих довготривалих транзакцій ви можете дізнатися з [оригінальної пропозиції](https://docs.anza.xyz/implemented-proposals/durable-tx-nonces) та [ознайомитися з прикладом](/content/guides/advanced/introduction-to-durable-nonces.md) у документації Solana. +3. Потім перевіряє, чи збережений довготривалий blockhash відповідає blockhash + транзакції. +4. Нарешті, система оновлює blockhash nonce-аккаунту до останнього недавнього + blockhash, щоб гарантувати, що ця ж транзакція не може бути оброблена + повторно. + +Детальніше про роботу цих довготривалих транзакцій ви можете дізнатися з +[оригінальної пропозиції](https://docs.anza.xyz/implemented-proposals/durable-tx-nonces) +та +[ознайомитися з прикладом](/content/guides/advanced/introduction-to-durable-nonces.md) +у документації Solana. diff --git a/docs/locales/uk/advanced/lookup-tables.md b/docs/locales/uk/advanced/lookup-tables.md index 360f13a6a..3bedf440d 100644 --- a/docs/locales/uk/advanced/lookup-tables.md +++ b/docs/locales/uk/advanced/lookup-tables.md @@ -2,28 +2,45 @@ sidebarSortOrder: 4 title: Таблиці пошуку адрес description: - Дізнайтеся, як використовувати таблиці пошуку адрес Solana (ALTs) для ефективної обробки до 64 адрес у кожній транзакції. Створюйте, розширюйте та використовуйте таблиці пошуку за допомогою web3.js. + Дізнайтеся, як використовувати таблиці пошуку адрес Solana (ALTs) для + ефективної обробки до 64 адрес у кожній транзакції. Створюйте, розширюйте та + використовуйте таблиці пошуку за допомогою web3.js. --- -Таблиці пошуку адрес, зазвичай відомі як "_lookup tables_" або скорочено "_ALTs_", дозволяють розробникам створювати колекції пов’язаних адрес для ефективного завантаження більшої кількості адрес в одній транзакції. +Таблиці пошуку адрес, зазвичай відомі як "_lookup tables_" або скорочено +"_ALTs_", дозволяють розробникам створювати колекції пов’язаних адрес для +ефективного завантаження більшої кількості адрес в одній транзакції. -Оскільки кожна транзакція в блокчейні Solana вимагає переліку всіх адрес, з якими вона взаємодіє, цей перелік фактично обмежується 32 адресами на транзакцію. Завдяки [Таблицям пошуку адрес](/docs/uk/advanced/lookup-tables.md) це обмеження можна збільшити до 64 адрес у кожній транзакції. +Оскільки кожна транзакція в блокчейні Solana вимагає переліку всіх адрес, з +якими вона взаємодіє, цей перелік фактично обмежується 32 адресами на +транзакцію. Завдяки [Таблицям пошуку адрес](/docs/uk/advanced/lookup-tables.md) +це обмеження можна збільшити до 64 адрес у кожній транзакції. ## Стиснення адрес на блокчейні -Після того, як усі необхідні адреси були збережені на блокчейні у Таблиці пошуку адрес, кожну адресу можна посилатися в транзакції за її 1-байтовим індексом у таблиці (замість повної 32-байтової адреси). Цей метод пошуку ефективно "_стискає_" 32-байтову адресу до 1-байтового значення індексу. +Після того, як усі необхідні адреси були збережені на блокчейні у Таблиці пошуку +адрес, кожну адресу можна посилатися в транзакції за її 1-байтовим індексом у +таблиці (замість повної 32-байтової адреси). Цей метод пошуку ефективно +"_стискає_" 32-байтову адресу до 1-байтового значення індексу. -Таке "_стиснення_" дозволяє зберігати до 256 адрес у одній таблиці пошуку для використання у будь-якій транзакції. +Таке "_стиснення_" дозволяє зберігати до 256 адрес у одній таблиці пошуку для +використання у будь-якій транзакції. ## Версійні транзакції -Щоб використовувати Таблицю пошуку адрес у транзакції, розробники повинні застосовувати транзакції версії v0, які були запроваджені з новим форматом [Версійних транзакцій](/docs/uk/advanced/versions.md). +Щоб використовувати Таблицю пошуку адрес у транзакції, розробники повинні +застосовувати транзакції версії v0, які були запроваджені з новим форматом +[Версійних транзакцій](/docs/uk/advanced/versions.md). ## Як створити таблицю пошуку адрес -Створення нової таблиці пошуку за допомогою бібліотеки `@solana/web3.js` подібне до старішого формату `legacy` транзакцій, але має певні відмінності. +Створення нової таблиці пошуку за допомогою бібліотеки `@solana/web3.js` подібне +до старішого формату `legacy` транзакцій, але має певні відмінності. -Використовуючи бібліотеку `@solana/web3.js`, ви можете скористатися функцією [`createLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#createLookupTable) для створення інструкції, необхідної для створення нової таблиці пошуку, а також для визначення її адреси. +Використовуючи бібліотеку `@solana/web3.js`, ви можете скористатися функцією +[`createLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#createLookupTable) +для створення інструкції, необхідної для створення нової таблиці пошуку, а також +для визначення її адреси. ```js const web3 = require("@solana/web3.js"); @@ -48,11 +65,18 @@ console.log("lookup table address:", lookupTableAddress.toBase58()); // send the `lookupTableInst` instruction in a transaction ``` -> ПРИМІТКА: Таблиці пошуку адрес можуть бути **створені** за допомогою як транзакцій `v0`, так і `legacy`. Але виконуюче середовище Solana може отримувати та обробляти додаткові адреси в таблиці пошуку лише під час використання [Версійних транзакцій v0](/docs/uk/advanced/versions.md#current-transaction-versions). +> ПРИМІТКА: Таблиці пошуку адрес можуть бути **створені** за допомогою як +> транзакцій `v0`, так і `legacy`. Але виконуюче середовище Solana може +> отримувати та обробляти додаткові адреси в таблиці пошуку лише під час +> використання +> [Версійних транзакцій v0](/docs/uk/advanced/versions.md#current-transaction-versions). ## Додавання адрес до таблиці пошуку -Додавання адрес до таблиці пошуку відоме як "_розширення_" ("_extending_"). Використовуючи бібліотеку `@solana/web3.js`, ви можете створити нову інструкцію для _розширення_ за допомогою методу [`extendLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#extendLookupTable): +Додавання адрес до таблиці пошуку відоме як "_розширення_" ("_extending_"). +Використовуючи бібліотеку `@solana/web3.js`, ви можете створити нову інструкцію +для _розширення_ за допомогою методу +[`extendLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/AddressLookupTableProgram.html#extendLookupTable): ```js // add addresses to the `lookupTableAddress` table via an `extend` instruction @@ -71,13 +95,22 @@ const extendInstruction = web3.AddressLookupTableProgram.extendLookupTable({ // to insert the listing of `addresses` into your lookup table with address `lookupTableAddress` ``` -> ПРИМІТКА: Через ті самі обмеження пам'яті транзакцій `legacy`, будь-яка транзакція, яка використовується для _розширення_ таблиці пошуку адрес, також обмежена в кількості адрес, які можна додати одночасно. Через це вам потрібно буде використовувати кілька транзакцій, щоб _розширити_ будь-яку таблицю більшою кількістю адрес (приблизно 20), ніж це дозволяють обмеження пам'яті однієї транзакції. +> ПРИМІТКА: Через ті самі обмеження пам'яті транзакцій `legacy`, будь-яка +> транзакція, яка використовується для _розширення_ таблиці пошуку адрес, також +> обмежена в кількості адрес, які можна додати одночасно. Через це вам потрібно +> буде використовувати кілька транзакцій, щоб _розширити_ будь-яку таблицю +> більшою кількістю адрес (приблизно 20), ніж це дозволяють обмеження пам'яті +> однієї транзакції. -Після того як ці адреси були вставлені в таблицю та збережені в блокчейні, ви зможете використовувати таблицю пошуку адрес у майбутніх транзакціях. Це дозволяє включити до 64 адрес у цих транзакціях. +Після того як ці адреси були вставлені в таблицю та збережені в блокчейні, ви +зможете використовувати таблицю пошуку адрес у майбутніх транзакціях. Це +дозволяє включити до 64 адрес у цих транзакціях. ## Отримання таблиці пошуку адрес -Аналогічно запиту іншого облікового запису (або PDA) з кластера, ви можете отримати повну таблицю пошуку адрес за допомогою методу [`getAddressLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getAddressLookupTable): +Аналогічно запиту іншого облікового запису (або PDA) з кластера, ви можете +отримати повну таблицю пошуку адрес за допомогою методу +[`getAddressLookupTable`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getAddressLookupTable): ```js // define the `PublicKey` of the lookup table to fetch @@ -93,7 +126,9 @@ const lookupTableAccount = ( console.log("Table address from cluster:", lookupTableAccount.key.toBase58()); ``` -Змінна `lookupTableAccount` тепер буде об'єктом типу `AddressLookupTableAccount`, який можна проаналізувати для читання списку всіх адрес, збережених у таблиці пошуку в блокчейні: +Змінна `lookupTableAccount` тепер буде об'єктом типу +`AddressLookupTableAccount`, який можна проаналізувати для читання списку всіх +адрес, збережених у таблиці пошуку в блокчейні: ```js // loop through and parse all the addresses stored in the table @@ -102,16 +137,23 @@ for (let i = 0; i < lookupTableAccount.state.addresses.length; i++) { console.log(i, address.toBase58()); } ``` + ## Як використовувати таблицю пошуку адрес у транзакції -Після того як ви створили таблицю пошуку і зберегли необхідні адреси в блокчейні (через розширення таблиці пошуку), ви можете створити транзакцію `v0`, щоб скористатися можливостями пошуку адрес в блокчейні. +Після того як ви створили таблицю пошуку і зберегли необхідні адреси в блокчейні +(через розширення таблиці пошуку), ви можете створити транзакцію `v0`, щоб +скористатися можливостями пошуку адрес в блокчейні. -Так само, як і для старих транзакцій `legacy`, ви можете створити всі -[інструкції](/docs/uk/terminology.md#instruction), які ваша транзакція виконуватиме в блокчейні. Потім ви можете передати масив цих інструкцій у -[Message](/docs/uk/terminology.md#message), що використовується в транзакції `v0`. +Так само, як і для старих транзакцій `legacy`, ви можете створити всі +[інструкції](/docs/uk/terminology.md#instruction), які ваша транзакція +виконуватиме в блокчейні. Потім ви можете передати масив цих інструкцій у +[Message](/docs/uk/terminology.md#message), що використовується в транзакції +`v0`. -> **Примітка:** Інструкції, що використовуються в транзакції `v0`, можна створювати за допомогою тих самих методів і функцій, які використовувалися раніше для створення інструкцій. -> Немає необхідності змінювати інструкції, пов'язані з використанням таблиці пошуку адрес. +> **Примітка:** Інструкції, що використовуються в транзакції `v0`, можна +> створювати за допомогою тих самих методів і функцій, які використовувалися +> раніше для створення інструкцій. Немає необхідності змінювати інструкції, +> пов'язані з використанням таблиці пошуку адрес. ```js // Assumptions: @@ -140,10 +182,13 @@ console.log( ); ``` -> **Примітка:** Під час відправлення `VersionedTransaction` до кластеру, вона має бути підписана **ДО** виклику методу `sendAndConfirmTransaction`. Якщо передати масив `Signer` (як у транзакціях `legacy`), метод викличе помилку! +> **Примітка:** Під час відправлення `VersionedTransaction` до кластеру, вона +> має бути підписана **ДО** виклику методу `sendAndConfirmTransaction`. Якщо +> передати масив `Signer` (як у транзакціях `legacy`), метод викличе помилку! ## Додаткові ресурси -- Ознайомтеся з [пропозицією](https://docs.anza.xyz/proposals/versioned-transactions) щодо таблиць пошуку адрес і версійованих транзакцій +- Ознайомтеся з + [пропозицією](https://docs.anza.xyz/proposals/versioned-transactions) щодо + таблиць пошуку адрес і версійованих транзакцій - [Приклад програми на Rust, яка використовує таблиці пошуку адрес](https://github.com/TeamRaccoons/address-lookup-table-multi-swap) - diff --git a/docs/locales/uk/advanced/retry.md b/docs/locales/uk/advanced/retry.md index 42d1ee4c8..9a5af666f 100644 --- a/docs/locales/uk/advanced/retry.md +++ b/docs/locales/uk/advanced/retry.md @@ -5,55 +5,90 @@ altRoutes: - /docs/core/transactions/retry description: Дізнайтеся, як обробляти втрачені транзакції та впроваджувати користувацьку - логіку повторної відправки у Solana. Цей посібник охоплює повторне - передавання транзакцій, перевірки перед виконанням (preflight) і найкращі - практики для забезпечення надійної обробки транзакцій у блокчейні Solana. + логіку повторної відправки у Solana. Цей посібник охоплює повторне передавання + транзакцій, перевірки перед виконанням (preflight) і найкращі практики для + забезпечення надійної обробки транзакцій у блокчейні Solana. --- # Повторна відправка транзакцій -Іноді здається, що дійсна транзакція може бути втрачена до її включення в блок. Це зазвичай трапляється під час завантаженості мережі, коли RPC-вузол не може повторно передати транзакцію до [лідера](/docs/uk/terminology.md#leader). Для кінцевого користувача це може виглядати так, ніби транзакція повністю зникає. Хоча RPC-вузли мають універсальний алгоритм повторного передавання, розробники додатків також можуть створювати власну логіку повторної передачі. +Іноді здається, що дійсна транзакція може бути втрачена до її включення в блок. +Це зазвичай трапляється під час завантаженості мережі, коли RPC-вузол не може +повторно передати транзакцію до [лідера](/docs/uk/terminology.md#leader). Для +кінцевого користувача це може виглядати так, ніби транзакція повністю зникає. +Хоча RPC-вузли мають універсальний алгоритм повторного передавання, розробники +додатків також можуть створювати власну логіку повторної передачі. ## Коротко: -- RPC-вузли намагатимуться повторно передати транзакції за допомогою універсального алгоритму. +- RPC-вузли намагатимуться повторно передати транзакції за допомогою + універсального алгоритму. - Розробники додатків можуть впроваджувати власну логіку повторного передавання. -- Розробникам слід використовувати параметр `maxRetries` у методі JSON-RPC `sendTransaction`. -- Розробникам слід вмикати перевірки перед виконанням (preflight), щоб виявляти помилки до відправки транзакцій. -- Перед повторним підписанням будь-якої транзакції важливо переконатися, що термін дії blockhash вихідної транзакції минув. +- Розробникам слід використовувати параметр `maxRetries` у методі JSON-RPC + `sendTransaction`. +- Розробникам слід вмикати перевірки перед виконанням (preflight), щоб виявляти + помилки до відправки транзакцій. +- Перед повторним підписанням будь-якої транзакції важливо переконатися, що + термін дії blockhash вихідної транзакції минув. ## Шлях транзакції ### Як клієнти відправляють транзакції -У Solana немає концепції мемпулу. Усі транзакції, незалежно від того, чи ініційовані вони програмно або користувачем, ефективно маршрутизуються до лідерів для обробки в блоках. Є два основні способи надсилання транзакцій до лідерів: +У Solana немає концепції мемпулу. Усі транзакції, незалежно від того, чи +ініційовані вони програмно або користувачем, ефективно маршрутизуються до +лідерів для обробки в блоках. Є два основні способи надсилання транзакцій до +лідерів: -1. Через RPC-сервер за допомогою методу JSON-RPC [sendTransaction](/docs/uk/rpc/http/sendTransaction.mdx). -2. Безпосередньо до лідерів через [TPU Client](https://docs.rs/solana-client/latest/solana_client/tpu_client/index.html). +1. Через RPC-сервер за допомогою методу JSON-RPC + [sendTransaction](/docs/uk/rpc/http/sendTransaction.mdx). +2. Безпосередньо до лідерів через + [TPU Client](https://docs.rs/solana-client/latest/solana_client/tpu_client/index.html). -Більшість користувачів відправляють транзакції через RPC-сервер. Коли клієнт надсилає транзакцію, RPC-вузол намагається передати її поточному та наступному лідерам. Поки транзакція не буде оброблена лідером, вона існує лише у вигляді запису в клієнта або проміжних RPC-вузлів. У випадку використання TPU клієнтом, передавання та маршрутизація обробляються програмним забезпеченням клієнта. +Більшість користувачів відправляють транзакції через RPC-сервер. Коли клієнт +надсилає транзакцію, RPC-вузол намагається передати її поточному та наступному +лідерам. Поки транзакція не буде оброблена лідером, вона існує лише у вигляді +запису в клієнта або проміжних RPC-вузлів. У випадку використання TPU клієнтом, +передавання та маршрутизація обробляються програмним забезпеченням клієнта. ![Огляд шляху транзакції, від клієнта до лідера](/assets/docs/rt-tx-journey.png) ### Як RPC-вузли передають транзакції -Після отримання транзакції через `sendTransaction`, RPC-вузол перетворює транзакцію в [UDP](https://uk.wikipedia.org/wiki/UDP) пакет і передає його відповідним лідерам. UDP дозволяє вузлам швидко обмінюватися даними, але не гарантує доставки пакетів. +Після отримання транзакції через `sendTransaction`, RPC-вузол перетворює +транзакцію в [UDP](https://uk.wikipedia.org/wiki/UDP) пакет і передає його +відповідним лідерам. UDP дозволяє вузлам швидко обмінюватися даними, але не +гарантує доставки пакетів. -Оскільки розклад лідерів Solana відомий заздалегідь для кожного [епоха](/docs/uk/terminology.md#epoch) (~2 дні), RPC-вузол передає транзакції безпосередньо до поточного та наступного лідерів. За замовчуванням RPC-вузли намагаються повторно передавати транзакції кожні дві секунди, доки транзакція не буде завершена або доки термін дії її blockhash не закінчиться (~1 хвилина 19 секунд). Якщо черга для повторної передачі перевищує [10,000 транзакцій](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/send-transaction-service/src/send_transaction_service.rs#L20), нові транзакції скидаються. +Оскільки розклад лідерів Solana відомий заздалегідь для кожного +[епоха](/docs/uk/terminology.md#epoch) (~2 дні), RPC-вузол передає транзакції +безпосередньо до поточного та наступного лідерів. За замовчуванням RPC-вузли +намагаються повторно передавати транзакції кожні дві секунди, доки транзакція не +буде завершена або доки термін дії її blockhash не закінчиться (~1 хвилина 19 +секунд). Якщо черга для повторної передачі перевищує +[10,000 транзакцій](https://github.com/solana-labs/solana/blob/bfbbc53dac93b3a5c6be9b4b65f679fdb13e41d9/send-transaction-service/src/send_transaction_service.rs#L20), +нові транзакції скидаються. ![Процес обробки транзакцій TPU](/assets/docs/rt-tpu-jito-labs.png) ## Як транзакції скидаються -Транзакції можуть бути скинуті через кілька причин, таких як перевантаження мережі, втрати пакетів UDP або конфлікти через різні статуси вузлів у пулі RPC. +Транзакції можуть бути скинуті через кілька причин, таких як перевантаження +мережі, втрати пакетів UDP або конфлікти через різні статуси вузлів у пулі RPC. ## Обробка скинутих транзакцій -Розробники можуть використовувати параметр `maxRetries` методу `sendTransaction` для створення власної логіки повторного передавання, зокрема перевірки `lastValidBlockHeight` і опитування стану мережі. +Розробники можуть використовувати параметр `maxRetries` методу `sendTransaction` +для створення власної логіки повторного передавання, зокрема перевірки +`lastValidBlockHeight` і опитування стану мережі. ## Налаштування власної логіки -Впровадження алгоритмів, таких як [експоненціальне збільшення інтервалів](https://uk.wikipedia.org/wiki/Експоненційне_зростання), або постійне повторне передавання, як у [Mango](https://github.com/blockworks-foundation/mango-ui/blob/b6abfc6c13b71fc17ebbe766f50b8215fa1ec54f/src/utils/send.tsx#L713), може допомогти впоратися із завантаженістю мережі. +Впровадження алгоритмів, таких як +[експоненціальне збільшення інтервалів](https://uk.wikipedia.org/wiki/Експоненційне_зростання), +або постійне повторне передавання, як у +[Mango](https://github.com/blockworks-foundation/mango-ui/blob/b6abfc6c13b71fc17ebbe766f50b8215fa1ec54f/src/utils/send.tsx#L713), +може допомогти впоратися із завантаженістю мережі. ```ts import { @@ -112,26 +147,48 @@ const sleep = async (ms: number) => { })(); ``` -При опитуванні через `getLatestBlockhash` додатки повинні вказувати бажаний рівень [зобов'язань (commitment)](/docs/uk/rpc/index.mdx#configuring-state-commitment). Встановлюючи зобов'язання на рівень `confirmed` (підтверджений) або `finalized` (~30 блоків після `confirmed`), додаток може уникнути опитування blockhash із меншості вузлів. - -Якщо додаток має доступ до RPC-вузлів за балансувальником навантаження, він також може розподіляти своє навантаження між конкретними вузлами. RPC-вузли, які обслуговують ресурсоємні запити, такі як -[getProgramAccounts](/content/guides/javascript/get-program-accounts.md), можуть відставати і бути менш ефективними для пересилання транзакцій. Для додатків, що обробляють транзакції в реальному часі, може бути розумним використовувати спеціалізовані вузли, які обслуговують лише `sendTransaction`. +При опитуванні через `getLatestBlockhash` додатки повинні вказувати бажаний +рівень +[зобов'язань (commitment)](/docs/uk/rpc/index.mdx#configuring-state-commitment). +Встановлюючи зобов'язання на рівень `confirmed` (підтверджений) або `finalized` +(~30 блоків після `confirmed`), додаток може уникнути опитування blockhash із +меншості вузлів. + +Якщо додаток має доступ до RPC-вузлів за балансувальником навантаження, він +також може розподіляти своє навантаження між конкретними вузлами. RPC-вузли, які +обслуговують ресурсоємні запити, такі як +[getProgramAccounts](/content/guides/javascript/get-program-accounts.md), можуть +відставати і бути менш ефективними для пересилання транзакцій. Для додатків, що +обробляють транзакції в реальному часі, може бути розумним використовувати +спеціалізовані вузли, які обслуговують лише `sendTransaction`. ### Вартість пропуску перевірки перед виконанням -За замовчуванням `sendTransaction` виконує три перевірки перед відправкою транзакції. Зокрема, `sendTransaction`: +За замовчуванням `sendTransaction` виконує три перевірки перед відправкою +транзакції. Зокрема, `sendTransaction`: - Перевіряє, що всі підписи є дійсними. - Перевіряє, що вказаний blockhash знаходиться в межах останніх 150 блоків. - Симулює транзакцію на основі слоту банку, зазначеного у `preflightCommitment`. -У разі, якщо одна з цих перевірок не пройде, `sendTransaction` видасть помилку до відправки транзакції. Перевірки перед виконанням можуть стати вирішальним фактором між втратою транзакції та можливістю клієнта обробити помилку. Щоб гарантувати врахування цих поширених помилок, рекомендується залишати `skipPreflight` встановленим у значення `false`. +У разі, якщо одна з цих перевірок не пройде, `sendTransaction` видасть помилку +до відправки транзакції. Перевірки перед виконанням можуть стати вирішальним +фактором між втратою транзакції та можливістю клієнта обробити помилку. Щоб +гарантувати врахування цих поширених помилок, рекомендується залишати +`skipPreflight` встановленим у значення `false`. ### Коли потрібно повторно підписувати транзакції -Попри всі спроби повторного передавання, іноді клієнт може бути змушений повторно підписати транзакцію. Перед повторним підписанням будь-якої транзакції **дуже важливо** переконатися, що термін дії blockhash вихідної транзакції закінчився. Якщо початковий blockhash все ще дійсний, обидві транзакції можуть бути прийняті мережею. Для кінцевого користувача це виглядатиме як ненавмисне повторне відправлення однієї і тієї ж транзакції. - -У Solana втрачену транзакцію можна безпечно відхилити, якщо blockhash, на який вона посилається, старший за `lastValidBlockHeight`, отриманий із -`getLatestBlockhash`. Розробникам слід відстежувати цей `lastValidBlockHeight`, опитуючи -[`getEpochInfo`](/docs/uk/rpc/http/getEpochInfo.mdx) і порівнюючи з `blockHeight` у відповіді. Після того, як blockhash стане недійсним, клієнти можуть повторно підписати транзакцію з новозапитаним blockhash. - +Попри всі спроби повторного передавання, іноді клієнт може бути змушений +повторно підписати транзакцію. Перед повторним підписанням будь-якої транзакції +**дуже важливо** переконатися, що термін дії blockhash вихідної транзакції +закінчився. Якщо початковий blockhash все ще дійсний, обидві транзакції можуть +бути прийняті мережею. Для кінцевого користувача це виглядатиме як ненавмисне +повторне відправлення однієї і тієї ж транзакції. + +У Solana втрачену транзакцію можна безпечно відхилити, якщо blockhash, на який +вона посилається, старший за `lastValidBlockHeight`, отриманий із +`getLatestBlockhash`. Розробникам слід відстежувати цей `lastValidBlockHeight`, +опитуючи [`getEpochInfo`](/docs/uk/rpc/http/getEpochInfo.mdx) і порівнюючи з +`blockHeight` у відповіді. Після того, як blockhash стане недійсним, клієнти +можуть повторно підписати транзакцію з новозапитаним blockhash. diff --git a/docs/locales/uk/advanced/state-compression.md b/docs/locales/uk/advanced/state-compression.md index c094491db..b2df0fdc9 100644 --- a/docs/locales/uk/advanced/state-compression.md +++ b/docs/locales/uk/advanced/state-compression.md @@ -2,20 +2,31 @@ sidebarSortOrder: 4 title: Стиснення стану (State Compression) description: - 'Стиснення стану - це метод дешевого та безпечного збереження - "відбитків" даних поза мережею в реєстрі Solana замість дорогих облікових записів.' + 'Стиснення стану - це метод дешевого та безпечного збереження "відбитків" + даних поза мережею в реєстрі Solana замість дорогих облікових записів.' --- -У Solana [стиснення стану](/docs/uk/advanced/state-compression.md) є методом створення "відбитку" (або гешу) даних поза мережею та збереження цього відбитку в мережі для безпечної перевірки. Цей процес використовує безпеку реєстру Solana для гарантування цілісності даних поза мережею, забезпечуючи їх незмінність. +У Solana [стиснення стану](/docs/uk/advanced/state-compression.md) є методом +створення "відбитку" (або гешу) даних поза мережею та збереження цього відбитку +в мережі для безпечної перевірки. Цей процес використовує безпеку реєстру Solana +для гарантування цілісності даних поза мережею, забезпечуючи їх незмінність. -Цей метод "стиснення" дозволяє програмам та децентралізованим додаткам (dApps) використовувати дешевий простір у [реєстрі](/docs/uk/terminology.md#ledger) блокчейну, замість більш дорогого простору [облікових записів](/docs/uk/terminology.md#account), для безпечного зберігання даних. +Цей метод "стиснення" дозволяє програмам та децентралізованим додаткам (dApps) +використовувати дешевий простір у [реєстрі](/docs/uk/terminology.md#ledger) +блокчейну, замість більш дорогого простору +[облікових записів](/docs/uk/terminology.md#account), для безпечного зберігання +даних. -Це досягається за допомогою спеціальної структури двійкового дерева, відомого як -[конкурентне мерклеве дерево](#what-is-a-concurrent-merkle-tree), яке створює геш кожного фрагмента даних (названого `листком`), об'єднує ці геші і зберігає тільки фінальний геш у мережі. +Це досягається за допомогою спеціальної структури двійкового дерева, відомого як +[конкурентне мерклеве дерево](#what-is-a-concurrent-merkle-tree), яке створює +геш кожного фрагмента даних (названого `листком`), об'єднує ці геші і зберігає +тільки фінальний геш у мережі. ## Що таке стиснення стану? -Простіше кажучи, стиснення стану використовує структури "**_дерев_**" для криптографічного хешування даних поза мережею детермінованим способом, щоб обчислити один кінцевий геш, який зберігається у мережі. +Простіше кажучи, стиснення стану використовує структури "**_дерев_**" для +криптографічного хешування даних поза мережею детермінованим способом, щоб +обчислити один кінцевий геш, який зберігається у мережі. Ці _дерева_ створюються таким "_детермінованим_" процесом: @@ -26,35 +37,63 @@ description: - Кожна `гілка` також хешується разом. - Процес повторюється, поки не буде обчислено фінальний `кореневий геш`. -Цей `кореневий геш` зберігається в мережі як верифіковане **_підтвердження_** для всіх даних у кожному листку. Це дозволяє криптографічно перевіряти всі дані поза мережею, використовуючи мінімальну кількість даних у мережі. Таким чином, значно знижуються витрати на зберігання/перевірку великих обсягів даних завдяки "стисненню стану". +Цей `кореневий геш` зберігається в мережі як верифіковане **_підтвердження_** +для всіх даних у кожному листку. Це дозволяє криптографічно перевіряти всі дані +поза мережею, використовуючи мінімальну кількість даних у мережі. Таким чином, +значно знижуються витрати на зберігання/перевірку великих обсягів даних завдяки +"стисненню стану". ## Мерклеві дерева та конкурентні мерклеві дерева -Стиснення стану у Solana використовує спеціальний тип -[мерклевого дерева](#what-is-a-merkle-tree), який дозволяє виконувати кілька змін у дереві, зберігаючи його цілісність і валідність. +Стиснення стану у Solana використовує спеціальний тип +[мерклевого дерева](#what-is-a-merkle-tree), який дозволяє виконувати кілька +змін у дереві, зберігаючи його цілісність і валідність. -Це спеціальне дерево, відоме як -"[конкурентне мерклеве дерево](#what-is-a-concurrent-merkle-tree)", зберігає "журнал змін" дерева в мережі. Це дозволяє виконувати кілька змін до дерева (наприклад, у межах одного блоку), не порушуючи підтвердження. +Це спеціальне дерево, відоме як +"[конкурентне мерклеве дерево](#what-is-a-concurrent-merkle-tree)", зберігає +"журнал змін" дерева в мережі. Це дозволяє виконувати кілька змін до дерева +(наприклад, у межах одного блоку), не порушуючи підтвердження. ### Що таке мерклеве дерево? -[Мерклеве дерево](https://uk.wikipedia.org/wiki/Мерклеве_дерево), або "дерево гешів", — це двійкова структура, у якій кожен `листок` є криптографічним гешем даних. Всі вузли, які **не** є листками, називаються `гілками` і є гешами їхніх дочірніх листків. +[Мерклеве дерево](https://uk.wikipedia.org/wiki/Мерклеве_дерево), або "дерево +гешів", — це двійкова структура, у якій кожен `листок` є криптографічним гешем +даних. Всі вузли, які **не** є листками, називаються `гілками` і є гешами їхніх +дочірніх листків. -Кожна гілка також хешується разом, поступово піднімаючись вгору, поки не залишиться один геш. Цей фінальний геш, званий `кореневим гешем`, можна використовувати разом із "шляхом підтвердження" для перевірки будь-яких даних, збережених у листковому вузлі. +Кожна гілка також хешується разом, поступово піднімаючись вгору, поки не +залишиться один геш. Цей фінальний геш, званий `кореневим гешем`, можна +використовувати разом із "шляхом підтвердження" для перевірки будь-яких даних, +збережених у листковому вузлі. ### Що таке Конкурентне Мерклеве дерево? -У високопродуктивних застосунках, таких як [середовище виконання Solana](/docs/uk/core/fees.md), запити на зміну ончейн _традиційного мерклевого дерева_ можуть надходити до валідаторів досить швидко (наприклад, у межах одного слота). У таких випадках кожна зміна даних у листках повинна виконуватися послідовно. Це призводить до невдачі наступних запитів на зміну, оскільки кореневий геш і підтвердження стають недійсними після попередньої зміни в слоті. +У високопродуктивних застосунках, таких як +[середовище виконання Solana](/docs/uk/core/fees.md), запити на зміну ончейн +_традиційного мерклевого дерева_ можуть надходити до валідаторів досить швидко +(наприклад, у межах одного слота). У таких випадках кожна зміна даних у листках +повинна виконуватися послідовно. Це призводить до невдачі наступних запитів на +зміну, оскільки кореневий геш і підтвердження стають недійсними після +попередньої зміни в слоті. Рішенням цієї проблеми є Конкурентні Мерклеві дерева. -**Конкурентне Мерклеве дерево** зберігає **захищений журнал змін**, який містить останні зміни, їх кореневий геш і підтвердження для його обчислення. Цей буфер змін ("changelog buffer") зберігається ончейн у спеціальному акаунті для кожного дерева, з обмеженням на максимальну кількість записів у журналі змін (`maxBufferSize`). +**Конкурентне Мерклеве дерево** зберігає **захищений журнал змін**, який містить +останні зміни, їх кореневий геш і підтвердження для його обчислення. Цей буфер +змін ("changelog buffer") зберігається ончейн у спеціальному акаунті для кожного +дерева, з обмеженням на максимальну кількість записів у журналі змін +(`maxBufferSize`). -Коли валідатори отримують кілька запитів на зміну даних у листках у межах одного слота, ончейн _конкурентне мерклеве дерево_ може використовувати цей буфер змін як джерело правдивої інформації для більш прийнятних підтверджень. Це дозволяє виконувати до `maxBufferSize` змін для одного дерева в межах одного слота, що значно підвищує пропускну здатність. +Коли валідатори отримують кілька запитів на зміну даних у листках у межах одного +слота, ончейн _конкурентне мерклеве дерево_ може використовувати цей буфер змін +як джерело правдивої інформації для більш прийнятних підтверджень. Це дозволяє +виконувати до `maxBufferSize` змін для одного дерева в межах одного слота, що +значно підвищує пропускну здатність. ## Розмір Конкурентного Мерклевого дерева -При створенні такого ончейн дерева існує 3 параметри, які визначають розмір дерева, вартість його створення і кількість одночасних змін: +При створенні такого ончейн дерева існує 3 параметри, які визначають розмір +дерева, вартість його створення і кількість одночасних змін: 1. Максимальна глибина (max depth) 2. Розмір буфера змін (max buffer size) @@ -62,20 +101,29 @@ description: ### Максимальна глибина -"Максимальна глибина" дерева — це **максимальна кількість** переходів від будь-якого `листка` даних до `кореня` дерева. +"Максимальна глибина" дерева — це **максимальна кількість** переходів від +будь-якого `листка` даних до `кореня` дерева. -Оскільки мерклеві дерева є двійковими, кожен листок з'єднаний лише з **одним** іншим листком; вони утворюють `пару листків`. +Оскільки мерклеві дерева є двійковими, кожен листок з'єднаний лише з **одним** +іншим листком; вони утворюють `пару листків`. -Таким чином, `maxDepth` дерева використовується для визначення максимальної кількості вузлів (тобто елементів даних або `листків`), які можна зберігати у дереві, за допомогою простої формули: +Таким чином, `maxDepth` дерева використовується для визначення максимальної +кількості вузлів (тобто елементів даних або `листків`), які можна зберігати у +дереві, за допомогою простої формули: ```text nodes_count = 2 ^ maxDepth ``` -Оскільки глибину дерева потрібно встановити під час його створення, ви повинні визначити, скільки елементів даних ви хочете зберігати у своєму дереві. Потім, використовуючи просту формулу вище, ви можете визначити найменше значення `maxDepth`, яке дозволить зберігати ваші дані. + +Оскільки глибину дерева потрібно встановити під час його створення, ви повинні +визначити, скільки елементів даних ви хочете зберігати у своєму дереві. Потім, +використовуючи просту формулу вище, ви можете визначити найменше значення +`maxDepth`, яке дозволить зберігати ваші дані. #### Приклад 1: Мінтинг 100 NFT -Якщо ви хочете створити дерево для зберігання 100 стиснутих NFT, вам знадобиться щонайменше "100 листків" або "100 вузлів". +Якщо ви хочете створити дерево для зберігання 100 стиснутих NFT, вам знадобиться +щонайменше "100 листків" або "100 вузлів". ```text // maxDepth=6 -> 64 nodes @@ -84,11 +132,14 @@ nodes_count = 2 ^ maxDepth // maxDepth=7 -> 128 nodes 2^7 = 128 ``` -Ми повинні використовувати значення `maxDepth` рівне `7`, щоб забезпечити можливість зберігати всі наші дані. + +Ми повинні використовувати значення `maxDepth` рівне `7`, щоб забезпечити +можливість зберігати всі наші дані. #### Приклад 2: Мінтинг 15000 NFT -Якщо ви хочете створити дерево для зберігання 15000 стиснутих NFT, вам знадобиться щонайменше "15000 листків" або "15000 вузлів". +Якщо ви хочете створити дерево для зберігання 15000 стиснутих NFT, вам +знадобиться щонайменше "15000 листків" або "15000 вузлів". ```text // maxDepth=13 -> 8192 nodes @@ -97,33 +148,51 @@ nodes_count = 2 ^ maxDepth // maxDepth=14 -> 16384 nodes 2^14 = 16384 ``` -Ми повинні використовувати `maxDepth` рівне `14`, щоб забезпечити можливість зберігати всі наші дані. + +Ми повинні використовувати `maxDepth` рівне `14`, щоб забезпечити можливість +зберігати всі наші дані. #### Чим більша максимальна глибина, тим вища вартість -Значення `maxDepth` є одним із основних чинників вартості під час створення дерева, оскільки ви оплачуєте цю вартість наперед при створенні дерева. Чим більша глибина дерева, тим більше даних (відбитків або хешів) можна зберігати, але тим вища вартість. +Значення `maxDepth` є одним із основних чинників вартості під час створення +дерева, оскільки ви оплачуєте цю вартість наперед при створенні дерева. Чим +більша глибина дерева, тим більше даних (відбитків або хешів) можна зберігати, +але тим вища вартість. --- ### Максимальний розмір буфера (maxBufferSize) -"Максимальний розмір буфера" — це максимальна кількість змін, які можуть бути внесені до дерева, доки кореневий хеш (`root hash`) залишається дійсним. +"Максимальний розмір буфера" — це максимальна кількість змін, які можуть бути +внесені до дерева, доки кореневий хеш (`root hash`) залишається дійсним. -Оскільки кореневий хеш є єдиним хешем для всіх даних листків, зміна будь-якого окремого листка інвалідовує proof, потрібний для всіх наступних спроб змінити будь-який інший листок у звичайному дереві. +Оскільки кореневий хеш є єдиним хешем для всіх даних листків, зміна будь-якого +окремого листка інвалідовує proof, потрібний для всіх наступних спроб змінити +будь-який інший листок у звичайному дереві. -У випадку [Concurrent Tree](#що-таке-concurrent-merkle-tree), існує журнал змін для цих proof, який задається під час створення дерева через параметр `maxBufferSize`. +У випадку [Concurrent Tree](#що-таке-concurrent-merkle-tree), існує журнал змін +для цих proof, який задається під час створення дерева через параметр +`maxBufferSize`. --- ### Глибина козирка (canopyDepth) -"Глибина козирка" або "розмір козирка" визначає кількість рівнів proof, які кешуються або зберігаються on-chain для даного proof-шляху. +"Глибина козирка" або "розмір козирка" визначає кількість рівнів proof, які +кешуються або зберігаються on-chain для даного proof-шляху. -Коли виконується дія оновлення для `leaf` (наприклад, передача права власності), **повний** proof-шлях повинен бути використаний для верифікації початкового права власності на листок. Це здійснюється шляхом обчислення поточного `root hash`. +Коли виконується дія оновлення для `leaf` (наприклад, передача права власності), +**повний** proof-шлях повинен бути використаний для верифікації початкового +права власності на листок. Це здійснюється шляхом обчислення поточного +`root hash`. -Для великих дерев потрібно більше proof-вузлів, щоб виконати цю перевірку. Наприклад, якщо `maxDepth` дорівнює `14`, потрібно `14` proof-вузлів. З використанням козирка частина цих вузлів зберігається on-chain, зменшуючи кількість proof-вузлів, які потрібно включити в транзакції. +Для великих дерев потрібно більше proof-вузлів, щоб виконати цю перевірку. +Наприклад, якщо `maxDepth` дорівнює `14`, потрібно `14` proof-вузлів. З +використанням козирка частина цих вузлів зберігається on-chain, зменшуючи +кількість proof-вузлів, які потрібно включити в транзакції. -Наприклад, дерево з `maxDepth` рівне `14` із козирком розміром `10` потребуватиме лише `4` proof-вузли на транзакцію. +Наприклад, дерево з `maxDepth` рівне `14` із козирком розміром `10` +потребуватиме лише `4` proof-вузли на транзакцію. ![Глибина козирка 1 для Concurrent Merkle Tree з максимальною глибиною 3](/assets/docs/compression/canopy-depth-1.png) @@ -131,19 +200,26 @@ nodes_count = 2 ^ maxDepth #### Чим більша глибина козирка, тим вища вартість -Значення `canopyDepth` також є одним із основних чинників вартості створення дерева. Чим більше proof-вузлів зберігається on-chain, тим вища вартість. +Значення `canopyDepth` також є одним із основних чинників вартості створення +дерева. Чим більше proof-вузлів зберігається on-chain, тим вища вартість. #### Низький козирок обмежує композитність -Низьке значення `canopyDepth` вимагає більше proof-вузлів у кожній транзакції оновлення. Це обмежує можливості для інтеграції вашого дерева з іншими Solana-програмами або dApps. +Низьке значення `canopyDepth` вимагає більше proof-вузлів у кожній транзакції +оновлення. Це обмежує можливості для інтеграції вашого дерева з іншими +Solana-програмами або dApps. -Наприклад, дерево, яке використовується для стиснутих NFT з низьким `canopyDepth`, може дозволяти лише базові дії, як-от передача, але не підтримувати розширені функції, такі як система ставок. +Наприклад, дерево, яке використовується для стиснутих NFT з низьким +`canopyDepth`, може дозволяти лише базові дії, як-от передача, але не +підтримувати розширені функції, такі як система ставок. --- ## Вартість створення дерева -Вартість створення Concurrent Merkle Tree залежить від його параметрів: `maxDepth`, `maxBufferSize`, і `canopyDepth`. Ці параметри визначають необхідний простір (у байтах) для дерева. +Вартість створення Concurrent Merkle Tree залежить від його параметрів: +`maxDepth`, `maxBufferSize`, і `canopyDepth`. Ці параметри визначають необхідний +простір (у байтах) для дерева. Використовуючи метод [`getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getminimumbalanceforrentexemption), @@ -161,7 +237,8 @@ nodes_count = 2 ^ maxDepth Далі, за допомогою функції [`getMinimumBalanceForRentExemption`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html#getMinimumBalanceForRentExemption), -можна визначити остаточну вартість (у лампортах) для створення дерева, подібно до будь-якого іншого акаунта. +можна визначити остаточну вартість (у лампортах) для створення дерева, подібно +до будь-якого іншого акаунта. ```ts // calculate the space required for the tree @@ -178,7 +255,8 @@ const storageCost = ### Приклади вартості -Нижче наведено кілька прикладів вартості для дерев різного розміру, включаючи кількість можливих листків: +Нижче наведено кілька прикладів вартості для дерев різного розміру, включаючи +кількість можливих листків: **Приклад №1: 16,384 вузлів, вартість 0.222 SOL** @@ -208,7 +286,11 @@ const storageCost = ## Стиснуті NFT -Стиснуті NFT є одним із найпопулярніших варіантів використання стиснення стану на Solana. Завдяки стисненню колекцію з одного мільйона NFT можна створити за `~50 SOL`, у порівнянні з `~12,000 SOL` для її нестиснутої еквівалентної колекції. +Стиснуті NFT є одним із найпопулярніших варіантів використання стиснення стану +на Solana. Завдяки стисненню колекцію з одного мільйона NFT можна створити за +`~50 SOL`, у порівнянні з `~12,000 SOL` для її нестиснутої еквівалентної +колекції. -Якщо ви зацікавлені в створенні стиснутих NFT, ознайомтеся з нашим посібником для розробників: +Якщо ви зацікавлені в створенні стиснутих NFT, ознайомтеся з нашим посібником +для розробників: [створення та передача стиснутих NFT](/content/guides/javascript/compressed-nfts.md). diff --git a/docs/locales/uk/advanced/versions.md b/docs/locales/uk/advanced/versions.md index b3f5c5aaf..998915a05 100644 --- a/docs/locales/uk/advanced/versions.md +++ b/docs/locales/uk/advanced/versions.md @@ -2,15 +2,19 @@ sidebarSortOrder: 3 title: "Версійні Транзакції" description: - "Дослідіть основні концепції Solana: транзакції, версійні транзакції, розширення функціональності в Solana Runtime, таблиці пошуку адрес та інше." + "Дослідіть основні концепції Solana: транзакції, версійні транзакції, + розширення функціональності в Solana Runtime, таблиці пошуку адрес та інше." altRoutes: - /docs/uk/core/transactions/versions --- -Версійні Транзакції - це новий формат транзакцій, який дозволяє додаткову функціональність у Solana Runtime, включаючи +Версійні Транзакції - це новий формат транзакцій, який дозволяє додаткову +функціональність у Solana Runtime, включаючи [Таблиці пошуку адрес](/docs/uk/advanced/lookup-tables.md). -Хоча зміни в ончейн-програмах **НЕ** потрібні для підтримки нової функціональності версійних транзакцій (або для зворотної сумісності), розробники **ПОВИННІ** оновити клієнтський код, щоб уникнути +Хоча зміни в ончейн-програмах **НЕ** потрібні для підтримки нової +функціональності версійних транзакцій (або для зворотної сумісності), розробники +**ПОВИННІ** оновити клієнтський код, щоб уникнути [помилок через різні версії транзакцій](#max-supported-transaction-version). ## Поточні версії транзакцій @@ -23,26 +27,32 @@ Solana Runtime підтримує дві версії транзакцій: ## Максимально підтримувана версія транзакцій -Усі RPC-запити, які повертають транзакцію, **_повинні_** вказувати найвищу версію транзакцій, яку вони підтримують у своїй програмі, використовуючи параметр -`maxSupportedTransactionVersion`, включаючи +Усі RPC-запити, які повертають транзакцію, **_повинні_** вказувати найвищу +версію транзакцій, яку вони підтримують у своїй програмі, використовуючи +параметр `maxSupportedTransactionVersion`, включаючи [`getBlock`](/docs/uk/rpc/http/getBlock.mdx) та [`getTransaction`](/docs/uk/rpc/http/getTransaction.mdx). -RPC-запит завершиться невдачею, якщо буде повернута версійна транзакція, яка має версію вище встановленої `maxSupportedTransactionVersion`. (наприклад, якщо повертається транзакція версії `0`, а встановлено `legacy`) +RPC-запит завершиться невдачею, якщо буде повернута версійна транзакція, яка має +версію вище встановленої `maxSupportedTransactionVersion`. (наприклад, якщо +повертається транзакція версії `0`, а встановлено `legacy`) -> УВАГА: Якщо значення `maxSupportedTransactionVersion` не встановлено, тоді лише транзакції `legacy` будуть дозволені у відповіді RPC. Таким чином, ваші RPC-запити **ПРИЗВЕДУТЬ ДО ПОМИЛКИ**, якщо буде повернута будь-яка транзакція версії `0`. +> УВАГА: Якщо значення `maxSupportedTransactionVersion` не встановлено, тоді +> лише транзакції `legacy` будуть дозволені у відповіді RPC. Таким чином, ваші +> RPC-запити **ПРИЗВЕДУТЬ ДО ПОМИЛКИ**, якщо буде повернута будь-яка транзакція +> версії `0`. ## Як встановити максимально підтримувану версію Ви можете встановити `maxSupportedTransactionVersion`, використовуючи бібліотеку -[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/) -або шляхом прямого надсилання JSON-запитів до RPC-ендпоінту. +[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/) або +шляхом прямого надсилання JSON-запитів до RPC-ендпоінту. ### Використання web3.js Використовуючи бібліотеку -[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/), -ви можете отримати останній блок або конкретну транзакцію: +[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/v1.x/), ви +можете отримати останній блок або конкретну транзакцію: ```js // підключення до кластера `devnet` та отримання поточного `slot` @@ -80,7 +90,8 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - ## Як створити версійну транзакцію -Версійні транзакції можна створити подібно до старого методу створення транзакцій. Є відмінності у використанні певних бібліотек, які слід враховувати. +Версійні транзакції можна створити подібно до старого методу створення +транзакцій. Є відмінності у використанні певних бібліотек, які слід враховувати. Нижче наведено приклад створення версійної транзакції з використанням бібліотеки `@solana/web3.js` для передачі SOL між двома рахунками. @@ -90,9 +101,11 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - - `payer` - це дійсний гаманець `Keypair`, наповнений SOL - `toAccount` - дійсний `Keypair` -Спочатку імпортуйте бібліотеку web3.js та створіть `connection` до бажаного кластера. +Спочатку імпортуйте бібліотеку web3.js та створіть `connection` до бажаного +кластера. -Далі визначте останній `blockhash` і `minRent`, які будуть потрібні для вашої транзакції та рахунку: +Далі визначте останній `blockhash` і `minRent`, які будуть потрібні для вашої +транзакції та рахунку: ```js const web3 = require("@solana/web3.js"); @@ -105,7 +118,8 @@ let blockhash = await connection .then(res => res.blockhash); ``` -Створіть `array` усіх `instructions`, які ви хочете відправити у вашій транзакції. У прикладі нижче ми створюємо просту інструкцію передачі SOL: +Створіть `array` усіх `instructions`, які ви хочете відправити у вашій +транзакції. У прикладі нижче ми створюємо просту інструкцію передачі SOL: ```js // створення масиву з вашими інструкціями @@ -138,7 +152,8 @@ const transaction = new web3.VersionedTransaction(messageV0); transaction.sign([payer]); ``` -Після того, як ваша `VersionedTransaction` підписана всіма необхідними рахунками, ви можете відправити її до кластера та отримати відповідь: +Після того, як ваша `VersionedTransaction` підписана всіма необхідними +рахунками, ви можете відправити її до кластера та отримати відповідь: ```js // відправка нашої транзакції v0 до кластера @@ -146,8 +161,10 @@ const txId = await connection.sendTransaction(transaction); console.log(`https://explorer.solana.com/tx/${txId}?cluster=devnet`); ``` -> УВАГА: На відміну від `legacy` транзакцій, відправка `VersionedTransaction` через -> `sendTransaction` **НЕ** підтримує підпис транзакцій через передачу масиву `Signers` як другого параметра. Ви повинні підписати транзакцію перед викликом `connection.sendTransaction()`. +> УВАГА: На відміну від `legacy` транзакцій, відправка `VersionedTransaction` +> через `sendTransaction` **НЕ** підтримує підпис транзакцій через передачу +> масиву `Signers` як другого параметра. Ви повинні підписати транзакцію перед +> викликом `connection.sendTransaction()`. ## Додаткові ресурси @@ -159,4 +176,3 @@ console.log(`https://explorer.solana.com/tx/${txId}?cluster=devnet`); - Читання [ухваленої пропозиції](https://docs.anza.xyz/proposals/versioned-transactions) для версійних транзакцій та таблиць пошуку адрес - diff --git a/docs/locales/uk/clients/javascript-reference.md b/docs/locales/uk/clients/javascript-reference.md index c8631101a..1ea13ade9 100644 --- a/docs/locales/uk/clients/javascript-reference.md +++ b/docs/locales/uk/clients/javascript-reference.md @@ -1,8 +1,8 @@ --- title: Web3.js API Приклади description: - Дізнайтеся, як взаємодіяти з блокчейном Solana за допомогою бібліотеки @solana/web3.js - через практичні приклади коду та пояснення. + Дізнайтеся, як взаємодіяти з блокчейном Solana за допомогою бібліотеки + @solana/web3.js через практичні приклади коду та пояснення. --- ## Довідник по Web3 API @@ -19,9 +19,13 @@ description: [Документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html) -Об'єкт `Connection` використовується для взаємодії з [Solana JSON RPC](/docs/uk/rpc). Ви можете використовувати Connection для підтвердження транзакцій, отримання інформації про облікові записи тощо. +Об'єкт `Connection` використовується для взаємодії з +[Solana JSON RPC](/docs/uk/rpc). Ви можете використовувати Connection для +підтвердження транзакцій, отримання інформації про облікові записи тощо. -Створення підключення здійснюється шляхом вказання URL-адреси RPC-кластера та бажаного рівня зобов'язань. Після цього ви можете використовувати цей об'єкт підключення для взаємодії з будь-яким із API JSON RPC Solana. +Створення підключення здійснюється шляхом вказання URL-адреси RPC-кластера та +бажаного рівня зобов'язань. Після цього ви можете використовувати цей об'єкт +підключення для взаємодії з будь-яким із API JSON RPC Solana. #### Приклад використання @@ -58,14 +62,20 @@ console.log(slotLeader); //49AqLYbpJYc2DrzGUAH1fhWJy62yxBxpLEkfJwjKy2jr ``` -Наведений вище приклад показує лише кілька методів класу Connection. Повний список можна знайти у +Наведений вище приклад показує лише кілька методів класу Connection. Повний +список можна знайти у [генерованій документації](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Connection.html). ### Транзакція [Документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Transaction.html) -Транзакція використовується для взаємодії з програмами на блокчейні Solana. Ці транзакції створюються за допомогою TransactionInstructions, які містять усі можливі облікові записи для взаємодії, а також необхідні дані або адреси програм. Кожна TransactionInstruction складається з ключів, даних і programId. Ви можете виконувати кілька інструкцій в одній транзакції, взаємодіючи з кількома програмами одночасно. +Транзакція використовується для взаємодії з програмами на блокчейні Solana. Ці +транзакції створюються за допомогою TransactionInstructions, які містять усі +можливі облікові записи для взаємодії, а також необхідні дані або адреси +програм. Кожна TransactionInstruction складається з ключів, даних і programId. +Ви можете виконувати кілька інструкцій в одній транзакції, взаємодіючи з +кількома програмами одночасно. #### Приклад використання @@ -135,7 +145,9 @@ await web3.sendAndConfirmRawTransaction(connection, rawTransaction); [Документація](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Keypair.html) -Keypair використовується для створення облікового запису з публічним і секретним ключами в Solana. Ви можете згенерувати Keypair, створити його з seed або секретного ключа. +Keypair використовується для створення облікового запису з публічним і секретним +ключами в Solana. Ви можете згенерувати Keypair, створити його з seed або +секретного ключа. #### Приклад використання @@ -170,20 +182,34 @@ console.log(accountFromSecret.secretKey); // Uint8Array(64) [...] ``` -Використання `generate` генерує випадкову Keypair для облікового запису на Solana. Використання `fromSeed` дозволяє створити Keypair з детермінованим конструктором. `fromSecret` створює Keypair із секретного масиву Uint8Array. Ви можете побачити, що publicKey для Keypair, створеної за допомогою `generate`, і `fromSecret` однакові, оскільки секретний ключ однаковий. +Використання `generate` генерує випадкову Keypair для облікового запису на +Solana. Використання `fromSeed` дозволяє створити Keypair з детермінованим +конструктором. `fromSecret` створює Keypair із секретного масиву Uint8Array. Ви +можете побачити, що publicKey для Keypair, створеної за допомогою `generate`, і +`fromSecret` однакові, оскільки секретний ключ однаковий. + ### Використання `generate` створює випадкову пару ключів для використання як обліковий запис у Solana. -Використання `fromSeed` дозволяє створити пару ключів за допомогою детермінованого конструктора. -`fromSecret` створює пару ключів із секретного масиву Uint8Array. Ви можете побачити, що publicKey для пари ключів `generate` і `fromSecret` є однаковими, оскільки секрет від пари ключів `generate` використовується в `fromSecret`. -**Попередження**: Не використовуйте `fromSeed`, якщо ви не створюєте seed із високою ентропією. Не розголошуйте ваш seed. Ставтеся до seed так само, як до приватного ключа. +Використання `fromSeed` дозволяє створити пару ключів за допомогою +детермінованого конструктора. `fromSecret` створює пару ключів із секретного +масиву Uint8Array. Ви можете побачити, що publicKey для пари ключів `generate` і +`fromSecret` є однаковими, оскільки секрет від пари ключів `generate` +використовується в `fromSecret`. + +**Попередження**: Не використовуйте `fromSeed`, якщо ви не створюєте seed із +високою ентропією. Не розголошуйте ваш seed. Ставтеся до seed так само, як до +приватного ключа. ### PublicKey [Джерело документації](https://solana-labs.github.io/solana-web3.js/v1.x/classes/PublicKey.html) -`PublicKey` використовується в `@solana/web3.js` для транзакцій, пар ключів і програм. Вам потрібен publicKey при зазначенні кожного облікового запису в транзакції, а також як загальний ідентифікатор у Solana. +`PublicKey` використовується в `@solana/web3.js` для транзакцій, пар ключів і +програм. Вам потрібен publicKey при зазначенні кожного облікового запису в +транзакції, а також як загальний ідентифікатор у Solana. -`PublicKey` можна створити за допомогою base58-строки, буфера, Uint8Array, числа або масиву чисел. +`PublicKey` можна створити за допомогою base58-строки, буфера, Uint8Array, числа +або масиву чисел. #### Приклад використання @@ -206,7 +232,9 @@ let programAddressFromKey = await web3.PublicKey.createProgramAddress( [highEntropyBuffer.slice(0, 31)], base58publicKey, ); -console.log(`Згенерована програмна адреса: ${programAddressFromKey.toBase58()}`); +console.log( + `Згенерована програмна адреса: ${programAddressFromKey.toBase58()}`, +); // Згенерована програмна адреса: 3thxPEEz4EDWHNxo1LpEpsAxZryPAHyvNVXJEJWgBgwJ @@ -224,7 +252,10 @@ console.log(`Дійсна програмна адреса: ${validProgramAddress [Джерело документації](https://solana-labs.github.io/solana-web3.js/v1.x/classes/SystemProgram.html) -`SystemProgram` дозволяє створювати облікові записи, виділяти дані облікових записів, призначати облікові записи програмам, працювати з nonce-обліковими записами та переводити лампорти. Ви можете використовувати клас `SystemInstruction` для декодування та читання окремих інструкцій. +`SystemProgram` дозволяє створювати облікові записи, виділяти дані облікових +записів, призначати облікові записи програмам, працювати з nonce-обліковими +записами та переводити лампорти. Ви можете використовувати клас +`SystemInstruction` для декодування та читання окремих інструкцій. #### Приклад використання @@ -313,13 +344,14 @@ await web3.sendAndConfirmTransaction(connection, assignTransaction, [ payer, assignedAccount, ]); - ``` + ### Secp256k1Program [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Secp256k1Program.html) -`Secp256k1Program` використовується для перевірки підписів `Secp256k1`, які використовуються як у Bitcoin, так і в Ethereum. +`Secp256k1Program` використовується для перевірки підписів `Secp256k1`, які +використовуються як у Bitcoin, так і в Ethereum. #### Приклад Використання @@ -381,7 +413,11 @@ await web3.sendAndConfirmTransaction(connection, transaction, [fromPublicKey]); [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Message.html) -`Message` використовується як альтернативний спосіб створення транзакцій. Ви можете створити повідомлення за допомогою облікових записів, заголовка, інструкцій та недавнього блочного хеша, які є частиною транзакції. [Transaction](/docs/uk/clients/javascript.md#Transaction) є `Message` плюс список необхідних підписів для виконання транзакції. +`Message` використовується як альтернативний спосіб створення транзакцій. Ви +можете створити повідомлення за допомогою облікових записів, заголовка, +інструкцій та недавнього блочного хеша, які є частиною транзакції. +[Transaction](/docs/uk/clients/javascript.md#Transaction) є `Message` плюс +список необхідних підписів для виконання транзакції. #### Приклад Використання @@ -443,7 +479,9 @@ await web3.sendAndConfirmTransaction(connection, transaction, [fromPublicKey]); [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Struct.html) -Клас `Struct` використовується для створення структур, сумісних із Rust, у JavaScript. Цей клас сумісний лише з Rust-структурами, закодованими за допомогою Borsh. +Клас `Struct` використовується для створення структур, сумісних із Rust, у +JavaScript. Цей клас сумісний лише з Rust-структурами, закодованими за допомогою +Borsh. #### Приклад Використання @@ -472,7 +510,11 @@ export class Fee extends Struct { [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Enum.html) -Клас `Enum` використовується для представлення сумісного з Rust енумератора у JavaScript. Енумератор буде представлений як строка при логуванні, але може бути правильно закодований/декодований при використанні разом з [Struct](/docs/uk/clients/javascript.md#Struct). Цей клас сумісний лише з Rust-енумераторами, закодованими за допомогою Borsh. +Клас `Enum` використовується для представлення сумісного з Rust енумератора у +JavaScript. Енумератор буде представлений як строка при логуванні, але може бути +правильно закодований/декодований при використанні разом з +[Struct](/docs/uk/clients/javascript.md#Struct). Цей клас сумісний лише з +Rust-енумераторами, закодованими за допомогою Borsh. #### Приклад Використання @@ -498,9 +540,15 @@ export class AccountType extends Enum {} [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/NonceAccount.html) -Зазвичай транзакція відхиляється, якщо поле `recentBlockhash` транзакції є застарілим. Для забезпечення певних кастодіальних послуг використовуються облікові записи `NonceAccount`. Транзакції, які використовують `recentBlockhash`, зафіксовані на блокчейні обліковим записом `NonceAccount`, не старіють доти, доки цей обліковий запис не буде оновлено. +Зазвичай транзакція відхиляється, якщо поле `recentBlockhash` транзакції є +застарілим. Для забезпечення певних кастодіальних послуг використовуються +облікові записи `NonceAccount`. Транзакції, які використовують +`recentBlockhash`, зафіксовані на блокчейні обліковим записом `NonceAccount`, не +старіють доти, доки цей обліковий запис не буде оновлено. -Ви можете створити `NonceAccount`, спочатку створивши звичайний обліковий запис, а потім використовуючи `SystemProgram`, щоб зробити цей обліковий запис `NonceAccount`. +Ви можете створити `NonceAccount`, спочатку створивши звичайний обліковий запис, +а потім використовуючи `SystemProgram`, щоб зробити цей обліковий запис +`NonceAccount`. #### Приклад Використання @@ -575,13 +623,17 @@ console.log(nonceAccountFromInfo); // } ``` -Наведений вище приклад показує як створити `NonceAccount` за допомогою `SystemProgram.createNonceAccount`, а також як отримати `NonceAccount` з accountInfo. Використовуючи nonce, ви можете створювати транзакції офлайн з nonce замість `recentBlockhash`. +Наведений вище приклад показує як створити `NonceAccount` за допомогою +`SystemProgram.createNonceAccount`, а також як отримати `NonceAccount` з +accountInfo. Використовуючи nonce, ви можете створювати транзакції офлайн з +nonce замість `recentBlockhash`. ### VoteAccount [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/VoteAccount.html) -`VoteAccount` — це об'єкт, який дозволяє декодувати облікові записи для голосування з використанням нативної програми голосування в мережі. +`VoteAccount` — це об'єкт, який дозволяє декодувати облікові записи для +голосування з використанням нативної програми голосування в мережі. #### Приклад Використання @@ -653,7 +705,12 @@ VoteAccount { [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/StakeProgram.html) -`StakeProgram` полегшує процес стейкінгу SOL і делегування їх будь-яким валідаторам у мережі. Ви можете використовувати `StakeProgram`, щоб створити стейк-обліковий запис, застейкати SOL, авторизувати облікові записи для виведення стейка, деактивувати стейк і вивести кошти. Клас `StakeInstruction` використовується для декодування та читання додаткових інструкцій з транзакцій, що викликають `StakeProgram`. +`StakeProgram` полегшує процес стейкінгу SOL і делегування їх будь-яким +валідаторам у мережі. Ви можете використовувати `StakeProgram`, щоб створити +стейк-обліковий запис, застейкати SOL, авторизувати облікові записи для +виведення стейка, деактивувати стейк і вивести кошти. Клас `StakeInstruction` +використовується для декодування та читання додаткових інструкцій з транзакцій, +що викликають `StakeProgram`. #### Приклад Використання @@ -749,15 +806,23 @@ await web3.sendAndConfirmTransaction(connection, withdrawTransaction, [ [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Authorized.html) -`Authorized` — це об'єкт, який використовується під час створення авторизованого облікового запису для стейкінгу в Solana. Ви можете окремо призначити `staker` і `withdrawer`, що дозволяє іншому обліковому запису виводити кошти, ніж той, що виконує стейкінг. +`Authorized` — це об'єкт, який використовується під час створення авторизованого +облікового запису для стейкінгу в Solana. Ви можете окремо призначити `staker` і +`withdrawer`, що дозволяє іншому обліковому запису виводити кошти, ніж той, що +виконує стейкінг. -Більше прикладів використання об'єкта `Authorized` ви можете знайти в розділі [`StakeProgram`](/docs/uk/clients/javascript.md#StakeProgram). +Більше прикладів використання об'єкта `Authorized` ви можете знайти в розділі +[`StakeProgram`](/docs/uk/clients/javascript.md#StakeProgram). ### Lockup [Документація Джерела](https://solana-labs.github.io/solana-web3.js/v1.x/classes/Lockup.html) -`Lockup` використовується разом із [StakeProgram](/docs/uk/clients/javascript.md#StakeProgram) для створення облікового запису. `Lockup` визначає, як довго стейк буде заблокований або недоступний для вилучення. Якщо `Lockup` встановлений на 0 як для епохи, так і для мітки часу Unix, блокування для облікового запису буде відключено. +`Lockup` використовується разом із +[StakeProgram](/docs/uk/clients/javascript.md#StakeProgram) для створення +облікового запису. `Lockup` визначає, як довго стейк буде заблокований або +недоступний для вилучення. Якщо `Lockup` встановлений на 0 як для епохи, так і +для мітки часу Unix, блокування для облікового запису буде відключено. #### Приклад Використання @@ -783,7 +848,10 @@ let createStakeAccountInstruction = StakeProgram.createAccount({ }); ``` -Наведений вище код створює `createStakeAccountInstruction`, який використовується для створення облікового запису за допомогою `StakeProgram`. Блокування встановлено на 0 як для епохи, так і для мітки часу Unix, що відключає блокування для облікового запису. - -Детальніше див. у розділі [StakeProgram](/docs/uk/clients/javascript.md#StakeProgram). +Наведений вище код створює `createStakeAccountInstruction`, який +використовується для створення облікового запису за допомогою `StakeProgram`. +Блокування встановлено на 0 як для епохи, так і для мітки часу Unix, що +відключає блокування для облікового запису. +Детальніше див. у розділі +[StakeProgram](/docs/uk/clients/javascript.md#StakeProgram). diff --git a/docs/locales/uk/clients/javascript.md b/docs/locales/uk/clients/javascript.md index 790d6f6ef..482da4c62 100644 --- a/docs/locales/uk/clients/javascript.md +++ b/docs/locales/uk/clients/javascript.md @@ -4,7 +4,9 @@ title: JavaScript Клієнт для Solana sidebarSortOrder: 2 description: Дізнайтеся, як взаємодіяти з Solana за допомогою клієнтської бібліотеки - JavaScript/TypeScript (@solana/web3.js). У цьому посібнику розглядаються підключення гаманця, транзакції та взаємодія з власними програмами з прикладами коду. + JavaScript/TypeScript (@solana/web3.js). У цьому посібнику розглядаються + підключення гаманця, транзакції та взаємодія з власними програмами з + прикладами коду. --- ## Що таке Solana-Web3.js? @@ -17,11 +19,11 @@ description: ## Загальна термінологія -| Термін | Визначення | -| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Програма | Безстанова виконувана програма, написана для інтерпретації інструкцій. Програми можуть виконувати дії на основі наданих інструкцій. | -| Інструкція | Найменша одиниця програми, яку клієнт може включити в транзакцію. Під час виконання коду інструкція може містити одну або кілька міжпрограмних викликів. | -| Транзакція | Одна або кілька інструкцій, підписаних клієнтом за допомогою одного або кількох Keypair, і виконуються атомарно з двома можливими результатами: успіх або невдача. | +| Термін | Визначення | +| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Програма | Безстанова виконувана програма, написана для інтерпретації інструкцій. Програми можуть виконувати дії на основі наданих інструкцій. | +| Інструкція | Найменша одиниця програми, яку клієнт може включити в транзакцію. Під час виконання коду інструкція може містити одну або кілька міжпрограмних викликів. | +| Транзакція | Одна або кілька інструкцій, підписаних клієнтом за допомогою одного або кількох Keypair, і виконуються атомарно з двома можливими результатами: успіх або невдача. | Для повного списку термінів дивіться [Термінологія Solana](/docs/terminology.md#cross-program-invocation-cpi) @@ -79,7 +81,9 @@ console.log(solanaWeb3); ### Підключення до гаманця -Щоб користувачі могли використовувати ваш dApp або додаток у Solana, їм потрібно отримати доступ до свого Keypair. Keypair - це приватний ключ з відповідним відкритим ключем, який використовується для підпису транзакцій. +Щоб користувачі могли використовувати ваш dApp або додаток у Solana, їм потрібно +отримати доступ до свого Keypair. Keypair - це приватний ключ з відповідним +відкритим ключем, який використовується для підпису транзакцій. Є два способи отримати Keypair: @@ -94,9 +98,11 @@ const { Keypair } = require("@solana/web3.js"); let keypair = Keypair.generate(); ``` -Це згенерує новий Keypair для користувача, який можна використовувати у вашому додатку. +Це згенерує новий Keypair для користувача, який можна використовувати у вашому +додатку. -Ви можете дозволити введення secretKey через текстове поле та отримати Keypair за допомогою `Keypair.fromSecretKey(secretKey)`. +Ви можете дозволити введення secretKey через текстове поле та отримати Keypair +за допомогою `Keypair.fromSecretKey(secretKey)`. ```javascript const { Keypair } = require("@solana/web3.js"); @@ -111,14 +117,23 @@ let secretKey = Uint8Array.from([ let keypair = Keypair.fromSecretKey(secretKey); ``` -Багато гаманців сьогодні дозволяють користувачам імпортувати свій Keypair за допомогою різних розширень або веб-гаманців. Загальна рекомендація - використовувати гаманці, а не Keypair, для підпису транзакцій. Гаманець створює шар розділення між dApp та Keypair, забезпечуючи, що dApp ніколи не має доступу до секретного ключа. Ви можете знайти способи підключення до зовнішніх гаманців за допомогою бібліотеки [wallet-adapter](https://github.com/solana-labs/wallet-adapter). +Багато гаманців сьогодні дозволяють користувачам імпортувати свій Keypair за +допомогою різних розширень або веб-гаманців. Загальна рекомендація - +використовувати гаманці, а не Keypair, для підпису транзакцій. Гаманець створює +шар розділення між dApp та Keypair, забезпечуючи, що dApp ніколи не має доступу +до секретного ключа. Ви можете знайти способи підключення до зовнішніх гаманців +за допомогою бібліотеки +[wallet-adapter](https://github.com/solana-labs/wallet-adapter). ### Створення та відправка транзакцій -Щоб взаємодіяти з програмами на Solana, ви створюєте, підписуєте та відправляєте транзакції до мережі. Транзакції - це колекції інструкцій з підписами. Порядок, в якому інструкції існують у транзакції, визначає порядок їх виконання. +Щоб взаємодіяти з програмами на Solana, ви створюєте, підписуєте та відправляєте +транзакції до мережі. Транзакції - це колекції інструкцій з підписами. Порядок, +в якому інструкції існують у транзакції, визначає порядок їх виконання. -Транзакція в Solana-Web3.js створюється за допомогою -об'єкта [`Transaction`](/docs/clients/javascript.md#Transaction) і додавання бажаних повідомлень, адрес або інструкцій. +Транзакція в Solana-Web3.js створюється за допомогою об'єкта +[`Transaction`](/docs/clients/javascript.md#Transaction) і додавання бажаних +повідомлень, адрес або інструкцій. Приклад транзакції передачі: @@ -143,9 +158,15 @@ transaction.add( ); ``` -Вищенаведений код створює транзакцію, готову до підпису та передачі в мережу. Інструкція `SystemProgram.transfer` була додана до транзакції, що містить суму lamports для відправки, а також публічні ключі `to` і `from`. +Вищенаведений код створює транзакцію, готову до підпису та передачі в мережу. +Інструкція `SystemProgram.transfer` була додана до транзакції, що містить суму +lamports для відправки, а також публічні ключі `to` і `from`. -Все, що залишилося зробити - підписати транзакцію за допомогою Keypair і відправити її через мережу. Ви можете виконати відправку транзакції за допомогою `sendAndConfirmTransaction`, якщо хочете сповістити користувача або зробити щось після завершення транзакції, або використовувати `sendTransaction`, якщо не потрібно чекати підтвердження транзакції. +Все, що залишилося зробити - підписати транзакцію за допомогою Keypair і +відправити її через мережу. Ви можете виконати відправку транзакції за допомогою +`sendAndConfirmTransaction`, якщо хочете сповістити користувача або зробити щось +після завершення транзакції, або використовувати `sendTransaction`, якщо не +потрібно чекати підтвердження транзакції. ```javascript const { @@ -160,13 +181,20 @@ let connection = new Connection(clusterApiUrl("testnet")); sendAndConfirmTransaction(connection, transaction, [keypair]); ``` -Вищенаведений код приймає `TransactionInstruction` за допомогою `SystemProgram`, створює `Transaction` і відправляє її через мережу. Ви використовуєте `Connection`, щоб визначити, до якої мережі Solana ви підключаєтесь, а саме `mainnet-beta`, `testnet` або `devnet`. +Вищенаведений код приймає `TransactionInstruction` за допомогою `SystemProgram`, +створює `Transaction` і відправляє її через мережу. Ви використовуєте +`Connection`, щоб визначити, до якої мережі Solana ви підключаєтесь, а саме +`mainnet-beta`, `testnet` або `devnet`. ### Взаємодія з власними програмами -Попередній розділ розглядає відправлення базових транзакцій. У Solana все, що ви робите, взаємодіє з різними програмами, включаючи транзакцію передачі в попередньому розділі. На момент написання програми на Solana пишуться на Rust або C. +Попередній розділ розглядає відправлення базових транзакцій. У Solana все, що ви +робите, взаємодіє з різними програмами, включаючи транзакцію передачі в +попередньому розділі. На момент написання програми на Solana пишуться на Rust +або C. -Розглянемо `SystemProgram`. Сигнатура методу для виділення простору в вашому обліковому записі в Solana на Rust виглядає так: +Розглянемо `SystemProgram`. Сигнатура методу для виділення простору в вашому +обліковому записі в Solana на Rust виглядає так: ```rust pub fn allocate( @@ -175,11 +203,19 @@ pub fn allocate( ) -> Instruction ``` -У Solana, коли ви хочете взаємодіяти з програмою, ви повинні спочатку знати всі облікові записи, з якими програма буде взаємодіяти. +У Solana, коли ви хочете взаємодіяти з програмою, ви повинні спочатку знати всі +облікові записи, з якими програма буде взаємодіяти. -Ви завжди повинні надавати кожен обліковий запис, з яким програма буде взаємодіяти в інструкції. Крім того, ви повинні вказати, чи є обліковий запис `isSigner` або `isWritable`. +Ви завжди повинні надавати кожен обліковий запис, з яким програма буде +взаємодіяти в інструкції. Крім того, ви повинні вказати, чи є обліковий запис +`isSigner` або `isWritable`. -У методі `allocate` вище потрібен один обліковий запис `pubkey`, а також кількість `space` для виділення. Ми знаємо, що метод `allocate` записує в обліковий запис, виділяючи в ньому простір, роблячи `pubkey` обов'язковим `isWritable`. `isSigner` потрібен, коли ви вказуєте обліковий запис, який виконує інструкцію. У цьому випадку підписувач - це обліковий запис, який викликає виділення простору в собі. +У методі `allocate` вище потрібен один обліковий запис `pubkey`, а також +кількість `space` для виділення. Ми знаємо, що метод `allocate` записує в +обліковий запис, виділяючи в ньому простір, роблячи `pubkey` обов'язковим +`isWritable`. `isSigner` потрібен, коли ви вказуєте обліковий запис, який +виконує інструкцію. У цьому випадку підписувач - це обліковий запис, який +викликає виділення простору в собі. Давайте подивимося, як викликати цю інструкцію за допомогою solana-web3.js: @@ -196,7 +232,9 @@ let airdropSignature = await connection.requestAirdrop( await connection.confirmTransaction({ signature: airdropSignature }); ``` -Спочатку ми налаштовуємо Keypair і підключення, щоб у нас був обліковий запис для виділення на тестовій мережі. Ми також створюємо Keypair для платника і додаємо трохи SOL, щоб оплатити транзакцію виділення. +Спочатку ми налаштовуємо Keypair і підключення, щоб у нас був обліковий запис +для виділення на тестовій мережі. Ми також створюємо Keypair для платника і +додаємо трохи SOL, щоб оплатити транзакцію виділення. ```javascript let allocateTransaction = new web3.Transaction({ @@ -206,7 +244,13 @@ let keys = [{ pubkey: keypair.publicKey, isSigner: true, isWritable: true }]; let params = { space: 100 }; ``` -Ми створюємо транзакцію `allocateTransaction`, об'єкти keys та params. Поле `feePayer` є необов'язковим при створенні транзакції, воно вказує, хто оплачує транзакцію, за замовчуванням використовується pubkey першого підписувача в транзакції. `keys` представляє всі облікові записи, з якими функція програми `allocate` буде взаємодіяти. Оскільки функція `allocate` також вимагає простору, ми створили `params`, щоб його використати пізніше при виклику функції `allocate`. +Ми створюємо транзакцію `allocateTransaction`, об'єкти keys та params. Поле +`feePayer` є необов'язковим при створенні транзакції, воно вказує, хто оплачує +транзакцію, за замовчуванням використовується pubkey першого підписувача в +транзакції. `keys` представляє всі облікові записи, з якими функція програми +`allocate` буде взаємодіяти. Оскільки функція `allocate` також вимагає простору, +ми створили `params`, щоб його використати пізніше при виклику функції +`allocate`. ```javascript let allocateStruct = { @@ -215,7 +259,11 @@ let allocateStruct = { }; ``` -Це створено за допомогою `u32` і `ns64` з `@solana/buffer-layout` для створення payload. Функція `allocate` приймає параметр `space`. Щоб взаємодіяти з функцією, ми повинні надати дані у форматі Buffer. Бібліотека `buffer-layout` допомагає з виділенням буфера та його правильним кодуванням для інтерпретації програмами на Rust в Solana. +Це створено за допомогою `u32` і `ns64` з `@solana/buffer-layout` для створення +payload. Функція `allocate` приймає параметр `space`. Щоб взаємодіяти з +функцією, ми повинні надати дані у форматі Buffer. Бібліотека `buffer-layout` +допомагає з виділенням буфера та його правильним кодуванням для інтерпретації +програмами на Rust в Solana. Давайте розглянемо цю структуру детальніше. @@ -229,7 +277,8 @@ let allocateStruct = { } ``` -`index` встановлений у 8, тому що функція `allocate` знаходиться на 8-й позиції у enum інструкцій для `SystemProgram`. +`index` встановлений у 8, тому що функція `allocate` знаходиться на 8-й позиції +у enum інструкцій для `SystemProgram`. ```rust /* https://github.com/solana-labs/solana/blob/21bc43ed58c63c827ba4db30426965ef3e807180/sdk/program/src/system_instruction.rs#L142-L305 */ @@ -262,8 +311,8 @@ pub enum SystemInstruction { } ``` -`layout` у структурі allocate завжди має мати `u32('instruction')` першим -при використанні для виклику інструкції. +`layout` у структурі allocate завжди має мати `u32('instruction')` першим при +використанні для виклику інструкції. ```javascript { @@ -275,7 +324,11 @@ pub enum SystemInstruction { } ``` -`ns64('space')` - це аргумент для функції `allocate`. Ви можете бачити, що в оригінальній функції `allocate` на Rust, space мав тип `u64`. `u64` є 64-бітовим unsigned integer. У Javascript за замовчуванням підтримуються тільки 53-бітові числа. `ns64` з `@solana/buffer-layout` допомагає з конвертацією типів між Rust і Javascript. Ви можете знайти більше конвертацій типів між Rust і Javascript на +`ns64('space')` - це аргумент для функції `allocate`. Ви можете бачити, що в +оригінальній функції `allocate` на Rust, space мав тип `u64`. `u64` є 64-бітовим +unsigned integer. У Javascript за замовчуванням підтримуються тільки 53-бітові +числа. `ns64` з `@solana/buffer-layout` допомагає з конвертацією типів між Rust +і Javascript. Ви можете знайти більше конвертацій типів між Rust і Javascript на [solana-labs/buffer-layout](https://github.com/solana-labs/buffer-layout). ```javascript @@ -284,7 +337,10 @@ let layoutFields = Object.assign({ instruction: allocateStruct.index }, params); allocateStruct.layout.encode(layoutFields, data); ``` -Використовуючи створений раніше bufferLayout, ми можемо виділити буфер даних. Потім ми присвоюємо наші params `{ space: 100 }`, щоб вони правильно відповідали макету, і кодуємо їх у буфер даних. Тепер дані готові для відправлення до програми. +Використовуючи створений раніше bufferLayout, ми можемо виділити буфер даних. +Потім ми присвоюємо наші params `{ space: 100 }`, щоб вони правильно відповідали +макету, і кодуємо їх у буфер даних. Тепер дані готові для відправлення до +програми. ```javascript allocateTransaction.add( @@ -301,7 +357,8 @@ await web3.sendAndConfirmTransaction(connection, allocateTransaction, [ ]); ``` -Нарешті, ми додаємо інструкцію транзакції з усіма ключами облікових записів, платником, даними та programId і передаємо транзакцію до мережі. +Нарешті, ми додаємо інструкцію транзакції з усіма ключами облікових записів, +платником, даними та programId і передаємо транзакцію до мережі. Повний код можна знайти нижче. diff --git a/docs/locales/uk/clients/rust.md b/docs/locales/uk/clients/rust.md index d058363e7..b9037668c 100644 --- a/docs/locales/uk/clients/rust.md +++ b/docs/locales/uk/clients/rust.md @@ -16,29 +16,33 @@ Rust пакети для Solana - [Створіть і розгорніть вашу першу програму Solana, використовуючи тільки ваш браузер](/content/guides/getstarted/hello-world-in-your-browser.md). Інсталяція не потрібна. -- [Налаштуйте ваше локальне середовище](/docs/uk/intro/installation) і використовуйте локальний тестовий валідатор. +- [Налаштуйте ваше локальне середовище](/docs/uk/intro/installation) і + використовуйте локальний тестовий валідатор. ## Rust Пакети -Нижче наведено найважливіші та найчастіше використовувані Rust пакети для розробки в Solana: +Нижче наведено найважливіші та найчастіше використовувані Rust пакети для +розробки в Solana: -- [`solana-program`] — Імпортується програмами, що працюють у Solana, і компілюється до - SBF. Цей пакет містить багато фундаментальних типів даних і реекспортується з - [`solana-sdk`], який не можна імпортувати у програму Solana. +- [`solana-program`] — Імпортується програмами, що працюють у Solana, і + компілюється до SBF. Цей пакет містить багато фундаментальних типів даних і + реекспортується з [`solana-sdk`], який не можна імпортувати у програму Solana. - [`solana-sdk`] — Базовий SDK для роботи поза мережею, реекспортує - [`solana-program`] і додає більше API на додаток до цього. Більшість програм Solana, - що не працюють у мережі, імпортують цей пакет. + [`solana-program`] і додає більше API на додаток до цього. Більшість програм + Solana, що не працюють у мережі, імпортують цей пакет. - [`solana-client`] — Для взаємодії з вузлом Solana через [JSON RPC API](/docs/uk/rpc). -- [`solana-cli-config`] — Завантаження та збереження конфігураційного файлу Solana CLI. +- [`solana-cli-config`] — Завантаження та збереження конфігураційного + файлу Solana CLI. -- [`solana-clap-utils`] — Рутини для налаштування CLI, використовуючи [`clap`], як у - основному CLI Solana. Включає функції для завантаження всіх типів підписантів, підтримуваних CLI. +- [`solana-clap-utils`] — Рутини для налаштування CLI, використовуючи + [`clap`], як у основному CLI Solana. Включає функції для завантаження всіх + типів підписантів, підтримуваних CLI. [`solana-program`]: https://docs.rs/solana-program [`solana-sdk`]: https://docs.rs/solana-sdk diff --git a/docs/locales/uk/core/accounts.md b/docs/locales/uk/core/accounts.md index f45f08df5..ab7f7bd41 100644 --- a/docs/locales/uk/core/accounts.md +++ b/docs/locales/uk/core/accounts.md @@ -3,10 +3,10 @@ sidebarSortOrder: 1 sidebarLabel: Модель облікових записів Solana title: Модель облікових записів Solana description: - Дізнайтеся про модель облікових записів Solana, включаючи те, як облікові записи зберігають дані - і програми, механіку оренди, власність облікових записів і взаємозв'язок між - програмами та обліковими записами даних. Зрозумійте основні концепції системи - зберігання ключ-значення Solana. + Дізнайтеся про модель облікових записів Solana, включаючи те, як облікові + записи зберігають дані і програми, механіку оренди, власність облікових + записів і взаємозв'язок між програмами та обліковими записами даних. + Зрозумійте основні концепції системи зберігання ключ-значення Solana. --- У Solana всі дані зберігаються в так званих "облікових записах". Спосіб @@ -18,73 +18,84 @@ description: ## Основні моменти -- Облікові записи можуть зберігати до 10 МБ даних, які можуть складатися з виконуваного - коду програми або стану програми. +- Облікові записи можуть зберігати до 10 МБ даних, які можуть складатися з + виконуваного коду програми або стану програми. -- Облікові записи потребують застави в SOL, пропорційної обсягу збережених даних, - яка повністю повертається при закритті облікового запису. +- Облікові записи потребують застави в SOL, пропорційної обсягу збережених + даних, яка повністю повертається при закритті облікового запису. -- Кожен обліковий запис має "власника" програми. Тільки програма, яка володіє обліковим записом, може - змінювати його дані або знімати баланс лампортів. Однак будь-хто може - збільшити баланс. +- Кожен обліковий запис має "власника" програми. Тільки програма, яка володіє + обліковим записом, може змінювати його дані або знімати баланс лампортів. + Однак будь-хто може збільшити баланс. -- Програми (смартконтракти) є безстанними обліковими записами, які зберігають виконуваний код. +- Програми (смартконтракти) є безстанними обліковими записами, які зберігають + виконуваний код. -- Облікові записи даних створюються програмами для зберігання і керування станом програми. +- Облікові записи даних створюються програмами для зберігання і керування станом + програми. -- Вбудовані програми - це вбудовані програми, які включені у середовище виконання Solana. +- Вбудовані програми - це вбудовані програми, які включені у середовище + виконання Solana. -- Системні облікові записи - це спеціальні облікові записи, які зберігають стан кластера мережі. +- Системні облікові записи - це спеціальні облікові записи, які зберігають стан + кластера мережі. ## Обліковий запис -Кожен обліковий запис ідентифікується його унікальною адресою, представленою у форматі 32 байт -як [Ed25519](https://ed25519.cr.yp.to/) `PublicKey`. Ви можете вважати -адресу унікальним ідентифікатором облікового запису. +Кожен обліковий запис ідентифікується його унікальною адресою, представленою у +форматі 32 байт як [Ed25519](https://ed25519.cr.yp.to/) `PublicKey`. Ви можете +вважати адресу унікальним ідентифікатором облікового запису. ![Адреса облікового запису](/assets/docs/core/accounts/account-address.svg) -Цей зв'язок між обліковим записом та його адресою можна розглядати як -пару ключ-значення, де адреса є ключем для пошуку відповідних -даних облікового запису в ланцюжку. +Цей зв'язок між обліковим записом та його адресою можна розглядати як пару +ключ-значення, де адреса є ключем для пошуку відповідних даних облікового запису +в ланцюжку. ### AccountInfo Облікові записи мають [максимальний розмір у 10 МБ](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L85) -(10 мегабайт), а дані, що зберігаються в кожному обліковому записі Solana, мають наступну -структуру, відому як +(10 мегабайт), а дані, що зберігаються в кожному обліковому записі Solana, мають +наступну структуру, відому як [AccountInfo](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/account_info.rs#L19). ![AccountInfo](/assets/docs/core/accounts/accountinfo.svg) `AccountInfo` для кожного облікового запису включає наступні поля: -- `data`: Масив байтів, який зберігає стан облікового запису. Якщо обліковий запис є - програмою (смартконтрактом), це поле зберігає виконуваний код програми. Це поле часто - називають "даними облікового запису". +- `data`: Масив байтів, який зберігає стан облікового запису. Якщо обліковий + запис є програмою (смартконтрактом), це поле зберігає виконуваний код + програми. Це поле часто називають "даними облікового запису". - `executable`: Булевий прапорець, який вказує, чи є обліковий запис програмою. - `lamports`: Числове представлення балансу облікового запису в [лампортах](/docs/terminology.md#lamport), найменшій одиниці SOL (1 SOL = 1 мільярд лампортів). -- `owner`: Вказує публічний ключ (Program ID) програми, яка володіє обліковим записом. +- `owner`: Вказує публічний ключ (Program ID) програми, яка володіє обліковим + записом. -Як ключова частина моделі облікових записів Solana, кожен обліковий запис у Solana має -визначеного "власника", а саме програму. Тільки програма, зазначена як власник облікового запису, може -змінювати дані, що зберігаються в обліковому записі, або знімати баланс лампортів. Важливо зазначити, що, хоча тільки власник може знімати баланс, будь-хто може збільшити баланс. +Як ключова частина моделі облікових записів Solana, кожен обліковий запис у +Solana має визначеного "власника", а саме програму. Тільки програма, зазначена +як власник облікового запису, може змінювати дані, що зберігаються в обліковому +записі, або знімати баланс лампортів. Важливо зазначити, що, хоча тільки власник +може знімати баланс, будь-хто може збільшити баланс. > Для зберігання даних у ланцюжку потрібно передати певну кількість SOL до -> облікового запису. Кількість, що передається, пропорційна розміру даних, що зберігаються в обліковому записі. Ця концепція зазвичай називається "орендою". Однак, ви можете розглядати "оренду" швидше як "депозит", оскільки SOL, виділені для облікового запису, можуть бути повністю відновлені при закритті облікового запису. +> облікового запису. Кількість, що передається, пропорційна розміру даних, що +> зберігаються в обліковому записі. Ця концепція зазвичай називається "орендою". +> Однак, ви можете розглядати "оренду" швидше як "депозит", оскільки SOL, +> виділені для облікового запису, можуть бути повністю відновлені при закритті +> облікового запису. ## Вбудовані програми -Solana містить невелику кількість вбудованих програм, які є частиною -реалізації валідатора і забезпечують різні основні функціональності для -мережі. Ви можете знайти повний список вбудованих програм +Solana містить невелику кількість вбудованих програм, які є частиною реалізації +валідатора і забезпечують різні основні функціональності для мережі. Ви можете +знайти повний список вбудованих програм [тут](https://docs.anza.xyz/runtime/programs). -При розробці користувацьких програм на Solana ви часто будете взаємодіяти з двома -вбудованими програмами: Системною Програмою і Завантажувачем BPF. +При розробці користувацьких програм на Solana ви часто будете взаємодіяти з +двома вбудованими програмами: Системною Програмою і Завантажувачем BPF. ### Системна Програма @@ -97,34 +108,40 @@ Solana містить невелику кількість вбудованих - [Виділення простору](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L70): Встановлює обсяг пам'яті для поля даних кожного облікового запису. - [Призначення власника програми](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/system/src/system_processor.rs#L112): - Після створення облікового запису Системною Програмою вона може перепризначити власника - програми іншому обліковому запису програми. Це спосіб, за яким користувацькі програми беруть - у власність нові облікові записи, створені Системною Програмою. + Після створення облікового запису Системною Програмою вона може перепризначити + власника програми іншому обліковому запису програми. Це спосіб, за яким + користувацькі програми беруть у власність нові облікові записи, створені + Системною Програмою. -У Solana "гаманець" просто є обліковим записом, який належить Системній Програмі. Баланс лампортів у гаманці є кількістю SOL, що належать обліковому запису. +У Solana "гаманець" просто є обліковим записом, який належить Системній +Програмі. Баланс лампортів у гаманці є кількістю SOL, що належать обліковому +запису. ![Системний Обліковий Запис](/assets/docs/core/accounts/system-account.svg) -> Тільки облікові записи, що належать Системній Програмі, можуть використовуватися як платники комісій за транзакції. +> Тільки облікові записи, що належать Системній Програмі, можуть +> використовуватися як платники комісій за транзакції. ### Завантажувач BPF [Завантажувач BPF](https://github.com/solana-labs/solana/tree/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src) -є програмою, яка призначена як "власник" усіх інших програм у мережі, -крім Вбудованих Програм. Він відповідає за розгортання, оновлення та виконання користувацьких програм. +є програмою, яка призначена як "власник" усіх інших програм у мережі, крім +Вбудованих Програм. Він відповідає за розгортання, оновлення та виконання +користувацьких програм. ## Системні Облікові Записи -Системні облікові записи - це спеціальні облікові записи, розташовані за попередньо визначеними адресами, які -надають доступ до даних про стан кластера мережі. Ці облікові записи динамічно оновлюються -даними про кластер мережі. Ви можете знайти повний список Системних Облікових Записів +Системні облікові записи - це спеціальні облікові записи, розташовані за +попередньо визначеними адресами, які надають доступ до даних про стан кластера +мережі. Ці облікові записи динамічно оновлюються даними про кластер мережі. Ви +можете знайти повний список Системних Облікових Записів [тут](https://docs.anza.xyz/runtime/sysvars). ## Користувацькі Програми -У Solana "смартконтракти" називаються -[програмами](/docs/core/programs.md). Програма є обліковим записом, який містить -виконуваний код, і позначається прапорцем "виконуваний", який встановлено в значення "true". +У Solana "смартконтракти" називаються [програмами](/docs/core/programs.md). +Програма є обліковим записом, який містить виконуваний код, і позначається +прапорцем "виконуваний", який встановлено в значення "true". Для детального пояснення процесу розгортання програми, зверніться до сторінки [Розгортання Програм](/docs/programs/deploying.md) цієї документації. @@ -135,16 +152,16 @@ Solana містить невелику кількість вбудованих [розгортаються](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L498) на Solana, технічно створюються три окремі облікові записи: -- **Обліковий Запис Програми**: Основний обліковий запис, який представляє програму в ланцюжку. Цей - обліковий запис зберігає адресу виконуваного облікового запису даних (який зберігає - зкомпільований код програми) і право на оновлення програми (адреса, яка - має дозвіл на внесення змін до програми). -- **Виконуваний Обліковий Запис Програми**: Обліковий запис, який містить виконуваний - байт-код програми. -- **Буферний Обліковий Запис**: Тимчасовий обліковий запис, який зберігає байт-код під час - активного розгортання або оновлення програми. Після завершення процесу дані - передаються до Виконуваного Облікового Запису Програми, а буферний обліковий запис - закривається. +- **Обліковий Запис Програми**: Основний обліковий запис, який представляє + програму в ланцюжку. Цей обліковий запис зберігає адресу виконуваного + облікового запису даних (який зберігає зкомпільований код програми) і право на + оновлення програми (адреса, яка має дозвіл на внесення змін до програми). +- **Виконуваний Обліковий Запис Програми**: Обліковий запис, який містить + виконуваний байт-код програми. +- **Буферний Обліковий Запис**: Тимчасовий обліковий запис, який зберігає + байт-код під час активного розгортання або оновлення програми. Після + завершення процесу дані передаються до Виконуваного Облікового Запису + Програми, а буферний обліковий запис закривається. Наприклад, ось посилання на Solana Explorer для Програмного Розширення Токенів [Обліковий Запис Програми](https://explorer.solana.com/address/TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb) @@ -157,28 +174,33 @@ Solana містить невелику кількість вбудованих ![Обліковий Запис Програми](/assets/docs/core/accounts/program-account-simple.svg) -> Адреса "Облікового Запису Програми" зазвичай називається "ID Програми", який використовується для виклику програми. +> Адреса "Облікового Запису Програми" зазвичай називається "ID Програми", який +> використовується для виклику програми. ### Обліковий Запис Даних Програми Solana є "безстанними", тобто облікові записи програм містять лише -виконуваний байт-код програми. Для зберігання та модифікації додаткових даних необхідно створювати нові -облікові записи. Ці облікові записи зазвичай називаються "обліковими записами даних". +виконуваний байт-код програми. Для зберігання та модифікації додаткових даних +необхідно створювати нові облікові записи. Ці облікові записи зазвичай +називаються "обліковими записами даних". -Облікові записи даних можуть зберігати будь-які довільні дані, визначені в коді програми-власника. +Облікові записи даних можуть зберігати будь-які довільні дані, визначені в коді +програми-власника. ![Обліковий Запис Даних](/assets/docs/core/accounts/data-account.svg) -Зверніть увагу, що тільки [Системна Програма](/docs/core/accounts.md#system-program) може -створювати нові облікові записи. Після створення облікового запису Системною Програмою вона може потім -передати власність нового облікового запису іншій програмі. +Зверніть увагу, що тільки +[Системна Програма](/docs/core/accounts.md#system-program) може створювати нові +облікові записи. Після створення облікового запису Системною Програмою вона може +потім передати власність нового облікового запису іншій програмі. -Іншими словами, створення облікового запису даних для користувацької програми вимагає двох кроків: +Іншими словами, створення облікового запису даних для користувацької програми +вимагає двох кроків: 1. Виклик Системної Програми для створення облікового запису, яка потім передає власність користувацькій програмі 2. Виклик користувацької програми, яка тепер володіє обліковим записом, для ініціалізації даних облікового запису, як це визначено в коді програми -Цей процес створення облікового запису даних часто абстрагується як єдиний крок, але -корисно розуміти підлеглий процес. +Цей процес створення облікового запису даних часто абстрагується як єдиний крок, +але корисно розуміти підлеглий процес. diff --git a/docs/locales/uk/core/clusters.md b/docs/locales/uk/core/clusters.md index abf086ecf..b2a5944fe 100644 --- a/docs/locales/uk/core/clusters.md +++ b/docs/locales/uk/core/clusters.md @@ -5,8 +5,8 @@ sidebarSortOrder: 8 description: Дізнайтеся про кластери мережі Solana (Devnet, Testnet і Mainnet Beta), їхні публічні точки доступу RPC, обмеження швидкості та випадки використання. - Дізнайтеся, як підключатися до різних мереж Solana для розробки, тестування - та виробничого середовища. + Дізнайтеся, як підключатися до різних мереж Solana для розробки, тестування та + виробничого середовища. --- Блокчейн Solana має кілька різних груп валідаторів, відомих як @@ -43,18 +43,19 @@ description: ## Основні відомості - Mainnet: Живе виробниче середовище для розгорнутих додатків. -- Devnet: Тестування з публічним доступом для розробників, які експериментують зі - своїми додатками. +- Devnet: Тестування з публічним доступом для розробників, які експериментують + зі своїми додатками. - Testnet: Стрес-тестування для оновлень мережі та продуктивності валідаторів. -**Приклади використання**: Можливо, ви захочете налагодити нову програму на Devnet -або перевірити метрики продуктивності на Testnet перед розгортанням на Mainnet. +**Приклади використання**: Можливо, ви захочете налагодити нову програму на +Devnet або перевірити метрики продуктивності на Testnet перед розгортанням на +Mainnet. -| **Кластер** | **Точка доступу** | **Призначення** | **Примітки** | -| ----------- | ---------------------------------------- | ------------------------------- | ------------------------------ | -| Mainnet | `https://api.mainnet-beta.solana.com` | Живе виробниче середовище | Потребує SOL для транзакцій | -| Devnet | `https://api.devnet.solana.com` | Публічне тестування та розробка | Безкоштовний SOL для тестування| -| Testnet | `https://api.testnet.solana.com` | Тестування валідаторів | Може мати періодичні простої | +| **Кластер** | **Точка доступу** | **Призначення** | **Примітки** | +| ----------- | ------------------------------------- | ------------------------------- | ------------------------------- | +| Mainnet | `https://api.mainnet-beta.solana.com` | Живе виробниче середовище | Потребує SOL для транзакцій | +| Devnet | `https://api.devnet.solana.com` | Публічне тестування та розробка | Безкоштовний SOL для тестування | +| Testnet | `https://api.testnet.solana.com` | Тестування валідаторів | Може мати періодичні простої | ## Devnet @@ -73,8 +74,8 @@ Devnet слугує тестовим майданчиком для будь-ко ### Точка доступу Devnet -- `https://api.devnet.solana.com` - єдиний вузол API, розміщений Solana Labs; - з обмеженнями швидкості +- `https://api.devnet.solana.com` - єдиний вузол API, розміщений Solana Labs; з + обмеженнями швидкості #### Приклад конфігурації командного рядка `solana` @@ -101,14 +102,14 @@ Testnet - це місце, де основні учасники Solana стре - Токени Testnet **не реальні**. - Testnet може піддаватися скиданням журналу. - Testnet включає крани для отримання токенів для тестування додатків. -- Testnet зазвичай працює на новішій гілці випуску програмного забезпечення, - ніж Devnet і Mainnet Beta. +- Testnet зазвичай працює на новішій гілці випуску програмного забезпечення, ніж + Devnet і Mainnet Beta. - Точка доступу Gossip для Testnet: `entrypoint.testnet.solana.com:8001` ### Точка доступу Testnet -- `https://api.testnet.solana.com` - єдиний вузол API, розміщений Solana Labs; - з обмеженнями швидкості +- `https://api.testnet.solana.com` - єдиний вузол API, розміщений Solana Labs; з + обмеженнями швидкості #### Приклад конфігурації командного рядка `solana` @@ -132,7 +133,8 @@ solana config set --url https://api.testnet.solana.com валідаторів та власників токенів. - Токени, випущені на Mainnet Beta, є **реальними** SOL. -- Точка доступу Gossip для Mainnet Beta: `entrypoint.mainnet-beta.solana.com:8001` +- Точка доступу Gossip для Mainnet Beta: + `entrypoint.mainnet-beta.solana.com:8001` ### Точка доступу Mainnet beta @@ -163,9 +165,10 @@ solana config set --url https://api.mainnet-beta.solana.com ## Загальні HTTP-коди помилок -- 403 -- Ваша IP-адреса або вебсайт було заблоковано. Настав час запустити власні - сервери RPC або знайти приватний сервіс. -- 429 -- Ваша IP-адреса перевищує обмеження швидкості. Зменшіть швидкість! Використовуйте +- 403 -- Ваша IP-адреса або вебсайт було заблоковано. Настав час запустити + власні сервери RPC або знайти приватний сервіс. +- 429 -- Ваша IP-адреса перевищує обмеження швидкості. Зменшіть швидкість! + Використовуйте [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) HTTP-заголовок відповіді, щоб визначити, як довго потрібно чекати перед повторною спробою. diff --git a/docs/locales/uk/core/cpi.md b/docs/locales/uk/core/cpi.md index cec59477d..a15da2bb8 100644 --- a/docs/locales/uk/core/cpi.md +++ b/docs/locales/uk/core/cpi.md @@ -8,8 +8,8 @@ description: функціональність у мережі Solana. --- -Виклик між програмами (CPI) відбувається, коли одна програма викликає -інструкції іншої програми. Цей механізм дозволяє складати програми Solana. +Виклик між програмами (CPI) відбувається, коли одна програма викликає інструкції +іншої програми. Цей механізм дозволяє складати програми Solana. Інструкції можна уявити як API-методи, які програма надає мережі, а CPI - це виклик одного API-методу іншим API-методом. @@ -22,17 +22,17 @@ description: розширюються на програму-отримувача (B). - Програма-отримувач (B) може здійснювати подальші CPI до інших програм до максимального рівня глибини 4 (наприклад, B->C, C->D). -- Програми можуть "підписувати" від імені [PDA](/docs/core/pda.md), що - створені з їхнього ID програми. +- Програми можуть "підписувати" від імені [PDA](/docs/core/pda.md), що створені + з їхнього ID програми. > У середовищі виконання програм Solana визначено константу під назвою > [`max_invoke_stack_height`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/program-runtime/src/compute_budget.rs#L31-L35), > яка має значення > [5](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/program-runtime/src/compute_budget.rs#L138). -> Це обмеження встановлює максимальну висоту стеку викликів інструкцій -> програми. Висота стеку починається з 1 для інструкцій транзакції, збільшується -> на 1 кожного разу, коли програма викликає іншу інструкцію. Це ефективно -> обмежує глибину викликів для CPI до 4. +> Це обмеження встановлює максимальну висоту стеку викликів інструкцій програми. +> Висота стеку починається з 1 для інструкцій транзакції, збільшується на 1 +> кожного разу, коли програма викликає іншу інструкцію. Це ефективно обмежує +> глибину викликів для CPI до 4. ## Основні моменти @@ -41,8 +41,8 @@ description: - Привілеї підпису від програми-виклику розширюються на програму-отримувача. -- Під час здійснення CPI програми можуть "підписувати" від імені PDA, - створених із їхнього власного ID програми. +- Під час здійснення CPI програми можуть "підписувати" від імені PDA, створених + із їхнього власного ID програми. - Програма-отримувач може здійснювати додаткові CPI до інших програм до максимальної глибини 4. @@ -50,8 +50,8 @@ description: ## Як написати CPI Написання інструкції для CPI слідує тій самій схемі, що й побудова -[інструкції](/docs/core/transactions.md#instruction) для додавання до транзакції. -Кожна інструкція CPI повинна зазначати таку інформацію: +[інструкції](/docs/core/transactions.md#instruction) для додавання до +транзакції. Кожна інструкція CPI повинна зазначати таку інформацію: - **Адреса програми**: Вказує програму, яка викликається - **Облікові записи**: Перераховує кожен обліковий запис, з якого інструкція @@ -71,9 +71,9 @@ description: Функція [`invoke`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/program.rs#L132) -використовується під час здійснення CPI, який не потребує підписантів PDA. Під час -здійснення CPI підписанти, надані програмі-виклику, автоматично розширюються на -програму-отримувача. +використовується під час здійснення CPI, який не потребує підписантів PDA. Під +час здійснення CPI підписанти, надані програмі-виклику, автоматично розширюються +на програму-отримувача. ```rust pub fn invoke( @@ -117,11 +117,10 @@ pub fn invoke_signed( інструкцію, яка також містить цього підписанта та/або обліковий запис із правом запису. -Хоча PDA не мають -[приватних ключів](/docs/core/pda.md#what-is-a-pda), вони все одно можуть діяти -як підписант в інструкції через CPI. Щоб підтвердити, що PDA створений із -програми, що викликає, необхідно включити насіння, використане для створення -PDA, як `signers_seeds`. +Хоча PDA не мають [приватних ключів](/docs/core/pda.md#what-is-a-pda), вони все +одно можуть діяти як підписант в інструкції через CPI. Щоб підтвердити, що PDA +створений із програми, що викликає, необхідно включити насіння, використане для +створення PDA, як `signers_seeds`. Коли CPI обробляється, середовище виконання Solana [викликає внутрішньо `create_program_address`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/syscalls/cpi.rs#L550) diff --git a/docs/locales/uk/core/fees.md b/docs/locales/uk/core/fees.md index 69689f7d0..87f200807 100644 --- a/docs/locales/uk/core/fees.md +++ b/docs/locales/uk/core/fees.md @@ -20,91 +20,165 @@ altRoutes: - /docs/uk/core/runtime --- -Блокчейн Solana має кілька типів плати та витрат, які виникають під час використання мережі без дозволу. Вони поділяються на кілька специфічних типів: +Блокчейн Solana має кілька типів плати та витрат, які виникають під час +використання мережі без дозволу. Вони поділяються на кілька специфічних типів: - **Транзакційні збори** — плата за обробку транзакцій/інструкцій валідаторами. -- **Пріоритизаційні збори** — додаткова плата для підвищення порядку обробки транзакцій. +- **Пріоритизаційні збори** — додаткова плата для підвищення порядку обробки + транзакцій. - **Оренда** — утримуваний баланс для збереження даних в ончейні. ## Транзакційні збори -Мала плата, яка сплачується за обробку логіки (інструкції) у програмі в ончейні на блокчейні Solana, називається "_транзакційною платою_". +Мала плата, яка сплачується за обробку логіки (інструкції) у програмі в ончейні +на блокчейні Solana, називається "_транзакційною платою_". -Кожна [транзакція](/docs/uk/core/transactions.md#transaction), яка містить одну або більше [інструкцій](/docs/uk/core/transactions.md#instruction), надсилається через мережу, де її обробляє поточний лідер-валідатор. Після підтвердження як глобальної транзакції ця "транзакційна плата" сплачується мережі для підтримки економічної моделі блокчейна Solana. +Кожна [транзакція](/docs/uk/core/transactions.md#transaction), яка містить одну +або більше [інструкцій](/docs/uk/core/transactions.md#instruction), надсилається +через мережу, де її обробляє поточний лідер-валідатор. Після підтвердження як +глобальної транзакції ця "транзакційна плата" сплачується мережі для підтримки +економічної моделі блокчейна Solana. -> Транзакційні збори відрізняються від плати за збереження даних в обліковому записі, відомої як [оренда](#rent). Транзакційні збори сплачуються за обробку інструкцій у мережі Solana, а депозит оренди утримується в обліковому записі для збереження даних в блокчейні та може бути повернутий. +> Транзакційні збори відрізняються від плати за збереження даних в обліковому +> записі, відомої як [оренда](#rent). Транзакційні збори сплачуються за обробку +> інструкцій у мережі Solana, а депозит оренди утримується в обліковому записі +> для збереження даних в блокчейні та може бути повернутий. -На даний момент базова транзакційна плата в Solana встановлена на рівні 5000 лампортів за підпис. На додаток до цієї базової плати, можуть бути додані додаткові [пріоритизаційні збори](#prioritization-fee). +На даний момент базова транзакційна плата в Solana встановлена на рівні 5000 +лампортів за підпис. На додаток до цієї базової плати, можуть бути додані +додаткові [пріоритизаційні збори](#prioritization-fee). ### Навіщо сплачувати транзакційні збори? -Транзакційні збори пропонують багато переваг у економічній моделі Solana, зокрема вони: +Транзакційні збори пропонують багато переваг у економічній моделі Solana, +зокрема вони: -- Забезпечують компенсацію мережі валідаторів за витрачені ресурси CPU/GPU для обробки транзакцій. +- Забезпечують компенсацію мережі валідаторів за витрачені ресурси CPU/GPU для + обробки транзакцій. - Зменшують спам у мережі, запроваджуючи реальну вартість транзакцій. -- Забезпечують довгострокову економічну стабільність мережі через протокольно захоплену мінімальну плату за транзакцію. +- Забезпечують довгострокову економічну стабільність мережі через протокольно + захоплену мінімальну плату за транзакцію. ### Основи економічної моделі -Багато блокчейн-мереж (включаючи Bitcoin та Ethereum) покладаються на інфляційні "протокольні нагороди" для короткострокової підтримки безпеки мережі. У довгостроковій перспективі ці мережі все більше покладаються на "транзакційні збори" для підтримки безпеки. +Багато блокчейн-мереж (включаючи Bitcoin та Ethereum) покладаються на інфляційні +"протокольні нагороди" для короткострокової підтримки безпеки мережі. У +довгостроковій перспективі ці мережі все більше покладаються на "транзакційні +збори" для підтримки безпеки. Те саме стосується Solana. Зокрема: -- Фіксована частка (спочатку 50%) кожної транзакційної плати "спалюється" (знищується), решта надходить до поточного [лідера](/docs/uk/terminology.md#leader), який обробляє транзакцію. -- Запланована глобальна інфляційна ставка забезпечує джерело [нагород](https://docs.anza.xyz/implemented-proposals/staking-rewards), які розподіляються серед [валідаторів Solana](https://docs.anza.xyz/operations). +- Фіксована частка (спочатку 50%) кожної транзакційної плати "спалюється" + (знищується), решта надходить до поточного + [лідера](/docs/uk/terminology.md#leader), який обробляє транзакцію. +- Запланована глобальна інфляційна ставка забезпечує джерело + [нагород](https://docs.anza.xyz/implemented-proposals/staking-rewards), які + розподіляються серед [валідаторів Solana](https://docs.anza.xyz/operations). ### Збір плати -Транзакції повинні мати щонайменше один обліковий запис, який підписав транзакцію та може бути змінений. Ці "записувані підписуючі облікові записи" серіалізуються першими у списку облікових записів, і перший з них завжди використовується як "платник плати". +Транзакції повинні мати щонайменше один обліковий запис, який підписав +транзакцію та може бути змінений. Ці "записувані підписуючі облікові записи" +серіалізуються першими у списку облікових записів, і перший з них завжди +використовується як "платник плати". -Перед обробкою будь-яких інструкцій транзакції баланс облікового запису платника плати [вираховується](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank.rs#L4045-L4064) для оплати транзакційних зборів. Якщо баланс платника плати недостатній для покриття зборів, обробка транзакції припиняється і вона визнається невдалою. +Перед обробкою будь-яких інструкцій транзакції баланс облікового запису платника +плати +[вираховується](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank.rs#L4045-L4064) +для оплати транзакційних зборів. Якщо баланс платника плати недостатній для +покриття зборів, обробка транзакції припиняється і вона визнається невдалою. -Якщо баланс був достатнім, плата буде вирахувана, і виконання інструкцій транзакції почнеться. Якщо будь-яка з інструкцій призведе до помилки, обробка транзакції буде припинена, і зрештою вона буде записана як невдала транзакція в книзі Solana. Плата все одно буде зібрана за ці невдалі транзакції. +Якщо баланс був достатнім, плата буде вирахувана, і виконання інструкцій +транзакції почнеться. Якщо будь-яка з інструкцій призведе до помилки, обробка +транзакції буде припинена, і зрештою вона буде записана як невдала транзакція в +книзі Solana. Плата все одно буде зібрана за ці невдалі транзакції. -Якщо будь-яка з інструкцій повертає помилку або порушує обмеження часу виконання, всі зміни облікових записів **_крім_** вирахування транзакційної плати будуть скасовані. Це тому, що мережа валідаторів вже витратила обчислювальні ресурси для збору транзакцій та початку їх обробки. +Якщо будь-яка з інструкцій повертає помилку або порушує обмеження часу +виконання, всі зміни облікових записів **_крім_** вирахування транзакційної +плати будуть скасовані. Це тому, що мережа валідаторів вже витратила +обчислювальні ресурси для збору транзакцій та початку їх обробки. ### Розподіл плати -Транзакційні збори [частково спалюються](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank/fee_distribution.rs#L55-L64), а решта зборів збираються валідатором, який створив блок, у якому включені відповідні транзакції. Зокрема, [50% спалюються](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/fee_calculator.rs#L79), а [50% розподіляються](https://github.com/anza-xyz/agave/blob/e621336acad4f5d6e5b860eaa1b074b01c99253c/runtime/src/bank/fee_distribution.rs#L58-L62) валідатору, який створив блок. +Транзакційні збори +[частково спалюються](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/runtime/src/bank/fee_distribution.rs#L55-L64), +а решта зборів збираються валідатором, який створив блок, у якому включені +відповідні транзакції. Зокрема, +[50% спалюються](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/fee_calculator.rs#L79), +а +[50% розподіляються](https://github.com/anza-xyz/agave/blob/e621336acad4f5d6e5b860eaa1b074b01c99253c/runtime/src/bank/fee_distribution.rs#L58-L62) +валідатору, який створив блок. ### Чому спалюються частина зборів? -Як згадано вище, фіксована частка кожної транзакційної плати "спалюється" (знищується). Це зроблено для зміцнення економічної цінності SOL і підтримки безпеки мережі. На відміну від системи, де всі транзакційні збори повністю спалюються, лідери все ще мають стимул включати якомога більше транзакцій у свої слоти (можливість створити блок). +Як згадано вище, фіксована частка кожної транзакційної плати "спалюється" +(знищується). Це зроблено для зміцнення економічної цінності SOL і підтримки +безпеки мережі. На відміну від системи, де всі транзакційні збори повністю +спалюються, лідери все ще мають стимул включати якомога більше транзакцій у свої +слоти (можливість створити блок). -Спалені збори також можуть допомогти запобігти зловмисним валідаторам у цензуруванні транзакцій через врахування в [виборі форку](/docs/uk/terminology.md#fork). +Спалені збори також можуть допомогти запобігти зловмисним валідаторам у +цензуруванні транзакцій через врахування в +[виборі форку](/docs/uk/terminology.md#fork). #### Приклад атаки: -У випадку [форку Proof of History (PoH)](/docs/uk/terminology.md#proof-of-history-poh) з лідером, що займається цензурою або зловживанням: +У випадку +[форку Proof of History (PoH)](/docs/uk/terminology.md#proof-of-history-poh) з +лідером, що займається цензурою або зловживанням: -- через втрати зборів, що виникають через цензуру, очікується, що загальні збори, які будуть спалені, будуть **_меншими_**, ніж у порівнянному чесному форку; -- якщо лідер, який займається цензурою, хоче компенсувати ці втрачені протокольні збори, він повинен буде самостійно замінити спалені збори на своєму форку; +- через втрати зборів, що виникають через цензуру, очікується, що загальні + збори, які будуть спалені, будуть **_меншими_**, ніж у порівнянному чесному + форку; +- якщо лідер, який займається цензурою, хоче компенсувати ці втрачені + протокольні збори, він повинен буде самостійно замінити спалені збори на + своєму форку; - таким чином, потенційно зменшуючи стимул до цензури в першу чергу. ### Обчислення транзакційних зборів -Повна плата за конкретну транзакцію розраховується на основі двох основних частин: +Повна плата за конкретну транзакцію розраховується на основі двох основних +частин: - Статично встановлена базова плата за підпис, і -- Обчислювальні ресурси, використані під час транзакції, виміряні у "[обчислювальних одиницях](/docs/uk/terminology.md#compute-units)". +- Обчислювальні ресурси, використані під час транзакції, виміряні у + "[обчислювальних одиницях](/docs/uk/terminology.md#compute-units)". -Оскільки кожна транзакція може вимагати різної кількості обчислювальних ресурсів, кожній транзакції виділяється максимальна кількість _обчислювальних одиниць_ у рамках "обчислювального бюджету". +Оскільки кожна транзакція може вимагати різної кількості обчислювальних +ресурсів, кожній транзакції виділяється максимальна кількість _обчислювальних +одиниць_ у рамках "обчислювального бюджету". ## Обчислювальний бюджет -Щоб запобігти зловживанню обчислювальними ресурсами, кожній транзакції виділяється "обчислювальний бюджет". Цей бюджет визначає: +Щоб запобігти зловживанню обчислювальними ресурсами, кожній транзакції +виділяється "обчислювальний бюджет". Цей бюджет визначає: -- обчислювальні витрати, пов'язані з різними типами операцій, які може виконувати транзакція (обчислювальні одиниці, спожиті на операцію), -- максимальну кількість обчислювальних одиниць, які може спожити транзакція (ліміт обчислювальних одиниць), -- та операційні межі, яких має дотримуватися транзакція (наприклад, ліміти розміру даних облікового запису). +- обчислювальні витрати, пов'язані з різними типами операцій, які може + виконувати транзакція (обчислювальні одиниці, спожиті на операцію), +- максимальну кількість обчислювальних одиниць, які може спожити транзакція + (ліміт обчислювальних одиниць), +- та операційні межі, яких має дотримуватися транзакція (наприклад, ліміти + розміру даних облікового запису). -Коли транзакція вичерпує свій обчислювальний бюджет (вичерпання обчислювального бюджету) або перевищує межі, наприклад, намагається перевищити [максимальну глибину стеку викликів](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L138) або [максимальний розмір завантажених даних облікового запису](#accounts-data-size-limit), виконання транзакції припиняється, і повертається помилка. Це призводить до невдалої транзакції та жодних змін стану (окрім збору плати за транзакцію). +Коли транзакція вичерпує свій обчислювальний бюджет (вичерпання обчислювального +бюджету) або перевищує межі, наприклад, намагається перевищити +[максимальну глибину стеку викликів](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L138) +або +[максимальний розмір завантажених даних облікового запису](#accounts-data-size-limit), +виконання транзакції припиняється, і повертається помилка. Це призводить до +невдалої транзакції та жодних змін стану (окрім збору плати за транзакцію). ### Ліміт розміру даних облікового запису -Транзакція може встановлювати максимальну кількість байтів даних облікового запису, які їй дозволено завантажувати, включивши інструкцію `SetLoadedAccountsDataSizeLimit` (не перевищуючи абсолютний максимум часу виконання). Якщо `SetLoadedAccountsDataSizeLimit` не надано, транзакція за замовчуванням використовує значення часу виконання [`MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L137-L139). +Транзакція може встановлювати максимальну кількість байтів даних облікового +запису, які їй дозволено завантажувати, включивши інструкцію +`SetLoadedAccountsDataSizeLimit` (не перевищуючи абсолютний максимум часу +виконання). Якщо `SetLoadedAccountsDataSizeLimit` не надано, транзакція за +замовчуванням використовує значення часу виконання +[`MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L137-L139). -Функцію `ComputeBudgetInstruction::set_loaded_accounts_data_size_limit` можна використовувати для створення цієї інструкції. +Функцію `ComputeBudgetInstruction::set_loaded_accounts_data_size_limit` можна +використовувати для створення цієї інструкції. ```rust let instruction = ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(100_000); @@ -112,13 +186,28 @@ let instruction = ComputeBudgetInstruction::set_loaded_accounts_data_size_limit( ### Обчислювальні одиниці -Усі операції, виконані ончейн у рамках транзакції, вимагають різного обсягу обчислювальних ресурсів, які витрачаються валідаторами під час обробки (обчислювальна вартість). Найменшою одиницею виміру цих ресурсів є _"обчислювальна одиниця"_. - -Під час обробки транзакції обчислювальні одиниці поступово споживаються кожною з її інструкцій, виконуваних ончейн (вичерпуючи бюджет). Оскільки кожна інструкція виконує різну логіку (запис у облікові записи, CPI, виконання системних викликів тощо), кожна може споживати [різну кількість](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L133-L178) обчислювальних одиниць. - -> Програма може записувати деталі про використання своїх обчислювальних ресурсів, включаючи залишок у виділеному обчислювальному бюджеті. Більше інформації ви можете знайти в цьому посібнику з [оптимізації використання обчислювальних ресурсів](/content/guides/advanced/how-to-optimize-compute.md). - -Кожній транзакції виділяється [ліміт обчислювальних одиниць](#compute-unit-limit), або за замовчуванням встановлений часом виконання, або шляхом явного запиту на вищий ліміт. Якщо транзакція перевищує свій ліміт обчислювальних одиниць, її обробка зупиняється, що призводить до невдалої транзакції. +Усі операції, виконані ончейн у рамках транзакції, вимагають різного обсягу +обчислювальних ресурсів, які витрачаються валідаторами під час обробки +(обчислювальна вартість). Найменшою одиницею виміру цих ресурсів є +_"обчислювальна одиниця"_. + +Під час обробки транзакції обчислювальні одиниці поступово споживаються кожною з +її інструкцій, виконуваних ончейн (вичерпуючи бюджет). Оскільки кожна інструкція +виконує різну логіку (запис у облікові записи, CPI, виконання системних викликів +тощо), кожна може споживати +[різну кількість](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L133-L178) +обчислювальних одиниць. + +> Програма може записувати деталі про використання своїх обчислювальних +> ресурсів, включаючи залишок у виділеному обчислювальному бюджеті. Більше +> інформації ви можете знайти в цьому посібнику з +> [оптимізації використання обчислювальних ресурсів](/content/guides/advanced/how-to-optimize-compute.md). + +Кожній транзакції виділяється +[ліміт обчислювальних одиниць](#compute-unit-limit), або за замовчуванням +встановлений часом виконання, або шляхом явного запиту на вищий ліміт. Якщо +транзакція перевищує свій ліміт обчислювальних одиниць, її обробка зупиняється, +що призводить до невдалої транзакції. Нижче наведено кілька поширених операцій, які мають обчислювальну вартість: @@ -132,60 +221,116 @@ let instruction = ComputeBudgetInstruction::set_loaded_accounts_data_size_limit( - міжпрограмні виклики (CPI) - криптографічні операції -> Для [міжпрограмних викликів](/docs/uk/core/cpi.md) викликана інструкція успадковує обчислювальний бюджет і ліміти свого батька. Якщо викликана інструкція споживає залишок бюджету транзакції або перевищує ліміт, весь ланцюжок викликів і обробка транзакції верхнього рівня зупиняються. +> Для [міжпрограмних викликів](/docs/uk/core/cpi.md) викликана інструкція +> успадковує обчислювальний бюджет і ліміти свого батька. Якщо викликана +> інструкція споживає залишок бюджету транзакції або перевищує ліміт, весь +> ланцюжок викликів і обробка транзакції верхнього рівня зупиняються. -Детальнішу інформацію про всі операції, які споживають обчислювальні одиниці, ви можете знайти в [ComputeBudget](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L19-L123) в часі виконання Solana. +Детальнішу інформацію про всі операції, які споживають обчислювальні одиниці, ви +можете знайти в +[ComputeBudget](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget.rs#L19-L123) +в часі виконання Solana. ### Ліміт обчислювальних одиниць -Кожна транзакція має максимальну кількість обчислювальних одиниць (CU), які вона може спожити, що називається _"лімітом обчислювальних одиниць"_. У часі виконання Solana встановлено абсолютний максимальний ліміт [1,4 мільйона CU](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L19) на транзакцію та за замовчуванням [200 тисяч CU на інструкцію](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L18). - -Транзакція може запитувати більш конкретний і оптимальний ліміт обчислювальних одиниць, включивши одну інструкцію `SetComputeUnitLimit`. Це може бути як вищий, так і нижчий ліміт. Але він ніколи не може перевищувати абсолютний максимальний ліміт на транзакцію. - -Хоча ліміт обчислювальних одиниць за замовчуванням підходить для простих транзакцій, він часто є менш оптимальним (як для часу виконання, так і для користувача). Для складніших транзакцій, наприклад, виклику програм, що виконують декілька CPI, може знадобитися запит вищого ліміту обчислювальних одиниць для транзакції. - -Запит оптимальних лімітів обчислювальних одиниць для вашої транзакції є важливим для зменшення витрат на транзакцію та кращого планування вашої транзакції в мережі. Гаманці, dApps та інші сервіси повинні переконатися, що їхні запити на обчислювальні одиниці є оптимальними, щоб забезпечити найкращий досвід для своїх користувачів. - -> Для отримання додаткової інформації та найкращих практик прочитайте цей посібник про [запит оптимальних лімітів обчислювальних ресурсів](/content/guides/advanced/how-to-request-optimal-compute.md). +Кожна транзакція має максимальну кількість обчислювальних одиниць (CU), які вона +може спожити, що називається _"лімітом обчислювальних одиниць"_. У часі +виконання Solana встановлено абсолютний максимальний ліміт +[1,4 мільйона CU](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L19) +на транзакцію та за замовчуванням +[200 тисяч CU на інструкцію](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L18). + +Транзакція може запитувати більш конкретний і оптимальний ліміт обчислювальних +одиниць, включивши одну інструкцію `SetComputeUnitLimit`. Це може бути як вищий, +так і нижчий ліміт. Але він ніколи не може перевищувати абсолютний максимальний +ліміт на транзакцію. + +Хоча ліміт обчислювальних одиниць за замовчуванням підходить для простих +транзакцій, він часто є менш оптимальним (як для часу виконання, так і для +користувача). Для складніших транзакцій, наприклад, виклику програм, що +виконують декілька CPI, може знадобитися запит вищого ліміту обчислювальних +одиниць для транзакції. + +Запит оптимальних лімітів обчислювальних одиниць для вашої транзакції є важливим +для зменшення витрат на транзакцію та кращого планування вашої транзакції в +мережі. Гаманці, dApps та інші сервіси повинні переконатися, що їхні запити на +обчислювальні одиниці є оптимальними, щоб забезпечити найкращий досвід для своїх +користувачів. + +> Для отримання додаткової інформації та найкращих практик прочитайте цей +> посібник про +> [запит оптимальних лімітів обчислювальних ресурсів](/content/guides/advanced/how-to-request-optimal-compute.md). ### Ціна обчислювальної одиниці -Якщо транзакція бажає сплатити вищу плату, щоб підвищити пріоритетність її обробки, вона може встановити _"ціну обчислювальної одиниці"_. Ця ціна, у поєднанні з [лімітом обчислювальних одиниць](#compute-unit-limit), буде використовуватися для визначення плати за пріоритизацію транзакції. +Якщо транзакція бажає сплатити вищу плату, щоб підвищити пріоритетність її +обробки, вона може встановити _"ціну обчислювальної одиниці"_. Ця ціна, у +поєднанні з [лімітом обчислювальних одиниць](#compute-unit-limit), буде +використовуватися для визначення плати за пріоритизацію транзакції. -За замовчуванням [ціна обчислювальної одиниці не встановлена](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L38), що призводить до відсутності додаткової плати за пріоритизацію. +За замовчуванням +[ціна обчислювальної одиниці не встановлена](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/program-runtime/src/compute_budget_processor.rs#L38), +що призводить до відсутності додаткової плати за пріоритизацію. ## Пріоритизаційні збори -Як частина [Compute Budget](#compute-budget), час виконання підтримує транзакції, що сплачують **опціональну** плату, відому як _"плата за пріоритизацію"_. Сплата цієї додаткової плати допомагає підвищити пріоритетність транзакції у порівнянні з іншими під час обробки, що призводить до швидшого виконання. +Як частина [Compute Budget](#compute-budget), час виконання підтримує +транзакції, що сплачують **опціональну** плату, відому як _"плата за +пріоритизацію"_. Сплата цієї додаткової плати допомагає підвищити пріоритетність +транзакції у порівнянні з іншими під час обробки, що призводить до швидшого +виконання. ### Як розраховується плата за пріоритизацію -Плата за пріоритизацію транзакції розраховується шляхом множення її **_ліміту обчислювальних одиниць_** на **_ціну обчислювальної одиниці_** (вимірюється в _мікролампортах_). Ці значення можна встановити один раз на транзакцію, включивши такі інструкції Compute Budget: +Плата за пріоритизацію транзакції розраховується шляхом множення її **_ліміту +обчислювальних одиниць_** на **_ціну обчислювальної одиниці_** (вимірюється в +_мікролампортах_). Ці значення можна встановити один раз на транзакцію, +включивши такі інструкції Compute Budget: -- [`SetComputeUnitLimit`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L47-L50) — встановлення максимальної кількості обчислювальних одиниць, які може спожити транзакція. -- [`SetComputeUnitPrice`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L52-L55) — встановлення бажаної додаткової плати, яку транзакція готова сплатити для підвищення пріоритетності. +- [`SetComputeUnitLimit`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L47-L50) + — встановлення максимальної кількості обчислювальних одиниць, які може спожити + транзакція. +- [`SetComputeUnitPrice`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/compute_budget.rs#L52-L55) + — встановлення бажаної додаткової плати, яку транзакція готова сплатити для + підвищення пріоритетності. -Якщо інструкція `SetComputeUnitLimit` не надана, буде використовуватися [ліміт обчислювальних одиниць за замовчуванням](#compute-unit-limit). +Якщо інструкція `SetComputeUnitLimit` не надана, буде використовуватися +[ліміт обчислювальних одиниць за замовчуванням](#compute-unit-limit). -Якщо інструкція `SetComputeUnitPrice` не надана, транзакція за замовчуванням матиме найнижчий пріоритет (тобто відсутність пріоритизаційної плати). +Якщо інструкція `SetComputeUnitPrice` не надана, транзакція за замовчуванням +матиме найнижчий пріоритет (тобто відсутність пріоритизаційної плати). ### Як встановити плату за пріоритизацію -Плата за пріоритизацію транзакції встановлюється шляхом включення інструкції `SetComputeUnitPrice` та, за бажанням, інструкції `SetComputeUnitLimit`. Час виконання використовуватиме ці значення для розрахунку плати за пріоритизацію, яка буде використовуватися для пріоритизації даної транзакції у блоці. +Плата за пріоритизацію транзакції встановлюється шляхом включення інструкції +`SetComputeUnitPrice` та, за бажанням, інструкції `SetComputeUnitLimit`. Час +виконання використовуватиме ці значення для розрахунку плати за пріоритизацію, +яка буде використовуватися для пріоритизації даної транзакції у блоці. -Ви можете створити кожну з цих інструкцій за допомогою функцій Rust або `@solana/web3.js`. Потім кожну інструкцію можна включити в транзакцію та надіслати до кластера як звичайно. Дивіться також [найкращі практики](#prioritization-fee-best-practices) нижче. +Ви можете створити кожну з цих інструкцій за допомогою функцій Rust або +`@solana/web3.js`. Потім кожну інструкцію можна включити в транзакцію та +надіслати до кластера як звичайно. Дивіться також +[найкращі практики](#prioritization-fee-best-practices) нижче. -На відміну від інших інструкцій усередині транзакції Solana, інструкції Compute Budget **НЕ** вимагають жодних облікових записів. Транзакція з кількома інструкціями одного типу завершиться невдачею. +На відміну від інших інструкцій усередині транзакції Solana, інструкції Compute +Budget **НЕ** вимагають жодних облікових записів. Транзакція з кількома +інструкціями одного типу завершиться невдачею. -Транзакції можуть містити лише **одну інструкцію кожного типу** інструкцій обчислювального бюджету. Дублікати інструкцій призведуть до помилки [`TransactionError::DuplicateInstruction`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/transaction/error.rs#L143-L145) і, зрештою, до невдачі транзакції. +Транзакції можуть містити лише **одну інструкцію кожного типу** інструкцій +обчислювального бюджету. Дублікати інструкцій призведуть до помилки +[`TransactionError::DuplicateInstruction`](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/src/transaction/error.rs#L143-L145) +і, зрештою, до невдачі транзакції. #### Rust -Бібліотека `solana-sdk` включає функції в рамках [`ComputeBudgetInstruction`](https://docs.rs/solana-sdk/latest/solana_sdk/compute_budget/enum.ComputeBudgetInstruction.html) для створення інструкцій для встановлення _ліміту обчислювальних одиниць_ та _ціни обчислювальної одиниці_. +Бібліотека `solana-sdk` включає функції в рамках +[`ComputeBudgetInstruction`](https://docs.rs/solana-sdk/latest/solana_sdk/compute_budget/enum.ComputeBudgetInstruction.html) +для створення інструкцій для встановлення _ліміту обчислювальних одиниць_ та +_ціни обчислювальної одиниці_. ```rust let instruction = ComputeBudgetInstruction::set_compute_unit_limit(300_000); @@ -194,9 +339,13 @@ let instruction = ComputeBudgetInstruction::set_compute_unit_limit(300_000); ```rust let instruction = ComputeBudgetInstruction::set_compute_unit_price(1); ``` + #### Javascript -Бібліотека `@solana/web3.js` включає функції в класі [`ComputeBudgetProgram`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/ComputeBudgetProgram.html) для створення інструкцій для встановлення _ліміту обчислювальних одиниць_ та _ціни обчислювальної одиниці_. +Бібліотека `@solana/web3.js` включає функції в класі +[`ComputeBudgetProgram`](https://solana-labs.github.io/solana-web3.js/v1.x/classes/ComputeBudgetProgram.html) +для створення інструкцій для встановлення _ліміту обчислювальних одиниць_ та +_ціни обчислювальної одиниці_. ```js const instruction = ComputeBudgetProgram.setComputeUnitLimit({ @@ -212,54 +361,109 @@ const instruction = ComputeBudgetProgram.setComputeUnitPrice({ ### Найкращі практики для плати за пріоритизацію -Нижче наведено загальну інформацію про найкращі практики для пріоритизаційних зборів. Більш детальну інформацію можна знайти в цьому посібнику про [запит оптимального використання обчислювальних ресурсів](/content/guides/advanced/how-to-request-optimal-compute.md), включаючи симуляцію транзакції для визначення її приблизного використання обчислювальних ресурсів. +Нижче наведено загальну інформацію про найкращі практики для пріоритизаційних +зборів. Більш детальну інформацію можна знайти в цьому посібнику про +[запит оптимального використання обчислювальних ресурсів](/content/guides/advanced/how-to-request-optimal-compute.md), +включаючи симуляцію транзакції для визначення її приблизного використання +обчислювальних ресурсів. #### Запитуйте мінімальну кількість обчислювальних одиниць -Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць, необхідну для виконання, щоб мінімізувати збори. Також зауважте, що збори не коригуються, якщо кількість запитаних обчислювальних одиниць перевищує фактично спожиту кількість у виконаній транзакції. +Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць, +необхідну для виконання, щоб мінімізувати збори. Також зауважте, що збори не +коригуються, якщо кількість запитаних обчислювальних одиниць перевищує фактично +спожиту кількість у виконаній транзакції. #### Отримуйте останні пріоритизаційні збори -Перед надсиланням транзакції до кластеру ви можете скористатися методом RPC [`getRecentPrioritizationFees`](/docs/uk/rpc/http/getRecentPrioritizationFees.mdx), щоб отримати список останніх сплачених пріоритизаційних зборів у нещодавно оброблених блоках вузла. +Перед надсиланням транзакції до кластеру ви можете скористатися методом RPC +[`getRecentPrioritizationFees`](/docs/uk/rpc/http/getRecentPrioritizationFees.mdx), +щоб отримати список останніх сплачених пріоритизаційних зборів у нещодавно +оброблених блоках вузла. -Ви можете використовувати ці дані для оцінки відповідної плати за пріоритизацію для вашої транзакції, щоб: +Ви можете використовувати ці дані для оцінки відповідної плати за пріоритизацію +для вашої транзакції, щоб: -(a) підвищити ймовірність її обробки кластером та -(b) мінімізувати сплачені збори. +(a) підвищити ймовірність її обробки кластером та (b) мінімізувати сплачені +збори. ## Оренда -Плата, що депонується на кожен [Обліковий запис Solana](/docs/uk/core/accounts.md) для збереження його пов'язаних даних в ончейні, називається "_орендою_". Ця плата утримується у звичайному балансі лампортів на кожному обліковому записі та може бути повернута під час закриття облікового запису. - -> Оренда відрізняється від [транзакційних зборів](#transaction-fees). Оренда "сплачується" (утримується в Обліковому записі) для збереження даних на блокчейні Solana та може бути повернута. У той час як транзакційні збори сплачуються за обробку [інструкцій](/docs/uk/core/transactions.md#instructions) у мережі. - -Усі облікові записи повинні підтримувати достатньо високий баланс лампортів (відносно їх виділеного простору), щоб стати [звільненими від оренди](#rent-exempt) і залишатися на блокчейні Solana. Будь-яка транзакція, що намагається зменшити баланс облікового запису нижче його відповідного мінімального балансу для звільнення від оренди, завершиться невдачею (якщо тільки баланс не зменшується до нуля). - -Коли власник облікового запису більше не бажає зберігати ці дані в ончейні та доступними в глобальному стані, він може закрити обліковий запис і повернути орендний депозит. - -Це здійснюється шляхом виведення (переказу) усього балансу лампортів облікового запису на інший обліковий запис (наприклад, ваш гаманець). Зменшивши баланс облікового запису до рівно `0`, час виконання видалить обліковий запис і його пов'язані дані з мережі в процесі _"[збирання сміття](#garbage-collection)"_. +Плата, що депонується на кожен +[Обліковий запис Solana](/docs/uk/core/accounts.md) для збереження його +пов'язаних даних в ончейні, називається "_орендою_". Ця плата утримується у +звичайному балансі лампортів на кожному обліковому записі та може бути повернута +під час закриття облікового запису. + +> Оренда відрізняється від [транзакційних зборів](#transaction-fees). Оренда +> "сплачується" (утримується в Обліковому записі) для збереження даних на +> блокчейні Solana та може бути повернута. У той час як транзакційні збори +> сплачуються за обробку +> [інструкцій](/docs/uk/core/transactions.md#instructions) у мережі. + +Усі облікові записи повинні підтримувати достатньо високий баланс лампортів +(відносно їх виділеного простору), щоб стати +[звільненими від оренди](#rent-exempt) і залишатися на блокчейні Solana. +Будь-яка транзакція, що намагається зменшити баланс облікового запису нижче його +відповідного мінімального балансу для звільнення від оренди, завершиться +невдачею (якщо тільки баланс не зменшується до нуля). + +Коли власник облікового запису більше не бажає зберігати ці дані в ончейні та +доступними в глобальному стані, він може закрити обліковий запис і повернути +орендний депозит. + +Це здійснюється шляхом виведення (переказу) усього балансу лампортів облікового +запису на інший обліковий запис (наприклад, ваш гаманець). Зменшивши баланс +облікового запису до рівно `0`, час виконання видалить обліковий запис і його +пов'язані дані з мережі в процесі _"[збирання сміття](#garbage-collection)"_. ### Ставка оренди -Ставка оренди Solana встановлюється на рівні всієї мережі, головним чином базуючись на часі виконання -"[лампорти _за_ байт _за_ рік](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/rent.rs#L27-L34)". Наразі ставка оренди є статичною величиною та зберігається в +Ставка оренди Solana встановлюється на рівні всієї мережі, головним чином +базуючись на часі виконання +"[лампорти _за_ байт _за_ рік](https://github.com/anza-xyz/agave/blob/b7bbe36918f23d98e2e73502e3c4cba78d395ba9/sdk/program/src/rent.rs#L27-L34)". +Наразі ставка оренди є статичною величиною та зберігається в [системній змінній Rent](https://docs.anza.xyz/runtime/sysvars#rent). -Ця ставка оренди використовується для розрахунку точної суми оренди, яка повинна бути утримана в обліковому записі для виділеного простору облікового запису (тобто кількість даних, які можуть бути збережені в обліковому записі). Чим більше простору виділяє обліковий запис, тим вищим буде утриманий орендний депозит. +Ця ставка оренди використовується для розрахунку точної суми оренди, яка повинна +бути утримана в обліковому записі для виділеного простору облікового запису +(тобто кількість даних, які можуть бути збережені в обліковому записі). Чим +більше простору виділяє обліковий запис, тим вищим буде утриманий орендний +депозит. ### Звільнення від оренди -Облікові записи повинні підтримувати баланс лампортів, що перевищує мінімум, необхідний для зберігання відповідних даних в ончейні. Це називається "_звільненням від оренди_", а цей баланс називається "_мінімальним балансом для звільнення від оренди_". - -> Нові облікові записи (та програми) на Solana **ЗОБОВ'ЯЗАНІ** бути ініціалізовані з достатньою кількістю лампортів, щоб стати _звільненими від оренди_. Так було не завжди. Раніше час виконання періодично та автоматично стягував плату з кожного облікового запису, що мав баланс нижче мінімуму для звільнення від оренди. Зрештою, такі облікові записи знижувалися до нульового балансу та видалялися з глобального стану (якщо їх не поповнювали вручну). - -У процесі створення нового облікового запису необхідно переконатися, що ви депонуєте достатньо лампортів, щоб перевищити цей мінімальний баланс. Все, що нижче цього мінімального порогу, призведе до невдачі транзакції. - -Кожного разу, коли баланс облікового запису зменшується, час виконання перевіряє, чи залишиться баланс цього облікового запису вище мінімального балансу для звільнення від оренди. Якщо тільки баланс не знижується до рівно `0` (закриття облікового запису), транзакції, які спричиняють падіння балансу облікового запису нижче порогу звільнення від оренди, завершаться невдачею. - -Специфічний мінімальний баланс для облікового запису, щоб стати звільненим від оренди, залежить від поточної [ставки оренди](#rent-rate) блокчейну та бажаного обсягу простору, який обліковий запис хоче виділити (розмір облікового запису). Тому рекомендується використовувати RPC-метод [`getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx) для розрахунку конкретного балансу для заданого розміру облікового запису. - -Суму необхідного орендного депозиту також можна оцінити за допомогою підкоманди CLI [`solana rent`](https://docs.anza.xyz/cli/usage#solana-rent). +Облікові записи повинні підтримувати баланс лампортів, що перевищує мінімум, +необхідний для зберігання відповідних даних в ончейні. Це називається +"_звільненням від оренди_", а цей баланс називається "_мінімальним балансом для +звільнення від оренди_". + +> Нові облікові записи (та програми) на Solana **ЗОБОВ'ЯЗАНІ** бути +> ініціалізовані з достатньою кількістю лампортів, щоб стати _звільненими від +> оренди_. Так було не завжди. Раніше час виконання періодично та автоматично +> стягував плату з кожного облікового запису, що мав баланс нижче мінімуму для +> звільнення від оренди. Зрештою, такі облікові записи знижувалися до нульового +> балансу та видалялися з глобального стану (якщо їх не поповнювали вручну). + +У процесі створення нового облікового запису необхідно переконатися, що ви +депонуєте достатньо лампортів, щоб перевищити цей мінімальний баланс. Все, що +нижче цього мінімального порогу, призведе до невдачі транзакції. + +Кожного разу, коли баланс облікового запису зменшується, час виконання +перевіряє, чи залишиться баланс цього облікового запису вище мінімального +балансу для звільнення від оренди. Якщо тільки баланс не знижується до рівно `0` +(закриття облікового запису), транзакції, які спричиняють падіння балансу +облікового запису нижче порогу звільнення від оренди, завершаться невдачею. + +Специфічний мінімальний баланс для облікового запису, щоб стати звільненим від +оренди, залежить від поточної [ставки оренди](#rent-rate) блокчейну та бажаного +обсягу простору, який обліковий запис хоче виділити (розмір облікового запису). +Тому рекомендується використовувати RPC-метод +[`getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx) +для розрахунку конкретного балансу для заданого розміру облікового запису. + +Суму необхідного орендного депозиту також можна оцінити за допомогою підкоманди +CLI [`solana rent`](https://docs.anza.xyz/cli/usage#solana-rent). ```shell solana rent 15000 @@ -269,16 +473,29 @@ Rent per byte-year: 0.00000348 SOL Rent per epoch: 0.000288276 SOL Rent-exempt minimum: 0.10529088 SOL ``` + ### Збирання сміття -Облікові записи, які не підтримують баланс лампортів більше нуля, видаляються з мережі в процесі, відомому як _збирання сміття_. Цей процес виконується, щоб зменшити загальну кількість збережених у мережі даних, які більше не використовуються або не підтримуються. +Облікові записи, які не підтримують баланс лампортів більше нуля, видаляються з +мережі в процесі, відомому як _збирання сміття_. Цей процес виконується, щоб +зменшити загальну кількість збережених у мережі даних, які більше не +використовуються або не підтримуються. -Після успішного зменшення балансу облікового запису до рівно `0` транзакцією, збирання сміття виконується автоматично часом виконання. Будь-яка транзакція, яка намагається зменшити баланс облікового запису нижче його мінімального балансу для звільнення від оренди (що не дорівнює нулю), завершиться невдачею. +Після успішного зменшення балансу облікового запису до рівно `0` транзакцією, +збирання сміття виконується автоматично часом виконання. Будь-яка транзакція, +яка намагається зменшити баланс облікового запису нижче його мінімального +балансу для звільнення від оренди (що не дорівнює нулю), завершиться невдачею. Важливо зазначити, що збирання сміття відбувається **після** завершення виконання транзакції. Якщо є інструкція "закрити" обліковий запис, зменшивши баланс облікового запису до нуля, обліковий запис може бути "повторно відкритий" у тій самій транзакції за допомогою наступної інструкції. Якщо стан облікового запису не було очищено в інструкції "закрити", наступна інструкція "повторного відкриття" матиме той самий стан облікового запису. Це є проблемою безпеки, тому важливо знати точний момент, коли збирання сміття набирає чинності. -Навіть після того, як обліковий запис було видалено з мережі (через збирання сміття), він все ще може мати транзакції, пов'язані з його адресою (або в історії, або в майбутньому). Незважаючи на те, що блокчейн-експлорер Solana може відображати повідомлення типу "обліковий запис не знайдено", ви все одно можете переглядати історію транзакцій, пов'язаних із цим обліковим записом. +Навіть після того, як обліковий запис було видалено з мережі (через збирання +сміття), він все ще може мати транзакції, пов'язані з його адресою (або в +історії, або в майбутньому). Незважаючи на те, що блокчейн-експлорер Solana може +відображати повідомлення типу "обліковий запис не знайдено", ви все одно можете +переглядати історію транзакцій, пов'язаних із цим обліковим записом. -Ви можете прочитати [запропоновану реалізацію](https://docs.anza.xyz/implemented-proposals/persistent-account-storage#garbage-collection) для збирання сміття, щоб дізнатися більше. \ No newline at end of file +Ви можете прочитати +[запропоновану реалізацію](https://docs.anza.xyz/implemented-proposals/persistent-account-storage#garbage-collection) +для збирання сміття, щоб дізнатися більше. diff --git a/docs/locales/uk/core/index.md b/docs/locales/uk/core/index.md index b084e320e..8743b8699 100644 --- a/docs/locales/uk/core/index.md +++ b/docs/locales/uk/core/index.md @@ -2,78 +2,116 @@ title: Основні концепції sidebarSortOrder: 2 description: - Дізнайтеся про основні концепції блокчейну Solana, включаючи облікові записи, транзакції, програми, адреси, отримані від програм, міжпрограмні виклики та як працюють токени на Solana. + Дізнайтеся про основні концепції блокчейну Solana, включаючи облікові записи, + транзакції, програми, адреси, отримані від програм, міжпрограмні виклики та як + працюють токени на Solana. --- -Розвивайте глибоке розуміння основних концепцій, які роблять Solana унікальним серед інших блокчейнів. Розуміння "моделі програмування Solana" через ці ключові концепції дуже важливе для максимального успіху як розробника блокчейну Solana. +Розвивайте глибоке розуміння основних концепцій, які роблять Solana унікальним +серед інших блокчейнів. Розуміння "моделі програмування Solana" через ці ключові +концепції дуже важливе для максимального успіху як розробника блокчейну Solana. ## Модель облікових записів Solana -У Solana всі дані зберігаються в тому, що називається "обліковими записами". Організація даних у блокчейні Solana нагадує [сховище ключів і значень](https://uk.wikipedia.org/wiki/Key%E2%80%93value_%D0%B1%D0%B0%D0%B7%D0%B0_%D0%B4%D0%B0%D0%BD%D0%B8%D1%85), де кожен запис у базі даних називається "обліковим записом". +У Solana всі дані зберігаються в тому, що називається "обліковими записами". +Організація даних у блокчейні Solana нагадує +[сховище ключів і значень](https://uk.wikipedia.org/wiki/Key%E2%80%93value_%D0%B1%D0%B0%D0%B7%D0%B0_%D0%B4%D0%B0%D0%BD%D0%B8%D1%85), +де кожен запис у базі даних називається "обліковим записом". Дізнайтеся більше про [Облікові записи](/docs/core/accounts.md) тут. ## Транзакції та інструкції -У Solana ми надсилаємо [транзакції](/docs/core/transactions#transaction), щоб взаємодіяти з мережею. Транзакції включають одну або більше [інструкцій](/docs/core/transactions#instruction), кожна з яких представляє конкретну операцію для обробки. Логіка виконання інструкцій зберігається в [програмах](/docs/core/programs), розгорнутих у мережі Solana, де кожна програма має свій власний набір інструкцій. +У Solana ми надсилаємо [транзакції](/docs/core/transactions#transaction), щоб +взаємодіяти з мережею. Транзакції включають одну або більше +[інструкцій](/docs/core/transactions#instruction), кожна з яких представляє +конкретну операцію для обробки. Логіка виконання інструкцій зберігається в +[програмах](/docs/core/programs), розгорнутих у мережі Solana, де кожна програма +має свій власний набір інструкцій. -Дізнайтеся більше про [Транзакції](/docs/core/transactions.md) та [Інструкції](/docs/core/transactions.md#instruction) тут. +Дізнайтеся більше про [Транзакції](/docs/core/transactions.md) та +[Інструкції](/docs/core/transactions.md#instruction) тут. ## Плата на Solana -Блокчейн Solana має кілька типів зборів та витрат, які виникають при використанні мережі без дозволу. Вони поділяються на кілька основних типів: +Блокчейн Solana має кілька типів зборів та витрат, які виникають при +використанні мережі без дозволу. Вони поділяються на кілька основних типів: -- [Транзакційні збори](/docs/core/fees.md#transaction-fees) — плата за обробку транзакцій/інструкцій валідаторами. -- [Пріоритизаційні збори](/docs/core/fees.md#prioritization-fees) — опціональна плата для підвищення порядку обробки транзакцій. -- [Оренда](/docs/core/fees.md#rent) — утримуваний баланс для збереження даних в ончейні. +- [Транзакційні збори](/docs/core/fees.md#transaction-fees) — плата за обробку + транзакцій/інструкцій валідаторами. +- [Пріоритизаційні збори](/docs/core/fees.md#prioritization-fees) — опціональна + плата для підвищення порядку обробки транзакцій. +- [Оренда](/docs/core/fees.md#rent) — утримуваний баланс для збереження даних в + ончейні. Дізнайтеся більше про [Плату на Solana](/docs/core/fees.md) тут. ## Програми на Solana -У екосистемі Solana "смарт-контракти" називаються програмами. Кожна програма є ончейн-обліковим записом, що зберігає виконувану логіку, організовану у функції, що називаються _інструкціями_, і викликаються через функції обробників інструкцій у відповідній розгорнутій програмі. +У екосистемі Solana "смарт-контракти" називаються програмами. Кожна програма є +ончейн-обліковим записом, що зберігає виконувану логіку, організовану у функції, +що називаються _інструкціями_, і викликаються через функції обробників +інструкцій у відповідній розгорнутій програмі. Дізнайтеся більше про [Програми на Solana](/docs/core/programs.md) тут. ## Адреси, отримані від програм -Адреси, отримані від програм (Program Derived Addresses, PDAs), надають розробникам Solana дві основні можливості: +Адреси, отримані від програм (Program Derived Addresses, PDAs), надають +розробникам Solana дві основні можливості: -- **Детерміновані адреси облікових записів**: PDAs забезпечують механізм детермінованого отримання адреси за допомогою комбінації опціональних "насіння" (заданих вхідних даних) і конкретного ідентифікатора програми. -- **Дозволити підписання програмою**: Час виконання Solana дозволяє програмам "підписувати" PDAs, які отримані від їх ідентифікатора програми. +- **Детерміновані адреси облікових записів**: PDAs забезпечують механізм + детермінованого отримання адреси за допомогою комбінації опціональних + "насіння" (заданих вхідних даних) і конкретного ідентифікатора програми. +- **Дозволити підписання програмою**: Час виконання Solana дозволяє програмам + "підписувати" PDAs, які отримані від їх ідентифікатора програми. -Можна уявити PDAs як спосіб створення ончейн-структур, схожих на хеш-таблиці, з набору заданих вхідних даних (наприклад, рядків, чисел та інших адрес облікових записів). +Можна уявити PDAs як спосіб створення ончейн-структур, схожих на хеш-таблиці, з +набору заданих вхідних даних (наприклад, рядків, чисел та інших адрес облікових +записів). Дізнайтеся більше про [Адреси, отримані від програм](/docs/core/pda.md) тут. ## Міжпрограмні виклики -Міжпрограмний виклик (Cross Program Invocation, CPI) означає, що одна програма викликає інструкції іншої програми. Цей механізм дозволяє програмам Solana бути композитивними. +Міжпрограмний виклик (Cross Program Invocation, CPI) означає, що одна програма +викликає інструкції іншої програми. Цей механізм дозволяє програмам Solana бути +композитивними. -Можна уявити інструкції як API-ендпоінти, які програма надає мережі, а CPI як один API, що викликає інший API внутрішньо. +Можна уявити інструкції як API-ендпоінти, які програма надає мережі, а CPI як +один API, що викликає інший API внутрішньо. Дізнайтеся більше про [Міжпрограмні виклики](/docs/core/cpi.md) тут. ## Токени на Solana -Токени — це цифрові активи, які представляють право власності на різні категорії активів. Токенізація дозволяє оцифровувати права власності, виступаючи фундаментальним компонентом для управління як взаємозамінними, так і невзаємозамінними активами. +Токени — це цифрові активи, які представляють право власності на різні категорії +активів. Токенізація дозволяє оцифровувати права власності, виступаючи +фундаментальним компонентом для управління як взаємозамінними, так і +невзаємозамінними активами. -- Взаємозамінні токени представляють взаємозамінні та подільні активи одного типу і вартості (наприклад, USDC). -- Невзаємозамінні токени (NFT) представляють право власності на неподільні активи (наприклад, твори мистецтва). +- Взаємозамінні токени представляють взаємозамінні та подільні активи одного + типу і вартості (наприклад, USDC). +- Невзаємозамінні токени (NFT) представляють право власності на неподільні + активи (наприклад, твори мистецтва). Дізнайтеся більше про [Токени на Solana](/docs/core/tokens.md) тут. ## Кластери та кінцеві точки -Блокчейн Solana має кілька різних груп валідаторів, відомих як [Кластери](/docs/core/clusters.md). Кожна з них виконує різні завдання в екосистемі та має спеціалізовані вузли API для виконання запитів [JSON-RPC](/docs/rpc/index.mdx) для свого кластеру. +Блокчейн Solana має кілька різних груп валідаторів, відомих як +[Кластери](/docs/core/clusters.md). Кожна з них виконує різні завдання в +екосистемі та має спеціалізовані вузли API для виконання запитів +[JSON-RPC](/docs/rpc/index.mdx) для свого кластеру. -Індивідуальні вузли в кластері належать і управляються третіми сторонами, причому для кожного з них доступна публічна кінцева точка. +Індивідуальні вузли в кластері належать і управляються третіми сторонами, +причому для кожного з них доступна публічна кінцева точка. -Є три основні кластери в мережі Solana, кожен з яких має свою публічну кінцеву точку: +Є три основні кластери в мережі Solana, кожен з яких має свою публічну кінцеву +точку: - Mainnet - `https://api.mainnet-beta.solana.com` - Devnet - `https://api.devnet.solana.com` - Testnet - `https://api.testnet.solana.com` Дізнайтеся більше про [Кластери та кінцеві точки](/docs/core/clusters.md) тут. - diff --git a/docs/locales/uk/core/pda.md b/docs/locales/uk/core/pda.md index 3221b2f8f..b3451e66e 100644 --- a/docs/locales/uk/core/pda.md +++ b/docs/locales/uk/core/pda.md @@ -3,16 +3,19 @@ title: Програмно Виведені Адреси (PDA) sidebarLabel: Програмно Виведені Адреси sidebarSortOrder: 5 description: - Дізнайтеся про Програмно Виведені Адреси (PDA) в Solana — детерміновані - адреси облікових записів, які забезпечують безпечне підписання програмами. - Розберіться у виведенні PDA, канонічних бампах і створенні облікових записів PDA. + Дізнайтеся про Програмно Виведені Адреси (PDA) в Solana — детерміновані адреси + облікових записів, які забезпечують безпечне підписання програмами. + Розберіться у виведенні PDA, канонічних бампах і створенні облікових записів + PDA. --- -Програмно Виведені Адреси (PDA) надають розробникам у Solana два основних варіанти використання: +Програмно Виведені Адреси (PDA) надають розробникам у Solana два основних +варіанти використання: - **Детерміновані адреси облікових записів**: PDA надають механізм для детермінованого виведення адреси за допомогою комбінації необов’язкових - "сідів" (заздалегідь визначених вхідних даних) та певного ідентифікатора програми. + "сідів" (заздалегідь визначених вхідних даних) та певного ідентифікатора + програми. - **Забезпечення підписання програмами**: Рантайм Solana дозволяє програмам "підписуватися" від імені PDA, які виведені з їхнього ідентифікатора програми. @@ -27,14 +30,14 @@ description: ![Програмно Виведена Адреса](/assets/docs/core/pda/pda.svg) Важливо розуміти, що просте виведення Програмно Виведеної Адреси (PDA) не -автоматично створює обліковий запис у блокчейні за цією адресою. Облікові -записи з PDA як адресою в блокчейні повинні бути явно створені через програму, -яка використовувалась для виведення адреси. Можна уявити виведення PDA як -пошук адреси на карті. Мати адресу — це ще не означає, що за цією адресою -щось побудовано. - -> У цьому розділі буде розглянуто деталі виведення PDA. Деталі того, як -> програми використовують PDA для підписання, будуть розглянуті в розділі +автоматично створює обліковий запис у блокчейні за цією адресою. Облікові записи +з PDA як адресою в блокчейні повинні бути явно створені через програму, яка +використовувалась для виведення адреси. Можна уявити виведення PDA як пошук +адреси на карті. Мати адресу — це ще не означає, що за цією адресою щось +побудовано. + +> У цьому розділі буде розглянуто деталі виведення PDA. Деталі того, як програми +> використовують PDA для підписання, будуть розглянуті в розділі > [Взаємодія між програмами (CPI)](/docs/uk/core/cpi.md), оскільки це потребує > контексту для обох концепцій. @@ -58,11 +61,12 @@ description: PDA — це адреси, які виводяться детерміновано та виглядають як стандартні публічні ключі, але не мають асоційованих приватних ключів. Це означає, що жоден -зовнішній користувач не може згенерувати дійсний підпис для цієї адреси. -Однак, рантайм Solana дозволяє програмам програмно "підписуватися" від імені -PDA без необхідності у приватному ключі. +зовнішній користувач не може згенерувати дійсний підпис для цієї адреси. Однак, +рантайм Solana дозволяє програмам програмно "підписуватися" від імені PDA без +необхідності у приватному ключі. -Для контексту, [Keypairs](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/signer/keypair.rs#L25) +Для контексту, +[Keypairs](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/signer/keypair.rs#L25) у Solana є точками на кривій Ed25519 (еліптична криптографія), які мають публічний ключ і відповідний приватний ключ. Ми часто використовуємо публічні ключі як унікальні ідентифікатори для нових облікових записів у блокчейні, а @@ -86,13 +90,13 @@ PDA може бути використана як адреса (унікальн Виведення PDA вимагає 3 вхідних даних. - **Необов’язкові сіди**: Заздалегідь визначені вхідні дані (наприклад, рядок, - число, інші адреси облікових записів), які використовуються для виведення - PDA. Ці вхідні дані конвертуються в буфер байтів. + число, інші адреси облікових записів), які використовуються для виведення PDA. + Ці вхідні дані конвертуються в буфер байтів. - **Бамп сід**: Додатковий вхідний параметр (зі значенням між 255-0), який використовується для забезпечення того, що згенерований PDA знаходиться поза кривою Ed25519. Цей бамп сід (починаючи з 255) додається до необов’язкових - сідів під час генерації PDA, щоб "виштовхнути" точку за межі кривої - Ed25519. Бамп сід іноді називають "нонсом". + сідів під час генерації PDA, щоб "виштовхнути" точку за межі кривої Ed25519. + Бамп сід іноді називають "нонсом". - **Ідентифікатор програми**: Адреса програми, з якої виведений PDA. Ця ж програма може "підписуватися" від імені PDA. @@ -130,14 +134,16 @@ const [PDA, bump] = PublicKey.findProgramAddressSync([], programId); console.log(`PDA: ${PDA}`); console.log(`Bump: ${bump}`); ``` + Ви можете запустити цей приклад на -[Solana Playground](https://beta.solpg.io/66031e5acffcf4b13384cfef). Виведення PDA та -бамп сіда завжди буде однаковим: +[Solana Playground](https://beta.solpg.io/66031e5acffcf4b13384cfef). Виведення +PDA та бамп сіда завжди буде однаковим: ``` PDA: Cu7NwqCXSmsR5vgGA3Vw9uYVViPi3kQvkbKByVQ8nPY9 Bump: 255 ``` + У наступному прикладі додається необов’язковий сід "helloWorld". ```ts /string/ @@ -154,9 +160,10 @@ const [PDA, bump] = PublicKey.findProgramAddressSync( console.log(`PDA: ${PDA}`); console.log(`Bump: ${bump}`); ``` + Ви також можете запустити цей приклад на -[Solana Playground](https://beta.solpg.io/66031ee5cffcf4b13384cff0). Виведення PDA та -бамп сіда завжди буде однаковим: +[Solana Playground](https://beta.solpg.io/66031ee5cffcf4b13384cff0). Виведення +PDA та бамп сіда завжди буде однаковим: ``` PDA: 46GZzzetjCURsdFPb7rcnspbEMnCBXe9kpjrsZAkKb6X @@ -182,8 +189,8 @@ Bump: 254 Значення бамп сіда починається з 255 і зменшується на 1, доки не буде знайдено дійсний PDA (поза кривою). -Ви можете відтворити попередній приклад, використовуючи `createProgramAddressSync` -та явно передавши бамп сід зі значенням 254. +Ви можете відтворити попередній приклад, використовуючи +`createProgramAddressSync` та явно передавши бамп сід зі значенням 254. ```ts /bump/ import { PublicKey } from "@solana/web3.js"; @@ -199,6 +206,7 @@ const PDA = PublicKey.createProgramAddressSync( console.log(`PDA: ${PDA}`); ``` + Запустіть цей приклад вище на [Solana Playground](https://beta.solpg.io/66031f8ecffcf4b13384cff1). За однакових сідів та ідентифікатора програми, виведення PDA буде відповідати @@ -211,11 +219,11 @@ PDA: 46GZzzetjCURsdFPb7rcnspbEMnCBXe9kpjrsZAkKb6X ### Канонічний бамп "Канонічний бамп" відноситься до першого значення бамп сіда (починаючи з 255 і -зменшуючи на 1), яке виводить дійсний PDA. З метою безпеки програм -рекомендовано використовувати лише PDA, виведені з канонічного бампа. +зменшуючи на 1), яке виводить дійсний PDA. З метою безпеки програм рекомендовано +використовувати лише PDA, виведені з канонічного бампа. -Використовуючи попередній приклад як орієнтир, приклад нижче намагається -вивести PDA, використовуючи всі значення бамп сіда від 255 до 0. +Використовуючи попередній приклад як орієнтир, приклад нижче намагається вивести +PDA, використовуючи всі значення бамп сіда від 255 до 0. ```ts import { PublicKey } from "@solana/web3.js"; @@ -236,7 +244,8 @@ for (let bump = 255; bump >= 0; bump--) { } } ``` -Запустіть приклад на + +Запустіть приклад на [Solana Playground](https://beta.solpg.io/66032009cffcf4b13384cff2), і ви повинні побачити наступний результат: @@ -250,12 +259,13 @@ bump 250: Error: Invalid seeds, address must fall off the curve ... // remaining bump outputs ``` -Як і очікувалось, бамп сід 255 викликає помилку, а перший бамп сід, який виводить -дійсний PDA, дорівнює 254. + +Як і очікувалось, бамп сід 255 викликає помилку, а перший бамп сід, який +виводить дійсний PDA, дорівнює 254. Однак зверніть увагу, що бамп сіди 253-251 також виводять дійсні PDA з різними -адресами. Це означає, що для заданих необов’язкових сідів та `programId` бамп сід -з іншим значенням все ще може вивести дійсний PDA. +адресами. Це означає, що для заданих необов’язкових сідів та `programId` бамп +сід з іншим значенням все ще може вивести дійсний PDA. При створенні програм на Solana рекомендовано додавати перевірки безпеки, @@ -271,10 +281,10 @@ bump 250: Error: Invalid seeds, address must fall off the curve показує, як створити обліковий запис, використовуючи PDA як адресу нового облікового запису. Програма написана з використанням фреймворку Anchor. -У файлі `lib.rs` ви знайдете наступну програму, яка включає єдину інструкцію -для створення нового облікового запису з використанням PDA як адреси -облікового запису. Новий обліковий запис зберігає адресу `user` та `bump` сід, -який використовувався для виведення PDA. +У файлі `lib.rs` ви знайдете наступну програму, яка включає єдину інструкцію для +створення нового облікового запису з використанням PDA як адреси облікового +запису. Новий обліковий запис зберігає адресу `user` та `bump` сід, який +використовувався для виведення PDA. ```rust filename="lib.rs" {11-14,26-29} use anchor_lang::prelude::*; @@ -321,9 +331,10 @@ pub struct DataAccount { pub bump: u8, } ``` -Сіди, які використовуються для виведення PDA, включають зафіксований рядок `data` -та адресу облікового запису `user`, передану в інструкції. Фреймворк Anchor -автоматично виводить канонічний `bump` сід. + +Сіди, які використовуються для виведення PDA, включають зафіксований рядок +`data` та адресу облікового запису `user`, передану в інструкції. Фреймворк +Anchor автоматично виводить канонічний `bump` сід. ```rust /data/ /user.key()/ /bump/ #[account( @@ -335,8 +346,9 @@ pub struct DataAccount { )] pub pda_account: Account<'info, DataAccount>, ``` -Обмеження `init` вказує Anchor викликати Системну Програму для створення нового -облікового запису з використанням PDA як адреси. Це виконується за допомогою + +Обмеження `init` вказує Anchor викликати Системну Програму для створення нового +облікового запису з використанням PDA як адреси. Це виконується за допомогою [Взаємодії між програмами (CPI)](/docs/uk/core/cpi.md). ```rust /init/ @@ -349,10 +361,10 @@ pub pda_account: Account<'info, DataAccount>, )] pub pda_account: Account<'info, DataAccount>, ``` -У тестовому файлі (`pda-account.test.ts`), розташованому за посиланням на -Solana Playground, наданим вище, ви знайдете еквівалентний код на Javascript -для виведення PDA. +У тестовому файлі (`pda-account.test.ts`), розташованому за посиланням на Solana +Playground, наданим вище, ви знайдете еквівалентний код на Javascript для +виведення PDA. ```ts /data/ /user.publicKey/ const [PDA] = PublicKey.findProgramAddressSync( @@ -360,10 +372,11 @@ const [PDA] = PublicKey.findProgramAddressSync( program.programId, ); ``` -Далі надсилається транзакція для виклику інструкції `initialize`, щоб створити -новий обліковий запис у блокчейні з використанням PDA як адреси. Після надсилання -транзакції PDA використовується для отримання облікового запису в блокчейні, -який був створений за цією адресою. + +Далі надсилається транзакція для виклику інструкції `initialize`, щоб створити +новий обліковий запис у блокчейні з використанням PDA як адреси. Після +надсилання транзакції PDA використовується для отримання облікового запису в +блокчейні, який був створений за цією адресою. ```ts /initialize()/ /PDA/ {14} it("Is initialized!", async () => { @@ -383,6 +396,8 @@ it("Fetch Account", async () => { console.log(JSON.stringify(pdaAccount, null, 2)); }); ``` -Зверніть увагу, що якщо ви викликаєте інструкцію `initialize` більше одного разу, -використовуючи ту саму адресу `user` як сід, транзакція завершиться помилкою. -Це відбувається тому, що обліковий запис вже існує за виведеною адресою. + +Зверніть увагу, що якщо ви викликаєте інструкцію `initialize` більше одного +разу, використовуючи ту саму адресу `user` як сід, транзакція завершиться +помилкою. Це відбувається тому, що обліковий запис вже існує за виведеною +адресою. diff --git a/docs/locales/uk/core/programs.md b/docs/locales/uk/core/programs.md index fc4d35564..0c796f12f 100644 --- a/docs/locales/uk/core/programs.md +++ b/docs/locales/uk/core/programs.md @@ -8,85 +8,89 @@ description: та перевірки програм у мережі Solana. --- -У екосистемі Solana "смарт-контракти" називаються програмами. Кожна -[програма](/docs/uk/core/accounts.md#program-account) є обліковим записом у блокчейні, -який зберігає виконувану логіку, організовану у вигляді конкретних функцій, які -називаються [інструкціями](/docs/uk/core/transactions.md#instruction). +У екосистемі Solana "смарт-контракти" називаються програмами. Кожна +[програма](/docs/uk/core/accounts.md#program-account) є обліковим записом у +блокчейні, який зберігає виконувану логіку, організовану у вигляді конкретних +функцій, які називаються +[інструкціями](/docs/uk/core/transactions.md#instruction). ## Основні моменти -- Програми — це облікові записи у блокчейні, які містять виконуваний код. Цей код - організований у вигляді окремих функцій, відомих як інструкції. +- Програми — це облікові записи у блокчейні, які містять виконуваний код. Цей + код організований у вигляді окремих функцій, відомих як інструкції. -- Програми не зберігають стану, але можуть включати інструкції для створення нових - облікових записів, які використовуються для зберігання та управління станом програми. +- Програми не зберігають стану, але можуть включати інструкції для створення + нових облікових записів, які використовуються для зберігання та управління + станом програми. -- Програми можуть оновлюватися за допомогою "авторитету оновлення". Програма стає - незмінною, коли авторитет оновлення встановлюється у значення null. +- Програми можуть оновлюватися за допомогою "авторитету оновлення". Програма + стає незмінною, коли авторитет оновлення встановлюється у значення null. -- Перевірювані збірки дозволяють користувачам переконатися, що програми у блокчейні - відповідають доступному публічно вихідному коду. +- Перевірювані збірки дозволяють користувачам переконатися, що програми у + блокчейні відповідають доступному публічно вихідному коду. ## Написання програм Solana -Програми Solana зазвичай пишуться мовою програмування +Програми Solana зазвичай пишуться мовою програмування [Rust](https://doc.rust-lang.org/book/) з використанням двох підходів: -- [Anchor](/docs/uk/programs/anchor): Фреймворк, створений для розробки програм Solana. - Він забезпечує швидший і простіший спосіб написання програм, використовуючи макроси - Rust для значного зменшення обсягу шаблонного коду. Для початківців рекомендується - починати з фреймворку Anchor. +- [Anchor](/docs/uk/programs/anchor): Фреймворк, створений для розробки програм + Solana. Він забезпечує швидший і простіший спосіб написання програм, + використовуючи макроси Rust для значного зменшення обсягу шаблонного коду. Для + початківців рекомендується починати з фреймворку Anchor. -- [Нативний Rust](/content/guides/getstarted/intro-to-native-rust.md): Цей підхід - передбачає написання програм Solana на Rust без використання фреймворків. Він - надає більше гнучкості, але супроводжується підвищеною складністю. +- [Нативний Rust](/content/guides/getstarted/intro-to-native-rust.md): Цей + підхід передбачає написання програм Solana на Rust без використання + фреймворків. Він надає більше гнучкості, але супроводжується підвищеною + складністю. ## Оновлення програм Solana -Програми у блокчейні можуть бути -[безпосередньо змінені](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L675) -обліковим записом, призначеним як "авторитет оновлення", зазвичай це обліковий +Програми у блокчейні можуть бути +[безпосередньо змінені](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L675) +обліковим записом, призначеним як "авторитет оновлення", зазвичай це обліковий запис, який початково розгорнув програму. -Якщо -[авторитет оновлення](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L865) -скасований і встановлений у `None`, програма стає незмінною і більше не може бути оновлена. +Якщо +[авторитет оновлення](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/programs/bpf_loader/src/lib.rs#L865) +скасований і встановлений у `None`, програма стає незмінною і більше не може +бути оновлена. ## Перевірювані програми -Забезпечення цілісності та перевірюваності коду у блокчейні є важливим. -Перевірювана збірка гарантує, що виконуваний код, розгорнутий у блокчейні, може -бути незалежно перевірений на відповідність його публічному вихідному коду -будь-якою третьою стороною. Цей процес підвищує прозорість і довіру, дозволяючи +Забезпечення цілісності та перевірюваності коду у блокчейні є важливим. +Перевірювана збірка гарантує, що виконуваний код, розгорнутий у блокчейні, може +бути незалежно перевірений на відповідність його публічному вихідному коду +будь-якою третьою стороною. Цей процес підвищує прозорість і довіру, дозволяючи виявляти розбіжності між вихідним кодом і розгорнутою програмою. -Спільнота розробників Solana створила інструменти для підтримки перевірюваних -збірок, які дозволяють як розробникам, так і користувачам переконатися, що +Спільнота розробників Solana створила інструменти для підтримки перевірюваних +збірок, які дозволяють як розробникам, так і користувачам переконатися, що програми у блокчейні точно відображають їхній публічний вихідний код. -- **Пошук перевірених програм**: Для швидкої перевірки програм користувачі можуть - знайти адресу програми у [SolanaFM](https://solana.fm/) Explorer і перейти на - вкладку "Verification". Приклад перевіреної програми можна побачити +- **Пошук перевірених програм**: Для швидкої перевірки програм користувачі + можуть знайти адресу програми у [SolanaFM](https://solana.fm/) Explorer і + перейти на вкладку "Verification". Приклад перевіреної програми можна побачити [тут](https://solana.fm/address/PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY). -- **Інструменти перевірки**: CLI - [Solana Verifiable Build](https://github.com/Ellipsis-Labs/solana-verifiable-build) - від Ellipsis Labs дозволяє незалежно перевірити програми у блокчейні на відповідність - опублікованому вихідному коду. +- **Інструменти перевірки**: CLI + [Solana Verifiable Build](https://github.com/Ellipsis-Labs/solana-verifiable-build) + від Ellipsis Labs дозволяє незалежно перевірити програми у блокчейні на + відповідність опублікованому вихідному коду. -- **Підтримка перевірюваних збірок в Anchor**: Anchor має вбудовану підтримку - перевірюваних збірок. Деталі можна знайти у +- **Підтримка перевірюваних збірок в Anchor**: Anchor має вбудовану підтримку + перевірюваних збірок. Деталі можна знайти у [документації Anchor](https://www.anchor-lang.com/docs/verifiable-builds). ## Berkeley Packet Filter (BPF) -Solana використовує [інфраструктуру компілятора LLVM](https://llvm.org/) для -компіляції програм у файли формату -[Executable and Linkable Format (ELF)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format). -Ці файли включають модифіковану версію байт-коду -[Berkeley Packet Filter (eBPF)](https://en.wikipedia.org/wiki/EBPF) для програм Solana, -відомого як "Solana Bytecode Format" (sBPF). +Solana використовує [інфраструктуру компілятора LLVM](https://llvm.org/) для +компіляції програм у файли формату +[Executable and Linkable Format (ELF)](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format). +Ці файли включають модифіковану версію байт-коду +[Berkeley Packet Filter (eBPF)](https://en.wikipedia.org/wiki/EBPF) для програм +Solana, відомого як "Solana Bytecode Format" (sBPF). -Використання LLVM дозволяє Solana підтримувати будь-яку мову програмування, яка -може компілюватися у BPF-бекенд LLVM. Це значно підвищує гнучкість Solana як платформи -для розробки. +Використання LLVM дозволяє Solana підтримувати будь-яку мову програмування, яка +може компілюватися у BPF-бекенд LLVM. Це значно підвищує гнучкість Solana як +платформи для розробки. diff --git a/docs/locales/uk/core/tokens.md b/docs/locales/uk/core/tokens.md index 62700b186..c9cd3812a 100644 --- a/docs/locales/uk/core/tokens.md +++ b/docs/locales/uk/core/tokens.md @@ -3,9 +3,9 @@ title: "Токени на Solana" sidebarSortOrder: 7 description: Дізнайтеся про токени Solana (SPL Tokens), включаючи взаємозамінні та - невзаємозамінні токени, Програму Токенів, Програму Розширень Токенів, - облікові записи випуску токенів, токен-облікові записи, а також практичні - приклади створення і управління токенами на Solana. + невзаємозамінні токени, Програму Токенів, Програму Розширень Токенів, облікові + записи випуску токенів, токен-облікові записи, а також практичні приклади + створення і управління токенами на Solana. --- Токени — це цифрові активи, які представляють право власності на різні категорії @@ -19,11 +19,11 @@ description: активи (наприклад, витвори мистецтва). У цьому розділі буде розглянуто основи представлення токенів у Solana. Ці токени -називаються SPL +називаються SPL ([Solana Program Library](https://github.com/solana-labs/solana-program-library)). -- [Програма Токенів](#token-program) містить всю логіку інструкцій для - взаємодії з токенами в мережі (як взаємозамінними, так і невзаємозамінними). +- [Програма Токенів](#token-program) містить всю логіку інструкцій для взаємодії + з токенами в мережі (як взаємозамінними, так і невзаємозамінними). - [Обліковий запис випуску токенів](#mint-account) представляє певний тип токена і зберігає глобальні метадані, такі як загальна кількість токенів і авторитет @@ -32,10 +32,10 @@ description: - [Токен-обліковий запис](#token-account) відстежує індивідуальну власність на певну кількість токенів конкретного типу (облікового запису випуску токенів). -> Наразі існує дві версії Програми Токенів: оригінальна +> Наразі існує дві версії Програми Токенів: оригінальна > [Програма Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) -> і -> [Програма Розширень Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program-2022) +> і +> [Програма Розширень Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program-2022) > (Token2022). Програма Розширень Токенів працює так само, як і оригінальна > Програма Токенів, але з додатковими функціями і покращеннями. Для створення > нових токенів рекомендовано використовувати Програму Розширень Токенів. @@ -57,16 +57,18 @@ description: облікового запису випуску токенів. - Асоційований Токен-обліковий запис — це токен-обліковий запис, створений із - адреси, отриманої із адреси власника та адреси облікового запису випуску токенів. + адреси, отриманої із адреси власника та адреси облікового запису випуску + токенів. ## Програма Токенів -[Програма Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) +[Програма Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program) містить всю логіку інструкцій для взаємодії з токенами в мережі (як -взаємозамінними, так і невзаємозамінними). Усі токени на Solana фактично є -[даними облікових записів](/docs/uk/core/accounts.md#data-account), якими володіє Програма Токенів. +взаємозамінними, так і невзаємозамінними). Усі токени на Solana фактично є +[даними облікових записів](/docs/uk/core/accounts.md#data-account), якими +володіє Програма Токенів. -Повний список інструкцій Програми Токенів можна знайти +Повний список інструкцій Програми Токенів можна знайти [тут](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/instruction.rs). ![Програма Токенів](/assets/docs/core/tokens/token-program.svg) @@ -74,33 +76,37 @@ description: Кілька найчастіше використовуваних інструкцій включають: - [`InitializeMint`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L29): - Створення нового облікового запису випуску токенів для представлення нового типу токена. + Створення нового облікового запису випуску токенів для представлення нового + типу токена. - [`InitializeAccount`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L84): - Створення нового токен-облікового запису для зберігання одиниць певного типу токенів (випуску). + Створення нового токен-облікового запису для зберігання одиниць певного типу + токенів (випуску). - [`MintTo`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L522): - Створення нових одиниць певного типу токенів і додавання їх до токен-облікового запису. - Це збільшує кількість токенів і може виконуватися лише авторитетом випуску - облікового запису випуску токенів. + Створення нових одиниць певного типу токенів і додавання їх до + токен-облікового запису. Це збільшує кількість токенів і може виконуватися + лише авторитетом випуску облікового запису випуску токенів. - [`Transfer`](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/processor.rs#L228): - Передача одиниць певного типу токенів із одного токен-облікового запису в інший. + Передача одиниць певного типу токенів із одного токен-облікового запису в + інший. ### Обліковий запис випуску токенів -Токени на Solana унікально ідентифікуються за адресою -[Облікового запису випуску токенів](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32), -яким володіє Програма Токенів. Цей обліковий запис фактично є глобальним лічильником -для певного токена і зберігає дані, такі як: +Токени на Solana унікально ідентифікуються за адресою +[Облікового запису випуску токенів](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32), +яким володіє Програма Токенів. Цей обліковий запис фактично є глобальним +лічильником для певного токена і зберігає дані, такі як: - Загальна кількість: Загальна кількість токенів. - Десяткові знаки: Точність токена у десяткових знаках. - Авторитет випуску: Обліковий запис, уповноважений створювати нові одиниці токенів, таким чином збільшуючи кількість. -- Авторитет замороження: Обліковий запис, уповноважений заморожувати токени, - щоб їх не можна було передати із "токен-облікових записів". +- Авторитет замороження: Обліковий запис, уповноважений заморожувати токени, щоб + їх не можна було передати із "токен-облікових записів". ![Обліковий запис випуску токенів](/assets/docs/core/tokens/mint-account.svg) -Повна інформація, яка зберігається в кожному обліковому записі випуску токенів, включає: +Повна інформація, яка зберігається в кожному обліковому записі випуску токенів, +включає: ```rust pub struct Mint { @@ -119,21 +125,26 @@ pub struct Mint { pub freeze_authority: COption, } ``` -Для довідки, ось посилання на Solana Explorer для + +Для довідки, ось посилання на Solana Explorer для [Облікового запису випуску USDC](https://explorer.solana.com/address/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v). ### Токен-обліковий запис -Для відстеження індивідуальної власності на кожну одиницю певного токена має бути -створений інший тип облікового запису даних, яким володіє Програма Токенів. Цей -обліковий запис називається +Для відстеження індивідуальної власності на кожну одиницю певного токена має +бути створений інший тип облікового запису даних, яким володіє Програма Токенів. +Цей обліковий запис називається [Токен-обліковий запис](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L89-L110). -Найчастіше згадувані дані, які зберігаються в Токен-обліковому записі, включають: +Найчастіше згадувані дані, які зберігаються в Токен-обліковому записі, +включають: -- **Випуск (Mint)**: Тип токена, одиниці якого зберігаються в Токен-обліковому записі. -- **Власник (Owner)**: Обліковий запис, уповноважений передавати токени з Токен-облікового запису. -- **Кількість (Amount)**: Кількість одиниць токена, які наразі зберігаються в Токен-обліковому записі. +- **Випуск (Mint)**: Тип токена, одиниці якого зберігаються в Токен-обліковому + записі. +- **Власник (Owner)**: Обліковий запис, уповноважений передавати токени з + Токен-облікового запису. +- **Кількість (Amount)**: Кількість одиниць токена, які наразі зберігаються в + Токен-обліковому записі. ![Токен-обліковий запис](/assets/docs/core/tokens/token-account.svg) @@ -163,19 +174,21 @@ pub struct Account { pub close_authority: COption, } ``` -Щоб гаманець міг володіти одиницями певного токена, потрібно створити токен-обліковий -запис для конкретного типу токена (випуску), який призначає гаманець власником -цього токен-облікового запису. Гаманець може створювати кілька токен-облікових -записів для одного і того ж типу токена, але кожен токен-обліковий запис може -належати лише одному гаманцю і зберігати одиниці лише одного типу токена. + +Щоб гаманець міг володіти одиницями певного токена, потрібно створити +токен-обліковий запис для конкретного типу токена (випуску), який призначає +гаманець власником цього токен-облікового запису. Гаманець може створювати +кілька токен-облікових записів для одного і того ж типу токена, але кожен +токен-обліковий запис може належати лише одному гаманцю і зберігати одиниці лише +одного типу токена. ![Взаємозв'язок облікових записів](/assets/docs/core/tokens/token-account-relationship.svg) -> Зверніть увагу, що дані кожного Токен-облікового запису містять поле `owner`, яке -> використовується для визначення того, хто має авторитет над цим Токен-обліковим записом. -> Це окремо від власника програми, зазначеного у -> [AccountInfo](/docs/uk/core/accounts.md#accountinfo), яким є Програма Токенів для всіх -> Токен-облікових записів. +> Зверніть увагу, що дані кожного Токен-облікового запису містять поле `owner`, +> яке використовується для визначення того, хто має авторитет над цим +> Токен-обліковим записом. Це окремо від власника програми, зазначеного у +> [AccountInfo](/docs/uk/core/accounts.md#accountinfo), яким є Програма Токенів +> для всіх Токен-облікових записів. ### Асоційований токен-обліковий запис @@ -195,11 +208,13 @@ pub struct Account { Це вводить ключове поняття в розробці Solana: [Програмно Виведена Адреса (PDA)](/docs/uk/core/pda.md). Концептуально PDA надає детермінований спосіб генерації адреси з використанням заздалегідь визначених -вхідних даних. Це дозволяє нам легко знайти адресу облікового запису в майбутньому. +вхідних даних. Це дозволяє нам легко знайти адресу облікового запису в +майбутньому. -Ось [приклад на Solana Playground](https://beta.solpg.io/656a2dd0fb53fa325bfd0c41), +Ось +[приклад на Solana Playground](https://beta.solpg.io/656a2dd0fb53fa325bfd0c41), який виводить адресу і власника Асоційованого токен-облікового запису USDC. Він -завжди генерує +завжди генерує [одну й ту саму адресу](https://explorer.solana.com/address/4kokFKCFMxpCpG41yLYkLEqXW8g1WPfCt2NC9KGivY6N) для одного і того ж випуску і власника. @@ -211,9 +226,10 @@ const associatedTokenAccountAddress = getAssociatedTokenAddressSync( OWNER_ADDRESS, ); ``` -Зокрема, адреса для Асоційованого токен-облікового запису виводиться за допомогою -наступних вхідних даних. Ось -[приклад на Solana Playground](https://beta.solpg.io/656a31d0fb53fa325bfd0c42), + +Зокрема, адреса для Асоційованого токен-облікового запису виводиться за +допомогою наступних вхідних даних. Ось +[приклад на Solana Playground](https://beta.solpg.io/656a31d0fb53fa325bfd0c42), який генерує ту саму адресу, що й у попередньому прикладі. ```ts @@ -228,25 +244,26 @@ const [PDA, bump] = PublicKey.findProgramAddressSync( ASSOCIATED_TOKEN_PROGRAM_ID, ); ``` + Щоб два гаманці могли зберігати одиниці одного і того ж типу токена, кожен -гаманець потребує свого токен-облікового запису для конкретного облікового запису -випуску токенів. Зображення нижче демонструє, як виглядає ця структура взаємозв'язку облікових записів. +гаманець потребує свого токен-облікового запису для конкретного облікового +запису випуску токенів. Зображення нижче демонструє, як виглядає ця структура +взаємозв'язку облікових записів. ![Розширений взаємозв'язок облікових записів](/assets/docs/core/tokens/token-account-relationship-ata.svg) ## Приклади роботи з токенами -CLI [`spl-token`](https://docs.anza.xyz/cli) можна використовувати для експериментів -з SPL токенами. У прикладах нижче ми використовуватимемо -[Solana Playground](https://beta.solpg.io/) для виконання CLI-команд прямо в +CLI [`spl-token`](https://docs.anza.xyz/cli) можна використовувати для +експериментів з SPL токенами. У прикладах нижче ми використовуватимемо +[Solana Playground](https://beta.solpg.io/) для виконання CLI-команд прямо в браузері без необхідності встановлення CLI локально. -Створення токенів і облікових записів вимагає SOL для депозитів за оренду -облікових записів та оплати транзакційних комісій. Якщо ви вперше використовуєте -Solana Playground, створіть гаманець у Playground і виконайте команду -`solana airdrop` у терміналі Playground. Ви також можете отримати SOL для -devnet, використовуючи публічний -[веб-фасет](https://faucet.solana.com/). +Створення токенів і облікових записів вимагає SOL для депозитів за оренду +облікових записів та оплати транзакційних комісій. Якщо ви вперше використовуєте +Solana Playground, створіть гаманець у Playground і виконайте команду +`solana airdrop` у терміналі Playground. Ви також можете отримати SOL для +devnet, використовуючи публічний [веб-фасет](https://faucet.solana.com/). ```sh solana airdrop 2 @@ -257,28 +274,29 @@ Run `spl-token --help` for a full description of available commands. ```sh spl-token --help ``` -Крім того, ви можете встановити CLI `spl-token` локально, використовуючи наступну -команду. Для цього спочатку потрібно + +Крім того, ви можете встановити CLI `spl-token` локально, використовуючи +наступну команду. Для цього спочатку потрібно [встановити Rust](https://rustup.rs/). > У наступних розділах адреси облікових записів, які відображаються під час -> виконання CLI-команд, можуть відрізнятися від прикладів, наведених нижче. Будь ласка, -> використовуйте адреси, які відображаються у вашому терміналі Playground, під час -> виконання команд. Наприклад, адреса, отримана в результаті виконання `create-token`, -> є обліковим записом випуску токенів, де ваш гаманець Playground призначений -> авторитетом випуску. +> виконання CLI-команд, можуть відрізнятися від прикладів, наведених нижче. Будь +> ласка, використовуйте адреси, які відображаються у вашому терміналі +> Playground, під час виконання команд. Наприклад, адреса, отримана в результаті +> виконання `create-token`, є обліковим записом випуску токенів, де ваш гаманець +> Playground призначений авторитетом випуску. ### Створення нового токена -Щоб створити новий токен -([обліковий запис випуску токенів](#mint-account)), виконайте наступну команду -в терміналі Solana Playground. +Щоб створити новий токен ([обліковий запис випуску токенів](#mint-account)), +виконайте наступну команду в терміналі Solana Playground. ```sh spl-token create-token ``` -Ви повинні побачити результат, подібний до наведеного нижче. Ви можете переглянути -деталі як токена, так і транзакції у + +Ви повинні побачити результат, подібний до наведеного нижче. Ви можете +переглянути деталі як токена, так і транзакції у [Solana Explorer](https://explorer.solana.com/?cluster=devnet), використовуючи `Address` (адресу) та `Signature` (підпис). @@ -293,19 +311,22 @@ Decimals: 9 Signature: 44fvKfT1ezBUwdzrCys3fvCdFxbLMnNvBstds76QZyE6cXag5NupBprSXwxPTzzjrC3cA6nvUZaLFTvmcKyzxrm1 ``` + Нові токени спочатку мають нульовий запас. Ви можете перевірити поточний запас токена, використовуючи наступну команду: ```sh spl-token supply ``` + Запуск команди `supply` для новоствореного токена поверне значення `0`: ```sh /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ spl-token supply 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg ``` + У своїй основі створення нового облікового запису випуску токенів (Mint Account) -вимагає надсилання транзакції з двома інструкціями. Ось приклад на Javascript у +вимагає надсилання транзакції з двома інструкціями. Ось приклад на Javascript у [Solana Playground](https://beta.solpg.io/660ce32ecffcf4b13384d00f). 1. Виклик Системної Програми для створення нового облікового запису з достатнім @@ -317,28 +338,30 @@ spl-token supply 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg ### Створення Токен-облікового запису -Щоб зберігати одиниці певного токена, вам потрібно спочатку створити +Щоб зберігати одиниці певного токена, вам потрібно спочатку створити [токен-обліковий запис](#token-account). Для створення нового токен-облікового запису скористайтеся наступною командою: ```sh spl-token create-account [OPTIONS] ``` + Наприклад, виконання наступної команди в терміналі Solana Playground: -```sh /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ +````sh /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ spl-token create-account 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg ```: Виведе наступний результат -- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9`це адреса токен-облікового запису, створеного для зберігання одиниць токена, +- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9`це адреса токен-облікового запису, створеного для зберігання одиниць токена, вказаного в команді `create-account`. ```shell filename="Terminal Output" /AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9/ Creating account AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9 Signature: 2BtrynuCLX9CNofFiaw6Yzbx6hit66pup9Sk7aFjwU2NEbFz7NCHD9w9sWhrCfEd73XveAGK1DxFpJoQZPXU9tS1 -``` -За замовчуванням команда `create-account` створює +```` + +За замовчуванням команда `create-account` створює [асоційований токен-обліковий запис](#associated-token-account) з адресою вашого гаманця як власника токен-облікового запису. @@ -348,33 +371,37 @@ Signature: 2BtrynuCLX9CNofFiaw6Yzbx6hit66pup9Sk7aFjwU2NEbFz7NCHD9w9sWhrCfEd73Xve ```sh spl-token create-account --owner ``` -Наприклад, виконання наступної команди: + +Наприклад, виконання наступної команди: + ```sh /2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR/ spl-token create-account --owner 2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg ``` Виведе наступний результат: -- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` — це адреса токен-облікового запису, - створеного для зберігання одиниць токена, вказаного в команді `create-account` - (`99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg`), і який належить адресі, - вказаній після прапора `--owner` - (`2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR`). Це корисно, коли вам потрібно - створити токен-обліковий запис для іншого користувача. +- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` — це адреса токен-облікового + запису, створеного для зберігання одиниць токена, вказаного в команді + `create-account` (`99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg`), і який + належить адресі, вказаній після прапора `--owner` + (`2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR`). Це корисно, коли вам + потрібно створити токен-обліковий запис для іншого користувача. ```shell filename="Terminal Output" /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ Creating account Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt Signature: 44vqKdfzspT592REDPY4goaRJH3uJ3Ce13G4BCuUHg35dVUbHuGTHvqn4ZjYF9BGe9QrjMfe9GmuLkQhSZCBQuEt ``` + За лаштунками створення Асоційованого токен-облікового запису потребує однієї інструкції, яка викликає [Програму Асоційованих Токенів](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src). -Ось приклад на Javascript у +Ось приклад на Javascript у [Solana Playground](https://beta.solpg.io/660ce868cffcf4b13384d011). -Програма Асоційованих Токенів використовує -[Перехресні Виклики Програм (CPI)](/docs/uk/core/cpi.md) для виконання наступного: +Програма Асоційованих Токенів використовує +[Перехресні Виклики Програм (CPI)](/docs/uk/core/cpi.md) для виконання +наступного: - [Виклик Системної Програми](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/associated-token-account/program/src/tools/account.rs#L19) для створення нового облікового запису, використовуючи надану PDA як адресу @@ -402,18 +429,21 @@ Signature: 44vqKdfzspT592REDPY4goaRJH3uJ3Ce13G4BCuUHg35dVUbHuGTHvqn4ZjYF9BGe9Qrj spl-token mint [OPTIONS] [--] [RECIPIENT_TOKEN_ACCOUNT_ADDRESS] ``` -Наприклад, виконання наступної команди: +Наприклад, виконання наступної команди: ```sh spl-token mint 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 ``` Виведе наступний результат: -- `99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg` — це адреса облікового запису - випуску токенів, для якого випускаються токени (збільшуючи загальну кількість). -- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` — це адреса токен-облікового запису - вашого гаманця, до якого випускаються одиниці токена (збільшуючи кількість). +- `99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg` — це адреса облікового запису + випуску токенів, для якого випускаються токени (збільшуючи загальну + кількість). + +- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` — це адреса токен-облікового + запису вашого гаманця, до якого випускаються одиниці токена (збільшуючи + кількість). ```shell filename="Terminal Output" /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ /AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9/ Minting 100 tokens @@ -422,19 +452,24 @@ Minting 100 tokens Signature: 2NJ1m7qCraPSBAVxbr2ssmWZmBU9Jc8pDtJAnyZsZJRcaYCYMqq1oRY1gqA4ddQno3g3xcnny5fzr1dvsnFKMEqG ``` -Щоб випустити токени до іншого токен-облікового запису, вкажіть адресу -потрібного облікового запису одержувача токенів. + +Щоб випустити токени до іншого токен-облікового запису, вкажіть адресу +потрібного облікового запису одержувача токенів. Наприклад, виконання наступної команди: ```sh /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ spl-token mint 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 -- Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt ``` + Повертає наступний результат: - - 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg — це адреса облікового запису випуску токенів, для якого випускаються токени (збільшуючи загальну кількість). +- 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg — це адреса облікового запису + випуску токенів, для якого випускаються токени (збільшуючи загальну + кількість). - - Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt — це адреса токен-облікового запису, до якого випускаються одиниці токена (збільшуючи кількість). +- Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt — це адреса токен-облікового + запису, до якого випускаються одиниці токена (збільшуючи кількість). ```shell filename="Terminal Output" /99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg/ /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ Minting 100 tokens @@ -443,10 +478,12 @@ Minting 100 tokens Signature: 3SQvNM3o9DsTiLwcEkSPT1Edr14RgE2wC54TEjonEP2swyVCp2jPWYWdD6RwXUGpvDNUkKWzVBZVFShn5yntxVd7 ``` -За лаштунками створення нових одиниць токена потребує виклику інструкції `MintTo` -у Програмі Токенів. Ця інструкція повинна бути підписана авторитетом випуску. -Інструкція випускає нові одиниці токена до Токен-облікового запису та збільшує -загальну кількість у Обліковому записі випуску токенів. Ось приклад на Javascript у + +За лаштунками створення нових одиниць токена потребує виклику інструкції +`MintTo` у Програмі Токенів. Ця інструкція повинна бути підписана авторитетом +випуску. Інструкція випускає нові одиниці токена до Токен-облікового запису та +збільшує загальну кількість у Обліковому записі випуску токенів. Ось приклад на +Javascript у [Solana Playground](https://beta.solpg.io/660cea45cffcf4b13384d012). ### Передача токенів @@ -458,17 +495,21 @@ Signature: 3SQvNM3o9DsTiLwcEkSPT1Edr14RgE2wC54TEjonEP2swyVCp2jPWYWdD6RwXUGpvDNUk spl-token transfer [OPTIONS] ``` + Наприклад, виконання наступної команди: + ```sh spl-token transfer 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt ``` + Повертає наступний результат: -- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` — це адреса токен-облікового запису, - з якого передаються токени. Це буде адреса вашого токен-облікового запису для - вказаного токена, який передається. -- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` — це адреса токен-облікового запису, - до якого передаються токени. +- `AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9` — це адреса токен-облікового + запису, з якого передаються токени. Це буде адреса вашого токен-облікового + запису для вказаного токена, який передається. + +- `Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt` — це адреса токен-облікового + запису, до якого передаються токени. ```shell filename="Terminal Output" /AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9/ /Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt/ Transfer 100 tokens @@ -477,21 +518,23 @@ Transfer 100 tokens Signature: 5y6HVwV8V2hHGLTVmTmdySRiEUCZnWmkasAvJ7J6m7JR46obbGKCBqUFgLpZu5zQGwM4Xy6GZ4M5LKd1h6Padx3o ``` -За лаштунками, передача токенів потребує виклику інструкції `Transfer` у Програмі Токенів. -Ця інструкція повинна бути підписана власником токен-облікового запису відправника. -Інструкція передає одиниці токена з одного Токен-облікового запису до іншого. -Ось приклад на Javascript у + +За лаштунками, передача токенів потребує виклику інструкції `Transfer` у +Програмі Токенів. Ця інструкція повинна бути підписана власником +токен-облікового запису відправника. Інструкція передає одиниці токена з одного +Токен-облікового запису до іншого. Ось приклад на Javascript у [Solana Playground](https://beta.solpg.io/660ced84cffcf4b13384d013). -Важливо розуміти, що як у відправника, так і у одержувача повинні існувати токен-облікові -записи для конкретного типу токена, який передається. Відправник може додати додаткові -інструкції до транзакції для створення токен-облікового запису одержувача, який, як правило, -є Асоційованим Токен-обліковим записом. +Важливо розуміти, що як у відправника, так і у одержувача повинні існувати +токен-облікові записи для конкретного типу токена, який передається. Відправник +може додати додаткові інструкції до транзакції для створення токен-облікового +запису одержувача, який, як правило, є Асоційованим Токен-обліковим записом. ### Створення метаданих токенів -Програма Розширень Токенів дозволяє додавати настроювані метадані (наприклад, назву, -символ, посилання на зображення) безпосередньо до Облікового запису випуску токенів. +Програма Розширень Токенів дозволяє додавати настроювані метадані (наприклад, +назву, символ, посилання на зображення) безпосередньо до Облікового запису +випуску токенів. Щоб використовувати параметри CLI для розширень токенів, переконайтеся, що ви маєте @@ -500,15 +543,17 @@ Signature: 5y6HVwV8V2hHGLTVmTmdySRiEUCZnWmkasAvJ7J6m7JR46obbGKCBqUFgLpZu5zQGwM4X `cargo install --version 3.4.0 spl-token-cli` -Щоб створити новий токен із увімкненим розширенням метаданих, скористайтеся наступною командою: +Щоб створити новий токен із увімкненим розширенням метаданих, скористайтеся +наступною командою: ```sh spl-token create-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb --enable-metadata ``` + Команда повертає наступний результат: -- `BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP` — це адреса нового токена, +- `BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP` — це адреса нового токена, створеного з увімкненим розширенням метаданих. ```shell filename="Terminal Output" /BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP/ @@ -520,7 +565,8 @@ Decimals: 9 Signature: 5iQofFeXdYhMi9uTzZghcq8stAaa6CY6saUwcdnELST13eNSifiuLbvR5DnRt311frkCTUh5oecj8YEvZSB3wfai ``` -Після створення нового токена з увімкненим розширенням метаданих використовуйте + +Після створення нового токена з увімкненим розширенням метаданих використовуйте наступну команду для ініціалізації метаданих: ```sh @@ -528,24 +574,24 @@ spl-token initialize-metadata ``` -Токен URI зазвичай є посиланням на позаблокові метадані, які ви хочете -асоціювати з токеном. Приклад формату JSON можна знайти +Токен URI зазвичай є посиланням на позаблокові метадані, які ви хочете +асоціювати з токеном. Приклад формату JSON можна знайти [тут](https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json). -Наприклад, виконання наступної команди дозволить зберегти додаткові метадані +Наприклад, виконання наступної команди дозволить зберегти додаткові метадані безпосередньо в зазначеному обліковому записі випуску токенів: ```sh /BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP/ spl-token initialize-metadata BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP "TokenName" "TokenSymbol" "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json" ``` -Ви можете знайти адресу облікового запису випуску токенів у експлорері, щоб -переглянути метадані. Наприклад, ось токен, створений із увімкненим розширенням -метаданих, у експлорері +Ви можете знайти адресу облікового запису випуску токенів у експлорері, щоб +переглянути метадані. Наприклад, ось токен, створений із увімкненим розширенням +метаданих, у експлорері [SolanaFm](https://solana.fm/address/BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP?cluster=devnet-solana). -Дізнатися більше можна у -[Посібнику з Розширення Метаданих](https://solana.com/developers/guides/token-extensions/metadata-pointer). -Деталі щодо різних Розширень Токенів ви знайдете у -[Посібнику Початківця з Розширень Токенів](https://solana.com/developers/guides/token-extensions/getting-started) +Дізнатися більше можна у +[Посібнику з Розширення Метаданих](https://solana.com/developers/guides/token-extensions/metadata-pointer). +Деталі щодо різних Розширень Токенів ви знайдете у +[Посібнику Початківця з Розширень Токенів](https://solana.com/developers/guides/token-extensions/getting-started) та [документації SPL](https://spl.solana.com/token-2022/extensions). diff --git a/docs/locales/uk/core/transactions.md b/docs/locales/uk/core/transactions.md index 610c168fd..400dfe83b 100644 --- a/docs/locales/uk/core/transactions.md +++ b/docs/locales/uk/core/transactions.md @@ -10,9 +10,9 @@ description: У Solana ми надсилаємо [транзакції](/docs/uk/core/transactions#transaction), щоб взаємодіяти з мережею. Транзакції включають одну або більше [інструкцій](/docs/uk/core/transactions#instruction), кожна з яких представляє -конкретну операцію, що має бути оброблена. Логіка виконання інструкцій зберігається -в [програмах](/docs/uk/core/programs), розгорнутих у мережі Solana, і кожна програма -зберігає свій набір інструкцій. +конкретну операцію, що має бути оброблена. Логіка виконання інструкцій +зберігається в [програмах](/docs/uk/core/programs), розгорнутих у мережі Solana, +і кожна програма зберігає свій набір інструкцій. Нижче наведено основні деталі щодо виконання транзакцій: @@ -75,8 +75,9 @@ description: ### Простий переказ SOL -Ось приклад із [Solana Playground](https://beta.solpg.io/656a0ea7fb53fa325bfd0c3e), -який демонструє, як створити інструкцію переказу SOL за допомогою методу +Ось приклад із +[Solana Playground](https://beta.solpg.io/656a0ea7fb53fa325bfd0c3e), який +демонструє, як створити інструкцію переказу SOL за допомогою методу `SystemProgram.transfer`: ```typescript @@ -93,11 +94,13 @@ const transferInstruction = SystemProgram.transfer({ // Додавання інструкції переказу до нової транзакції const transaction = new Transaction().add(transferInstruction); ``` -Запустіть скрипт і перевірте деталі транзакції, що виводяться в консоль. У наступних розділах ми розглянемо, що відбувається "під капотом". + +Запустіть скрипт і перевірте деталі транзакції, що виводяться в консоль. У +наступних розділах ми розглянемо, що відбувається "під капотом". ## Транзакція -Транзакція Solana +Транзакція Solana [transaction](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/transaction/mod.rs#L173) складається з: @@ -110,30 +113,43 @@ const transaction = new Transaction().add(transferInstruction); Структура повідомлення транзакції складається з: -- [Заголовка повідомлення](/docs/uk/core/transactions#message-header): Вказує кількість підписантів та облікових записів тільки для читання. -- [Масиву адрес облікових записів](/docs/uk/core/transactions#array-of-account-addresses): Масив адрес облікових записів, необхідних для інструкцій у транзакції. -- [Недавнього блоку хешу](/docs/uk/core/transactions#recent-blockhash): Використовується як мітка часу для транзакції. -- [Масиву інструкцій](/docs/uk/core/transactions#array-of-instructions): Масив інструкцій, які слід виконати. +- [Заголовка повідомлення](/docs/uk/core/transactions#message-header): Вказує + кількість підписантів та облікових записів тільки для читання. +- [Масиву адрес облікових записів](/docs/uk/core/transactions#array-of-account-addresses): + Масив адрес облікових записів, необхідних для інструкцій у транзакції. +- [Недавнього блоку хешу](/docs/uk/core/transactions#recent-blockhash): + Використовується як мітка часу для транзакції. +- [Масиву інструкцій](/docs/uk/core/transactions#array-of-instructions): Масив + інструкцій, які слід виконати. ![Повідомлення транзакції](/assets/docs/core/transactions/legacy_message.png) ### Розмір транзакції -Мережа Solana дотримується максимального розміру пакета (MTU) у 1280 байт, що відповідає -[MTU IPv6](https://en.wikipedia.org/wiki/IPv6_packet). Це забезпечує швидку та надійну передачу інформації у кластері через UDP. Після врахування необхідних заголовків (40 байт для IPv6 та 8 байт для заголовка фрагмента), -[1232 байти залишаються для даних пакета](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/packet.rs#L16-L21), таких як серіалізовані транзакції. +Мережа Solana дотримується максимального розміру пакета (MTU) у 1280 байт, що +відповідає [MTU IPv6](https://en.wikipedia.org/wiki/IPv6_packet). Це забезпечує +швидку та надійну передачу інформації у кластері через UDP. Після врахування +необхідних заголовків (40 байт для IPv6 та 8 байт для заголовка фрагмента), +[1232 байти залишаються для даних пакета](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/src/packet.rs#L16-L21), +таких як серіалізовані транзакції. -Це означає, що загальний розмір транзакції Solana обмежений 1232 байтами. Підписи та повідомлення у комбінації не можуть перевищувати цей ліміт. +Це означає, що загальний розмір транзакції Solana обмежений 1232 байтами. +Підписи та повідомлення у комбінації не можуть перевищувати цей ліміт. -- Підписи: Кожен підпис займає 64 байти. Кількість підписів може варіювати залежно від вимог транзакції. -- Повідомлення: Повідомлення включає інструкції, облікові записи та додаткові метадані. Кожен обліковий запис займає 32 байти. Загальний розмір облікових записів плюс метадані може варіювати залежно від інструкцій у транзакції. +- Підписи: Кожен підпис займає 64 байти. Кількість підписів може варіювати + залежно від вимог транзакції. +- Повідомлення: Повідомлення включає інструкції, облікові записи та додаткові + метадані. Кожен обліковий запис займає 32 байти. Загальний розмір облікових + записів плюс метадані може варіювати залежно від інструкцій у транзакції. ![Формат транзакції](/assets/docs/core/transactions/issues_with_legacy_txs.png) ### Заголовок повідомлення [Заголовок повідомлення](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/mod.rs#L96) -вказує на привілеї облікових записів, включених у масив адрес транзакції. Він складається з трьох байтів, кожен з яких містить ціле число типу u8, що колективно вказує: +вказує на привілеї облікових записів, включених у масив адрес транзакції. Він +складається з трьох байтів, кожен з яких містить ціле число типу u8, що +колективно вказує: 1. Кількість необхідних підписів для транзакції. 2. Кількість облікових записів тільки для читання, які потребують підписів. @@ -143,7 +159,8 @@ const transaction = new Transaction().add(transferInstruction); ### Формат компактного масиву -Компактний масив у контексті повідомлення транзакції посилається на масив, серіалізований у наступному форматі: +Компактний масив у контексті повідомлення транзакції посилається на масив, +серіалізований у наступному форматі: 1. Довжина масиву, закодована як [compact-u16](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/short_vec.rs). @@ -151,18 +168,22 @@ const transaction = new Transaction().add(transferInstruction); ![Формат компактного масиву](/assets/docs/core/transactions/compact_array_format.png) -Цей метод кодування використовується для вказівки довжин як -[масиву адрес облікових записів](/docs/uk/core/transactions#array-of-account-addresses), так і -[масиву інструкцій](/docs/uk/core/transactions#array-of-instructions) у повідомленні транзакції. +Цей метод кодування використовується для вказівки довжин як +[масиву адрес облікових записів](/docs/uk/core/transactions#array-of-account-addresses), +так і [масиву інструкцій](/docs/uk/core/transactions#array-of-instructions) у +повідомленні транзакції. ### Масив адрес облікових записів -Повідомлення транзакції включає масив, що містить усі +Повідомлення транзакції включає масив, що містить усі [адреси облікових записів](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L119), необхідні для інструкцій у транзакції. -Цей масив починається з кодування -[compact-u16](/docs/uk/core/transactions#compact-array-format) довжини масиву, після чого йдуть адреси, впорядковані за привілеями облікових записів. Метадані в заголовку повідомлення використовуються для визначення кількості облікових записів у кожному розділі. +Цей масив починається з кодування +[compact-u16](/docs/uk/core/transactions#compact-array-format) довжини масиву, +після чого йдуть адреси, впорядковані за привілеями облікових записів. Метадані +в заголовку повідомлення використовуються для визначення кількості облікових +записів у кожному розділі. - Облікові записи, що є змінюваними та підписантами. - Облікові записи тільки для читання, що є підписантами. @@ -173,42 +194,66 @@ const transaction = new Transaction().add(transferInstruction); ### Недавній блок-хеш -Усі транзакції включають +Усі транзакції включають [недавній блок-хеш](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L122), -який використовується як мітка часу для транзакції. Блок-хеш запобігає дублюванню транзакцій і виключає застарілі транзакції. - -Максимальний вік блок-хеша для транзакції становить 150 блоків (~1 хвилина, якщо час блоку складає 400 мс). Якщо блок-хеш транзакції старіший за 150 блоків від останнього блок-хеша, вона вважається протермінованою. Це означає, що транзакції, які не були оброблені вчасно, ніколи не будуть виконані. - -Ви можете скористатися RPC-методом -[`getLatestBlockhash`](/docs/uk/rpc/http/getlatestblockhash), -щоб отримати поточний блок-хеш і останню висоту блоку, на якій блок-хеш залишатиметься дійсним. Ось приклад у +який використовується як мітка часу для транзакції. Блок-хеш запобігає +дублюванню транзакцій і виключає застарілі транзакції. + +Максимальний вік блок-хеша для транзакції становить 150 блоків (~1 хвилина, якщо +час блоку складає 400 мс). Якщо блок-хеш транзакції старіший за 150 блоків від +останнього блок-хеша, вона вважається протермінованою. Це означає, що +транзакції, які не були оброблені вчасно, ніколи не будуть виконані. + +Ви можете скористатися RPC-методом +[`getLatestBlockhash`](/docs/uk/rpc/http/getlatestblockhash), щоб отримати +поточний блок-хеш і останню висоту блоку, на якій блок-хеш залишатиметься +дійсним. Ось приклад у [Solana Playground](https://beta.solpg.io/661a06e1cffcf4b13384d046). + ### Масив інструкцій -Повідомлення транзакції включає масив усіх +Повідомлення транзакції включає масив усіх [інструкцій](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/message/legacy.rs#L128), які запитуються для обробки. Інструкції у повідомленні транзакції мають формат [CompiledInstruction](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L633). -Подібно до масиву адрес облікових записів, цей компактний масив починається з кодування -[compact-u16](/docs/uk/core/transactions#compact-array-format) кількості інструкцій, після чого йде масив інструкцій. Кожна інструкція в масиві вказує наступну інформацію: - -1. **Program ID**: Ідентифікатор програми в мережі, яка оброблятиме інструкцію. Це представлено у вигляді індексу типу u8, що вказує на адресу програми у масиві адрес облікових записів. -2. **Компактний масив індексів адрес облікових записів**: Масив індексів типу u8, що вказує на масив адрес облікових записів для кожного облікового запису, потрібного для інструкції. -3. **Компактний масив байтів даних**: Масив байтів типу u8, специфічний для викликаної програми. Ці дані вказують, яку інструкцію викликати у програмі, разом із будь-якими додатковими даними, потрібними для виконання інструкції (наприклад, аргументами функції). +Подібно до масиву адрес облікових записів, цей компактний масив починається з +кодування [compact-u16](/docs/uk/core/transactions#compact-array-format) +кількості інструкцій, після чого йде масив інструкцій. Кожна інструкція в масиві +вказує наступну інформацію: + +1. **Program ID**: Ідентифікатор програми в мережі, яка оброблятиме інструкцію. + Це представлено у вигляді індексу типу u8, що вказує на адресу програми у + масиві адрес облікових записів. +2. **Компактний масив індексів адрес облікових записів**: Масив індексів типу + u8, що вказує на масив адрес облікових записів для кожного облікового запису, + потрібного для інструкції. +3. **Компактний масив байтів даних**: Масив байтів типу u8, специфічний для + викликаної програми. Ці дані вказують, яку інструкцію викликати у програмі, + разом із будь-якими додатковими даними, потрібними для виконання інструкції + (наприклад, аргументами функції). ![Компактний масив інструкцій](/assets/docs/core/transactions/compact_array_of_ixs.png) ### Приклад структури транзакції -Нижче наведено приклад структури транзакції, яка включає одну інструкцію для -[передачі SOL](/docs/uk/core/transactions#basic-example). Тут показано деталі повідомлення, включаючи заголовок, ключі облікових записів, блок-хеш та інструкції, разом із підписом для транзакції. +Нижче наведено приклад структури транзакції, яка включає одну інструкцію для +[передачі SOL](/docs/uk/core/transactions#basic-example). Тут показано деталі +повідомлення, включаючи заголовок, ключі облікових записів, блок-хеш та +інструкції, разом із підписом для транзакції. -- `header`: Містить дані, які використовуються для вказання привілеїв читання/запису та підписання у масиві `accountKeys`. -- `accountKeys`: Масив, що включає адреси облікових записів для всіх інструкцій у транзакції. +- `header`: Містить дані, які використовуються для вказання привілеїв + читання/запису та підписання у масиві `accountKeys`. +- `accountKeys`: Масив, що включає адреси облікових записів для всіх інструкцій + у транзакції. - `recentBlockhash`: Блок-хеш, включений у транзакцію під час її створення. -- `instructions`: Масив, що включає всі інструкції у транзакції. Кожен `account` та `programIdIndex` в інструкції посилаються на масив `accountKeys` за індексом. -- `signatures`: Масив, що включає підписи для всіх облікових записів, потрібних як підписанти для інструкцій у транзакції. Підпис створюється шляхом підписання повідомлення транзакції за допомогою відповідного приватного ключа для облікового запису. +- `instructions`: Масив, що включає всі інструкції у транзакції. Кожен `account` + та `programIdIndex` в інструкції посилаються на масив `accountKeys` за + індексом. +- `signatures`: Масив, що включає підписи для всіх облікових записів, потрібних + як підписанти для інструкцій у транзакції. Підпис створюється шляхом + підписання повідомлення транзакції за допомогою відповідного приватного ключа + для облікового запису. ```json "transaction": { @@ -242,45 +287,58 @@ const transaction = new Transaction().add(transferInstruction); ] } ``` + ## Інструкція [Інструкція](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L329) -— це запит на виконання конкретної дії в мережі. Це найменша неподільна одиниця логіки виконання у -[програмі](/docs/uk/core/accounts#program-account). +— це запит на виконання конкретної дії в мережі. Це найменша неподільна одиниця +логіки виконання у [програмі](/docs/uk/core/accounts#program-account). -При створенні інструкції для додавання до транзакції кожна інструкція повинна включати наступну інформацію: +При створенні інструкції для додавання до транзакції кожна інструкція повинна +включати наступну інформацію: - **Адреса програми**: Вказує програму, яку буде викликано. -- **Облікові записи**: Перелік кожного облікового запису, з якого інструкція читає або до якого пише, включаючи інші програми, за допомогою структури `AccountMeta`. -- **Дані інструкції**: Масив байтів, що вказує, який - [обробник інструкцій](/docs/uk/terminology#instruction-handler) викликати у програмі, а також будь-які додаткові дані, необхідні обробнику інструкцій (аргументи функції). +- **Облікові записи**: Перелік кожного облікового запису, з якого інструкція + читає або до якого пише, включаючи інші програми, за допомогою структури + `AccountMeta`. +- **Дані інструкції**: Масив байтів, що вказує, який + [обробник інструкцій](/docs/uk/terminology#instruction-handler) викликати у + програмі, а також будь-які додаткові дані, необхідні обробнику інструкцій + (аргументи функції). ![Інструкція транзакції](/assets/docs/core/transactions/instruction.svg) ### AccountMeta -Для кожного облікового запису, необхідного для інструкції, потрібно вказати наступну інформацію: +Для кожного облікового запису, необхідного для інструкції, потрібно вказати +наступну інформацію: - `pubkey`: Адреса облікового запису в мережі. - `is_signer`: Вказує, чи є обліковий запис підписантом у транзакції. - `is_writable`: Вказує, чи будуть змінені дані облікового запису. -Ця інформація називається +Ця інформація називається [AccountMeta](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/instruction.rs#L539). ![AccountMeta](/assets/docs/core/transactions/accountmeta.svg) -Завдяки вказанню всіх облікових записів, необхідних для інструкції, і зазначенню, які з них можуть бути змінені, транзакції можуть виконуватися паралельно. +Завдяки вказанню всіх облікових записів, необхідних для інструкції, і +зазначенню, які з них можуть бути змінені, транзакції можуть виконуватися +паралельно. -Наприклад, дві транзакції, які не включають жодних облікових записів, що записують в той самий стан, можуть виконуватися одночасно. +Наприклад, дві транзакції, які не включають жодних облікових записів, що +записують в той самий стан, можуть виконуватися одночасно. ### Приклад структури інструкції -Нижче наведено приклад структури інструкції для -[передачі SOL](/docs/uk/core/transactions#basic-examples), яка деталізує ключі облікових записів, ідентифікатор програми та дані, необхідні для інструкції. +Нижче наведено приклад структури інструкції для +[передачі SOL](/docs/uk/core/transactions#basic-examples), яка деталізує ключі +облікових записів, ідентифікатор програми та дані, необхідні для інструкції. -- `keys`: Містить `AccountMeta` для кожного облікового запису, необхідного для інструкції. -- `programId`: Адреса програми, яка містить логіку виконання для викликаної інструкції. +- `keys`: Містить `AccountMeta` для кожного облікового запису, необхідного для + інструкції. +- `programId`: Адреса програми, яка містить логіку виконання для викликаної + інструкції. - `data`: Дані інструкції у вигляді буфера байтів. ``` @@ -301,13 +359,18 @@ const transaction = new Transaction().add(transferInstruction); "data": [2,0,0,0,128,150,152,0,0,0,0,0] } ``` + ## Розширений приклад -Деталі створення програмних інструкцій часто приховуються клієнтськими бібліотеками. Проте, якщо такої бібліотеки немає, завжди можна вручну створити інструкцію. +Деталі створення програмних інструкцій часто приховуються клієнтськими +бібліотеками. Проте, якщо такої бібліотеки немає, завжди можна вручну створити +інструкцію. ### Ручна передача SOL -Ось приклад на [Solana Playground](https://beta.solpg.io/656a102efb53fa325bfd0c3f), який демонструє, як вручну створити інструкцію для передачі SOL: +Ось приклад на +[Solana Playground](https://beta.solpg.io/656a102efb53fa325bfd0c3f), який +демонструє, як вручну створити інструкцію для передачі SOL: ```typescript // Define the amount to transfer @@ -336,5 +399,9 @@ const transferInstruction = new TransactionInstruction({ // Add the transfer instruction to a new transaction const transaction = new Transaction().add(transferInstruction); ``` -Під капотом [простий приклад](/docs/uk/core/transactions#simple-sol-transfer) з використанням методу `SystemProgram.transfer` функціонально еквівалентний більш детальному прикладу вище. Метод `SystemProgram.transfer` просто приховує деталі створення буфера даних інструкції та `AccountMeta` для кожного облікового запису, необхідного для інструкції. +Під капотом [простий приклад](/docs/uk/core/transactions#simple-sol-transfer) з +використанням методу `SystemProgram.transfer` функціонально еквівалентний більш +детальному прикладу вище. Метод `SystemProgram.transfer` просто приховує деталі +створення буфера даних інструкції та `AccountMeta` для кожного облікового +запису, необхідного для інструкції. diff --git a/docs/locales/uk/economics/index.md b/docs/locales/uk/economics/index.md index ecfa6d94f..512f698e6 100644 --- a/docs/locales/uk/economics/index.md +++ b/docs/locales/uk/economics/index.md @@ -8,14 +8,45 @@ sidebarSortOrder: 5 **Може бути змінено.** -Криптоекономічна система Solana розроблена для сприяння здоровій, довгостроковій самопідтримуваній економіці, в якій стимули учасників узгоджуються із забезпеченням безпеки та децентралізації мережі. Основними учасниками цієї економіки є валідаційні клієнти. Їхній внесок у мережу, перевірка стану та відповідні механізми стимулювання розглядаються нижче. +Криптоекономічна система Solana розроблена для сприяння здоровій, довгостроковій +самопідтримуваній економіці, в якій стимули учасників узгоджуються із +забезпеченням безпеки та децентралізації мережі. Основними учасниками цієї +економіки є валідаційні клієнти. Їхній внесок у мережу, перевірка стану та +відповідні механізми стимулювання розглядаються нижче. -Основними каналами винагород для учасників є винагороди, засновані на протоколі, та транзакційні комісії. Винагороди, засновані на протоколі, генеруються за рахунок інфляційного випуску згідно з визначеним протоколом графіком інфляції. Ці винагороди становитимуть загальну винагороду на основі протоколу, яка буде надаватися валідаційним клієнтам, решта забезпечується за рахунок транзакційних комісій. У перші дні роботи мережі ймовірно, що винагороди, засновані на протоколі, розподілені згідно з попередньо визначеним графіком випуску, стануть основним стимулом для учасників мережі. +Основними каналами винагород для учасників є винагороди, засновані на протоколі, +та транзакційні комісії. Винагороди, засновані на протоколі, генеруються за +рахунок інфляційного випуску згідно з визначеним протоколом графіком інфляції. +Ці винагороди становитимуть загальну винагороду на основі протоколу, яка буде +надаватися валідаційним клієнтам, решта забезпечується за рахунок транзакційних +комісій. У перші дні роботи мережі ймовірно, що винагороди, засновані на +протоколі, розподілені згідно з попередньо визначеним графіком випуску, стануть +основним стимулом для учасників мережі. -Ці винагороди розраховуються за кожну епоху і розподіляються серед активного делегованого стейку та набору валідаторів (з урахуванням комісії валідаторів). Як описано нижче, річний рівень інфляції ґрунтується на визначеному дисінфляційному графіку. Це забезпечує мережі передбачуваність поставок, що підтримує довгострокову економічну стабільність та безпеку. +Ці винагороди розраховуються за кожну епоху і розподіляються серед активного +делегованого стейку та набору валідаторів (з урахуванням комісії валідаторів). +Як описано нижче, річний рівень інфляції ґрунтується на визначеному +дисінфляційному графіку. Це забезпечує мережі передбачуваність поставок, що +підтримує довгострокову економічну стабільність та безпеку. -Транзакційні комісії є переказами між учасниками, що додаються до взаємодії з мережею як стимул та компенсація за включення і виконання запропонованої транзакції. Також обговорюється механізм довгострокової економічної стабільності та захисту від розгалужень через часткове спалювання кожної транзакційної комісії. +Транзакційні комісії є переказами між учасниками, що додаються до взаємодії з +мережею як стимул та компенсація за включення і виконання запропонованої +транзакції. Також обговорюється механізм довгострокової економічної стабільності +та захисту від розгалужень через часткове спалювання кожної транзакційної +комісії. -Спочатку подано огляд дизайну інфляції. Цей розділ починається з визначення та уточнення [Термінології](/docs/uk/economics/inflation/terminology.md), що часто використовується у подальшому обговоренні інфляції та пов'язаних компонентів. Далі ми окреслюємо запропонований [Графік Інфляції](/docs/uk/economics/inflation/inflation_schedule.md) Solana, тобто конкретні параметри, які унікально визначають інфляційний випуск, керований протоколом, з плином часу. Наступним є короткий розділ про [Скориговану Доходність Стейкінгу](/docs/uk/economics/inflation/_adjusted_staking_yield.md) і те, як розбавлення токенів може вплинути на поведінку стейкінгу. +Спочатку подано огляд дизайну інфляції. Цей розділ починається з визначення та +уточнення [Термінології](/docs/uk/economics/inflation/terminology.md), що часто +використовується у подальшому обговоренні інфляції та пов'язаних компонентів. +Далі ми окреслюємо запропонований +[Графік Інфляції](/docs/uk/economics/inflation/inflation_schedule.md) Solana, +тобто конкретні параметри, які унікально визначають інфляційний випуск, +керований протоколом, з плином часу. Наступним є короткий розділ про +[Скориговану Доходність Стейкінгу](/docs/uk/economics/inflation/_adjusted_staking_yield.md) +і те, як розбавлення токенів може вплинути на поведінку стейкінгу. -Огляд [Транзакційних Комісій](/docs/uk/core/fees.md#transaction-fees) у Solana супроводжується обговоренням [Економіки Оренди для Зберігання](/docs/uk/core/fees.md#rent), у якому описується реалізація орендної плати за зберігання для обліку зовнішніх витрат на підтримання активного стану реєстру. +Огляд [Транзакційних Комісій](/docs/uk/core/fees.md#transaction-fees) у Solana +супроводжується обговоренням +[Економіки Оренди для Зберігання](/docs/uk/core/fees.md#rent), у якому +описується реалізація орендної плати за зберігання для обліку зовнішніх витрат +на підтримання активного стану реєстру. diff --git a/docs/locales/uk/economics/inflation/_adjusted_staking_yield.md b/docs/locales/uk/economics/inflation/_adjusted_staking_yield.md index a515b96f7..566f3676d 100644 --- a/docs/locales/uk/economics/inflation/_adjusted_staking_yield.md +++ b/docs/locales/uk/economics/inflation/_adjusted_staking_yield.md @@ -4,19 +4,33 @@ title: Скоригована Дохідність Стейкінгу ### Дилюція Токенів -Подібним чином ми можемо розглянути очікувану _Дилюцію Стейкінгу_ (тобто _Скориговану Дохідність Стейкінгу_) та _Дилюцію Нестейкінгованих Токенів_, як було визначено раніше. У цьому контексті _дилюція_ означає зміну фракційного представлення (тобто частки власності) набору токенів у рамках більшого пулу. У цьому сенсі дилюція може бути позитивною (збільшення частки власності, стейкінгова дилюція / _Скоригована Дохідність Стейкінгу_) або негативною (зменшення частки власності, нестейкінгова дилюція). - -Нас цікавить відносна зміна власності стейкінгованих і нестейкінгованих токенів у міру збільшення загального пулу токенів через інфляційний випуск. Як було зазначено, цей випуск розподіляється лише серед власників стейкінгованих токенів, збільшуючи їх частку у _Загальному Поточному Обсязі_. - -Продовжуючи з тими ж параметрами _Графіку Інфляції_, що й раніше, ми бачимо зростання частки стейкінгового пулу, як показано нижче. +Подібним чином ми можемо розглянути очікувану _Дилюцію Стейкінгу_ (тобто +_Скориговану Дохідність Стейкінгу_) та _Дилюцію Нестейкінгованих Токенів_, як +було визначено раніше. У цьому контексті _дилюція_ означає зміну фракційного +представлення (тобто частки власності) набору токенів у рамках більшого пулу. У +цьому сенсі дилюція може бути позитивною (збільшення частки власності, +стейкінгова дилюція / _Скоригована Дохідність Стейкінгу_) або негативною +(зменшення частки власності, нестейкінгова дилюція). + +Нас цікавить відносна зміна власності стейкінгованих і нестейкінгованих токенів +у міру збільшення загального пулу токенів через інфляційний випуск. Як було +зазначено, цей випуск розподіляється лише серед власників стейкінгованих +токенів, збільшуючи їх частку у _Загальному Поточному Обсязі_. + +Продовжуючи з тими ж параметрами _Графіку Інфляції_, що й раніше, ми бачимо +зростання частки стейкінгового пулу, як показано нижче. ![Графік зростання частки стейкінгового пулу](/assets/docs/economics/example_staked_supply_w_range_initial_stake.png) -Через цю відносну зміну у представництві частка стейкінгу будь-якого власника токенів також змінюється як функція _Графіку Інфляції_ та частки стейкінгованих токенів. +Через цю відносну зміну у представництві частка стейкінгу будь-якого власника +токенів також змінюється як функція _Графіку Інфляції_ та частки стейкінгованих +токенів. ### Розрахунок Дилюції Нестейкінгованих Токенів -Особливий інтерес викликає _Дилюція Нестейкінгованих Токенів_, або $D_{us}$. У випадку нестейкінгованих токенів дилюція залежить лише від _Графіку Інфляції_, оскільки кількість нестейкінгованих токенів не змінюється з часом. +Особливий інтерес викликає _Дилюція Нестейкінгованих Токенів_, або $D_{us}$. У +випадку нестейкінгованих токенів дилюція залежить лише від _Графіку Інфляції_, +оскільки кількість нестейкінгованих токенів не змінюється з часом. $$ \begin{aligned} @@ -25,7 +39,8 @@ $$ \end{aligned} $$ -Оскільки випуск інфляції лише збільшує загальну кількість токенів, а нестейкінгована кількість залишається незмінною: +Оскільки випуск інфляції лише збільшує загальну кількість токенів, а +нестейкінгована кількість залишається незмінною: $$ \begin{aligned} @@ -41,7 +56,8 @@ $$ ### Оцінка Скоригованої Дохідності Стейкінгу -Ми також можемо розрахувати _Скориговану Дохідність Стейкінгу_ $Y_{adj}$ як зміну частки стейкінгованих токенів у пулі: +Ми також можемо розрахувати _Скориговану Дохідність Стейкінгу_ $Y_{adj}$ як +зміну частки стейкінгованих токенів у пулі: $$ Y_{adj} = \frac{P_s(t_2) - P_s(t_1)}{P_s(t_1)} @@ -55,12 +71,17 @@ $$ ### Відносна Дилюція -Відношення $D_{us}/Y_{adj}$ дозволяє зрозуміти, наскільки сильніше нестейкінговані токени піддаються дилюції у порівнянні зі стейкінгованими: +Відношення $D_{us}/Y_{adj}$ дозволяє зрозуміти, наскільки сильніше +нестейкінговані токени піддаються дилюції у порівнянні зі стейкінгованими: $$ \frac{D_{us}}{Y_{adj}} = \frac{ P_s }{ 1 - P_s } $$ -На основі цього видно, що збільшення частки стейкінгованих токенів значно збільшує дилюцію нестейкінгованих токенів. Наприклад, якщо $80\%$ токенів мережі стейкінговано, власник нестейкінгованих токенів зіткнеться з дилюцією у $400\%$ більшою, ніж стейкінгований власник. +На основі цього видно, що збільшення частки стейкінгованих токенів значно +збільшує дилюцію нестейкінгованих токенів. Наприклад, якщо $80\%$ токенів мережі +стейкінговано, власник нестейкінгованих токенів зіткнеться з дилюцією у $400\%$ +більшою, ніж стейкінгований власник. -Це підкреслює стимул для власників токенів до стейкінгу, щоб отримати _Дохідність Стейкінгу_ та уникнути _Дилюції Нестейкінгованих Токенів_. +Це підкреслює стимул для власників токенів до стейкінгу, щоб отримати +_Дохідність Стейкінгу_ та уникнути _Дилюції Нестейкінгованих Токенів_. diff --git a/docs/locales/uk/economics/inflation/inflation-schedule.md b/docs/locales/uk/economics/inflation/inflation-schedule.md index f9d69885d..dab4750e1 100644 --- a/docs/locales/uk/economics/inflation/inflation-schedule.md +++ b/docs/locales/uk/economics/inflation/inflation-schedule.md @@ -6,37 +6,78 @@ altRoutes: - /docs/uk/intro/economics --- -Як було зазначено вище, _Графік Інфляції_ мережі унікально описується трьома параметрами: _Початкова Ставка Інфляції_, _Ставка Дезінфляції_ та _Довгострокова Ставка Інфляції_. При розгляді цих значень слід враховувати багато факторів: +Як було зазначено вище, _Графік Інфляції_ мережі унікально описується трьома +параметрами: _Початкова Ставка Інфляції_, _Ставка Дезінфляції_ та _Довгострокова +Ставка Інфляції_. При розгляді цих значень слід враховувати багато факторів: -- Значна частина SOL, випущених через інфляцію, буде розподілена між власниками стейкінгу пропорційно до кількості стейкінгованих SOL. Ми хочемо переконатися, що дизайн _Графіку Інфляції_ забезпечує розумну _Дохідність Стейкінгу_ для власників токенів, які делегують SOL, та провайдерів послуг валідації (через комісії, які беруться з _Дохідності Стейкінгу_). -- Основний драйвер _Дохідності Стейкінгу_ — це кількість SOL у стейкінгу, поділена на загальну кількість SOL (% від загальної кількості SOL у стейкінгу). Таким чином, розподіл і делегування токенів серед валідаторів є важливими факторами при визначенні початкових параметрів інфляції. -- Обмеження дохідності — це поточна область досліджень, яка може вплинути на _Дохідність Стейкінгу_. Це не враховано у цій дискусії чи в моделюванні нижче. -- Загальний випуск токенів — тобто якою ми очікуємо _Поточну Загальну Пропозицію_ через 10 чи 20 років? -- Довгострокова, стабільна інфляція є важливим фактором не тільки для сталого підтримання екосистеми валідаторів і грантових програм Фонду Solana, але також має бути налаштована з урахуванням очікуваних втрат і спалювання токенів з часом. -- Темпи очікуваного зростання використання мережі як фактор для розгляду ставки дезінфляції. З часом ми плануємо зниження інфляції та очікуємо зростання використання. +- Значна частина SOL, випущених через інфляцію, буде розподілена між власниками + стейкінгу пропорційно до кількості стейкінгованих SOL. Ми хочемо переконатися, + що дизайн _Графіку Інфляції_ забезпечує розумну _Дохідність Стейкінгу_ для + власників токенів, які делегують SOL, та провайдерів послуг валідації (через + комісії, які беруться з _Дохідності Стейкінгу_). +- Основний драйвер _Дохідності Стейкінгу_ — це кількість SOL у стейкінгу, + поділена на загальну кількість SOL (% від загальної кількості SOL у + стейкінгу). Таким чином, розподіл і делегування токенів серед валідаторів є + важливими факторами при визначенні початкових параметрів інфляції. +- Обмеження дохідності — це поточна область досліджень, яка може вплинути на + _Дохідність Стейкінгу_. Це не враховано у цій дискусії чи в моделюванні нижче. +- Загальний випуск токенів — тобто якою ми очікуємо _Поточну Загальну + Пропозицію_ через 10 чи 20 років? +- Довгострокова, стабільна інфляція є важливим фактором не тільки для сталого + підтримання екосистеми валідаторів і грантових програм Фонду Solana, але також + має бути налаштована з урахуванням очікуваних втрат і спалювання токенів з + часом. +- Темпи очікуваного зростання використання мережі як фактор для розгляду ставки + дезінфляції. З часом ми плануємо зниження інфляції та очікуємо зростання + використання. -Виходячи з цих міркувань і обговорень у спільноті після початкового дизайну, Фонд Solana пропонує наступні параметри _Графіку Інфляції_: +Виходячи з цих міркувань і обговорень у спільноті після початкового дизайну, +Фонд Solana пропонує наступні параметри _Графіку Інфляції_: - Початкова Ставка Інфляції: 8% - Ставка Дезінфляції: -15% - Довгострокова Ставка Інфляції: 1.5% -Ці параметри визначають запропонований _Графік Інфляції_. Нижче показано наслідки цих параметрів. Ці графіки лише показують вплив інфляційного випуску, заданого _Графіком Інфляції_, як параметризовано вище. Вони _не враховують_ інші фактори, які можуть вплинути на _Загальну Пропозицію_, такі як спалювання комісій/рент, штрафи чи інші непередбачувані події знищення токенів у майбутньому. Тому тут представлено **верхню межу** кількості SOL, випущених через інфляцію. +Ці параметри визначають запропонований _Графік Інфляції_. Нижче показано +наслідки цих параметрів. Ці графіки лише показують вплив інфляційного випуску, +заданого _Графіком Інфляції_, як параметризовано вище. Вони _не враховують_ інші +фактори, які можуть вплинути на _Загальну Пропозицію_, такі як спалювання +комісій/рент, штрафи чи інші непередбачувані події знищення токенів у +майбутньому. Тому тут представлено **верхню межу** кількості SOL, випущених +через інфляцію. ![Графік прикладу запропонованого графіку інфляції](/assets/docs/economics/proposed_inflation_schedule.png) -На графіку вище показано відсоток річної ставки інфляції з часом, виходячи з запропонованих параметрів інфляції. +На графіку вище показано відсоток річної ставки інфляції з часом, виходячи з +запропонованих параметрів інфляції. ![Графік прикладу загальної пропозиції](/assets/docs/economics/proposed_total_supply.png) -Подібним чином, тут показано _Поточну Загальну Пропозицію_ SOL [млн] з часом, за умови початкової _Поточна Загальна Пропозиція_ `488,587,349 SOL` (тобто, у цьому прикладі, взято _Поточну Загальну Пропозицію_ станом на `2020-01-25` і моделюється інфляція, починаючи з цього дня). +Подібним чином, тут показано _Поточну Загальну Пропозицію_ SOL [млн] з часом, за +умови початкової _Поточна Загальна Пропозиція_ `488,587,349 SOL` (тобто, у цьому +прикладі, взято _Поточну Загальну Пропозицію_ станом на `2020-01-25` і +моделюється інфляція, починаючи з цього дня). -Відставляючи осторонь доступність валідаторів і комісії, очікувані показники _Дохідності Стейкінгу_ та _Скоригованої Дохідності Стейкінгу_ є в першу чергу функцією % від загального SOL у стейкінгу. Тому ми можемо моделювати _Дохідність Стейкінгу_, якщо введемо додатковий параметр _% Стейкінгованих SOL_: +Відставляючи осторонь доступність валідаторів і комісії, очікувані показники +_Дохідності Стейкінгу_ та _Скоригованої Дохідності Стейкінгу_ є в першу чергу +функцією % від загального SOL у стейкінгу. Тому ми можемо моделювати _Дохідність +Стейкінгу_, якщо введемо додатковий параметр _% Стейкінгованих SOL_: -Цей параметр має бути оцінений, оскільки це динамічна властивість власників токенів і стимулів стейкінгу. Значення _% Стейкінгованих SOL_, представлені тут, варіюються від 60% до 90%, що, на нашу думку, охоплює ймовірний діапазон, який ми очікуємо, базуючись на зворотному зв’язку від спільнот інвесторів і валідаторів, а також спостереженнях на порівнянних протоколах Proof-of-Stake. +Цей параметр має бути оцінений, оскільки це динамічна властивість власників +токенів і стимулів стейкінгу. Значення _% Стейкінгованих SOL_, представлені тут, +варіюються від 60% до 90%, що, на нашу думку, охоплює ймовірний діапазон, який +ми очікуємо, базуючись на зворотному зв’язку від спільнот інвесторів і +валідаторів, а також спостереженнях на порівнянних протоколах Proof-of-Stake. ![Графік прикладу дохідності стейкінгу](/assets/docs/economics/example_staked_yields.png) -На графіку вище показано приклад _Дохідності Стейкінгу_, яку може очікувати учасник стейкінгу з часом у мережі Solana з вказаним _Графіком Інфляції_. Це ідеалізована _Дохідність Стейкінгу_, оскільки вона не враховує вплив доступності валідаторів на винагороди, комісії валідаторів, можливе обмеження дохідності та можливі інциденти зі штрафами. Вона також ігнорує, що _% Стейкінгованих SOL_ є динамічним за своєю суттю — економічні стимули, створені цим _Графіком Інфляції_, стають більш зрозумілими, коли враховується _Дилюція Токенів_ (див. розділ **Скоригована Дохідність Стейкінгу** нижче). +На графіку вище показано приклад _Дохідності Стейкінгу_, яку може очікувати +учасник стейкінгу з часом у мережі Solana з вказаним _Графіком Інфляції_. Це +ідеалізована _Дохідність Стейкінгу_, оскільки вона не враховує вплив доступності +валідаторів на винагороди, комісії валідаторів, можливе обмеження дохідності та +можливі інциденти зі штрафами. Вона також ігнорує, що _% Стейкінгованих SOL_ є +динамічним за своєю суттю — економічні стимули, створені цим _Графіком +Інфляції_, стають більш зрозумілими, коли враховується _Дилюція Токенів_ (див. +розділ **Скоригована Дохідність Стейкінгу** нижче). diff --git a/docs/locales/uk/economics/inflation/terminology.md b/docs/locales/uk/economics/inflation/terminology.md index bdd0cbe94..23debb50c 100644 --- a/docs/locales/uk/economics/inflation/terminology.md +++ b/docs/locales/uk/economics/inflation/terminology.md @@ -3,44 +3,86 @@ sidebarLabel: Терміни, Пов’язані з Інфляцією title: Терміни, Пов’язані з Інфляцією --- -При обговоренні інфляції та пов’язаних компонентів (наприклад, винагород/дохідності/відсотків) використовується багато термінів. Тут ми намагаємося визначити та уточнити деякі загальновживані поняття: +При обговоренні інфляції та пов’язаних компонентів (наприклад, +винагород/дохідності/відсотків) використовується багато термінів. Тут ми +намагаємося визначити та уточнити деякі загальновживані поняття: ### Поточна Загальна Пропозиція [SOL] -Загальна кількість токенів (заблокованих або незаблокованих), які були створені (через генезисний блок або інфляцію протоколу) мінус будь-які токени, які були спалені (через комісії за транзакції або інші механізми) чи списані. Під час запуску мережі було створено 500,000,000 SOL у генезисному блоці. З того часу Поточна Загальна Пропозиція зменшилася через спалювання комісій за транзакції та заплановану подію зменшення кількості токенів. _Поточну Загальну Пропозицію_ Solana можна знайти за адресою: https://explorer.solana.com/supply +Загальна кількість токенів (заблокованих або незаблокованих), які були створені +(через генезисний блок або інфляцію протоколу) мінус будь-які токени, які були +спалені (через комісії за транзакції або інші механізми) чи списані. Під час +запуску мережі було створено 500,000,000 SOL у генезисному блоці. З того часу +Поточна Загальна Пропозиція зменшилася через спалювання комісій за транзакції та +заплановану подію зменшення кількості токенів. _Поточну Загальну Пропозицію_ +Solana можна знайти за адресою: https://explorer.solana.com/supply ### Ставка Інфляції [%] -Протокол Solana автоматично створює нові токени за заздалегідь визначеним графіком інфляції (обговорено нижче). _Ставка Інфляції [%]_ — це річний темп зростання _Поточна Загальна Пропозиція_ на будь-який момент часу. +Протокол Solana автоматично створює нові токени за заздалегідь визначеним +графіком інфляції (обговорено нижче). _Ставка Інфляції [%]_ — це річний темп +зростання _Поточна Загальна Пропозиція_ на будь-який момент часу. ### Графік Інфляції -Детерміноване описання випуску токенів з часом. Фонд Solana пропонує дезінфляційний _Графік Інфляції_. Тобто інфляція починається з найвищого значення, а її темп зменшується з часом, доки не стабілізується на заздалегідь визначеному довгостроковому рівні (див. обговорення нижче). Цей графік повністю та унікально параметризується трьома числами: +Детерміноване описання випуску токенів з часом. Фонд Solana пропонує +дезінфляційний _Графік Інфляції_. Тобто інфляція починається з найвищого +значення, а її темп зменшується з часом, доки не стабілізується на заздалегідь +визначеному довгостроковому рівні (див. обговорення нижче). Цей графік повністю +та унікально параметризується трьома числами: -- **Початкова Ставка Інфляції [%]**: Початкова _Ставка Інфляції_ для моменту активації інфляції. Темп випуску токенів може тільки знижуватися з цього моменту. +- **Початкова Ставка Інфляції [%]**: Початкова _Ставка Інфляції_ для моменту + активації інфляції. Темп випуску токенів може тільки знижуватися з цього + моменту. - **Ставка Дезінфляції [%]**: Темп, з яким зменшується _Ставка Інфляції_. -- **Довгострокова Ставка Інфляції [%]**: Стабільна, довгострокова _Ставка Інфляції_. +- **Довгострокова Ставка Інфляції [%]**: Стабільна, довгострокова _Ставка + Інфляції_. ### Ефективна Ставка Інфляції [%] -Фактична ставка інфляції, що спостерігається в мережі Solana, після врахування інших факторів, які можуть зменшити _Поточну Загальну Пропозицію_. Зазначимо, що створення токенів поза описаним _Графіком Інфляції_ неможливе. +Фактична ставка інфляції, що спостерігається в мережі Solana, після врахування +інших факторів, які можуть зменшити _Поточну Загальну Пропозицію_. Зазначимо, що +створення токенів поза описаним _Графіком Інфляції_ неможливе. -- Хоча _Графік Інфляції_ визначає, як протокол випускає SOL, він не враховує одночасного знищення токенів через різні фактори. Основний механізм спалювання токенів — це спалювання частини кожної комісії за транзакцію. 50% кожної комісії за транзакцію спалюється, решта залишається валідатору, який обробив транзакцію. -- Додаткові фактори, такі як втрата приватних ключів і списання токенів, також слід враховувати в комплексному аналізі _Ефективної Ставки Інфляції_. Наприклад, оцінюється, що 10–20% всіх BTC втрачені та недоступні, і мережі можуть зазнавати подібних щорічних втрат на рівні 1–2%. +- Хоча _Графік Інфляції_ визначає, як протокол випускає SOL, він не враховує + одночасного знищення токенів через різні фактори. Основний механізм спалювання + токенів — це спалювання частини кожної комісії за транзакцію. 50% кожної + комісії за транзакцію спалюється, решта залишається валідатору, який обробив + транзакцію. +- Додаткові фактори, такі як втрата приватних ключів і списання токенів, також + слід враховувати в комплексному аналізі _Ефективної Ставки Інфляції_. + Наприклад, оцінюється, що 10–20% всіх BTC втрачені та недоступні, і мережі + можуть зазнавати подібних щорічних втрат на рівні 1–2%. ### Дохідність Стейкінгу [%] -Темп повернення (також відомий як _відсоток_), який отримується за SOL, поставлені на стейкінг у мережі. Зазвичай він зазначається як річний темп (наприклад, "дохідність стейкінгу в мережі наразі становить 10% на рік"). - -- _Дохідність стейкінгу_ дуже цікавить валідаторів і власників токенів, які бажають делегувати свої токени, щоб уникнути розмивання токенів через інфляцію (масштаб якої обговорено нижче). -- 100% інфляційних випусків розподіляються між власниками стейкінгованих токенів пропорційно до їхнього стейкінгованого SOL, а також валідаторами, які стягують комісію з винагороди, отриманої за делегований SOL. - - Може бути враховано майбутнє розділення інфляційних випусків із введенням _Архіваторів_ у економіку. _Архіватори_ — це учасники мережі, які надають децентралізовані послуги зберігання, і їх також слід стимулювати розподілом токенів з інфляційних випусків за цю послугу. -- _Дохідність Стейкінгу_ можна розрахувати за _Графіком Інфляції_ разом із часткою _Поточна Загальна Пропозиція_, що перебуває в стейкінгу. +Темп повернення (також відомий як _відсоток_), який отримується за SOL, +поставлені на стейкінг у мережі. Зазвичай він зазначається як річний темп +(наприклад, "дохідність стейкінгу в мережі наразі становить 10% на рік"). + +- _Дохідність стейкінгу_ дуже цікавить валідаторів і власників токенів, які + бажають делегувати свої токени, щоб уникнути розмивання токенів через інфляцію + (масштаб якої обговорено нижче). +- 100% інфляційних випусків розподіляються між власниками стейкінгованих токенів + пропорційно до їхнього стейкінгованого SOL, а також валідаторами, які стягують + комісію з винагороди, отриманої за делегований SOL. + - Може бути враховано майбутнє розділення інфляційних випусків із введенням + _Архіваторів_ у економіку. _Архіватори_ — це учасники мережі, які надають + децентралізовані послуги зберігання, і їх також слід стимулювати розподілом + токенів з інфляційних випусків за цю послугу. +- _Дохідність Стейкінгу_ можна розрахувати за _Графіком Інфляції_ разом із + часткою _Поточна Загальна Пропозиція_, що перебуває в стейкінгу. ### Дилюція Токенів [%] -Розмивання визначається тут як зміна пропорційного представлення набору токенів у більшому наборі через введення нових токенів. У практичному сенсі ми обговорюємо розмивання стейкінгованих або нестейкінгованих токенів через введення та розподіл інфляційних випусків по мережі. +Розмивання визначається тут як зміна пропорційного представлення набору токенів +у більшому наборі через введення нових токенів. У практичному сенсі ми +обговорюємо розмивання стейкінгованих або нестейкінгованих токенів через +введення та розподіл інфляційних випусків по мережі. ### Скоригована Дохідність Стейкінгу [%] -Повна оцінка потенціалу заробітку від стейкінгу токенів повинна враховувати стейкінговану _Дилюцію Токенів_ та її вплив на _Дохідність Стейкінгу_. Для цього ми визначаємо _Скориговану Дохідність Стейкінгу_ як зміну фракційної власності токенів у стейкінгу через розподіл інфляційних випусків. +Повна оцінка потенціалу заробітку від стейкінгу токенів повинна враховувати +стейкінговану _Дилюцію Токенів_ та її вплив на _Дохідність Стейкінгу_. Для цього +ми визначаємо _Скориговану Дохідність Стейкінгу_ як зміну фракційної власності +токенів у стейкінгу через розподіл інфляційних випусків. diff --git a/docs/locales/uk/economics/staking/index.md b/docs/locales/uk/economics/staking/index.md index 09160d228..7f9a56564 100644 --- a/docs/locales/uk/economics/staking/index.md +++ b/docs/locales/uk/economics/staking/index.md @@ -3,86 +3,97 @@ sidebarLabel: Стейкінг title: Стейкінг у Solana --- -_Примітка перед читанням: Усі згадки про збільшення значень стосуються абсолютних -показників балансу SOL. Цей документ не містить жодних припущень щодо +_Примітка перед читанням: Усі згадки про збільшення значень стосуються +абсолютних показників балансу SOL. Цей документ не містить жодних припущень щодо грошової вартості SOL у будь-який час._ Стейкуючи ваші токени SOL, ви допомагаєте забезпечувати безпеку мережі та [отримувати винагороди](https://docs.anza.xyz/implemented-proposals/staking-rewards) у процесі цього. -Ви можете здійснювати стейкінг, делегуючи ваші токени валідаторам, які обробляють транзакції -та забезпечують роботу мережі. - -Делегування стейкінгу — це фінансова модель з розподіленим ризиком і винагородою, яка може -забезпечити дохід для власників токенів, делегованих на тривалий період. Це досягається -шляхом узгодження фінансових інтересів власників токенів (делегаторів) та валідаторів, -яким вони делегують токени. - -Чим більше стейку делеговано валідатору, тим частіше цей валідатор обирається для запису -нових транзакцій до реєстру. Чим більше транзакцій записує валідатор, тим більше винагород -отримують валідатор і його делегатори. Валідатори, які налаштовують свої системи для обробки -більшої кількості транзакцій, заробляють пропорційно більше винагород і допомагають -підтримувати мережу якомога швидшою та стабільнішою. - -Валідатори несуть витрати на обслуговування та підтримку своїх систем, і ці витрати передаються -делегаторам у формі комісії, яка стягується як відсоток від зароблених винагород. Ця комісія -називається _комісією валідатора_. Оскільки валідатори отримують більше винагород за більше -делегованого стейку, вони можуть конкурувати між собою, пропонуючи найнижчу комісію за свої послуги. - -Хоча це не реалізовано в протоколі Solana сьогодні, у майбутньому делегатори можуть ризикувати -втратити токени через процес, відомий як _слешинг_. Слешинг передбачає вилучення та знищення частини -SOL валідатора у відповідь на навмисну зловмисну поведінку, наприклад, створення недійсних транзакцій -або цензурування певних типів транзакцій чи учасників мережі. - -На даний момент у протоколі Solana немає реалізації слешингу. Для отримання додаткової інформації -про слешинг перегляньте +Ви можете здійснювати стейкінг, делегуючи ваші токени валідаторам, які +обробляють транзакції та забезпечують роботу мережі. + +Делегування стейкінгу — це фінансова модель з розподіленим ризиком і +винагородою, яка може забезпечити дохід для власників токенів, делегованих на +тривалий період. Це досягається шляхом узгодження фінансових інтересів власників +токенів (делегаторів) та валідаторів, яким вони делегують токени. + +Чим більше стейку делеговано валідатору, тим частіше цей валідатор обирається +для запису нових транзакцій до реєстру. Чим більше транзакцій записує валідатор, +тим більше винагород отримують валідатор і його делегатори. Валідатори, які +налаштовують свої системи для обробки більшої кількості транзакцій, заробляють +пропорційно більше винагород і допомагають підтримувати мережу якомога швидшою +та стабільнішою. + +Валідатори несуть витрати на обслуговування та підтримку своїх систем, і ці +витрати передаються делегаторам у формі комісії, яка стягується як відсоток від +зароблених винагород. Ця комісія називається _комісією валідатора_. Оскільки +валідатори отримують більше винагород за більше делегованого стейку, вони можуть +конкурувати між собою, пропонуючи найнижчу комісію за свої послуги. + +Хоча це не реалізовано в протоколі Solana сьогодні, у майбутньому делегатори +можуть ризикувати втратити токени через процес, відомий як _слешинг_. Слешинг +передбачає вилучення та знищення частини SOL валідатора у відповідь на навмисну +зловмисну поведінку, наприклад, створення недійсних транзакцій або цензурування +певних типів транзакцій чи учасників мережі. + +На даний момент у протоколі Solana немає реалізації слешингу. Для отримання +додаткової інформації про слешинг перегляньте [дорожню карту слешингу](https://docs.anza.xyz/proposals/optimistic-confirmation-and-slashing#slashing-roadmap). ## Як здійснити стейкінг моїх токенів SOL? -Ви можете здійснити стейкінг SOL, перемістивши свої токени в гаманець, який підтримує стейкінг. Гаманець -надасть інструкції для створення облікового запису стейкінгу та делегування. +Ви можете здійснити стейкінг SOL, перемістивши свої токени в гаманець, який +підтримує стейкінг. Гаманець надасть інструкції для створення облікового запису +стейкінгу та делегування. #### Підтримувані Гаманці -Багато веб- та мобільних гаманців підтримують операції стейкінгу Solana. Будь ласка, перевірте -статус підтримки у розробників вашого улюбленого гаманця. +Багато веб- та мобільних гаманців підтримують операції стейкінгу Solana. Будь +ласка, перевірте статус підтримки у розробників вашого улюбленого гаманця. #### Інструменти командного рядка Solana -- Інструменти командного рядка Solana дозволяють виконувати всі операції стейкінгу в поєднанні з - гаманцем у вигляді файлу ключів, паперовим гаманцем або підключеним Ledger Nano. +- Інструменти командного рядка Solana дозволяють виконувати всі операції + стейкінгу в поєднанні з гаманцем у вигляді файлу ключів, паперовим гаманцем + або підключеним Ledger Nano. [Команди для стейкінгу за допомогою інструментів командного рядка Solana](https://docs.anza.xyz/cli/examples/delegate-stake). #### Створення Облікового Запису Стейкінгу -Виконуйте інструкції гаманця для створення облікового запису стейкінгу. Цей обліковий запис -відрізняється від облікових записів, які використовуються для відправлення та отримання токенів. +Виконуйте інструкції гаманця для створення облікового запису стейкінгу. Цей +обліковий запис відрізняється від облікових записів, які використовуються для +відправлення та отримання токенів. #### Вибір Валідатора -Дотримуйтесь інструкцій гаманця для вибору валідатора. Ви можете отримати інформацію про потенційно -ефективних валідаторів за посиланнями нижче. Фонд Solana не рекомендує конкретних валідаторів. +Дотримуйтесь інструкцій гаманця для вибору валідатора. Ви можете отримати +інформацію про потенційно ефективних валідаторів за посиланнями нижче. Фонд +Solana не рекомендує конкретних валідаторів. -Сайт solanabeach.io створений і підтримується одним з наших валідаторів, -Staking Facilities. Він надає графічну інформацію про мережу в цілому, а також -список кожного валідатора з деякими останніми статистиками їхньої продуктивності. +Сайт solanabeach.io створений і підтримується одним з наших валідаторів, Staking +Facilities. Він надає графічну інформацію про мережу в цілому, а також список +кожного валідатора з деякими останніми статистиками їхньої продуктивності. - https://solanabeach.io -Для перегляду статистики виробництва блоків використовуйте інструменти командного рядка Solana: +Для перегляду статистики виробництва блоків використовуйте інструменти +командного рядка Solana: - `solana validators` - `solana block-production` -Команда Solana не надає рекомендацій щодо інтерпретації цієї інформації. Виконуйте власне дослідження. +Команда Solana не надає рекомендацій щодо інтерпретації цієї інформації. +Виконуйте власне дослідження. #### Делегування Стейку -Виконуйте інструкції гаманця для делегування вашого стейку обраному вами валідатору. +Виконуйте інструкції гаманця для делегування вашого стейку обраному вами +валідатору. ## Деталі Облікового Запису Стейкінгу -Для отримання додаткової інформації про операції та дозволи, пов’язані з обліковим записом стейкінгу, -дивіться [Облікові Записи Стейкінгу](/docs/uk/economics/staking/stake-accounts.md) +Для отримання додаткової інформації про операції та дозволи, пов’язані з +обліковим записом стейкінгу, дивіться +[Облікові Записи Стейкінгу](/docs/uk/economics/staking/stake-accounts.md) diff --git a/docs/locales/uk/economics/staking/stake-accounts.md b/docs/locales/uk/economics/staking/stake-accounts.md index 9eb222c24..683a6d5a2 100644 --- a/docs/locales/uk/economics/staking/stake-accounts.md +++ b/docs/locales/uk/economics/staking/stake-accounts.md @@ -3,23 +3,46 @@ sidebarLabel: Облікові Записи Стейкінгу title: Облікові Записи Стейкінгу --- -Обліковий запис стейкінгу на Solana може використовуватися для делегування токенів валідаторам у мережі з можливістю отримання винагород для власника облікового запису стейкінгу. Облікові записи стейкінгу створюються та керуються інакше, ніж традиційні адреси гаманців, відомі як _системні облікові записи_. Системний обліковий запис здатний лише надсилати та отримувати SOL від інших облікових записів у мережі, тоді як обліковий запис стейкінгу підтримує складніші операції, необхідні для управління делегуванням токенів. - -Облікові записи стейкінгу на Solana також працюють інакше, ніж у інших блокчейн-мережах Proof-of-Stake, з якими ви могли бути знайомі. У цьому документі описується загальна структура та функції облікового запису стейкінгу Solana. +Обліковий запис стейкінгу на Solana може використовуватися для делегування +токенів валідаторам у мережі з можливістю отримання винагород для власника +облікового запису стейкінгу. Облікові записи стейкінгу створюються та керуються +інакше, ніж традиційні адреси гаманців, відомі як _системні облікові записи_. +Системний обліковий запис здатний лише надсилати та отримувати SOL від інших +облікових записів у мережі, тоді як обліковий запис стейкінгу підтримує +складніші операції, необхідні для управління делегуванням токенів. + +Облікові записи стейкінгу на Solana також працюють інакше, ніж у інших +блокчейн-мережах Proof-of-Stake, з якими ви могли бути знайомі. У цьому +документі описується загальна структура та функції облікового запису стейкінгу +Solana. #### Адреса Облікового Запису -Кожен обліковий запис стейкінгу має унікальну адресу, яка може використовуватися для перегляду інформації про обліковий запис через командний рядок або будь-які інструменти дослідження мережі. Однак, на відміну від адреси гаманця, власник ключової пари адреси не обов'язково має контроль над обліковим записом. Насправді, для адреси облікового запису стейкінгу може навіть не існувати ключова пара чи приватний ключ. +Кожен обліковий запис стейкінгу має унікальну адресу, яка може використовуватися +для перегляду інформації про обліковий запис через командний рядок або будь-які +інструменти дослідження мережі. Однак, на відміну від адреси гаманця, власник +ключової пари адреси не обов'язково має контроль над обліковим записом. +Насправді, для адреси облікового запису стейкінгу може навіть не існувати +ключова пара чи приватний ключ. -Ключова пара створюється лише під час [створення облікового запису стейкінгу за допомогою інструментів командного рядка](https://docs.anza.xyz/cli/examples/delegate-stake#create-a-stake-account). Нова ключова пара створюється виключно для забезпечення унікальності адреси облікового запису стейкінгу. +Ключова пара створюється лише під час +[створення облікового запису стейкінгу за допомогою інструментів командного рядка](https://docs.anza.xyz/cli/examples/delegate-stake#create-a-stake-account). +Нова ключова пара створюється виключно для забезпечення унікальності адреси +облікового запису стейкінгу. #### Розуміння Авторитетів Облікового Запису -Деякі типи облікових записів можуть мати один або більше _авторитетів підпису_, пов’язаних з обліковим записом. Авторитет облікового запису використовується для підпису певних транзакцій для облікового запису, яким він керує. Це відрізняється від інших блокчейнів, де власник ключової пари контролює всі дії облікового запису. +Деякі типи облікових записів можуть мати один або більше _авторитетів підпису_, +пов’язаних з обліковим записом. Авторитет облікового запису використовується для +підпису певних транзакцій для облікового запису, яким він керує. Це +відрізняється від інших блокчейнів, де власник ключової пари контролює всі дії +облікового запису. -Кожен обліковий запис стейкінгу має два авторитети підпису, які вказані їхніми відповідними адресами: +Кожен обліковий запис стейкінгу має два авторитети підпису, які вказані їхніми +відповідними адресами: - _Авторитет стейкінгу_ використовується для підпису транзакцій, пов’язаних із: + - Делегуванням стейку - Деактивацією делегування стейку - Розділенням облікового запису на два окремі @@ -33,24 +56,32 @@ title: Облікові Записи Стейкінгу #### Множинне Делегування -Один обліковий запис стейкінгу може бути делегований лише одному валідатору. Усі токени в обліковому записі є або делегованими, або неделегованими. Щоб делегувати частину токенів кільком валідаторам, потрібно створити кілька облікових записів стейкінгу. +Один обліковий запис стейкінгу може бути делегований лише одному валідатору. Усі +токени в обліковому записі є або делегованими, або неделегованими. Щоб +делегувати частину токенів кільком валідаторам, потрібно створити кілька +облікових записів стейкінгу. #### Об'єднання Облікових Записів -Два облікові записи стейкінгу з однаковими авторитетами та параметрами блокування можуть бути об’єднані в один. +Два облікові записи стейкінгу з однаковими авторитетами та параметрами +блокування можуть бути об’єднані в один. #### Розігрів та Охолодження Делегування -Процес делегування або деактивації делегування не є миттєвим і може займати кілька [епох](/docs/terminology.md#epoch). +Процес делегування або деактивації делегування не є миттєвим і може займати +кілька [епох](/docs/terminology.md#epoch). #### Блокування -Облікові записи стейкінгу можуть мати блокування, яке забороняє виведення токенів до досягнення певної дати або епохи. +Облікові записи стейкінгу можуть мати блокування, яке забороняє виведення +токенів до досягнення певної дати або епохи. #### Видалення Облікового Запису -Обліковий запис стейкінгу, баланс якого дорівнює 0 SOL, автоматично припиняє існувати. +Обліковий запис стейкінгу, баланс якого дорівнює 0 SOL, автоматично припиняє +існувати. #### Перегляд Облікових Записів Стейкінгу -Інформацію про обліковий запис стейкінгу можна переглянути через [Solana Explorer](http://explorer.solana.com/accounts). +Інформацію про обліковий запис стейкінгу можна переглянути через +[Solana Explorer](http://explorer.solana.com/accounts). diff --git a/docs/locales/uk/economics/staking/stake-programming.md b/docs/locales/uk/economics/staking/stake-programming.md index f914000a2..ce5511476 100644 --- a/docs/locales/uk/economics/staking/stake-programming.md +++ b/docs/locales/uk/economics/staking/stake-programming.md @@ -2,14 +2,30 @@ title: Програмування Стейкінгу --- -Для максимізації розподілу стейку, децентралізації та стійкості до цензури в мережі Solana, стейкінг може виконуватись програмно. Команда та спільнота розробили кілька програм для роботи як на ланцюгу, так і поза ним, щоб зробити управління стейками простішим. +Для максимізації розподілу стейку, децентралізації та стійкості до цензури в +мережі Solana, стейкінг може виконуватись програмно. Команда та спільнота +розробили кілька програм для роботи як на ланцюгу, так і поза ним, щоб зробити +управління стейками простішим. #### Stake-o-matic, також відомий як боти автоделегування -Ця позаланцюгова програма управляє великою кількістю валідаторів, яким делегує стейк центральний орган. Фонд Solana використовує бота автоделегування для регулярного делегування свого стейку "неспійманим" валідаторам, які відповідають визначеним вимогам продуктивності. +Ця позаланцюгова програма управляє великою кількістю валідаторів, яким делегує +стейк центральний орган. Фонд Solana використовує бота автоделегування для +регулярного делегування свого стейку "неспійманим" валідаторам, які відповідають +визначеним вимогам продуктивності. #### Stake Pools -Ця програма на ланцюгу об'єднує SOL для стейкінгу, яким управляє менеджер, дозволяючи власникам SOL здійснювати стейкінг та отримувати винагороди без необхідності управляти стейками. Користувачі депонують SOL в обмін на SPL-токени (похідні стейкінгу), які представляють їхню частку в пулі стейкінгу. Менеджер пулу здійснює стейкінг внесених SOL відповідно до своєї стратегії, можливо, використовуючи варіант бота автоделегування, описаного вище. Коли стейки отримують винагороди, вартість пулу та токенів пулу пропорційно зростає. Нарешті, власники токенів пулу можуть повернути SPL-токени назад у пул стейкінгу для викупу SOL, тим самим беручи участь у децентралізації з мінімальними зусиллями. +Ця програма на ланцюгу об'єднує SOL для стейкінгу, яким управляє менеджер, +дозволяючи власникам SOL здійснювати стейкінг та отримувати винагороди без +необхідності управляти стейками. Користувачі депонують SOL в обмін на SPL-токени +(похідні стейкінгу), які представляють їхню частку в пулі стейкінгу. Менеджер +пулу здійснює стейкінг внесених SOL відповідно до своєї стратегії, можливо, +використовуючи варіант бота автоделегування, описаного вище. Коли стейки +отримують винагороди, вартість пулу та токенів пулу пропорційно зростає. +Нарешті, власники токенів пулу можуть повернути SPL-токени назад у пул стейкінгу +для викупу SOL, тим самим беручи участь у децентралізації з мінімальними +зусиллями. -Детальнішу інформацію можна знайти в [документації SPL Stake Pool](https://spl.solana.com/stake-pool). +Детальнішу інформацію можна знайти в +[документації SPL Stake Pool](https://spl.solana.com/stake-pool). diff --git a/docs/locales/uk/index.md b/docs/locales/uk/index.md index 10ac0c1ec..94f35a425 100644 --- a/docs/locales/uk/index.md +++ b/docs/locales/uk/index.md @@ -4,8 +4,8 @@ title: Документація Solana seoTitle: Дізнайтеся, як працює блокчейн Solana description: "Solana — це високопродуктивний блокчейн, створений для масового впровадження. - Дізнайтеся, чому Solana є найкращим вибором для розробників, які прагнуть створювати - масштабовані блокчейн-додатки." + Дізнайтеся, чому Solana є найкращим вибором для розробників, які прагнуть + створювати масштабовані блокчейн-додатки." altRoutes: - /docs/intro/history - /docs/intro @@ -13,61 +13,93 @@ altRoutes: isHiddenInNavSidebar: true --- -Solana — це блокчейн, створений для масового використання. Це високопродуктивна мережа, яка використовується для різних сфер, включаючи фінанси, NFT, платежі та ігри. Solana працює як єдина глобальна станова машина, є відкритою, інтероперабельною та децентралізованою. +Solana — це блокчейн, створений для масового використання. Це високопродуктивна +мережа, яка використовується для різних сфер, включаючи фінанси, NFT, платежі та +ігри. Solana працює як єдина глобальна станова машина, є відкритою, +інтероперабельною та децентралізованою. ## Початок роботи -Пориньте у світ Solana, щоб почати створювати або налаштовувати своє локальне середовище. +Пориньте у світ Solana, щоб почати створювати або налаштовувати своє локальне +середовище. -- [Швидкий старт](/docs/intro/quick-start) — Створіть і розгорніть свою першу програму на Solana прямо у браузері за допомогою Solana Playground -- [Налаштування локального середовища](/docs/intro/installation) — Встановіть CLI Solana для налаштування локального середовища розробки +- [Швидкий старт](/docs/intro/quick-start) — Створіть і розгорніть свою першу + програму на Solana прямо у браузері за допомогою Solana Playground +- [Налаштування локального середовища](/docs/intro/installation) — Встановіть + CLI Solana для налаштування локального середовища розробки ## Почніть навчання -Поглиблено вивчіть основні концепції, які роблять Solana унікальною серед інших блокчейнів. +Поглиблено вивчіть основні концепції, які роблять Solana унікальною серед інших +блокчейнів. - [Акаунти](/docs/core/accounts) — Механізм зберігання даних і стану для Solana -- [Комісії в Solana](/docs/core/fees) — Різні витрати, пов’язані з використанням мережі -- [Транзакції](/docs/core/transactions) — Набір інструкцій для виконання блокчейном -- [Програми](/docs/core/programs) — Виконуваний код для виконання дій у блокчейні -- [Програмно похідні адреси](/docs/core/pda) — Детерміновано створені адреси, які дозволяють програмам Solana програмно "підписувати" транзакції -- [Виклики між програмами](/docs/core/cpi) — Основний механізм "композованості" Solana, який дозволяє програмам "викликати" одна одну +- [Комісії в Solana](/docs/core/fees) — Різні витрати, пов’язані з використанням + мережі +- [Транзакції](/docs/core/transactions) — Набір інструкцій для виконання + блокчейном +- [Програми](/docs/core/programs) — Виконуваний код для виконання дій у + блокчейні +- [Програмно похідні адреси](/docs/core/pda) — Детерміновано створені адреси, + які дозволяють програмам Solana програмно "підписувати" транзакції +- [Виклики між програмами](/docs/core/cpi) — Основний механізм "композованості" + Solana, який дозволяє програмам "викликати" одна одну ## Розуміння архітектури Дізнайтеся, як працює блокчейн Proof-of-Stake у основі Solana. -- [Валідатори](https://docs.anza.xyz/validator/anatomy) — окремі вузли, які є основою мережі -- [Кластери](/docs/core/clusters) — група валідаторів, що працюють разом для досягнення консенсусу +- [Валідатори](https://docs.anza.xyz/validator/anatomy) — окремі вузли, які є + основою мережі +- [Кластери](/docs/core/clusters) — група валідаторів, що працюють разом для + досягнення консенсусу ## Запуск валідатора -Дізнайтеся, що потрібно для роботи валідатора Solana та забезпечення безпеки мережі. +Дізнайтеся, що потрібно для роботи валідатора Solana та забезпечення безпеки +мережі. -- [Системні вимоги](https://docs.anza.xyz/operations/requirements) — Рекомендовані апаратні вимоги та очікувана кількість SOL, необхідна для запуску валідатора -- [Швидкий старт](https://docs.anza.xyz/operations/setup-a-validator) — Налаштуйте валідатор і підключіться до кластера вперше +- [Системні вимоги](https://docs.anza.xyz/operations/requirements) — + Рекомендовані апаратні вимоги та очікувана кількість SOL, необхідна для + запуску валідатора +- [Швидкий старт](https://docs.anza.xyz/operations/setup-a-validator) — + Налаштуйте валідатор і підключіться до кластера вперше ## Чому Solana? -Створена для масштабування, Solana призначена для того, щоб блокчейн-додатки могли досягати мільйонів користувачів. Замість оптимізації під блокчейн-рівень розробники можуть зосередитися на створенні додатків, які досягнуть відповідності ринку. Мережа не тільки може масштабуватися для поточних потреб блокчейн-додатків, але й постійно оптимізується з урахуванням досвіду користувачів. +Створена для масштабування, Solana призначена для того, щоб блокчейн-додатки +могли досягати мільйонів користувачів. Замість оптимізації під блокчейн-рівень +розробники можуть зосередитися на створенні додатків, які досягнуть +відповідності ринку. Мережа не тільки може масштабуватися для поточних потреб +блокчейн-додатків, але й постійно оптимізується з урахуванням досвіду +користувачів. -Створення найкращого користувацького досвіду є головним пріоритетом для розробників. У блокчейнах користувацький досвід часто обмежений базовими технологіями, що спричиняє повільний час відгуку та високі комісії. Низькі комісії Solana та час підтвердження в 400 мс дозволяють розробникам створювати зручні для користувачів додатки, доступні кожному. +Створення найкращого користувацького досвіду є головним пріоритетом для +розробників. У блокчейнах користувацький досвід часто обмежений базовими +технологіями, що спричиняє повільний час відгуку та високі комісії. Низькі +комісії Solana та час підтвердження в 400 мс дозволяють розробникам створювати +зручні для користувачів додатки, доступні кожному. ## Особливості Solana -| Функція | Опис | -| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Розробка програм на блокчейні | Можливість розробляти та розгортати програми на блокчейні. Користувачі можуть взаємодіяти з цими програмами без дозволу, усуваючи потребу у посередниках для створення додатків. | -| 400 мс для блоків | Кожна транзакція користувачів у Solana підтверджується в блоці. З цільовим часом 400 мс для кожного блоку, взаємодія користувачів є швидкою, забезпечуючи найкращий у своєму класі досвід. | -| Низькі комісії | Комісії в Solana відомі своєю низькістю. Середня комісія становить 0.00064 SOL за транзакцію, що дозволяє створювати додатки для користувачів з усього світу, незалежно від їх походження. | -| Висока пропускна здатність | Масштабування до тисяч транзакцій за секунду, Solana створена для масштабування відповідно до потреб користувачів вашого додатку. | +| Функція | Опис | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Розробка програм на блокчейні | Можливість розробляти та розгортати програми на блокчейні. Користувачі можуть взаємодіяти з цими програмами без дозволу, усуваючи потребу у посередниках для створення додатків. | +| 400 мс для блоків | Кожна транзакція користувачів у Solana підтверджується в блоці. З цільовим часом 400 мс для кожного блоку, взаємодія користувачів є швидкою, забезпечуючи найкращий у своєму класі досвід. | +| Низькі комісії | Комісії в Solana відомі своєю низькістю. Середня комісія становить 0.00064 SOL за транзакцію, що дозволяє створювати додатки для користувачів з усього світу, незалежно від їх походження. | +| Висока пропускна здатність | Масштабування до тисяч транзакцій за секунду, Solana створена для масштабування відповідно до потреб користувачів вашого додатку. | ## Як користуватися цими документами -Зліва ви знайдете бічну панель документації. Вона містить документацію у порядку від базової до більш просунутої інформації. Якщо ви новачок у Solana, рекомендуємо почати з самого верху і рухатися вниз. Однак ви можете читати їх у будь-якому порядку, який вам подобається. +Зліва ви знайдете бічну панель документації. Вона містить документацію у порядку +від базової до більш просунутої інформації. Якщо ви новачок у Solana, +рекомендуємо почати з самого верху і рухатися вниз. Однак ви можете читати їх у +будь-якому порядку, який вам подобається. -Коли будете готові почати створення, ознайомтеся з посібником [Швидкий старт](/docs/intro/quick-start). +Коли будете готові почати створення, ознайомтеся з посібником +[Швидкий старт](/docs/intro/quick-start). ## Потрібна допомога? -Отримайте допомогу від спільноти Solana на [Solana StackExchange](https://solana.stackexchange.com). +Отримайте допомогу від спільноти Solana на +[Solana StackExchange](https://solana.stackexchange.com). diff --git a/docs/locales/uk/intro/dev.md b/docs/locales/uk/intro/dev.md index ac56bb2d1..725c8aeb0 100644 --- a/docs/locales/uk/intro/dev.md +++ b/docs/locales/uk/intro/dev.md @@ -13,32 +13,61 @@ keywords: Ласкаво просимо до документації для розробників Solana! -На цій сторінці зібрано все, що вам потрібно знати для початку розробки на Solana, включаючи основні вимоги, принципи роботи та інструменти, необхідні для старту. +На цій сторінці зібрано все, що вам потрібно знати для початку розробки на +Solana, включаючи основні вимоги, принципи роботи та інструменти, необхідні для +старту. ## Огляд Розробки на Високому Рівні Розробку на Solana можна розділити на дві основні частини: -1. **Розробка Програм на Блокчейні**: Тут ви створюєте та розгортаєте користувацькі програми безпосередньо у блокчейні. Після розгортання будь-хто, хто знає, як із ними працювати, може їх використовувати. Ці програми можна писати на Rust, C або C++. Rust наразі має найбільшу підтримку для розробки програм на блокчейні. -2. **Клієнтська Розробка**: Це створення програмного забезпечення (децентралізованих додатків або dApps), яке взаємодіє з програмами на блокчейні. Ваші додатки можуть надсилати транзакції для виконання дій у блокчейні. Клієнтську розробку можна виконувати на будь-якій мові програмування. - -"Зв'язок" між клієнтською та блокчейн-частиною забезпечується [Solana JSON RPC API](https://solana.com/docs/rpc). Клієнтська частина надсилає запити RPC до мережі Solana для взаємодії з програмами на блокчейні. Це дуже схоже на звичайний процес розробки між frontend і backend. Головна відмінність у роботі з Solana — це те, що backend є глобальним блокчейном без дозволів. Це означає, що будь-хто може взаємодіяти з вашою програмою на блокчейні без необхідності видачі API-ключів або будь-яких інших форм дозволів. +1. **Розробка Програм на Блокчейні**: Тут ви створюєте та розгортаєте + користувацькі програми безпосередньо у блокчейні. Після розгортання будь-хто, + хто знає, як із ними працювати, може їх використовувати. Ці програми можна + писати на Rust, C або C++. Rust наразі має найбільшу підтримку для розробки + програм на блокчейні. +2. **Клієнтська Розробка**: Це створення програмного забезпечення + (децентралізованих додатків або dApps), яке взаємодіє з програмами на + блокчейні. Ваші додатки можуть надсилати транзакції для виконання дій у + блокчейні. Клієнтську розробку можна виконувати на будь-якій мові + програмування. + +"Зв'язок" між клієнтською та блокчейн-частиною забезпечується +[Solana JSON RPC API](https://solana.com/docs/rpc). Клієнтська частина надсилає +запити RPC до мережі Solana для взаємодії з програмами на блокчейні. Це дуже +схоже на звичайний процес розробки між frontend і backend. Головна відмінність у +роботі з Solana — це те, що backend є глобальним блокчейном без дозволів. Це +означає, що будь-хто може взаємодіяти з вашою програмою на блокчейні без +необхідності видачі API-ключів або будь-яких інших форм дозволів. ![Як клієнти працюють із блокчейном Solana](/assets/docs/intro/developer_flow.png) -Розробка на Solana відрізняється від інших блокчейнів завдяки своїм високо-композитним програмам на блокчейні. Це означає, що ви можете будувати на базі вже існуючих програм, часто без необхідності створення власних. Наприклад, якщо ви хочете працювати з токенами, ви можете використовувати [Token Program](/docs/uk/core/tokens.md), який вже розгорнутий у мережі. Уся розробка вашого додатка буде клієнтською, на обраній вами мові програмування. +Розробка на Solana відрізняється від інших блокчейнів завдяки своїм +високо-композитним програмам на блокчейні. Це означає, що ви можете будувати на +базі вже існуючих програм, часто без необхідності створення власних. Наприклад, +якщо ви хочете працювати з токенами, ви можете використовувати +[Token Program](/docs/uk/core/tokens.md), який вже розгорнутий у мережі. Уся +розробка вашого додатка буде клієнтською, на обраній вами мові програмування. -Розробники, які хочуть будувати на Solana, знайдуть, що стек розробки дуже схожий на інші. Основна відмінність у тому, що ви працюєте з блокчейном і повинні враховувати, як користувачі взаємодіють із вашим додатком на блокчейні, а не тільки у frontend. Розробка на Solana все ще включає CI/CD, тестування, інструменти для налагодження, frontend і backend, як і будь-який звичайний процес розробки. +Розробники, які хочуть будувати на Solana, знайдуть, що стек розробки дуже +схожий на інші. Основна відмінність у тому, що ви працюєте з блокчейном і +повинні враховувати, як користувачі взаємодіють із вашим додатком на блокчейні, +а не тільки у frontend. Розробка на Solana все ще включає CI/CD, тестування, +інструменти для налагодження, frontend і backend, як і будь-який звичайний +процес розробки. ## Що Вам Потрібно для Початку -Для початку розробки на Solana вам знадобляться різні інструменти залежно від того, чи ви розробляєте клієнтські додатки, програми на блокчейні або обидва. +Для початку розробки на Solana вам знадобляться різні інструменти залежно від +того, чи ви розробляєте клієнтські додатки, програми на блокчейні або обидва. ### Клієнтська Розробка Якщо ви розробляєте програми на блокчейні, вам потрібно знати Rust. -Якщо ж ви розробляєте клієнтські додатки, ви можете працювати на будь-якій мові програмування, з якою вам зручно. Solana має SDK, створені спільнотою, щоб допомогти розробникам взаємодіяти з мережею Solana на більшості популярних мов: +Якщо ж ви розробляєте клієнтські додатки, ви можете працювати на будь-якій мові +програмування, з якою вам зручно. Solana має SDK, створені спільнотою, щоб +допомогти розробникам взаємодіяти з мережею Solana на більшості популярних мов: | Мова | SDK | | ---------- | -------------------------------------------------------------------------------------------------------- | @@ -53,71 +82,116 @@ keywords: | C# | [solnet](https://github.com/bmresearch/Solnet) | | GdScript | [godot](https://github.com/Virus-Axel/godot-solana-sdk/) | -Вам також знадобиться підключення до RPC для взаємодії з мережею. Ви можете скористатися [провайдером RPC](https://solana.com/rpc) або [запустити власний RPC-вузол](https://docs.anza.xyz/operations/setup-an-rpc-node). +Вам також знадобиться підключення до RPC для взаємодії з мережею. Ви можете +скористатися [провайдером RPC](https://solana.com/rpc) або +[запустити власний RPC-вузол](https://docs.anza.xyz/operations/setup-an-rpc-node). -Щоб швидко розпочати роботу з фронтендом для вашого додатка, ви можете згенерувати налаштовуваний каркас Solana, ввівши наступну команду у ваш CLI: +Щоб швидко розпочати роботу з фронтендом для вашого додатка, ви можете +згенерувати налаштовуваний каркас Solana, ввівши наступну команду у ваш CLI: ```bash npx create-solana-dapp ``` -Ця команда створить новий проєкт із усіма необхідними файлами та базовою конфігурацією для початку розробки на Solana. Каркас включатиме як приклад фронтенда, так і шаблон програми на блокчейні (якщо ви його обрали). Ви можете ознайомитися з [документацією `create-solana-dapp`](https://github.com/solana-developers/create-solana-dapp?tab=readme-ov-file#create-solana-dapp), щоб дізнатися більше. +Ця команда створить новий проєкт із усіма необхідними файлами та базовою +конфігурацією для початку розробки на Solana. Каркас включатиме як приклад +фронтенда, так і шаблон програми на блокчейні (якщо ви його обрали). Ви можете +ознайомитися з +[документацією `create-solana-dapp`](https://github.com/solana-developers/create-solana-dapp?tab=readme-ov-file#create-solana-dapp), +щоб дізнатися більше. ### Розробка Програм на Блокчейні -Розробка програм на блокчейні включає написання програм на Rust, C або C++. Спочатку переконайтеся, що у вас встановлений Rust. Ви можете зробити це за допомогою наступної команди: +Розробка програм на блокчейні включає написання програм на Rust, C або C++. +Спочатку переконайтеся, що у вас встановлений Rust. Ви можете зробити це за +допомогою наступної команди: ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -Вам також потрібно встановити [Solana CLI](/docs/uk/intro/installation.md), щоб компілювати та розгортати ваші програми. Ви можете встановити Solana CLI, виконавши наступну команду: - +Вам також потрібно встановити [Solana CLI](/docs/uk/intro/installation.md), щоб +компілювати та розгортати ваші програми. Ви можете встановити Solana CLI, +виконавши наступну команду: ```bash sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)" ``` -Використовуючи Solana CLI, рекомендується запускати локальний валідатор для тестування вашої програми. Щоб запустити локальний валідатор після встановлення Solana CLI, виконайте наступну команду: - +Використовуючи Solana CLI, рекомендується запускати локальний валідатор для +тестування вашої програми. Щоб запустити локальний валідатор після встановлення +Solana CLI, виконайте наступну команду: ```bash solana-test-validator ``` -Це запустить локальний валідатор на вашій машині, який ви можете використовувати для тестування ваших програм. Ви можете [докладніше прочитати про локальну розробку в цьому посібнику](/docs/uk/intro/installation.md). - -Під час розробки програм на блокчейні ви можете вибрати між написанням програм на чистому Rust (без фреймворку) або використанням фреймворку Anchor. Anchor спрощує розробку на Solana, надаючи високорівневий API для розробників. Подумайте про Anchor як про використання React для створення вебсайтів замість чистого Javascript і HTML. Хоча Javascript і HTML дають вам більше контролю, React прискорює розробку та робить її простішою. Докладніше про [Anchor](https://www.anchor-lang.com/) можна дізнатися на їхньому сайті. - -Вам знадобиться спосіб тестування вашої програми. Ось кілька способів тестування залежно від ваших уподобань щодо мови програмування: - -- [solana-program-test](https://docs.rs/solana-program-test/latest/solana_program_test/) — фреймворк для тестування, написаний на Rust. -- [solana-bankrun](https://kevinheavey.github.io/solana-bankrun/) — фреймворк для тестування, написаний для тестів на Typescript. -- [bankrun](https://kevinheavey.github.io/solders/tutorials/bankrun.html) — фреймворк для тестування, написаний для тестів на Python. - -Якщо ви не хочете розробляти програми локально, існує також [онлайн IDE Solana Playground](https://beta.solpg.io). Solana Playground дозволяє писати, тестувати та розгортати програми на Solana. Ви можете розпочати роботу з Solana Playground, [слідувавши нашому посібнику швидкого старту](/docs/uk/intro/quick-start). +Це запустить локальний валідатор на вашій машині, який ви можете використовувати +для тестування ваших програм. Ви можете +[докладніше прочитати про локальну розробку в цьому посібнику](/docs/uk/intro/installation.md). + +Під час розробки програм на блокчейні ви можете вибрати між написанням програм +на чистому Rust (без фреймворку) або використанням фреймворку Anchor. Anchor +спрощує розробку на Solana, надаючи високорівневий API для розробників. +Подумайте про Anchor як про використання React для створення вебсайтів замість +чистого Javascript і HTML. Хоча Javascript і HTML дають вам більше контролю, +React прискорює розробку та робить її простішою. Докладніше про +[Anchor](https://www.anchor-lang.com/) можна дізнатися на їхньому сайті. + +Вам знадобиться спосіб тестування вашої програми. Ось кілька способів тестування +залежно від ваших уподобань щодо мови програмування: + +- [solana-program-test](https://docs.rs/solana-program-test/latest/solana_program_test/) + — фреймворк для тестування, написаний на Rust. +- [solana-bankrun](https://kevinheavey.github.io/solana-bankrun/) — фреймворк + для тестування, написаний для тестів на Typescript. +- [bankrun](https://kevinheavey.github.io/solders/tutorials/bankrun.html) — + фреймворк для тестування, написаний для тестів на Python. + +Якщо ви не хочете розробляти програми локально, існує також +[онлайн IDE Solana Playground](https://beta.solpg.io). Solana Playground +дозволяє писати, тестувати та розгортати програми на Solana. Ви можете розпочати +роботу з Solana Playground, +[слідувавши нашому посібнику швидкого старту](/docs/uk/intro/quick-start). ### Середовища Розробки -Вибір правильного середовища залежно від вашої роботи дуже важливий. У Solana є кілька середовищ (кластерів) для забезпечення якісного тестування та CI/CD практик: +Вибір правильного середовища залежно від вашої роботи дуже важливий. У Solana є +кілька середовищ (кластерів) для забезпечення якісного тестування та CI/CD +практик: -- **Mainnet Beta**: Продуктивна мережа, де відбувається вся дія. Транзакції тут коштують реальних грошей. -- **Devnet**: Мережа для забезпечення якості, де ви розгортаєте ваші програми для тестування перед розгортанням у продуктивне середовище. Це як "середовище для постановки". -- **Local**: Локальна мережа, яку ви запускаєте на своїй машині за допомогою `solana-test-validator` для тестування ваших програм. Це має бути вашим першим вибором під час розробки. +- **Mainnet Beta**: Продуктивна мережа, де відбувається вся дія. Транзакції тут + коштують реальних грошей. +- **Devnet**: Мережа для забезпечення якості, де ви розгортаєте ваші програми + для тестування перед розгортанням у продуктивне середовище. Це як "середовище + для постановки". +- **Local**: Локальна мережа, яку ви запускаєте на своїй машині за допомогою + `solana-test-validator` для тестування ваших програм. Це має бути вашим першим + вибором під час розробки. ## Побудова на Основі Прикладів -Під час початку розробки на Solana є кілька ресурсів, які допоможуть прискорити ваш шлях: +Під час початку розробки на Solana є кілька ресурсів, які допоможуть прискорити +ваш шлях: -- [Solana Cookbook](https://solana.com/developers/cookbook): Збірка довідників і фрагментів коду для допомоги у розробці на Solana. -- [Приклади Програм Solana](https://github.com/solana-developers/program-examples): Репозиторій прикладів програм, що надають будівельні блоки для різних дій у ваших програмах. -- [Посібники](https://solana.com/developers/guides): Посібники та інструкції, які проведуть вас через процес розробки на Solana. +- [Solana Cookbook](https://solana.com/developers/cookbook): Збірка довідників і + фрагментів коду для допомоги у розробці на Solana. +- [Приклади Програм Solana](https://github.com/solana-developers/program-examples): + Репозиторій прикладів програм, що надають будівельні блоки для різних дій у + ваших програмах. +- [Посібники](https://solana.com/developers/guides): Посібники та інструкції, + які проведуть вас через процес розробки на Solana. ## Отримання Підтримки -Найкращу підтримку ви можете знайти на [Solana StackExchange](https://solana.stackexchange.com/). Спочатку пошукайте своє питання там — є велика ймовірність, що вже існує схоже питання з відповіддю. Якщо його там немає, додайте нове питання! Не забудьте включити якомога більше деталей у ваше питання, і, будь ласка, використовуйте текст (а не скріншоти) для відображення повідомлень про помилки, щоб інші люди з такою ж проблемою могли знайти ваше питання! +Найкращу підтримку ви можете знайти на +[Solana StackExchange](https://solana.stackexchange.com/). Спочатку пошукайте +своє питання там — є велика ймовірність, що вже існує схоже питання з +відповіддю. Якщо його там немає, додайте нове питання! Не забудьте включити +якомога більше деталей у ваше питання, і, будь ласка, використовуйте текст (а не +скріншоти) для відображення повідомлень про помилки, щоб інші люди з такою ж +проблемою могли знайти ваше питання! ## Наступні кроки [Тепер ви готові почати створювати на Solana!](/docs/uk/intro/quick-start) - diff --git a/docs/locales/uk/intro/installation.md b/docs/locales/uk/intro/installation.md index fb7dce6fc..117c101dd 100644 --- a/docs/locales/uk/intro/installation.md +++ b/docs/locales/uk/intro/installation.md @@ -14,50 +14,64 @@ altRoutes: - /setup --- -Цей розділ охоплює етапи налаштування локального середовища для розробки на Solana. +Цей розділ охоплює етапи налаштування локального середовища для розробки на +Solana. ## Встановлення Залежностей -- Користувачі Windows повинні спочатку встановити WSL (Windows Subsystem for Linux), а потім встановити залежності, зазначені в розділі Linux нижче. -- Користувачі Linux повинні спочатку встановити залежності, зазначені в розділі Linux нижче. +- Користувачі Windows повинні спочатку встановити WSL (Windows Subsystem for + Linux), а потім встановити залежності, зазначені в розділі Linux нижче. +- Користувачі Linux повинні спочатку встановити залежності, зазначені в розділі + Linux нижче. - Користувачі Mac повинні почати з інструкцій з установки Rust нижче. Для розробки програм Solana на Windows **необхідно використовувати -[WSL](https://learn.microsoft.com/en-us/windows/wsl/install)** (Windows Subsystem for Linux). Усі додаткові залежності необхідно встановлювати через термінал Linux. +[WSL](https://learn.microsoft.com/en-us/windows/wsl/install)** (Windows +Subsystem for Linux). Усі додаткові залежності необхідно встановлювати через +термінал Linux. -Після встановлення WSL встановіть залежності, зазначені в розділі Linux нижче, перш ніж переходити до установки Rust, Solana CLI та Anchor CLI. +Після встановлення WSL встановіть залежності, зазначені в розділі Linux нижче, +перш ніж переходити до установки Rust, Solana CLI та Anchor CLI. Щоб встановити WSL, виконайте наступну команду у Windows PowerShell: - ```shell wsl --install ``` -Процес встановлення запропонує вам створити обліковий запис користувача за замовчуванням. +Процес встановлення запропонує вам створити обліковий запис користувача за +замовчуванням. ![WSL Install](/assets/docs/intro/installation/wsl-install.png) -За замовчуванням WSL встановлює Ubuntu. Ви можете відкрити термінал Linux, ввівши "Ubuntu" у пошуковому рядку. +За замовчуванням WSL встановлює Ubuntu. Ви можете відкрити термінал Linux, +ввівши "Ubuntu" у пошуковому рядку. ![WSL Ubuntu](/assets/docs/intro/installation/wsl-ubuntu-search.png) -Якщо ваш термінал Ubuntu виглядає так, як на зображенні нижче, ви можете зіткнутися з проблемою, коли комбінація `ctrl + v` (вставити) не працює у терміналі. +Якщо ваш термінал Ubuntu виглядає так, як на зображенні нижче, ви можете +зіткнутися з проблемою, коли комбінація `ctrl + v` (вставити) не працює у +терміналі. ![Ubuntu Terminal](/assets/docs/intro/installation/wsl-ubuntu-terminal-1.png) -Якщо виникла ця проблема, відкрийте Windows Terminal, ввівши "Terminal" у пошуковому рядку. +Якщо виникла ця проблема, відкрийте Windows Terminal, ввівши "Terminal" у +пошуковому рядку. ![Windows Terminal](/assets/docs/intro/installation/wsl-windows-terminal.png) -Далі закрийте Windows Terminal і знову відкрийте термінал Linux, ввівши "Ubuntu" у пошуку. Тепер термінал має виглядати так, як на зображенні нижче, і комбінація `ctrl + v` (вставити) має працювати. +Далі закрийте Windows Terminal і знову відкрийте термінал Linux, ввівши "Ubuntu" +у пошуку. Тепер термінал має виглядати так, як на зображенні нижче, і комбінація +`ctrl + v` (вставити) має працювати. ![Ubuntu Terminal](/assets/docs/intro/installation/wsl-ubuntu-terminal-2.png) -Якщо ви використовуєте VS Code, розширення [WSL extension](https://code.visualstudio.com/docs/remote/wsl-tutorial) дозволяє використовувати WSL та VS Code разом. +Якщо ви використовуєте VS Code, розширення +[WSL extension](https://code.visualstudio.com/docs/remote/wsl-tutorial) дозволяє +використовувати WSL та VS Code разом. ![WSL Setup in VS Code](/assets/docs/intro/installation/wsl-vscode.png) @@ -65,7 +79,9 @@ wsl --install ![WSL: Ubuntu](/assets/docs/intro/installation/wsl-vscode-ubuntu.png) -Після налаштування WSL всі додаткові залежності потрібно встановлювати через термінал Linux. Встановіть залежності, зазначені в розділі Linux нижче, перш ніж переходити до встановлення Rust, Solana CLI та Anchor CLI. +Після налаштування WSL всі додаткові залежності потрібно встановлювати через +термінал Linux. Встановіть залежності, зазначені в розділі Linux нижче, перш ніж +переходити до встановлення Rust, Solana CLI та Anchor CLI. @@ -77,8 +93,8 @@ wsl --install ```shell sudo apt-get update ``` -Далі встановіть наступні залежності: +Далі встановіть наступні залежності: ```shell sudo apt-get install -y \ @@ -87,7 +103,9 @@ sudo apt-get install -y \ libudev-dev llvm libclang-dev \ protobuf-compiler libssl-dev ``` -Якщо під час встановлення `protobuf-compiler` ви зіткнетеся з такою помилкою, спочатку переконайтеся, що виконали команду `sudo apt-get update`: + +Якщо під час встановлення `protobuf-compiler` ви зіткнетеся з такою помилкою, +спочатку переконайтеся, що виконали команду `sudo apt-get update`: ``` Package protobuf-compiler is not available, but is referred to by another package. @@ -102,9 +120,11 @@ is only available from another source ### Встановлення Rust -Програми Solana пишуться на [мові програмування Rust](https://www.rust-lang.org/). +Програми Solana пишуться на +[мові програмування Rust](https://www.rust-lang.org/). -Рекомендований метод встановлення Rust — це [rustup](https://www.rust-lang.org/tools/install). +Рекомендований метод встановлення Rust — це +[rustup](https://www.rust-lang.org/tools/install). Виконайте наступну команду для встановлення Rust: @@ -135,7 +155,8 @@ source "$HOME/.cargo/env.fish" # For fish -Виконайте наступну команду, щоб оновити змінну середовища PATH і включити директорію `bin` Cargo: +Виконайте наступну команду, щоб оновити змінну середовища PATH і включити +директорію `bin` Cargo: ```shell . "$HOME/.cargo/env" @@ -155,17 +176,22 @@ rustc 1.80.1 (3f5fd8dd4 2024-08-06) ### Встановлення Solana CLI -Solana CLI надає всі необхідні інструменти для створення та розгортання програм Solana. +Solana CLI надає всі необхідні інструменти для створення та розгортання програм +Solana. -Встановіть набір інструментів Solana CLI за допомогою офіційної команди встановлення: +Встановіть набір інструментів Solana CLI за допомогою офіційної команди +встановлення: ```shell sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)" ``` -Ви можете замінити `stable` на тег релізу, який відповідає версії програмного забезпечення потрібного релізу (наприклад, `v2.0.3`), або використовувати один із трьох символічних назв каналів: `stable`, `beta` або `edge`. +Ви можете замінити `stable` на тег релізу, який відповідає версії програмного +забезпечення потрібного релізу (наприклад, `v2.0.3`), або використовувати один +із трьох символічних назв каналів: `stable`, `beta` або `edge`. -Якщо ви встановлюєте Solana CLI вперше, ви можете побачити таке повідомлення із запитом на додавання змінної середовища PATH: +Якщо ви встановлюєте Solana CLI вперше, ви можете побачити таке повідомлення із +запитом на додавання змінної середовища PATH: ``` Close and reopen your terminal to apply the PATH changes or run the following in your existing shell: @@ -176,7 +202,9 @@ export PATH="/Users/test/.local/share/solana/install/active_release/bin:$PATH" -Якщо ви використовуєте термінал Linux або WSL, ви можете додати змінну середовища PATH у файл конфігурації вашої оболонки, виконавши команду, зазначену під час встановлення, або перезапустивши термінал. +Якщо ви використовуєте термінал Linux або WSL, ви можете додати змінну +середовища PATH у файл конфігурації вашої оболонки, виконавши команду, зазначену +під час встановлення, або перезапустивши термінал. ```shell export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" @@ -185,16 +213,19 @@ export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH" -Якщо ви використовуєте Mac із оболонкою `zsh`, виконання стандартної команди `export PATH`, зазначеної під час встановлення, не зберігається після закриття термінала. +Якщо ви використовуєте Mac із оболонкою `zsh`, виконання стандартної команди +`export PATH`, зазначеної під час встановлення, не зберігається після закриття +термінала. -Замість цього ви можете додати PATH у файл конфігурації оболонки, виконавши наступну команду: +Замість цього ви можете додати PATH у файл конфігурації оболонки, виконавши +наступну команду: ```shell echo 'export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"' >> ~/.zshrc ``` -Далі виконайте наступну команду, щоб оновити сесію термінала, або перезапустіть термінал. - +Далі виконайте наступну команду, щоб оновити сесію термінала, або перезапустіть +термінал. ```shell source ~/.zshrc @@ -205,27 +236,28 @@ source ~/.zshrc Щоб перевірити, чи встановлення було успішним, перевірте версію Solana CLI: - ```shell solana --version ``` -Ви повинні побачити результат, схожий на наступний: +Ви повинні побачити результат, схожий на наступний: ``` solana-cli 1.18.22 (src:9efdd74b; feat:4215500110, client:Agave) ``` -Ви можете переглянути всі доступні версії у [репозиторії Agave на Github](https://github.com/anza-xyz/agave/releases). +Ви можете переглянути всі доступні версії у +[репозиторії Agave на Github](https://github.com/anza-xyz/agave/releases). -Agave — це клієнт валідатора від [Anza](https://www.anza.xyz/), раніше відомий як клієнт валідатора Solana Labs. +Agave — це клієнт валідатора від [Anza](https://www.anza.xyz/), раніше відомий +як клієнт валідатора Solana Labs. -Щоб оновити Solana CLI до останньої версії, ви можете використати наступну команду: - +Щоб оновити Solana CLI до останньої версії, ви можете використати наступну +команду: ```shell agave-install update @@ -233,38 +265,43 @@ agave-install update ### Встановлення Anchor CLI -[Anchor](https://www.anchor-lang.com/) — це фреймворк для розробки програм на Solana. Anchor використовує макроси Rust, щоб спростити процес написання програм на Solana. +[Anchor](https://www.anchor-lang.com/) — це фреймворк для розробки програм на +Solana. Anchor використовує макроси Rust, щоб спростити процес написання програм +на Solana. Існує два способи встановлення Anchor CLI та інструментів: -1. За допомогою Anchor Version Manager (AVM) — **рекомендований спосіб встановлення**, оскільки він спрощує оновлення версій Anchor у майбутньому. -2. Без AVM — вимагає більш ручного процесу для оновлення версій Anchor у майбутньому. +1. За допомогою Anchor Version Manager (AVM) — **рекомендований спосіб + встановлення**, оскільки він спрощує оновлення версій Anchor у майбутньому. +2. Без AVM — вимагає більш ручного процесу для оновлення версій Anchor у + майбутньому. -Менеджер версій Anchor (AVM) дозволяє встановлювати та керувати різними версіями Anchor на вашій системі, включаючи зручне оновлення версій у майбутньому. +Менеджер версій Anchor (AVM) дозволяє встановлювати та керувати різними версіями +Anchor на вашій системі, включаючи зручне оновлення версій у майбутньому. Встановіть AVM за допомогою наступної команди: ```shell cargo install --git https://github.com/coral-xyz/anchor avm --force ``` -Перевірте, щоб переконатися, що AVM було встановлено та він доступний: +Перевірте, щоб переконатися, що AVM було встановлено та він доступний: ```shell avm --version ``` -Встановіть останню версію Anchor CLI за допомогою AVM: +Встановіть останню версію Anchor CLI за допомогою AVM: ```shell avm install latest avm use latest ``` -Або встановіть конкретну версію Anchor CLI, вказавши бажану версію: +Або встановіть конкретну версію Anchor CLI, вказавши бажану версію: ```shell avm install 0.30.1 @@ -290,7 +327,8 @@ cargo install --git https://github.com/coral-xyz/anchor --tag v0.30.1 anchor-cli -Під час встановлення ви можете побачити таке попередження. Однак це не впливає на процес встановлення. +Під час встановлення ви можете побачити таке попередження. Однак це не впливає +на процес встановлення. @@ -329,7 +367,8 @@ anchor --version anchor-cli 0.30.1 ``` -Під час встановлення Anchor CLI на Linux або WSL ви можете зіткнутися з такою помилкою: +Під час встановлення Anchor CLI на Linux або WSL ви можете зіткнутися з такою +помилкою: ``` error: could not exec the linker cc = note: Permission denied (os error 13) @@ -342,12 +381,15 @@ error: could not exec the linker cc = note: Permission denied (os error 13) #### Node.js та Yarn -Node.js та Yarn необхідні для запуску тестового файлу (TypeScript), створеного за допомогою команди `anchor init`. (Шаблон тестів на Rust також доступний за допомогою `anchor init --test-template rust`) +Node.js та Yarn необхідні для запуску тестового файлу (TypeScript), створеного +за допомогою команди `anchor init`. (Шаблон тестів на Rust також доступний за +допомогою `anchor init --test-template rust`) -Рекомендований спосіб встановлення Node — використання [Node Version Manager (nvm)](https://github.com/nvm-sh/nvm). +Рекомендований спосіб встановлення Node — використання +[Node Version Manager (nvm)](https://github.com/nvm-sh/nvm). Встановіть nvm за допомогою наступної команди: @@ -387,11 +429,13 @@ v22.7.0 ```shell npm install --global yarn ``` + Щоб перевірити, чи встановлення було успішним, перевірте версію Yarn: ``` yarn --version ``` + Ви повинні побачити наступний результат: ``` @@ -409,6 +453,7 @@ yarn --version ``` error: not a directory: '.../solana-release/bin/sdk/sbf/dependencies/platform-tools/rust/lib' ``` + Спробуйте ці рішення: 1. Примусове встановлення за допомогою наступної команди: @@ -433,16 +478,19 @@ rm -rf ~/.cache/solana/* version = 3 ``` -Дивіться [це обговорення](https://github.com/coral-xyz/anchor/issues/3392) для отримання додаткової інформації. - +Дивіться [це обговорення](https://github.com/coral-xyz/anchor/issues/3392) для +отримання додаткової інформації. -Після застосування будь-якого з рішень спробуйте знову виконати команду `anchor build`. +Після застосування будь-якого з рішень спробуйте знову виконати команду +`anchor build`. -Якщо ви використовуєте Linux або WSL і стикаєтеся з такими помилками під час виконання команди `anchor test` після створення нового проєкту Anchor, це може бути через відсутність Node.js або Yarn: +Якщо ви використовуєте Linux або WSL і стикаєтеся з такими помилками під час +виконання команди `anchor test` після створення нового проєкту Anchor, це може +бути через відсутність Node.js або Yarn: ``` Permission denied (os error 13) @@ -456,7 +504,8 @@ No such file or directory (os error 2) ## Основи Solana CLI -Цей розділ ознайомить вас із деякими поширеними командами Solana CLI для початку роботи. +Цей розділ ознайомить вас із деякими поширеними командами Solana CLI для початку +роботи. @@ -464,7 +513,6 @@ No such file or directory (os error 2) Щоб переглянути вашу поточну конфігурацію: - ```shell solana config get ``` @@ -479,7 +527,8 @@ Keypair Path: /Users/test/.config/solana/id.json Commitment: confirmed ``` -RPC URL та Websocket URL вказують кластер Solana, до якого CLI надсилатиме запити. За замовчуванням це буде mainnet-beta. +RPC URL та Websocket URL вказують кластер Solana, до якого CLI надсилатиме +запити. За замовчуванням це буде mainnet-beta. Ви можете оновити кластер Solana CLI за допомогою наступних команд: @@ -489,6 +538,7 @@ solana config set --url devnet solana config set --url localhost solana config set --url testnet ``` + Ви також можете використовувати наступні скорочені опції: ``` @@ -498,14 +548,19 @@ solana config set -ul # For localhost solana config set -ut # For testnet ``` -Шлях до ключової пари (Keypair Path) вказує розташування гаманця за замовчуванням, який використовується Solana CLI (для оплати комісій за транзакції та розгортання програм). Шлях за замовчуванням: `~/.config/solana/id.json`. У наступному кроці описано, як створити ключову пару за цим шляхом. +Шлях до ключової пари (Keypair Path) вказує розташування гаманця за +замовчуванням, який використовується Solana CLI (для оплати комісій за +транзакції та розгортання програм). Шлях за замовчуванням: +`~/.config/solana/id.json`. У наступному кроці описано, як створити ключову пару +за цим шляхом. ### Створення Гаманця -Для взаємодії з мережею Solana за допомогою Solana CLI вам потрібен гаманець Solana, поповнений SOL. - -Щоб створити ключову пару за замовчуванням у Keypair Path, виконайте наступну команду: +Для взаємодії з мережею Solana за допомогою Solana CLI вам потрібен гаманець +Solana, поповнений SOL. +Щоб створити ключову пару за замовчуванням у Keypair Path, виконайте наступну +команду: ```shell solana-keygen new @@ -534,11 +589,14 @@ cream bleak tortoise ocean nasty game gift forget fancy salon mimic amazing -Якщо у вас вже є гаманець у файловій системі, збережений у місці за замовчуванням, ця команда **НЕ** перезапише його, якщо ви явно не використаєте прапорець `--force`. +Якщо у вас вже є гаманець у файловій системі, збережений у місці за +замовчуванням, ця команда **НЕ** перезапише його, якщо ви явно не використаєте +прапорець `--force`. -Після створення ключової пари ви можете отримати адресу (публічний ключ) цієї пари за допомогою наступної команди: +Після створення ключової пари ви можете отримати адресу (публічний ключ) цієї +пари за допомогою наступної команди: ```shell solana address @@ -546,43 +604,47 @@ solana address ### Airdrop SOL -Після налаштування локального гаманця запросіть airdrop SOL для поповнення вашого гаманця. SOL потрібні для оплати комісій за транзакції та розгортання програм. +Після налаштування локального гаманця запросіть airdrop SOL для поповнення +вашого гаманця. SOL потрібні для оплати комісій за транзакції та розгортання +програм. Встановіть ваш кластер на devnet: - ```shell solana config set -ud ``` Далі запросіть airdrop SOL у devnet: - ```shell solana airdrop 2 ``` Щоб перевірити баланс SOL вашого гаманця, виконайте наступну команду: - ```shell solana balance ``` -Команда `solana airdrop` наразі обмежена 5 SOL за запит у devnet. Помилки можуть виникати через обмеження частоти запитів. +Команда `solana airdrop` наразі обмежена 5 SOL за запит у devnet. Помилки можуть +виникати через обмеження частоти запитів. -Як альтернативу, ви можете отримати SOL у devnet за допомогою [Solana Web Faucet](https://faucet.solana.com). +Як альтернативу, ви можете отримати SOL у devnet за допомогою +[Solana Web Faucet](https://faucet.solana.com). ### Запуск Локального Валідатора -Solana CLI постачається з вбудованим [тестовим валідатором](https://docs.anza.xyz/cli/examples/test-validator). Запуск локального валідатора дозволить вам розгортати та тестувати програми локально. - -У окремому терміналі виконайте наступну команду, щоб запустити локальний валідатор: +Solana CLI постачається з вбудованим +[тестовим валідатором](https://docs.anza.xyz/cli/examples/test-validator). +Запуск локального валідатора дозволить вам розгортати та тестувати програми +локально. +У окремому терміналі виконайте наступну команду, щоб запустити локальний +валідатор: ```shell solana-test-validator @@ -590,8 +652,8 @@ solana-test-validator -У WSL вам може знадобитися спочатку перейти до папки, де у вас є права запису за замовчуванням: - +У WSL вам може знадобитися спочатку перейти до папки, де у вас є права запису за +замовчуванням: ```shell cd ~ @@ -602,7 +664,8 @@ solana-test-validator -Переконайтеся, що оновили конфігурацію Solana CLI до `localhost` перед виконанням команд: +Переконайтеся, що оновили конфігурацію Solana CLI до `localhost` перед +виконанням команд: ```shell solana config set -ul diff --git a/docs/locales/uk/intro/quick-start/cross-program-invocation.md b/docs/locales/uk/intro/quick-start/cross-program-invocation.md index 58f36f10d..efc88ee2b 100644 --- a/docs/locales/uk/intro/quick-start/cross-program-invocation.md +++ b/docs/locales/uk/intro/quick-start/cross-program-invocation.md @@ -3,30 +3,30 @@ sidebarLabel: Крос-програмні виклики title: Крос-програмні виклики sidebarSortOrder: 5 description: - Дізнайтеся, як реалізувати крос-програмні виклики (CPIs) у програмах Solana - за допомогою фреймворку Anchor. У цьому підручнику демонструється, як - здійснювати переказ SOL між акаунтами, взаємодіяти з Системною програмою та - працювати з адресами, отриманими від програми (PDAs), у CPIs. Ідеально - підходить для розробників, які хочуть створювати інтегровані програми Solana. + Дізнайтеся, як реалізувати крос-програмні виклики (CPIs) у програмах Solana за + допомогою фреймворку Anchor. У цьому підручнику демонструється, як здійснювати + переказ SOL між акаунтами, взаємодіяти з Системною програмою та працювати з + адресами, отриманими від програми (PDAs), у CPIs. Ідеально підходить для + розробників, які хочуть створювати інтегровані програми Solana. --- У цьому розділі ми оновимо програму CRUD з попереднього розділу про PDA, щоб -додати крос-програмні виклики (CPIs). Ми модифікуємо програму, щоб -забезпечити переказ SOL між акаунтами в інструкціях `update` та `delete`, -демонструючи, як взаємодіяти з іншими програмами (у цьому випадку з -Системною програмою) зсередини нашої програми. +додати крос-програмні виклики (CPIs). Ми модифікуємо програму, щоб забезпечити +переказ SOL між акаунтами в інструкціях `update` та `delete`, демонструючи, як +взаємодіяти з іншими програмами (у цьому випадку з Системною програмою) +зсередини нашої програми. Метою цього розділу є покрокове пояснення процесу реалізації CPIs у програмі Solana за допомогою фреймворку Anchor, спираючись на концепції PDA, які ми -розглядали в попередньому розділі. Для отримання додаткової інформації -перейдіть на сторінку [Крос-програмні виклики](/docs/uk/core/cpi). +розглядали в попередньому розділі. Для отримання додаткової інформації перейдіть +на сторінку [Крос-програмні виклики](/docs/uk/core/cpi). ### Модифікація інструкції Update -Спочатку ми реалізуємо простий механізм "оплати за оновлення" шляхом -модифікації структури `Update` та функції `update`. +Спочатку ми реалізуємо простий механізм "оплати за оновлення" шляхом модифікації +структури `Update` та функції `update`. Розпочнемо з оновлення файлу `lib.rs`, щоб включити до області видимості елементи з модуля `system_program`. @@ -46,7 +46,9 @@ use anchor_lang::system_program::{transfer, Transfer}; -Далі оновіть структуру Update, щоб включити додатковий акаунт під назвою `vault_account`. Цей акаунт, який контролюється нашою програмою, отримуватиме SOL від користувача, коли той оновлює свій акаунт повідомлень. +Далі оновіть структуру Update, щоб включити додатковий акаунт під назвою +`vault_account`. Цей акаунт, який контролюється нашою програмою, отримуватиме +SOL від користувача, коли той оновлює свій акаунт повідомлень. ```rs filename="lib.rs" #[account( @@ -90,7 +92,9 @@ pub struct Update<'info> { Ми додаємо новий акаунт під назвою `vault_account` до нашої структури `Update`. Цей акаунт служить програмно-контрольованим "сейфом", який буде отримувати SOL від користувачів, коли вони оновлюють свої повідомлення. -Використовуючи PDA (Program Derived Address) для сейфа, ми створюємо програмно-контрольований акаунт, унікальний для кожного користувача, що дозволяє нам управляти коштами користувачів у межах логіки нашої програми. +Використовуючи PDA (Program Derived Address) для сейфа, ми створюємо +програмно-контрольований акаунт, унікальний для кожного користувача, що дозволяє +нам управляти коштами користувачів у межах логіки нашої програми. --- @@ -100,26 +104,31 @@ pub struct Update<'info> { Адреса акаунта є PDA, що отримується за допомогою сідів: `[b"vault", user.key().as_ref()]` - **Відсутність приватного ключа**: - Оскільки це PDA, він не має приватного ключа, тому лише наша програма може "підписуватися" за цю адресу під час виконання CPIs. + Оскільки це PDA, він не має приватного ключа, тому лише наша програма може + "підписуватися" за цю адресу під час виконання CPIs. - **Тип акаунта**: - Це акаунт типу `SystemAccount`, який належить до Системної програми, як і звичайні гаманці. + Це акаунт типу `SystemAccount`, який належить до Системної програми, як і + звичайні гаманці. --- Ця структура дозволяє нашій програмі: - Генерувати унікальні, детерміновані адреси для кожного "сейфа" користувача. -- Контролювати кошти без необхідності використання приватного ключа для підписання транзакцій. +- Контролювати кошти без необхідності використання приватного ключа для + підписання транзакцій. --- -У інструкції `delete` ми покажемо, як наша програма може "підписуватися" за цей PDA під час CPI. +У інструкції `delete` ми покажемо, як наша програма може "підписуватися" за цей +PDA під час CPI. --- Далі: реалізуйте логіку CPI в інструкції `update` -Реалізуйте логіку CPI для переказу **0.001 SOL** з акаунта користувача на акаунт сейфа. +Реалізуйте логіку CPI для переказу **0.001 SOL** з акаунта користувача на акаунт +сейфа. ```rs filename="lib.rs" let transfer_accounts = Transfer { @@ -158,9 +167,12 @@ transfer(cpi_context, 1_000_000)?; -В інструкції `update` ми реалізуємо виклик між програмами (CPI), щоб викликати інструкцію `transfer` Системної програми. Це демонструє, як виконати CPI у межах нашої програми, забезпечуючи композиційність програм у Solana. +В інструкції `update` ми реалізуємо виклик між програмами (CPI), щоб викликати +інструкцію `transfer` Системної програми. Це демонструє, як виконати CPI у межах +нашої програми, забезпечуючи композиційність програм у Solana. -Структура `Transfer` визначає необхідні акаунти для інструкції `transfer` Системної програми: +Структура `Transfer` визначає необхідні акаунти для інструкції `transfer` +Системної програми: - `from` - Акаунт користувача (джерело коштів) - `to` - Акаунт сейфа (ціль для переказу коштів) @@ -171,7 +183,8 @@ transfer(cpi_context, 1_000_000)?; to: ctx.accounts.vault_account.to_account_info(), }; ``` -`CpiContext` визначає: + + `CpiContext` визначає: - Програму, яку потрібно викликати (Системна програма) - Акаунти, необхідні для CPI (визначені у структурі `Transfer`) @@ -188,13 +201,16 @@ transfer(cpi_context, 1_000_000)?; - `cpi_context` (програму та акаунти) - Суму для переказу (1,000,000 лампортів, що еквівалентно 0.001 SOL) - ```rs filename="lib.rs" transfer(cpi_context, 1_000_000)?; ``` --- -Налаштування для CPI відповідає тому, як створюються інструкції на стороні клієнта, де ми вказуємо програму, акаунти та дані інструкції для виклику конкретної інструкції. Коли викликається інструкція `update` нашої програми, вона внутрішньо викликає інструкцію переказу Системної програми. + +Налаштування для CPI відповідає тому, як створюються інструкції на стороні +клієнта, де ми вказуємо програму, акаунти та дані інструкції для виклику +конкретної інструкції. Коли викликається інструкція `update` нашої програми, +вона внутрішньо викликає інструкцію переказу Системної програми. @@ -204,11 +220,15 @@ transfer(cpi_context, 1_000_000)?; ```shell filename="Terminal" build ``` + ### Змініть Інструкцію Delete -Ми реалізуємо механізм "повернення коштів при видаленні", змінивши структуру `Delete` та функцію `delete`. +Ми реалізуємо механізм "повернення коштів при видаленні", змінивши структуру +`Delete` та функцію `delete`. -Спершу оновіть структуру `Delete`, додавши до неї `vault_account`. Це дозволить нам переказати всі SOL із сейфа назад користувачеві, коли він закриває свій акаунт повідомлення. +Спершу оновіть структуру `Delete`, додавши до неї `vault_account`. Це дозволить +нам переказати всі SOL із сейфа назад користувачеві, коли він закриває свій +акаунт повідомлення. ```rs filename="lib.rs" #[account( @@ -219,7 +239,8 @@ build pub vault_account: SystemAccount<'info>, ``` -Також додайте `system_program`, оскільки CPI для переказу вимагає виклику Системної програми. +Також додайте `system_program`, оскільки CPI для переказу вимагає виклику +Системної програми. ```rs filename="lib.rs" pub system_program: Program<'info, System>, @@ -256,12 +277,15 @@ pub struct Delete<'info> { Акаунт `vault_account` використовує той самий PDA, що і в структурі `Update`. -Додавання `vault_account` до структури `Delete` дозволяє нашій програмі отримати доступ до сейфа користувача під час виконання інструкції видалення, щоб переказати накопичені SOL назад користувачеві. +Додавання `vault_account` до структури `Delete` дозволяє нашій програмі отримати +доступ до сейфа користувача під час виконання інструкції видалення, щоб +переказати накопичені SOL назад користувачеві. -Далі реалізуйте логіку CPI в інструкції `delete`, щоб переказати SOL із сейфа назад на акаунт користувача. +Далі реалізуйте логіку CPI в інструкції `delete`, щоб переказати SOL із сейфа +назад на акаунт користувача. ```rs filename="lib.rs" let user_key = ctx.accounts.user.key(); @@ -279,7 +303,8 @@ let cpi_context = CpiContext::new( transfer(cpi_context, ctx.accounts.vault_account.lamports())?; ``` -Зверніть увагу, що ми оновили `_ctx: Context` до `ctx: Context`, оскільки будемо використовувати контекст у тілі функції. +Зверніть увагу, що ми оновили `_ctx: Context` до `ctx: Context`, +оскільки будемо використовувати контекст у тілі функції. @@ -318,19 +343,21 @@ let user_key = ctx.accounts.user.key(); let signer_seeds: &[&[&[u8]]] = &[&[b"vault", user_key.as_ref(), &[ctx.bumps.vault_account]]]; ``` -Структура `Transfer` визначає необхідні акаунти для інструкції переказу Системної програми: + +Структура `Transfer` визначає необхідні акаунти для інструкції переказу +Системної програми: - `from`: Акаунт сейфа (джерело коштів) - `to`: Акаунт користувача (ціль для переказу коштів) - ```rs filename="lib.rs" let transfer_accounts = Transfer { from: ctx.accounts.vault_account.to_account_info(), to: ctx.accounts.user.to_account_info(), }; ``` -`CpiContext` визначає: + + `CpiContext` визначає: - Програму, яку потрібно викликати (Системна програма) - Акаунти, задіяні у переказі (визначені у структурі `Transfer`) @@ -342,7 +369,9 @@ let signer_seeds: &[&[&[u8]]] = transfer_accounts, ).with_signer(signer_seeds); ``` -Функція `transfer` викликає інструкцію переказу в Системній програмі, передаючи: + + Функція `transfer` викликає інструкцію переказу в Системній програмі, + передаючи: - `cpi_context` (програму, акаунти та підписувач на основі PDA) - Суму для переказу (весь баланс акаунта сейфа) @@ -350,7 +379,11 @@ let signer_seeds: &[&[&[u8]]] = ```rs filename="lib.rs" transfer(cpi_context, ctx.accounts.vault_account.lamports())?; ``` -Ця реалізація CPI демонструє, як програми можуть використовувати PDA для управління коштами. Коли викликається інструкція `delete` нашої програми, вона внутрішньо викликає інструкцію переказу Системної програми, підписуючи за PDA, щоб авторизувати переказ усіх коштів із сейфа назад користувачеві. + + Ця реалізація CPI демонструє, як програми можуть використовувати PDA для + управління коштами. Коли викликається інструкція `delete` нашої програми, вона + внутрішньо викликає інструкцію переказу Системної програми, підписуючи за PDA, + щоб авторизувати переказ усіх коштів із сейфа назад користувачеві. @@ -363,7 +396,10 @@ build ### Розгортання Програми -Після внесення цих змін нам потрібно повторно розгорнути оновлену програму. Це забезпечує доступність модифікованої програми для тестування. У Solana оновлення програми вимагає лише розгортання скомпільованої програми за тим самим ідентифікатором програми (program ID). +Після внесення цих змін нам потрібно повторно розгорнути оновлену програму. Це +забезпечує доступність модифікованої програми для тестування. У Solana оновлення +програми вимагає лише розгортання скомпільованої програми за тим самим +ідентифікатором програми (program ID). ```shell filename="Terminal" deploy @@ -381,22 +417,28 @@ Deployment successful. Completed in 17s. -Лише орган влади оновлення (upgrade authority) програми може її оновити. Орган влади оновлення встановлюється під час розгортання програми, і це єдиний акаунт, який має дозвіл модифікувати або закривати програму. Якщо орган влади оновлення відкликається, програма стає незмінною і її ніколи не можна буде закрити або оновити. +Лише орган влади оновлення (upgrade authority) програми може її оновити. Орган +влади оновлення встановлюється під час розгортання програми, і це єдиний акаунт, +який має дозвіл модифікувати або закривати програму. Якщо орган влади оновлення +відкликається, програма стає незмінною і її ніколи не можна буде закрити або +оновити. -Під час розгортання програм у Solana Playground гаманцем Playground є орган влади оновлення для всіх ваших програм. +Під час розгортання програм у Solana Playground гаманцем Playground є орган +влади оновлення для всіх ваших програм. ### Оновлення Файлу Тестів -Далі ми оновимо наш файл `anchor.test.ts`, щоб включити новий акаунт сейфа у наші інструкції. Це вимагає отримання PDA сейфа та його включення до викликів інструкцій `update` і `delete`. +Далі ми оновимо наш файл `anchor.test.ts`, щоб включити новий акаунт сейфа у +наші інструкції. Це вимагає отримання PDA сейфа та його включення до викликів +інструкцій `update` і `delete`. #### Отримання PDA Сейфа Спершу додайте код для отримання PDA сейфа: - ```ts filename="anchor.test.ts" const [vaultPda, vaultBump] = PublicKey.findProgramAddressSync( [Buffer.from("vault"), wallet.publicKey.toBuffer()], @@ -489,7 +531,8 @@ const transactionSignature = await program.methods ### Перезапуск Тестів -Після внесення цих змін запустіть тести, щоб переконатися, що все працює, як очікувалося: +Після внесення цих змін запустіть тести, щоб переконатися, що все працює, як +очікувалося: ```shell filename="Terminal" test @@ -531,22 +574,34 @@ Running tests... ![Delete CPI](/assets/docs/intro/quickstart/cpi-delete.png) -Якщо ви зіткнулися з помилками, ви можете переглянути [фінальний код](https://beta.solpg.io/668304cfcffcf4b13384d20a). +Якщо ви зіткнулися з помилками, ви можете переглянути +[фінальний код](https://beta.solpg.io/668304cfcffcf4b13384d20a). ## Наступні Кроки -Ви завершили посібник з швидкого старту Solana! Ви дізналися про акаунти, транзакції, PDA, CPI та розгорнули власні програми. +Ви завершили посібник з швидкого старту Solana! Ви дізналися про акаунти, +транзакції, PDA, CPI та розгорнули власні програми. -Відвідайте сторінки [Основні Концепції](/docs/uk/core/accounts) для більш детального пояснення тем, розглянутих у цьому посібнику. +Відвідайте сторінки [Основні Концепції](/docs/uk/core/accounts) для більш +детального пояснення тем, розглянутих у цьому посібнику. -Додаткові навчальні матеріали доступні на сторінці [Ресурси для Розробників](/developers). +Додаткові навчальні матеріали доступні на сторінці +[Ресурси для Розробників](/developers). ### Досліджуйте Більше Прикладів -Якщо ви віддаєте перевагу навчанню через приклади, перегляньте [Репозиторій з Прикладами Програм](https://github.com/solana-developers/program-examples) для різноманітних прикладів програм. +Якщо ви віддаєте перевагу навчанню через приклади, перегляньте +[Репозиторій з Прикладами Програм](https://github.com/solana-developers/program-examples) +для різноманітних прикладів програм. -Solana Playground пропонує зручну функцію, яка дозволяє імпортувати або переглядати проєкти за їх посиланнями на GitHub. Наприклад, відкрийте це [посилання Solana Playground](https://beta.solpg.io/https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor), щоб переглянути Anchor-проєкт із цього [репозиторію GitHub](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor). +Solana Playground пропонує зручну функцію, яка дозволяє імпортувати або +переглядати проєкти за їх посиланнями на GitHub. Наприклад, відкрийте це +[посилання Solana Playground](https://beta.solpg.io/https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor), +щоб переглянути Anchor-проєкт із цього +[репозиторію GitHub](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/anchor). -Натисніть кнопку `Import` і введіть ім'я проєкту, щоб додати його до свого списку проєктів у Solana Playground. Після імпорту проєкту всі зміни автоматично зберігаються та залишаються у середовищі Playground. +Натисніть кнопку `Import` і введіть ім'я проєкту, щоб додати його до свого +списку проєктів у Solana Playground. Після імпорту проєкту всі зміни автоматично +зберігаються та залишаються у середовищі Playground. diff --git a/docs/locales/uk/intro/quick-start/deploying-programs.md b/docs/locales/uk/intro/quick-start/deploying-programs.md index ddcbbc83a..f81745580 100644 --- a/docs/locales/uk/intro/quick-start/deploying-programs.md +++ b/docs/locales/uk/intro/quick-start/deploying-programs.md @@ -3,14 +3,19 @@ sidebarLabel: Розгортання Програм title: Розгортання Вашої Першої Програми Solana sidebarSortOrder: 3 description: - Дізнайтеся, як створити, розгорнути та протестувати вашу першу програму Solana за допомогою - фреймворку Anchor та Solana Playground. Цей посібник для початківців демонструє, як створити просту програму, - розгорнути її на devnet, виконати тести та закрити програму. + Дізнайтеся, як створити, розгорнути та протестувати вашу першу програму Solana + за допомогою фреймворку Anchor та Solana Playground. Цей посібник для + початківців демонструє, як створити просту програму, розгорнути її на devnet, + виконати тести та закрити програму. --- -У цьому розділі ми створимо, розгорнемо та протестуємо просту програму Solana за допомогою фреймворку Anchor. Наприкінці ви розгорнете свою першу програму у блокчейні Solana! +У цьому розділі ми створимо, розгорнемо та протестуємо просту програму Solana за +допомогою фреймворку Anchor. Наприкінці ви розгорнете свою першу програму у +блокчейні Solana! -Мета цього розділу — ознайомити вас із Solana Playground. Ми розглянемо більш детальний приклад у розділах про PDA та CPI. Для отримання додаткової інформації відвідайте сторінку [Програми на Solana](/docs/core/programs). +Мета цього розділу — ознайомити вас із Solana Playground. Ми розглянемо більш +детальний приклад у розділах про PDA та CPI. Для отримання додаткової інформації +відвідайте сторінку [Програми на Solana](/docs/core/programs). @@ -20,7 +25,8 @@ description: - Натисніть кнопку "Create a new project" у лівій панелі. -- Введіть назву проєкту, виберіть Anchor як фреймворк, потім натисніть кнопку "Create". +- Введіть назву проєкту, виберіть Anchor як фреймворк, потім натисніть кнопку + "Create". ![Новий Проєкт](/assets/docs/intro/quickstart/pg-new-project.gif) @@ -66,12 +72,15 @@ pub struct NewAccount { На даний момент ми розглянемо лише загальний огляд коду програми: -- Макрос `declare_id!` визначає адресy вашої програми у блокчейні. Ця адреса буде автоматично оновлена, коли ми скомпілюємо програму на наступному етапі. +- Макрос `declare_id!` визначає адресy вашої програми у блокчейні. Ця адреса + буде автоматично оновлена, коли ми скомпілюємо програму на наступному етапі. ```rs declare_id!("11111111111111111111111111111111"); ``` -- Макрос `#[program]` позначає модуль, який містить функції, що представляють інструкції програми. + +- Макрос `#[program]` позначає модуль, який містить функції, що представляють + інструкції програми. ```rs #[program] @@ -84,28 +93,38 @@ pub struct NewAccount { } } ``` -У цьому прикладі інструкція `initialize` приймає два параметри: -1. `ctx: Context` — надає доступ до акаунтів, необхідних для цієї інструкції, як це зазначено у структурі `Initialize`. -2. `data: u64` — параметр інструкції, який передається під час виклику інструкції. + У цьому прикладі інструкція `initialize` приймає два параметри: -Тіло функції встановлює значення поля `data` для `new_account` відповідно до переданого аргументу `data`, а потім виводить повідомлення до журналу програми. +1. `ctx: Context` — надає доступ до акаунтів, необхідних для цієї + інструкції, як це зазначено у структурі `Initialize`. +2. `data: u64` — параметр інструкції, який передається під час виклику + інструкції. -- Макрос `#[derive(Accounts)]` використовується для визначення структури, яка задає акаунти, необхідні для певної інструкції, де кожне поле представляє окремий акаунт. +Тіло функції встановлює значення поля `data` для `new_account` відповідно до +переданого аргументу `data`, а потім виводить повідомлення до журналу програми. -Типи полів (наприклад, `Signer<'info>`) і обмеження (наприклад, `#[account(mut)]`) використовуються Anchor для автоматичного виконання стандартних перевірок безпеки, пов'язаних із валідацією акаунтів. +- Макрос `#[derive(Accounts)]` використовується для визначення структури, яка + задає акаунти, необхідні для певної інструкції, де кожне поле представляє + окремий акаунт. - ```rs - #[derive(Accounts)] - pub struct Initialize<'info> { - #[account(init, payer = signer, space = 8 + 8)] - pub new_account: Account<'info, NewAccount>, - #[account(mut)] - pub signer: Signer<'info>, - pub system_program: Program<'info, System>, - } - ``` -- Макрос `#[account]` використовується для визначення структури, яка представляє структуру даних акаунта, створеного та керованого програмою. +Типи полів (наприклад, `Signer<'info>`) і обмеження (наприклад, +`#[account(mut)]`) використовуються Anchor для автоматичного виконання +стандартних перевірок безпеки, пов'язаних із валідацією акаунтів. + +```rs +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = signer, space = 8 + 8)] + pub new_account: Account<'info, NewAccount>, + #[account(mut)] + pub signer: Signer<'info>, + pub system_program: Program<'info, System>, +} +``` + +- Макрос `#[account]` використовується для визначення структури, яка представляє + структуру даних акаунта, створеного та керованого програмою. ```rs #[account] @@ -124,7 +143,9 @@ pub struct NewAccount { ```shell filename="Terminal" build ``` -Зверніть увагу, що адреса у `declare_id!()` була оновлена. Це адреса вашої програми у блокчейні. + +Зверніть увагу, що адреса у `declare_id!()` була оновлена. Це адреса вашої +програми у блокчейні. @@ -139,7 +160,9 @@ Build successful. Completed in 1.46s. Після компіляції програми виконайте команду `deploy` у терміналі, щоб розгорнути програму в мережі (за замовчуванням devnet). Для розгортання програми необхідно виділити SOL для акаунта у блокчейні, який зберігатиме програму. -Перед розгортанням переконайтеся, що у вас достатньо SOL. Ви можете отримати devnet SOL, виконавши команду `solana airdrop 5` у терміналі Playground або скориставшись [веб-фонтаном](https://faucet.solana.com/). +Перед розгортанням переконайтеся, що у вас достатньо SOL. Ви можете отримати +devnet SOL, виконавши команду `solana airdrop 5` у терміналі Playground або +скориставшись [веб-фонтаном](https://faucet.solana.com/). ```shell filename="Terminal" deploy @@ -158,7 +181,8 @@ Deployment successful. Completed in 19s. -Альтернативно, ви також можете скористатися кнопками `Build` і `Deploy` на лівій панелі. +Альтернативно, ви також можете скористатися кнопками `Build` і `Deploy` на лівій +панелі. ![Build and Deploy](/assets/docs/intro/quickstart/pg-build-deploy.png) @@ -166,7 +190,9 @@ Deployment successful. Completed in 19s. ### Тестування Програми -Разом із стартовим кодом включений тестовий файл, який знаходиться у `tests/anchor.test.ts`. У цьому файлі показано, як викликати інструкцію `initialize` у стартовій програмі з клієнта. +Разом із стартовим кодом включений тестовий файл, який знаходиться у +`tests/anchor.test.ts`. У цьому файлі показано, як викликати інструкцію +`initialize` у стартовій програмі з клієнта. ```ts filename="anchor.test.ts" // No imports needed: web3, anchor, pg and more are globally available @@ -204,11 +230,14 @@ describe("Test", () => { }); }); ``` -Щоб запустити тестовий файл після розгортання програми, виконайте команду `test` у терміналі. + +Щоб запустити тестовий файл після розгортання програми, виконайте команду `test` +у терміналі. ```shell filename="Terminal" test ``` + Ви повинні побачити результат, який вказує, що тест пройшов успішно. @@ -231,7 +260,8 @@ Running tests... ![Run Test](/assets/docs/intro/quickstart/pg-test.png) -Потім ви можете переглянути журнали транзакцій, виконавши команду `solana confirm -v` та вказавши хеш транзакції (підпис) із результатів тесту: +Потім ви можете переглянути журнали транзакцій, виконавши команду +`solana confirm -v` та вказавши хеш транзакції (підпис) із результатів тесту: ```shell filename="Terminal" solana confirm -v [TxHash] @@ -289,7 +319,10 @@ Confirmed -Альтернативно, ви можете переглянути деталі транзакції на [SolanaFM](https://solana.fm/) або [Solana Explorer](https://explorer.solana.com/?cluster=devnet), здійснивши пошук за підписом (хешем) транзакції. +Альтернативно, ви можете переглянути деталі транзакції на +[SolanaFM](https://solana.fm/) або +[Solana Explorer](https://explorer.solana.com/?cluster=devnet), здійснивши пошук +за підписом (хешем) транзакції. Нагадуємо, що потрібно оновити підключення до кластеру (мережі) у вибраному Explorer, щоб воно відповідало кластеру Solana Playground. За замовчуванням у Solana Playground використовується кластер devnet. @@ -297,9 +330,11 @@ Confirmed ### Закриття Програми -Нарешті, SOL, виділений для програми у блокчейні, може бути повністю повернутий шляхом закриття програми. +Нарешті, SOL, виділений для програми у блокчейні, може бути повністю повернутий +шляхом закриття програми. -Ви можете закрити програму, виконавши наступну команду та вказавши адресу програми, яка знаходиться у `declare_id!()`: +Ви можете закрити програму, виконавши наступну команду та вказавши адресу +програми, яка знаходиться у `declare_id!()`: ```shell filename="Terminal" solana program close [ProgramID] @@ -322,14 +357,18 @@ Closed Program Id 2VvQ11q8xrn5tkPNyeraRsPaATdiPx8weLAD8aD4dn2r, 2.79511512 SOL r -Тільки орган влади оновлення програми може її закрити. Орган влади оновлення встановлюється під час розгортання програми, і це єдиний акаунт, який має дозвіл модифікувати або закривати програму. Якщо орган влади оновлення відкликається, програма стає незмінною і її ніколи не можна буде закрити або оновити. +Тільки орган влади оновлення програми може її закрити. Орган влади оновлення +встановлюється під час розгортання програми, і це єдиний акаунт, який має дозвіл +модифікувати або закривати програму. Якщо орган влади оновлення відкликається, +програма стає незмінною і її ніколи не можна буде закрити або оновити. -Під час розгортання програм у Solana Playground гаманцем Playground є орган влади оновлення для всіх ваших програм. +Під час розгортання програм у Solana Playground гаманцем Playground є орган +влади оновлення для всіх ваших програм. -Вітаємо! Ви щойно створили та розгорнули свою першу програму Solana за допомогою фреймворку Anchor! +Вітаємо! Ви щойно створили та розгорнули свою першу програму Solana за допомогою +фреймворку Anchor! - diff --git a/docs/locales/uk/intro/quick-start/index.md b/docs/locales/uk/intro/quick-start/index.md index 1a164ae56..3d22ddc46 100644 --- a/docs/locales/uk/intro/quick-start/index.md +++ b/docs/locales/uk/intro/quick-start/index.md @@ -8,33 +8,48 @@ description: Solana Playground – без необхідності встановлення. --- -Ласкаво просимо до посібника з швидкого старту Solana! Цей практичний посібник ознайомить вас із ключовими концепціями створення програм на Solana, незалежно від вашого попереднього досвіду. Після завершення цього уроку у вас буде базове розуміння розробки на Solana, і ви зможете досліджувати більш складні теми. +Ласкаво просимо до посібника з швидкого старту Solana! Цей практичний посібник +ознайомить вас із ключовими концепціями створення програм на Solana, незалежно +від вашого попереднього досвіду. Після завершення цього уроку у вас буде базове +розуміння розробки на Solana, і ви зможете досліджувати більш складні теми. ## Чого Ви Навчитеся У цьому уроці ви дізнаєтеся про: - **Розуміння акаунтів**: Дослідження зберігання даних у мережі Solana. -- **Надсилання транзакцій**: Взаємодія з мережею Solana шляхом надсилання транзакцій. -- **Створення та розгортання програм**: Створіть свою першу програму Solana та розгорніть її в мережі. -- **Program Derived Addresses (PDA)**: Як використовувати PDA для створення детермінованих адрес акаунтів. -- **Cross-Program Invocations (CPI)**: Як зробити так, щоб ваші програми взаємодіяли з іншими програмами на Solana. - -Найкраще те, що вам нічого не потрібно встановлювати! Ми будемо використовувати Solana Playground, браузерне середовище розробки, для всіх наших прикладів. Це означає, що ви можете слідувати урокам, копіювати та вставляти код і одразу бачити результати прямо у вашому браузері. Базові знання програмування бажані, але не обов’язкові. +- **Надсилання транзакцій**: Взаємодія з мережею Solana шляхом надсилання + транзакцій. +- **Створення та розгортання програм**: Створіть свою першу програму Solana та + розгорніть її в мережі. +- **Program Derived Addresses (PDA)**: Як використовувати PDA для створення + детермінованих адрес акаунтів. +- **Cross-Program Invocations (CPI)**: Як зробити так, щоб ваші програми + взаємодіяли з іншими програмами на Solana. + +Найкраще те, що вам нічого не потрібно встановлювати! Ми будемо використовувати +Solana Playground, браузерне середовище розробки, для всіх наших прикладів. Це +означає, що ви можете слідувати урокам, копіювати та вставляти код і одразу +бачити результати прямо у вашому браузері. Базові знання програмування бажані, +але не обов’язкові. Давайте почнемо будувати на Solana! ## Solana Playground -Solana Playground (Solpg) – це браузерне середовище розробки, яке дозволяє швидко розробляти, розгортати та тестувати програми Solana! +Solana Playground (Solpg) – це браузерне середовище розробки, яке дозволяє +швидко розробляти, розгортати та тестувати програми Solana! -Відкрийте нову вкладку у своєму браузері та перейдіть на [https://beta.solpg.io/](https://beta.solpg.io/). +Відкрийте нову вкладку у своєму браузері та перейдіть на +[https://beta.solpg.io/](https://beta.solpg.io/). ### Створення Гаманця Playground -Якщо ви новачок у Solana Playground, першим кроком буде створення гаманця Playground. Цей гаманець дозволить вам взаємодіяти з мережею Solana безпосередньо з вашого браузера. +Якщо ви новачок у Solana Playground, першим кроком буде створення гаманця +Playground. Цей гаманець дозволить вам взаємодіяти з мережею Solana +безпосередньо з вашого браузера. #### Крок 1. Підключіться до Playground @@ -44,11 +59,13 @@ Solana Playground (Solpg) – це браузерне середовище ро #### Крок 2. Створіть Свій Гаманець -Вам буде запропоновано зберегти ключову пару вашого гаманця. За бажанням збережіть ключову пару для резервної копії, а потім натисніть "Continue". +Вам буде запропоновано зберегти ключову пару вашого гаманця. За бажанням +збережіть ключову пару для резервної копії, а потім натисніть "Continue". ![Create Playground Wallet](/assets/docs/intro/quickstart/pg-create-wallet.png) -Тепер ви повинні побачити адресу вашого гаманця, баланс SOL і підключений кластер (за замовчуванням devnet) у нижній частині вікна. +Тепер ви повинні побачити адресу вашого гаманця, баланс SOL і підключений +кластер (за замовчуванням devnet) у нижній частині вікна. ![Connected](/assets/docs/intro/quickstart/pg-connected.png) @@ -58,8 +75,14 @@ Solana Playground (Solpg) – це браузерне середовище ро Декілька корисних визначень: -- **_адреса гаманця_**: Унікальний ідентифікатор цифрового гаманця, який використовується для надсилання або отримання криптоактивів у блокчейні. Це схоже на електронну адресу чи номер банківського рахунку – щоб хтось надіслав вам криптовалюту, йому потрібна ваша адреса гаманця. -- **_підключений кластер_**: Набір вузлів мережі, які працюють разом, щоб підтримувати синхронізовану копію блокчейна. Кластери важливі для надання децентралізованого розподіленого реєстру, перевірки транзакцій, забезпечення безпеки ланцюга та виконання програм (смарт-контрактів). +- **_адреса гаманця_**: Унікальний ідентифікатор цифрового гаманця, який + використовується для надсилання або отримання криптоактивів у блокчейні. Це + схоже на електронну адресу чи номер банківського рахунку – щоб хтось надіслав + вам криптовалюту, йому потрібна ваша адреса гаманця. +- **_підключений кластер_**: Набір вузлів мережі, які працюють разом, щоб + підтримувати синхронізовану копію блокчейна. Кластери важливі для надання + децентралізованого розподіленого реєстру, перевірки транзакцій, забезпечення + безпеки ланцюга та виконання програм (смарт-контрактів). ### Отримання Devnet SOL @@ -74,8 +97,8 @@ Solana Playground (Solpg) – це браузерне середовище ро #### Варіант 1: Використання Терміналу Playground -Щоб поповнити ваш гаманець Playground devnet SOL, виконайте у терміналі Playground команду: - +Щоб поповнити ваш гаманець Playground devnet SOL, виконайте у терміналі +Playground команду: ```shell filename="Terminal" solana airdrop 5 @@ -83,9 +106,11 @@ solana airdrop 5 #### Варіант 2: Використання Devnet Faucet -Якщо команда airdrop не працює (через обмеження або помилки), скористайтеся [Web Faucet](https://faucet.solana.com/). +Якщо команда airdrop не працює (через обмеження або помилки), скористайтеся +[Web Faucet](https://faucet.solana.com/). -- Введіть адресу свого гаманця (знаходиться в нижній частині екрана Playground) і виберіть суму +- Введіть адресу свого гаманця (знаходиться в нижній частині екрана Playground) + і виберіть суму - Натисніть "Confirm Airdrop", щоб отримати ваш devnet SOL ![Faucet Airdrop](/assets/docs/intro/quickstart/faucet-airdrop.gif) diff --git a/docs/locales/uk/intro/quick-start/program-derived-address.md b/docs/locales/uk/intro/quick-start/program-derived-address.md index e025756e1..e259518a8 100644 --- a/docs/locales/uk/intro/quick-start/program-derived-address.md +++ b/docs/locales/uk/intro/quick-start/program-derived-address.md @@ -11,21 +11,31 @@ description: використовувати PDAs у програмах Solana. --- -У цьому розділі ми розглянемо, як створити базову CRUD (Create, Read, Update, Delete) програму. Програма зберігатиме повідомлення користувача, використовуючи Program Derived Address (PDA) як адресу акаунта. +У цьому розділі ми розглянемо, як створити базову CRUD (Create, Read, Update, +Delete) програму. Програма зберігатиме повідомлення користувача, використовуючи +Program Derived Address (PDA) як адресу акаунта. -Мета цього розділу – провести вас через етапи створення і тестування програми Solana, використовуючи фреймворк Anchor, і показати, як використовувати PDA у програмі. Для отримання додаткової інформації відвідайте сторінку [Programs Derived Address](/docs/uk/core/pda). +Мета цього розділу – провести вас через етапи створення і тестування програми +Solana, використовуючи фреймворк Anchor, і показати, як використовувати PDA у +програмі. Для отримання додаткової інформації відвідайте сторінку +[Programs Derived Address](/docs/uk/core/pda). -Для довідки ось [фінальний код](https://beta.solpg.io/668304cfcffcf4b13384d20a), завершений після розгляду розділів PDA і CPI. +Для довідки ось [фінальний код](https://beta.solpg.io/668304cfcffcf4b13384d20a), +завершений після розгляду розділів PDA і CPI. ### Стартовий Код -Почніть, відкривши це [посилання на Solana Playground](https://beta.solpg.io/66734b7bcffcf4b13384d1ad) зі стартовим кодом. Потім натисніть кнопку "Import", щоб додати програму до вашого списку проєктів у Solana Playground. +Почніть, відкривши це +[посилання на Solana Playground](https://beta.solpg.io/66734b7bcffcf4b13384d1ad) +зі стартовим кодом. Потім натисніть кнопку "Import", щоб додати програму до +вашого списку проєктів у Solana Playground. ![Import](/assets/docs/intro/quickstart/pg-import.png) -У файлі `lib.rs` ви знайдете шаблон програми з інструкціями `create`, `update` і `delete`, які ми реалізуємо на наступних етапах. +У файлі `lib.rs` ви знайдете шаблон програми з інструкціями `create`, `update` і +`delete`, які ми реалізуємо на наступних етапах. ```rs filename="lib.rs" use anchor_lang::prelude::*; @@ -61,7 +71,9 @@ pub struct Delete {} #[account] pub struct MessageAccount {} ``` -Перед початком виконайте команду `build` у терміналі Playground, щоб переконатися, що стартова програма успішно компілюється. + +Перед початком виконайте команду `build` у терміналі Playground, щоб +переконатися, що стартова програма успішно компілюється. ```shell filename="Terminal" build @@ -81,7 +93,8 @@ Build successful. Completed in 3.50s. ### Визначення Типу Акаунта Повідомлення -Спочатку визначимо структуру акаунта повідомлення, який створюватиме наша програма. Це дані, які ми зберігатимемо в акаунті, створеному програмою. +Спочатку визначимо структуру акаунта повідомлення, який створюватиме наша +програма. Це дані, які ми зберігатимемо в акаунті, створеному програмою. У файлі `lib.rs` оновіть структуру `MessageAccount` наступним кодом: @@ -112,17 +125,27 @@ pub struct MessageAccount { -Макрос `#[account]` у програмі Anchor використовується для позначення структур, які представляють дані акаунта (тип даних, що зберігається у полі даних `AccountInfo`). +Макрос `#[account]` у програмі Anchor використовується для позначення структур, +які представляють дані акаунта (тип даних, що зберігається у полі даних +`AccountInfo`). -У цьому прикладі ми визначаємо структуру `MessageAccount` для зберігання повідомлення, створеного користувачами, яка містить три поля: +У цьому прикладі ми визначаємо структуру `MessageAccount` для зберігання +повідомлення, створеного користувачами, яка містить три поля: -- `user` — `Pubkey`, який представляє користувача, що створив акаунт повідомлення. +- `user` — `Pubkey`, який представляє користувача, що створив акаунт + повідомлення. - `message` — `String`, який містить повідомлення користувача. -- `bump` — `u8`, що зберігає ["bump" seed](/docs/uk/core/pda#canonical-bump), використаний для отримання адреси, створеної програмою (PDA). Зберігання цього значення економить обчислювальні ресурси, оскільки усуває необхідність повторного обчислення для кожного використання в наступних інструкціях. +- `bump` — `u8`, що зберігає ["bump" seed](/docs/uk/core/pda#canonical-bump), + використаний для отримання адреси, створеної програмою (PDA). Зберігання цього + значення економить обчислювальні ресурси, оскільки усуває необхідність + повторного обчислення для кожного використання в наступних інструкціях. -Коли акаунт створюється, дані `MessageAccount` будуть серіалізовані та збережені у полі даних нового акаунта. +Коли акаунт створюється, дані `MessageAccount` будуть серіалізовані та збережені +у полі даних нового акаунта. -Пізніше, під час читання з акаунта, ці дані можна буде десеріалізувати назад у тип даних `MessageAccount`. Процес створення та читання даних акаунта буде продемонстровано у розділі тестування. +Пізніше, під час читання з акаунта, ці дані можна буде десеріалізувати назад у +тип даних `MessageAccount`. Процес створення та читання даних акаунта буде +продемонстровано у розділі тестування. @@ -132,13 +155,17 @@ pub struct MessageAccount { ```shell filename="Terminal" build ``` -Ми визначили, як виглядатиме наш акаунт повідомлення. Далі ми реалізуємо інструкції програми. + +Ми визначили, як виглядатиме наш акаунт повідомлення. Далі ми реалізуємо +інструкції програми. ### Реалізація Інструкції Create -Тепер реалізуємо інструкцію `create` для створення та ініціалізації `MessageAccount`. +Тепер реалізуємо інструкцію `create` для створення та ініціалізації +`MessageAccount`. -Почніть із визначення акаунтів, необхідних для цієї інструкції, оновивши структуру `Create` наступним кодом: +Почніть із визначення акаунтів, необхідних для цієї інструкції, оновивши +структуру `Create` наступним кодом: ```rs filename="lib.rs" #[derive(Accounts)] @@ -188,9 +215,13 @@ pub struct Create<'info> { Макрос `#[derive(Accounts)]` у програмі Anchor використовується для позначення структур, які представляють список акаунтів, необхідних для інструкції, де кожне поле в структурі є акаунтом. -Кожен акаунт (поле) у структурі позначається типом акаунта (наприклад, `Signer<'info>`) і може бути додатково позначений обмеженнями (наприклад, `#[account(mut)]`). Тип акаунта разом із обмеженнями акаунта використовуються для виконання перевірок безпеки акаунтів, переданих до інструкції. +Кожен акаунт (поле) у структурі позначається типом акаунта (наприклад, +`Signer<'info>`) і може бути додатково позначений обмеженнями (наприклад, +`#[account(mut)]`). Тип акаунта разом із обмеженнями акаунта використовуються +для виконання перевірок безпеки акаунтів, переданих до інструкції. -Назви кожного поля використовуються лише для нашого розуміння і не впливають на валідацію акаунтів, однак рекомендується використовувати описові імена акаунтів. +Назви кожного поля використовуються лише для нашого розуміння і не впливають на +валідацію акаунтів, однак рекомендується використовувати описові імена акаунтів. --- @@ -199,48 +230,60 @@ pub struct Create<'info> { 1. `user: Signer<'info>` - Представляє користувача, який створює акаунт повідомлення. - - Позначений як змінний (`#[account(mut)]`), оскільки оплачує створення нового акаунта. - - Повинен бути підписувачем, щоб підтвердити транзакцію, оскільки лампорти будуть списані з акаунта. + - Позначений як змінний (`#[account(mut)]`), оскільки оплачує створення + нового акаунта. + - Повинен бути підписувачем, щоб підтвердити транзакцію, оскільки лампорти + будуть списані з акаунта. 2. `message_account: Account<'info, MessageAccount>` - Новий акаунт, створений для зберігання повідомлення користувача. - Обмеження `init` вказує, що акаунт буде створено в інструкції. - - Обмеження `seeds` і `bump` вказують, що адреса акаунта є Program Derived Address (PDA). + - Обмеження `seeds` і `bump` вказують, що адреса акаунта є Program Derived + Address (PDA). - `payer = user` вказує акаунт, який оплачує створення нового акаунта. - `space` вказує кількість байтів, виділених для поля даних нового акаунта. 3. `system_program: Program<'info, System>` - Необхідна для створення нових акаунтів. - - На рівні механіки обмеження `init` викликає Системну програму для створення нового акаунта з виділенням вказаного `space` та переназначає власника програми на поточну програму. + - На рівні механіки обмеження `init` викликає Системну програму для створення + нового акаунта з виділенням вказаного `space` та переназначає власника + програми на поточну програму. --- -Анотація `#[instruction(message: String)]` дозволяє структурі `Create` отримувати доступ до параметра `message` з інструкції `create`. +Анотація `#[instruction(message: String)]` дозволяє структурі `Create` +отримувати доступ до параметра `message` з інструкції `create`. --- -Обмеження `seeds` і `bump` використовуються разом для вказівки, що адреса акаунта є Program Derived Address (PDA). +Обмеження `seeds` і `bump` використовуються разом для вказівки, що адреса +акаунта є Program Derived Address (PDA). ```rs filename="lib.rs" seeds = [b"message", user.key().as_ref()], bump, ``` -Обмеження `seeds` визначає необов’язкові вхідні значення, які використовуються для отримання PDA: + +Обмеження `seeds` визначає необов’язкові вхідні значення, які використовуються +для отримання PDA: - `b"message"` — Жорстко закодований рядок як перше значення seed. - `user.key().as_ref()` — Публічний ключ акаунта `user` як друге значення seed. -Обмеження `bump` вказує Anchor автоматично знайти та використовувати правильний bump seed. Anchor використовує `seeds` і `bump` для отримання PDA. +Обмеження `bump` вказує Anchor автоматично знайти та використовувати правильний +bump seed. Anchor використовує `seeds` і `bump` для отримання PDA. --- -Розрахунок `space` (8 + 32 + 4 + message.len() + 1) виділяє простір для даних типу `MessageAccount`: +Розрахунок `space` (8 + 32 + 4 + message.len() + 1) виділяє простір для даних +типу `MessageAccount`: - Дискримінатор акаунта Anchor (ідентифікатор): 8 байтів - Адреса користувача (Pubkey): 32 байти -- Повідомлення користувача (String): 4 байти для довжини + змінна довжина повідомлення +- Повідомлення користувача (String): 4 байти для довжини + змінна довжина + повідомлення - Bump seed для PDA (u8): 1 байт ```rs filename="lib.rs" @@ -251,14 +294,19 @@ pub struct MessageAccount { pub bump: u8, } ``` -Усі акаунти, створені за допомогою програми Anchor, вимагають 8 байтів для дискримінатора акаунта, який є ідентифікатором типу акаунта і генерується автоматично під час створення акаунта. -Тип `String` вимагає 4 байти для зберігання довжини рядка, а решта — це фактичні дані. +Усі акаунти, створені за допомогою програми Anchor, вимагають 8 байтів для +дискримінатора акаунта, який є ідентифікатором типу акаунта і генерується +автоматично під час створення акаунта. + +Тип `String` вимагає 4 байти для зберігання довжини рядка, а решта — це фактичні +дані. -Далі реалізуйте бізнес-логіку для інструкції `create`, оновивши функцію `create` наступним кодом: +Далі реалізуйте бізнес-логіку для інструкції `create`, оновивши функцію `create` +наступним кодом: ```rs filename="lib.rs" pub fn create(ctx: Context, message: String) -> Result<()> { @@ -292,9 +340,11 @@ pub fn create(ctx: Context, message: String) -> Result<()> { -Функція `create` реалізує логіку для ініціалізації даних нового акаунта повідомлення. Вона приймає два параметри: +Функція `create` реалізує логіку для ініціалізації даних нового акаунта +повідомлення. Вона приймає два параметри: -1. `ctx: Context` — Надає доступ до акаунтів, зазначених у структурі `Create`. +1. `ctx: Context` — Надає доступ до акаунтів, зазначених у структурі + `Create`. 2. `message: String` — Повідомлення користувача, яке буде збережено. Тіло функції виконує наступну логіку: @@ -304,15 +354,17 @@ pub fn create(ctx: Context, message: String) -> Result<()> { ```rs msg!("Create Message: {}", message); ``` + 2. Ініціалізація Даних Акаунта: - Отримує доступ до `message_account` з контексту. - + ```rs let account_data = &mut ctx.accounts.message_account; ``` + - Встановлює поле `user` як публічний ключ акаунта `user`. - + ```rs account_data.user = ctx.accounts.user.key(); ``` @@ -322,7 +374,9 @@ pub fn create(ctx: Context, message: String) -> Result<()> { ```rs account_data.message = message; ``` - - Встановлює значення `bump`, використане для отримання PDA, отримане з `ctx.bumps.message_account`. + + - Встановлює значення `bump`, використане для отримання PDA, отримане з + `ctx.bumps.message_account`. ```rs account_data.bump = ctx.bumps.message_account; @@ -336,11 +390,14 @@ pub fn create(ctx: Context, message: String) -> Result<()> { ```shell filename="Terminal" build ``` + ### Реалізація Інструкції Update -Далі реалізуйте інструкцію `update` для оновлення `MessageAccount` новим повідомленням. +Далі реалізуйте інструкцію `update` для оновлення `MessageAccount` новим +повідомленням. -Як і раніше, першим кроком є визначення акаунтів, необхідних для інструкції `update`. +Як і раніше, першим кроком є визначення акаунтів, необхідних для інструкції +`update`. Оновіть структуру `Update` наступним кодом: @@ -397,7 +454,8 @@ pub struct Update<'info> { 1. `user: Signer<'info>` - Представляє користувача, який оновлює акаунт повідомлення. - - Позначений як змінний (`#[account(mut)]`), оскільки може оплачувати додатковий простір для `message_account`, якщо це необхідно. + - Позначений як змінний (`#[account(mut)]`), оскільки може оплачувати + додатковий простір для `message_account`, якщо це необхідно. - Повинен бути підписувачем для підтвердження транзакції. 2. `message_account: Account<'info, MessageAccount>` @@ -410,15 +468,19 @@ pub struct Update<'info> { 3. `system_program: Program<'info, System>` - Необхідна для можливої зміни розміру простору акаунта. - - Обмеження `realloc` викликає Системну програму для налаштування розміру даних акаунта. + - Обмеження `realloc` викликає Системну програму для налаштування розміру + даних акаунта. --- -Зверніть увагу, що обмеження `bump = message_account.bump` використовує bump seed, який зберігається в `message_account`, замість того, щоб Anchor обчислював його знову. +Зверніть увагу, що обмеження `bump = message_account.bump` використовує bump +seed, який зберігається в `message_account`, замість того, щоб Anchor обчислював +його знову. --- -Анотація `#[instruction(message: String)]` дозволяє структурі `Update` отримувати доступ до параметра `message` з інструкції `update`. +Анотація `#[instruction(message: String)]` дозволяє структурі `Update` +отримувати доступ до параметра `message` з інструкції `update`. @@ -454,7 +516,8 @@ pub fn update(ctx: Context, message: String) -> Result<()> { Функція `update` реалізує логіку для модифікації існуючого акаунта повідомлення. Вона приймає два параметри: -1. `ctx: Context` — Надає доступ до акаунтів, зазначених у структурі `Update`. +1. `ctx: Context` — Надає доступ до акаунтів, зазначених у структурі + `Update`. 2. `message: String` — Нове повідомлення, яке замінить існуюче. Тіло функції виконує такі дії: @@ -473,6 +536,7 @@ pub fn update(ctx: Context, message: String) -> Result<()> { ```shell filename="Terminal" build ``` + ### Реалізація Інструкції Delete Далі реалізуйте інструкцію `delete` для закриття `MessageAccount`. @@ -525,15 +589,18 @@ pub struct Delete<'info> { 1. `user: Signer<'info>` - Представляє користувача, який закриває акаунт повідомлення. - - Позначений як змінний (`#[account(mut)]`), оскільки він отримуватиме лампорти з закритого акаунта. - - Повинен бути підписувачем, щоб гарантувати, що тільки відповідний користувач може закрити свій акаунт повідомлення. + - Позначений як змінний (`#[account(mut)]`), оскільки він отримуватиме + лампорти з закритого акаунта. + - Повинен бути підписувачем, щоб гарантувати, що тільки відповідний + користувач може закрити свій акаунт повідомлення. 2. `message_account: Account<'info, MessageAccount>` - Акаунт, який буде закритий. - Обмеження `mut` вказує, що цей акаунт буде змінено. - Обмеження `seeds` і `bump` гарантують, що акаунт є правильним PDA. - - Обмеження `close = user` вказує, що цей акаунт буде закритий, а його лампорти передані в акаунт `user`. + - Обмеження `close = user` вказує, що цей акаунт буде закритий, а його + лампорти передані в акаунт `user`. @@ -566,9 +633,13 @@ pub fn delete(_ctx: Context) -> Result<()> { Функція `delete` приймає один параметр: -1. `_ctx: Context` — Надає доступ до акаунтів, зазначених у структурі `Delete`. Використання `_ctx` вказує, що контекст не буде використовуватися в тілі функції. +1. `_ctx: Context` — Надає доступ до акаунтів, зазначених у структурі + `Delete`. Використання `_ctx` вказує, що контекст не буде використовуватися в + тілі функції. -Тіло функції лише виводить повідомлення у журнали програми за допомогою макроса `msg!()`. Додаткова логіка не потрібна, оскільки фактичне закриття акаунта виконується за допомогою обмеження `close` у структурі `Delete`. +Тіло функції лише виводить повідомлення у журнали програми за допомогою макроса +`msg!()`. Додаткова логіка не потрібна, оскільки фактичне закриття акаунта +виконується за допомогою обмеження `close` у структурі `Delete`. @@ -581,7 +652,8 @@ build ### Розгортання Програми -Базова CRUD-програма завершена. Розгорніть програму, виконавши команду `deploy` у терміналі Playground. +Базова CRUD-програма завершена. Розгорніть програму, виконавши команду `deploy` +у терміналі Playground. ```shell filename="Terminal" deploy @@ -614,6 +686,7 @@ describe("pda", () => { it("Delete Message Account", async () => {}); }); ``` + Додайте наведений нижче код всередину блоку `describe`, але перед секціями `it`. ```ts filename="anchor.test.ts" @@ -654,15 +727,17 @@ const [messagePda, messageBump] = PublicKey.findProgramAddressSync( У цьому розділі ми просто налаштовуємо тестовий файл. -Solana Playground спрощує початкову підготовку: `pg.program` дозволяє отримати доступ до клієнтської бібліотеки для взаємодії з програмою, а `pg.wallet` представляє ваш гаманець у Playground. +Solana Playground спрощує початкову підготовку: `pg.program` дозволяє отримати +доступ до клієнтської бібліотеки для взаємодії з програмою, а `pg.wallet` +представляє ваш гаманець у Playground. ```ts filename="anchor.test.ts" const program = pg.program; const wallet = pg.wallet; ``` -У рамках налаштування ми отримуємо PDA акаунта повідомлення. Це демонструє, як отримати PDA у Javascript, використовуючи сіди, визначені у програмі. - +У рамках налаштування ми отримуємо PDA акаунта повідомлення. Це демонструє, як +отримати PDA у Javascript, використовуючи сіди, визначені у програмі. ```ts filename="anchor.test.ts" const [messagePda, messageBump] = PublicKey.findProgramAddressSync( @@ -674,8 +749,9 @@ const [messagePda, messageBump] = PublicKey.findProgramAddressSync( -Запустіть тестовий файл, виконавши команду `test` у терміналі Playground, щоб переконатися, що файл працює, як очікувалося. Ми реалізуємо тести на наступних етапах. - +Запустіть тестовий файл, виконавши команду `test` у терміналі Playground, щоб +переконатися, що файл працює, як очікувалося. Ми реалізуємо тести на наступних +етапах. ```shell filename="Terminal" test @@ -702,7 +778,6 @@ Running tests... Оновіть перший тест наступним кодом: - ```ts filename="anchor.test.ts" it("Create Message Account", async () => { const message = "Hello, World!"; @@ -757,8 +832,8 @@ it("Create Message Account", async () => { -Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `create`, передаючи "Hello, World!" як повідомлення. - +Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `create`, передаючи +"Hello, World!" як повідомлення. ```ts filename="anchor.test.ts" const message = "Hello, World!"; @@ -770,8 +845,8 @@ const transactionSignature = await program.methods .rpc({ commitment: "confirmed" }); ``` -Після надсилання транзакції та створення акаунта ми отримуємо акаунт за його адресою (`messagePda`). - +Після надсилання транзакції та створення акаунта ми отримуємо акаунт за його +адресою (`messagePda`). ```ts filename="anchor.test.ts" const messageAccount = await program.account.messageAccount.fetch( @@ -780,8 +855,8 @@ const messageAccount = await program.account.messageAccount.fetch( ); ``` -Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей транзакції. - +Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей +транзакції. ```ts filename="anchor.test.ts" console.log(JSON.stringify(messageAccount, null, 2)); @@ -798,7 +873,6 @@ console.log( Оновіть другий тест наступним кодом: - ```ts filename="anchor.test.ts" it("Update Message Account", async () => { const message = "Hello, Solana!"; @@ -853,8 +927,8 @@ it("Update Message Account", async () => { -Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `update`, передаючи "Hello, Solana!" як нове повідомлення. - +Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `update`, передаючи +"Hello, Solana!" як нове повідомлення. ```ts filename="anchor.test.ts" const message = "Hello, Solana!"; @@ -866,7 +940,8 @@ const transactionSignature = await program.methods .rpc({ commitment: "confirmed" }); ``` -Після надсилання транзакції та оновлення акаунта ми отримуємо акаунт за його адресою (`messagePda`). +Після надсилання транзакції та оновлення акаунта ми отримуємо акаунт за його +адресою (`messagePda`). ```ts filename="anchor.test.ts" const messageAccount = await program.account.messageAccount.fetch( @@ -875,8 +950,8 @@ const messageAccount = await program.account.messageAccount.fetch( ); ``` -Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей транзакції. - +Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей +транзакції. ```ts filename="anchor.test.ts" console.log(JSON.stringify(messageAccount, null, 2)); @@ -893,7 +968,6 @@ console.log( Оновіть третій тест наступним кодом: - ```ts filename="anchor.test.ts" it("Delete Message Account", async () => { const transactionSignature = await program.methods @@ -946,8 +1020,8 @@ it("Delete Message Account", async () => { -Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `delete` для закриття акаунта повідомлення. - +Спочатку ми надсилаємо транзакцію, яка викликає інструкцію `delete` для закриття +акаунта повідомлення. ```ts filename="anchor.test.ts" const transactionSignature = await program.methods @@ -958,8 +1032,9 @@ const transactionSignature = await program.methods .rpc({ commitment: "confirmed" }); ``` -Після надсилання транзакції та закриття акаунта ми намагаємося отримати акаунт за його адресою (`messagePda`), використовуючи `fetchNullable`, оскільки ми очікуємо, що результат буде `null`, тому що акаунт закритий. - +Після надсилання транзакції та закриття акаунта ми намагаємося отримати акаунт +за його адресою (`messagePda`), використовуючи `fetchNullable`, оскільки ми +очікуємо, що результат буде `null`, тому що акаунт закритий. ```ts filename="anchor.test.ts" const messageAccount = await program.account.messageAccount.fetchNullable( @@ -968,8 +1043,8 @@ const messageAccount = await program.account.messageAccount.fetchNullable( ); ``` -Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей транзакції, де дані акаунта повинні бути відображені як `null`. - +Нарешті, ми виводимо у журнал дані акаунта та посилання для перегляду деталей +транзакції, де дані акаунта повинні бути відображені як `null`. ```ts filename="anchor.test.ts" console.log(JSON.stringify(messageAccount, null, 2)); @@ -984,8 +1059,8 @@ console.log( ### Запуск Тестів -Після налаштування тестів запустіть тестовий файл, виконавши команду `test` у терміналі Playground. - +Після налаштування тестів запустіть тестовий файл, виконавши команду `test` у +терміналі Playground. ```shell filename="Terminal" test diff --git a/docs/locales/uk/intro/quick-start/reading-from-network.md b/docs/locales/uk/intro/quick-start/reading-from-network.md index 1403a31ef..e7dd00e7f 100644 --- a/docs/locales/uk/intro/quick-start/reading-from-network.md +++ b/docs/locales/uk/intro/quick-start/reading-from-network.md @@ -4,33 +4,47 @@ title: Читання з Мережі sidebarSortOrder: 1 description: Дізнайтеся, як зчитувати дані з блокчейн-мережі Solana. Цей посібник охоплює - отримання акаунтів гаманців, програмних акаунтів і акаунтів випуску токенів - за допомогою JavaScript/TypeScript із практичними прикладами на основі - бібліотеки Solana web3.js. + отримання акаунтів гаманців, програмних акаунтів і акаунтів випуску токенів за + допомогою JavaScript/TypeScript із практичними прикладами на основі бібліотеки + Solana web3.js. --- -Давайте розглянемо, як зчитувати дані з мережі Solana. Ми отримаємо кілька різних акаунтів, щоб зрозуміти структуру акаунта Solana. +Давайте розглянемо, як зчитувати дані з мережі Solana. Ми отримаємо кілька +різних акаунтів, щоб зрозуміти структуру акаунта Solana. -У Solana всі дані містяться у так званих "акаунтах". Ви можете думати про дані в Solana як про загальнодоступну базу даних із єдиною таблицею "Accounts", де кожен запис у цій таблиці є окремим акаунтом. +У Solana всі дані містяться у так званих "акаунтах". Ви можете думати про дані в +Solana як про загальнодоступну базу даних із єдиною таблицею "Accounts", де +кожен запис у цій таблиці є окремим акаунтом. -Акаунти Solana можуть містити "стан" або виконувані програми, які можна розглядати як записи в одній таблиці "Accounts". Кожен акаунт має "адресу" (публічний ключ), яка є унікальним ідентифікатором для доступу до відповідних даних у блокчейні. +Акаунти Solana можуть містити "стан" або виконувані програми, які можна +розглядати як записи в одній таблиці "Accounts". Кожен акаунт має "адресу" +(публічний ключ), яка є унікальним ідентифікатором для доступу до відповідних +даних у блокчейні. Акаунти Solana можуть містити: -- **Стан**: Дані, які призначені для зчитування і зберігання. Це може бути інформація про токени, дані користувачів або будь-які інші дані, визначені у програмі. -- **Виконувані програми**: Акаунти, які містять фактичний код програм Solana. Вони включають інструкції, які можна виконувати у мережі. +- **Стан**: Дані, які призначені для зчитування і зберігання. Це може бути + інформація про токени, дані користувачів або будь-які інші дані, визначені у + програмі. +- **Виконувані програми**: Акаунти, які містять фактичний код програм Solana. + Вони включають інструкції, які можна виконувати у мережі. -Цей поділ програмного коду та стану програми є ключовою особливістю Моделі Акаунтів Solana. Для отримання додаткової інформації відвідайте сторінку [Модель Акаунтів Solana](/docs/uk/core/accounts). +Цей поділ програмного коду та стану програми є ключовою особливістю Моделі +Акаунтів Solana. Для отримання додаткової інформації відвідайте сторінку +[Модель Акаунтів Solana](/docs/uk/core/accounts). ## Отримання Гаманця Playground -Почнемо з розгляду знайомого акаунта — вашого власного гаманця Playground! Ми отримаємо цей акаунт і розглянемо його структуру, щоб зрозуміти, як виглядає базовий акаунт Solana. +Почнемо з розгляду знайомого акаунта — вашого власного гаманця Playground! Ми +отримаємо цей акаунт і розглянемо його структуру, щоб зрозуміти, як виглядає +базовий акаунт Solana. ### Відкриття Прикладу 1 -Натисніть це [посилання](https://beta.solpg.io/6671c5e5cffcf4b13384d198), щоб відкрити приклад у Solana Playground. Ви побачите такий код: +Натисніть це [посилання](https://beta.solpg.io/6671c5e5cffcf4b13384d198), щоб +відкрити приклад у Solana Playground. Ви побачите такий код: ```ts filename="client.ts" const address = pg.wallet.publicKey; @@ -73,7 +87,8 @@ console.log(JSON.stringify(accountInfo, null, 2)); run ``` -Ви повинні побачити деталі вашого акаунта гаманця, включаючи його баланс у лампортах, із результатом, схожим на наступний: +Ви повинні побачити деталі вашого акаунта гаманця, включаючи його баланс у +лампортах, із результатом, схожим на наступний: @@ -98,23 +113,36 @@ Running client... -Ваш гаманець насправді є лише акаунтом, яким керує Системна програма. Основна мета акаунта гаманця — зберігати баланс SOL (значення у полі `lamports`). +Ваш гаманець насправді є лише акаунтом, яким керує Системна програма. Основна +мета акаунта гаманця — зберігати баланс SOL (значення у полі `lamports`). --- -В основі всі акаунти Solana представлені у стандартному форматі, який називається `AccountInfo`. Тип даних [AccountInfo](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/account_info.rs#L19-L36) є базовою структурою даних для всіх акаунтів Solana. +В основі всі акаунти Solana представлені у стандартному форматі, який +називається `AccountInfo`. Тип даних +[AccountInfo](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/account_info.rs#L19-L36) +є базовою структурою даних для всіх акаунтів Solana. Розберемо поля у виведених даних: -- `data` — Це поле містить те, що ми зазвичай називаємо "даними" акаунта. Для гаманця воно порожнє (0 байтів), але інші акаунти використовують це поле для зберігання будь-яких довільних даних у вигляді серіалізованого буфера байтів. +- `data` — Це поле містить те, що ми зазвичай називаємо "даними" акаунта. Для + гаманця воно порожнє (0 байтів), але інші акаунти використовують це поле для + зберігання будь-яких довільних даних у вигляді серіалізованого буфера байтів. -> Коли дані "буферизуються" таким чином, вони зберігають свою цілісність і можуть пізніше бути десеріалізовані назад у свій початковий вигляд для використання у програмах. Цей процес широко використовується в блокчейні для ефективної обробки даних. +> Коли дані "буферизуються" таким чином, вони зберігають свою цілісність і +> можуть пізніше бути десеріалізовані назад у свій початковий вигляд для +> використання у програмах. Цей процес широко використовується в блокчейні для +> ефективної обробки даних. -- `executable` — Прапорець, який вказує, чи є акаунт виконуваною програмою. Для гаманців та будь-яких акаунтів, які зберігають стан, значення `false`. -- `owner` — Це поле показує, яка програма контролює акаунт. Для гаманців це завжди Системна програма з адресою `11111111111111111111111111111111`. +- `executable` — Прапорець, який вказує, чи є акаунт виконуваною програмою. Для + гаманців та будь-яких акаунтів, які зберігають стан, значення `false`. +- `owner` — Це поле показує, яка програма контролює акаунт. Для гаманців це + завжди Системна програма з адресою `11111111111111111111111111111111`. - `lamports` — Баланс акаунта у лампортах (1 SOL = 1,000,000,000 лампортів). -- `rentEpoch` — Поле, пов’язане зі старим механізмом збору оренди Solana (наразі не використовується). -- `space` — Вказує ємність (довжину) поля `data`, але не є полем типу `AccountInfo`. +- `rentEpoch` — Поле, пов’язане зі старим механізмом збору оренди Solana (наразі + не використовується). +- `space` — Вказує ємність (довжину) поля `data`, але не є полем типу + `AccountInfo`. @@ -123,13 +151,15 @@ Running client... ## Отримання Програми Token Program -Далі ми розглянемо програму Token Extensions, яка є виконуваною програмою для взаємодії з токенами на Solana. +Далі ми розглянемо програму Token Extensions, яка є виконуваною програмою для +взаємодії з токенами на Solana. ### Відкриття Прикладу 2 -Натисніть це [посилання](https://beta.solpg.io/6671c6e7cffcf4b13384d199), щоб відкрити приклад у Solana Playground. Ви побачите такий код: +Натисніть це [посилання](https://beta.solpg.io/6671c6e7cffcf4b13384d199), щоб +відкрити приклад у Solana Playground. Ви побачите такий код: ```ts filename="client.ts" {3} import { PublicKey } from "@solana/web3.js"; @@ -139,17 +169,20 @@ const accountInfo = await pg.connection.getAccountInfo(address); console.log(JSON.stringify(accountInfo, null, 2)); ``` -Замість отримання вашого гаманця Playground, тут ми отримуємо адресу акаунта програми Token Extensions. + +Замість отримання вашого гаманця Playground, тут ми отримуємо адресу акаунта +програми Token Extensions. ### Запуск Прикладу 2 Запустіть код, виконавши команду `run` у терміналі. - ```shell filename="Terminal" run ``` -Ознайомтеся з виведеними даними та тим, чим цей акаунт програми відрізняється від вашого акаунта гаманця. + +Ознайомтеся з виведеними даними та тим, чим цей акаунт програми відрізняється +від вашого акаунта гаманця. @@ -180,13 +213,19 @@ Running client... -Програма Token Extensions є виконуваним акаунтом програми, але має таку ж структуру `AccountInfo`. +Програма Token Extensions є виконуваним акаунтом програми, але має таку ж +структуру `AccountInfo`. Основні відмінності в `AccountInfo`: -- **`executable`** — Встановлено у `true`, що вказує на те, що цей акаунт є виконуваною програмою. -- **`data`** — Містить серіалізовані дані (на відміну від порожніх даних у акаунті гаманця). Дані для акаунта програми зберігають адресу іншого акаунта (Program Executable Data Account), який містить байт-код програми. -- **`owner`** — Акаунт належить завантажувачу Upgradable BPF Loader (`BPFLoaderUpgradeab1e11111111111111111111111`), спеціальній програмі, яка управляє виконуваними акаунтами. +- **`executable`** — Встановлено у `true`, що вказує на те, що цей акаунт є + виконуваною програмою. +- **`data`** — Містить серіалізовані дані (на відміну від порожніх даних у + акаунті гаманця). Дані для акаунта програми зберігають адресу іншого акаунта + (Program Executable Data Account), який містить байт-код програми. +- **`owner`** — Акаунт належить завантажувачу Upgradable BPF Loader + (`BPFLoaderUpgradeab1e11111111111111111111111`), спеціальній програмі, яка + управляє виконуваними акаунтами. --- @@ -195,7 +234,8 @@ Running client... та його відповідного [Program Executable Data Account](https://explorer.solana.com/address/DoU57AYuPFu2QU514RktNPG22QhApEjnKxnBcu4BHDTY). -Program Executable Data Account містить скомпільований байт-код програми Token Extensions +Program Executable Data Account містить скомпільований байт-код програми Token +Extensions [вихідний код](https://github.com/solana-labs/solana-program-library/tree/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program-2022/src). @@ -205,14 +245,15 @@ Program Executable Data Account містить скомпільований ба ## Отримання Акаунта Mint -На цьому етапі ми розглянемо акаунт Mint, який представляє унікальний токен у мережі Solana. +На цьому етапі ми розглянемо акаунт Mint, який представляє унікальний токен у +мережі Solana. ### Відкриття Прикладу 3 -Натисніть це [посилання](https://beta.solpg.io/6671c9aecffcf4b13384d19a), щоб відкрити приклад у Solana Playground. Ви побачите такий код: - +Натисніть це [посилання](https://beta.solpg.io/6671c9aecffcf4b13384d19a), щоб +відкрити приклад у Solana Playground. Ви побачите такий код: ```ts filename="client.ts" {3} import { PublicKey } from "@solana/web3.js"; @@ -222,13 +263,13 @@ const accountInfo = await pg.connection.getAccountInfo(address); console.log(JSON.stringify(accountInfo, null, 2)); ``` + У цьому прикладі ми отримаємо адресу існуючого акаунта Mint у devnet. ### Запуск Прикладу 3 Запустіть код, виконавши команду `run`. - ```shell filename="Terminal" run ``` @@ -264,20 +305,33 @@ Running client... Основні відмінності в `AccountInfo`: -- **`owner`** — Акаунт mint належить програмі Token Extensions (`TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`). -- **`executable`** — Встановлено у `false`, оскільки цей акаунт зберігає стан, а не виконуваний код. -- **`data`** — Містить серіалізовані дані про токен (авторитет випуску, загальну кількість, кількість знаків після коми тощо). +- **`owner`** — Акаунт mint належить програмі Token Extensions + (`TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`). +- **`executable`** — Встановлено у `false`, оскільки цей акаунт зберігає стан, а + не виконуваний код. +- **`data`** — Містить серіалізовані дані про токен (авторитет випуску, загальну + кількість, кількість знаків після коми тощо). ### Десеріалізація Даних Акаунта Mint -Щоб зчитати поле `data` з будь-якого акаунта, потрібно десеріалізувати буфер даних у очікуваний тип даних. Це часто виконується за допомогою допоміжних функцій клієнтських бібліотек для конкретної програми. +Щоб зчитати поле `data` з будь-якого акаунта, потрібно десеріалізувати буфер +даних у очікуваний тип даних. Це часто виконується за допомогою допоміжних +функцій клієнтських бібліотек для конкретної програми. -**Десеріалізація** — це процес перетворення даних зі збереженого формату (наприклад, необроблених байтів або JSON) назад у використовуваний структурований формат у програмі. У блокчейні це включає взяття необроблених, закодованих даних із мережі та їх перетворення назад в об'єкти, класи або читабельні структури, щоб розробники могли отримати доступ до конкретної інформації та маніпулювати нею у програмі. Десеріалізація є важливою для інтерпретації даних акаунтів або транзакцій, отриманих із мережі, у формі, яку програма може обробляти і відображати осмислено. +**Десеріалізація** — це процес перетворення даних зі збереженого формату +(наприклад, необроблених байтів або JSON) назад у використовуваний +структурований формат у програмі. У блокчейні це включає взяття необроблених, +закодованих даних із мережі та їх перетворення назад в об'єкти, класи або +читабельні структури, щоб розробники могли отримати доступ до конкретної +інформації та маніпулювати нею у програмі. Десеріалізація є важливою для +інтерпретації даних акаунтів або транзакцій, отриманих із мережі, у формі, яку +програма може обробляти і відображати осмислено. -Відкрийте цей [приклад](https://beta.solpg.io/6671cd8acffcf4b13384d19b) у Solana Playground. Ви побачите такий код: +Відкрийте цей [приклад](https://beta.solpg.io/6671cd8acffcf4b13384d19b) у Solana +Playground. Ви побачите такий код: ```ts filename="client.ts" import { PublicKey } from "@solana/web3.js"; @@ -294,13 +348,15 @@ const mintData = await getMint( console.log(mintData); ``` -Цей приклад використовує функцію `getMint`, яка автоматично десеріалізує поле `data` акаунта Mint. +Цей приклад використовує функцію `getMint`, яка автоматично десеріалізує поле +`data` акаунта Mint. Запустіть код, виконавши команду `run`. ```shell filename="Terminal" run ``` + Ви повинні побачити наступні десеріалізовані дані акаунта Mint. @@ -321,20 +377,25 @@ Running client... -Функція `getMint` десеріалізує дані акаунта у тип даних [Mint](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32), визначений у вихідному коді програми Token Extensions. +Функція `getMint` десеріалізує дані акаунта у тип даних +[Mint](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32), +визначений у вихідному коді програми Token Extensions. - **`address`** — Адреса акаунта Mint. - **`mintAuthority`** — Авторитет, який може випускати нові токени. - **`supply`** — Загальна кількість токенів в обігу. - **`decimals`** — Кількість десяткових знаків для токена. - **`isInitialized`** — Чи були дані Mint ініціалізовані. -- **`freezeAuthority`** — Авторитет, який має право заморожувати акаунти токенів. -- **`tlvData`** — Додаткові дані для Token Extensions (вимагають подальшої десеріалізації). +- **`freezeAuthority`** — Авторитет, який має право заморожувати акаунти + токенів. +- **`tlvData`** — Додаткові дані для Token Extensions (вимагають подальшої + десеріалізації). -Ви можете переглянути повністю десеріалізовані [дані акаунта Mint](https://explorer.solana.com/address/C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR?cluster=devnet), включаючи активовані Token Extensions, у Solana Explorer. +Ви можете переглянути повністю десеріалізовані +[дані акаунта Mint](https://explorer.solana.com/address/C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR?cluster=devnet), +включаючи активовані Token Extensions, у Solana Explorer. - diff --git a/docs/locales/uk/intro/quick-start/writing-to-network.md b/docs/locales/uk/intro/quick-start/writing-to-network.md index 1e17da27f..37bbbc4bf 100644 --- a/docs/locales/uk/intro/quick-start/writing-to-network.md +++ b/docs/locales/uk/intro/quick-start/writing-to-network.md @@ -4,23 +4,33 @@ title: Запис у Мережу sidebarSortOrder: 2 description: Дізнайтеся, як взаємодіяти з мережею Solana шляхом надсилання транзакцій та - інструкцій. Слідуйте покроковим прикладам для переказу токенів SOL та створення - нових токенів за допомогою System Program та Token Extensions Program. + інструкцій. Слідуйте покроковим прикладам для переказу токенів SOL та + створення нових токенів за допомогою System Program та Token Extensions + Program. --- -Тепер, коли ми розглянули зчитування даних із мережі Solana, давайте навчимося записувати дані до неї. У Solana взаємодія з мережею здійснюється шляхом надсилання транзакцій, що складаються з інструкцій. Ці інструкції визначаються програмами, які містять бізнес-логіку про те, як мають оновлюватися акаунти. +Тепер, коли ми розглянули зчитування даних із мережі Solana, давайте навчимося +записувати дані до неї. У Solana взаємодія з мережею здійснюється шляхом +надсилання транзакцій, що складаються з інструкцій. Ці інструкції визначаються +програмами, які містять бізнес-логіку про те, як мають оновлюватися акаунти. -Розглянемо два поширені операції, переказ SOL і створення токена, щоб продемонструвати, як створювати і надсилати транзакції. Для отримання додаткової інформації відвідайте сторінки [Транзакції та Інструкції](/docs/uk/core/transactions) і [Комісії у Solana](/docs/uk/core/fees). +Розглянемо два поширені операції, переказ SOL і створення токена, щоб +продемонструвати, як створювати і надсилати транзакції. Для отримання додаткової +інформації відвідайте сторінки +[Транзакції та Інструкції](/docs/uk/core/transactions) і +[Комісії у Solana](/docs/uk/core/fees). ## Переказ SOL -Почнемо із простої операції переказу SOL з вашого гаманця на інший акаунт. Це вимагає виклику інструкції переказу у System Program. +Почнемо із простої операції переказу SOL з вашого гаманця на інший акаунт. Це +вимагає виклику інструкції переказу у System Program. ### Відкриття Прикладу 1 -Натисніть це [посилання](https://beta.solpg.io/6671d85ecffcf4b13384d19e), щоб відкрити приклад у Solana Playground. Ви побачите такий код: +Натисніть це [посилання](https://beta.solpg.io/6671d85ecffcf4b13384d19e), щоб +відкрити приклад у Solana Playground. Ви побачите такий код: ```ts filename="client.ts" import { @@ -97,7 +107,8 @@ console.log( ); ``` -- Виводить посилання на SolanaFM у термінал Playground для перегляду деталей транзакції. +- Виводить посилання на SolanaFM у термінал Playground для перегляду деталей + транзакції. ```ts console.log( @@ -113,12 +124,12 @@ console.log( Запустіть код, виконавши команду `run`. - ```shell filename="Terminal" run ``` -Натисніть на посилання у виведених даних, щоб переглянути деталі транзакції у SolanaFM Explorer. +Натисніть на посилання у виведених даних, щоб переглянути деталі транзакції у +SolanaFM Explorer. @@ -134,13 +145,16 @@ Running client... ![Transfer SOL](/assets/docs/intro/quickstart/transfer-sol.png) -Ви щойно надіслали свою першу транзакцію у Solana! Зверніть увагу, як ми створили інструкцію, додали її до транзакції, а потім відправили цю транзакцію до мережі. Це базовий процес для створення будь-якої транзакції. +Ви щойно надіслали свою першу транзакцію у Solana! Зверніть увагу, як ми +створили інструкцію, додали її до транзакції, а потім відправили цю транзакцію +до мережі. Це базовий процес для створення будь-якої транзакції. ## Створення Токена -Тепер створимо новий токен шляхом створення та ініціалізації акаунта Mint. Для цього потрібні дві інструкції: +Тепер створимо новий токен шляхом створення та ініціалізації акаунта Mint. Для +цього потрібні дві інструкції: - Виклик System Program для створення нового акаунта. - Виклик Token Extensions Program для ініціалізації даних акаунта. @@ -149,7 +163,8 @@ Running client... ### Відкриття Прикладу 2 -Натисніть це [посилання](https://beta.solpg.io/6671da4dcffcf4b13384d19f), щоб відкрити приклад у Solana Playground. Ви побачите наступний код: +Натисніть це [посилання](https://beta.solpg.io/6671da4dcffcf4b13384d19f), щоб +відкрити приклад у Solana Playground. Ви побачите наступний код: ```ts filename="client.ts" import { @@ -226,6 +241,7 @@ console.log( Цей скрипт виконує наступні кроки: - Налаштовує ваш гаманець Playground і з'єднання з devnet Solana: + ```ts const wallet = pg.wallet; const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); @@ -243,7 +259,8 @@ console.log( const rentLamports = await getMinimumBalanceForRentExemptMint(connection); ``` -- Створює інструкцію для створення нового акаунта mint, вказуючи програму Token Extensions (TOKEN_2022_PROGRAM_ID) як власника нового акаунта: +- Створює інструкцію для створення нового акаунта mint, вказуючи програму Token + Extensions (TOKEN_2022_PROGRAM_ID) як власника нового акаунта: ```ts const createAccountInstruction = SystemProgram.createAccount({ @@ -276,7 +293,10 @@ console.log( ); ``` -- Відправляє та підтверджує транзакцію. Гаманець і ключова пара mint передаються як підписувачі транзакції. Гаманець потрібен для оплати створення нового акаунта, а ключова пара mint потрібна, оскільки її публічний ключ використовується як адреса нового акаунта: +- Відправляє та підтверджує транзакцію. Гаманець і ключова пара mint передаються + як підписувачі транзакції. Гаманець потрібен для оплати створення нового + акаунта, а ключова пара mint потрібна, оскільки її публічний ключ + використовується як адреса нового акаунта: ```ts const transactionSignature = await sendAndConfirmTransaction( @@ -286,7 +306,8 @@ console.log( ); ``` -- Виводить посилання для перегляду транзакції та деталей акаунта mint на SolanaFM: +- Виводить посилання для перегляду транзакції та деталей акаунта mint на + SolanaFM: ```ts console.log( @@ -316,7 +337,8 @@ run - Одне для деталей транзакції - Інше для новоствореного акаунта mint -Натисніть на посилання, щоб переглянути деталі транзакції та новостворений акаунт mint у SolanaFM. +Натисніть на посилання, щоб переглянути деталі транзакції та новостворений +акаунт mint у SolanaFM. @@ -337,6 +359,9 @@ Mint Account: https://solana.fm/address/CoZ3Nz488rmATDhy1hPk5fvwSZaipCngvf8rYBYV ![Mint Account](/assets/docs/intro/quickstart/mint-account.png) -Зверніть увагу, як цього разу ми створили транзакцію з кількома інструкціями. Спочатку ми створили новий акаунт, а потім ініціалізували його дані як mint. Таким чином створюються складніші транзакції, які включають інструкції з кількох програм. +Зверніть увагу, як цього разу ми створили транзакцію з кількома інструкціями. +Спочатку ми створили новий акаунт, а потім ініціалізували його дані як mint. +Таким чином створюються складніші транзакції, які включають інструкції з кількох +програм. diff --git a/docs/locales/uk/intro/wallets.md b/docs/locales/uk/intro/wallets.md index f12d22c36..e3af2e607 100644 --- a/docs/locales/uk/intro/wallets.md +++ b/docs/locales/uk/intro/wallets.md @@ -4,32 +4,67 @@ title: Посібник із Гаманців Solana sidebarSortOrder: 3 --- -Цей документ описує різні варіанти гаманців, доступних користувачам Solana, які хочуть надсилати, отримувати та взаємодіяти з токенами SOL у блокчейні Solana. +Цей документ описує різні варіанти гаманців, доступних користувачам Solana, які +хочуть надсилати, отримувати та взаємодіяти з токенами SOL у блокчейні Solana. ## Що таке Гаманець? -Криптогаманець — це пристрій або програма, яка зберігає набір ключів і може використовуватися для надсилання, отримання та відстеження володіння криптовалютами. Гаманці можуть мати різні форми. Гаманець може бути каталогом або файлом у файловій системі вашого комп’ютера, аркушем паперу або спеціалізованим пристроєм, який називається _апаратний гаманець_. Також існують різні програми для смартфонів і комп’ютерів, які надають зручний спосіб створення та управління гаманцями. +Криптогаманець — це пристрій або програма, яка зберігає набір ключів і може +використовуватися для надсилання, отримання та відстеження володіння +криптовалютами. Гаманці можуть мати різні форми. Гаманець може бути каталогом +або файлом у файловій системі вашого комп’ютера, аркушем паперу або +спеціалізованим пристроєм, який називається _апаратний гаманець_. Також існують +різні програми для смартфонів і комп’ютерів, які надають зручний спосіб +створення та управління гаманцями. ### Keypair -[_Keypair_](/docs/uk/terminology.md#keypair) — це безпечно згенерований [_секретний ключ_](#secret-key) і його криптографічно виведений [_публічний ключ_](#public-key). Секретний ключ та його відповідний публічний ключ разом називаються _ключовою парою_. Гаманець містить колекцію однієї або кількох ключових пар і надає засоби для взаємодії з ними. +[_Keypair_](/docs/uk/terminology.md#keypair) — це безпечно згенерований +[_секретний ключ_](#secret-key) і його криптографічно виведений +[_публічний ключ_](#public-key). Секретний ключ та його відповідний публічний +ключ разом називаються _ключовою парою_. Гаманець містить колекцію однієї або +кількох ключових пар і надає засоби для взаємодії з ними. ### Публічний ключ -[_Публічний ключ_](/docs/uk/terminology.md#public-key-pubkey) (часто скорочується до _pubkey_) відомий як _адреса для отримання_ гаманця або просто його _адреса_. Адресу гаманця **можна вільно передавати та показувати**. Коли інша сторона збирається надіслати певну кількість криптовалюти на гаманець, їй потрібно знати адресу для отримання. Залежно від реалізації блокчейну, адреса також може використовуватися для перегляду певної інформації про гаманець, наприклад, балансу, але вона не дозволяє змінювати гаманець або знімати з нього токени. +[_Публічний ключ_](/docs/uk/terminology.md#public-key-pubkey) (часто +скорочується до _pubkey_) відомий як _адреса для отримання_ гаманця або просто +його _адреса_. Адресу гаманця **можна вільно передавати та показувати**. Коли +інша сторона збирається надіслати певну кількість криптовалюти на гаманець, їй +потрібно знати адресу для отримання. Залежно від реалізації блокчейну, адреса +також може використовуватися для перегляду певної інформації про гаманець, +наприклад, балансу, але вона не дозволяє змінювати гаманець або знімати з нього +токени. ### Секретний ключ -[_Секретний ключ_](/docs/uk/terminology.md#private-key) (також називається _приватним ключем_) потрібен для цифрового підпису будь-яких транзакцій для відправлення криптовалюти на іншу адресу або внесення змін до гаманця. Секретний ключ **ніколи не повинен бути переданий іншим**. Якщо хтось отримає доступ до секретного ключа гаманця, він може зняти всі токени, які він містить. Якщо секретний ключ гаманця втрачено, будь-які токени, відправлені на адресу цього гаманця, **назавжди втрачені**. +[_Секретний ключ_](/docs/uk/terminology.md#private-key) (також називається +_приватним ключем_) потрібен для цифрового підпису будь-яких транзакцій для +відправлення криптовалюти на іншу адресу або внесення змін до гаманця. Секретний +ключ **ніколи не повинен бути переданий іншим**. Якщо хтось отримає доступ до +секретного ключа гаманця, він може зняти всі токени, які він містить. Якщо +секретний ключ гаманця втрачено, будь-які токени, відправлені на адресу цього +гаманця, **назавжди втрачені**. ## Безпека -Різні рішення для гаманців пропонують різні підходи до безпеки ключової пари, взаємодії з нею та підписання транзакцій для використання/витрачання токенів. Деякі є простішими у використанні, ніж інші. Деякі забезпечують більш безпечне зберігання та резервне копіювання секретних ключів. Solana підтримує кілька типів гаманців, тому ви можете обрати правильний баланс між безпекою та зручністю. +Різні рішення для гаманців пропонують різні підходи до безпеки ключової пари, +взаємодії з нею та підписання транзакцій для використання/витрачання токенів. +Деякі є простішими у використанні, ніж інші. Деякі забезпечують більш безпечне +зберігання та резервне копіювання секретних ключів. Solana підтримує кілька +типів гаманців, тому ви можете обрати правильний баланс між безпекою та +зручністю. -**Якщо ви хочете отримувати токени SOL у блокчейні Solana, вам спочатку потрібно створити гаманець.** +**Якщо ви хочете отримувати токени SOL у блокчейні Solana, вам спочатку потрібно +створити гаманець.** ## Підтримувані Гаманці -Кілька гаманців на основі браузера та мобільних додатків підтримують Solana. Знайдіть варіанти, які можуть підійти вам, на сторінці [Solana Wallets](https://solana.com/wallets). +Кілька гаманців на основі браузера та мобільних додатків підтримують Solana. +Знайдіть варіанти, які можуть підійти вам, на сторінці +[Solana Wallets](https://solana.com/wallets). -Для досвідчених користувачів або розробників більше підходять [гаманці командного рядка](https://docs.anza.xyz/cli/wallets), оскільки нові функції в блокчейні Solana завжди спочатку підтримуються в командному рядку, перш ніж бути інтегрованими у сторонні рішення. +Для досвідчених користувачів або розробників більше підходять +[гаманці командного рядка](https://docs.anza.xyz/cli/wallets), оскільки нові +функції в блокчейні Solana завжди спочатку підтримуються в командному рядку, +перш ніж бути інтегрованими у сторонні рішення. diff --git a/docs/locales/uk/more/exchange.md b/docs/locales/uk/more/exchange.md index 19a773cbc..9958a67a3 100644 --- a/docs/locales/uk/more/exchange.md +++ b/docs/locales/uk/more/exchange.md @@ -2,19 +2,27 @@ title: Додати Solana на Вашу Біржу --- -Цей посібник описує, як додати нативний токен Solana (SOL) до вашої криптовалютної біржі. +Цей посібник описує, як додати нативний токен Solana (SOL) до вашої +криптовалютної біржі. ## Налаштування Ноди -Ми наполегливо рекомендуємо налаштувати щонайменше дві ноди на високопродуктивних комп’ютерах або хмарних інстанціях, своєчасно оновлювати їх до нових версій і відстежувати роботу сервісу за допомогою вбудованих інструментів моніторингу. +Ми наполегливо рекомендуємо налаштувати щонайменше дві ноди на +високопродуктивних комп’ютерах або хмарних інстанціях, своєчасно оновлювати їх +до нових версій і відстежувати роботу сервісу за допомогою вбудованих +інструментів моніторингу. Це налаштування дозволяє вам: -- мати самостійно керований шлюз до кластеру Solana mainnet-beta для отримання даних і надсилання транзакцій на виведення +- мати самостійно керований шлюз до кластеру Solana mainnet-beta для отримання + даних і надсилання транзакцій на виведення - мати повний контроль над тим, скільки історичних даних блоків зберігається - забезпечувати доступність вашого сервісу навіть у разі відмови однієї з нод -Ноди Solana вимагають відносно високої обчислювальної потужності для обробки швидких блоків і високої пропускної здатності (TPS). Для конкретних вимог дивіться [рекомендації щодо апаратного забезпечення](https://docs.anza.xyz/operations/requirements). +Ноди Solana вимагають відносно високої обчислювальної потужності для обробки +швидких блоків і високої пропускної здатності (TPS). Для конкретних вимог +дивіться +[рекомендації щодо апаратного забезпечення](https://docs.anza.xyz/operations/requirements). Щоб запустити ноду API: @@ -35,70 +43,132 @@ solana-validator \ --only-known-rpc ``` -Налаштуйте параметр `--ledger` для бажаного розташування зберігання леджера та параметр `--rpc-port` для порту, який ви хочете зробити доступним. +Налаштуйте параметр `--ledger` для бажаного розташування зберігання леджера та +параметр `--rpc-port` для порту, який ви хочете зробити доступним. -Параметри `--entrypoint` та `--expected-genesis-hash` є специфічними для кластера, до якого ви приєднуєтеся. +Параметри `--entrypoint` та `--expected-genesis-hash` є специфічними для +кластера, до якого ви приєднуєтеся. [Поточні параметри для Mainnet Beta](https://docs.anza.xyz/clusters/available#example-solana-validator-command-line-2) -Параметр `--limit-ledger-size` дозволяє вказати, скільки [шредів](/docs/uk/terminology.md#shred) леджера ваша нода зберігатиме на диску. Якщо цей параметр не вказано, валідатор зберігатиме весь леджер, доки не закінчиться місце на диску. Значення за замовчуванням намагається обмежити використання місця на диску леджером до 500 ГБ. За потреби можна змінити це значення, додавши аргумент до параметра `--limit-ledger-size`. Для перегляду значення за замовчуванням, яке використовується параметром `--limit-ledger-size`, виконайте команду `solana-validator --help`. Більше інформації про вибір власного значення обмеження можна знайти [тут](https://github.com/solana-labs/solana/blob/583cec922b6107e0f85c7e14cb5e642bc7dfb340/core/src/ledger_cleanup_service.rs#L15-L26). - -Вказівка одного або кількох параметрів `--known-validator` може захистити вас від запуску з підробленого знімку. +Параметр `--limit-ledger-size` дозволяє вказати, скільки +[шредів](/docs/uk/terminology.md#shred) леджера ваша нода зберігатиме на диску. +Якщо цей параметр не вказано, валідатор зберігатиме весь леджер, доки не +закінчиться місце на диску. Значення за замовчуванням намагається обмежити +використання місця на диску леджером до 500 ГБ. За потреби можна змінити це +значення, додавши аргумент до параметра `--limit-ledger-size`. Для перегляду +значення за замовчуванням, яке використовується параметром +`--limit-ledger-size`, виконайте команду `solana-validator --help`. Більше +інформації про вибір власного значення обмеження можна знайти +[тут](https://github.com/solana-labs/solana/blob/583cec922b6107e0f85c7e14cb5e642bc7dfb340/core/src/ledger_cleanup_service.rs#L15-L26). + +Вказівка одного або кількох параметрів `--known-validator` може захистити вас +від запуску з підробленого знімку. [Більше про цінність запуску з відомими валідаторами](https://docs.anza.xyz/operations/guides/validator-start#known-validators) Додаткові параметри, які варто розглянути: -- `--private-rpc` забороняє публікацію вашого RPC-порту для використання іншими нодами +- `--private-rpc` забороняє публікацію вашого RPC-порту для використання іншими + нодами - `--rpc-bind-address` дозволяє вказати іншу IP-адресу для прив’язки RPC-порту ### Автоматичний Перезапуск та Моніторинг -Ми рекомендуємо налаштувати кожну з ваших нод на автоматичний перезапуск після завершення роботи, щоб мінімізувати втрату даних. Запуск програмного забезпечення Solana як служби systemd є одним із чудових варіантів. +Ми рекомендуємо налаштувати кожну з ваших нод на автоматичний перезапуск після +завершення роботи, щоб мінімізувати втрату даних. Запуск програмного +забезпечення Solana як служби systemd є одним із чудових варіантів. -Для моніторингу ми надаємо інструмент -[`solana-watchtower`](https://github.com/solana-labs/solana/blob/master/watchtower/README.md), -який може моніторити ваш валідатор і визначати, чи є процес `solana-validator` несправним. Він може бути налаштований для сповіщень через Slack, Telegram, Discord або Twilio. Для деталей виконайте команду `solana-watchtower --help`. +Для моніторингу ми надаємо інструмент +[`solana-watchtower`](https://github.com/solana-labs/solana/blob/master/watchtower/README.md), +який може моніторити ваш валідатор і визначати, чи є процес `solana-validator` +несправним. Він може бути налаштований для сповіщень через Slack, Telegram, +Discord або Twilio. Для деталей виконайте команду `solana-watchtower --help`. ```shell solana-watchtower --validator-identity ``` -> Додаткову інформацію про [найкращі практики для Solana Watchtower](https://docs.anza.xyz/operations/best-practices/monitoring#solana-watchtower) можна знайти у документації. + +> Додаткову інформацію про +> [найкращі практики для Solana Watchtower](https://docs.anza.xyz/operations/best-practices/monitoring#solana-watchtower) +> можна знайти у документації. #### Оголошення про Нові Релізи ПЗ -Ми випускаємо нове програмне забезпечення часто (приблизно один реліз на тиждень). Іноді нові версії містять несумісні протокольні зміни, які вимагають своєчасного оновлення ПЗ, щоб уникнути помилок при обробці блоків. +Ми випускаємо нове програмне забезпечення часто (приблизно один реліз на +тиждень). Іноді нові версії містять несумісні протокольні зміни, які вимагають +своєчасного оновлення ПЗ, щоб уникнути помилок при обробці блоків. -Наші офіційні оголошення про всі види релізів (звичайні та пов’язані з безпекою) публікуються в [каналі Discord](https://solana.com/discord) під назвою `#mb-announcement` (`mb` означає `mainnet-beta`). +Наші офіційні оголошення про всі види релізів (звичайні та пов’язані з безпекою) +публікуються в [каналі Discord](https://solana.com/discord) під назвою +`#mb-announcement` (`mb` означає `mainnet-beta`). -Як і для валідаторів зі ставками, ми очікуємо, що валідатори, які обслуговуються біржами, будуть оновлюватися протягом одного-двох робочих днів після оголошення про звичайний реліз. Для релізів, пов’язаних із безпекою, може знадобитися більш термінове реагування. +Як і для валідаторів зі ставками, ми очікуємо, що валідатори, які обслуговуються +біржами, будуть оновлюватися протягом одного-двох робочих днів після оголошення +про звичайний реліз. Для релізів, пов’язаних із безпекою, може знадобитися більш +термінове реагування. ### Цілісність Леджера -За замовчуванням кожна з ваших нод завантажується зі знімку, наданого одним із ваших відомих валідаторів. Цей знімок відображає поточний стан ланцюга, але не містить повного історичного леджера. Якщо одна з ваших нод зупиняється та завантажується з нового знімка, у леджері цієї ноди може з’явитися прогалина. Щоб уникнути цієї проблеми, додайте параметр `--no-snapshot-fetch` до команди `solana-validator`, щоб отримувати історичні дані леджера замість знімка. +За замовчуванням кожна з ваших нод завантажується зі знімку, наданого одним із +ваших відомих валідаторів. Цей знімок відображає поточний стан ланцюга, але не +містить повного історичного леджера. Якщо одна з ваших нод зупиняється та +завантажується з нового знімка, у леджері цієї ноди може з’явитися прогалина. +Щоб уникнути цієї проблеми, додайте параметр `--no-snapshot-fetch` до команди +`solana-validator`, щоб отримувати історичні дані леджера замість знімка. -Не додавайте параметр `--no-snapshot-fetch` під час початкового завантаження, оскільки неможливо завантажити ноду від самого генезис-блоку. Спочатку завантажтеся зі знімка, а потім додайте параметр `--no-snapshot-fetch` для наступних перезавантажень. +Не додавайте параметр `--no-snapshot-fetch` під час початкового завантаження, +оскільки неможливо завантажити ноду від самого генезис-блоку. Спочатку +завантажтеся зі знімка, а потім додайте параметр `--no-snapshot-fetch` для +наступних перезавантажень. -Варто зазначити, що обсяг доступного історичного леджера від інших нод у мережі обмежений. Якщо ваші валідатори зазнають значних простоїв, вони можуть не змогти синхронізуватися з мережею і будуть змушені завантажити новий знімок від відомого валідатора, що створить прогалину в історичному леджері, яку неможливо заповнити. +Варто зазначити, що обсяг доступного історичного леджера від інших нод у мережі +обмежений. Якщо ваші валідатори зазнають значних простоїв, вони можуть не змогти +синхронізуватися з мережею і будуть змушені завантажити новий знімок від +відомого валідатора, що створить прогалину в історичному леджері, яку неможливо +заповнити. ### Мінімізація Доступу до Портів Валідатора -Валідатору необхідно, щоб різні UDP- і TCP-порти були відкриті для вхідного трафіку від усіх інших валідаторів Solana. Хоча це найефективніший режим роботи і настійно рекомендується, можливо обмежити валідатор лише для вхідного трафіку від одного іншого валідатора Solana. - -Спочатку додайте аргумент `--restricted-repair-only-mode`. Це призведе до роботи валідатора в обмеженому режимі, в якому він не отримуватиме push-повідомлення від інших валідаторів і замість цього постійно опитуватиме інші валідатори для отримання блоків. Валідатор буде передавати UDP-пакети іншим валідаторам лише через порти _Gossip_ та _ServeR_ ("serve repair") і отримуватиме UDP-пакети лише через порти _Gossip_ та _Repair_. - -Порт _Gossip_ є двостороннім і дозволяє вашому валідатору підтримувати зв’язок із рештою кластеру. Ваш валідатор передаватиме запити на ремонт через порт _ServeR_, щоб отримувати нові блоки від решти мережі, оскільки Turbine тепер відключено. Ваш валідатор отримуватиме відповіді на запити ремонту через порт _Repair_ від інших валідаторів. - -Щоб додатково обмежити валідатор для запитів блоків лише від одного або кількох валідаторів, спочатку визначте публічний ключ (pubkey) цього валідатора та додайте аргументи `--gossip-pull-validator PUBKEY --repair-validator PUBKEY` для кожного PUBKEY. Це створить навантаження на кожен валідатор, який ви додаєте, тому робіть це обережно і лише після консультації з цільовим валідатором. - -Ваш валідатор тепер повинен спілкуватися лише з чітко вказаними валідаторами і лише через порти _Gossip_, _Repair_ та _ServeR_. +Валідатору необхідно, щоб різні UDP- і TCP-порти були відкриті для вхідного +трафіку від усіх інших валідаторів Solana. Хоча це найефективніший режим роботи +і настійно рекомендується, можливо обмежити валідатор лише для вхідного трафіку +від одного іншого валідатора Solana. + +Спочатку додайте аргумент `--restricted-repair-only-mode`. Це призведе до роботи +валідатора в обмеженому режимі, в якому він не отримуватиме push-повідомлення +від інших валідаторів і замість цього постійно опитуватиме інші валідатори для +отримання блоків. Валідатор буде передавати UDP-пакети іншим валідаторам лише +через порти _Gossip_ та _ServeR_ ("serve repair") і отримуватиме UDP-пакети лише +через порти _Gossip_ та _Repair_. + +Порт _Gossip_ є двостороннім і дозволяє вашому валідатору підтримувати зв’язок +із рештою кластеру. Ваш валідатор передаватиме запити на ремонт через порт +_ServeR_, щоб отримувати нові блоки від решти мережі, оскільки Turbine тепер +відключено. Ваш валідатор отримуватиме відповіді на запити ремонту через порт +_Repair_ від інших валідаторів. + +Щоб додатково обмежити валідатор для запитів блоків лише від одного або кількох +валідаторів, спочатку визначте публічний ключ (pubkey) цього валідатора та +додайте аргументи `--gossip-pull-validator PUBKEY --repair-validator PUBKEY` для +кожного PUBKEY. Це створить навантаження на кожен валідатор, який ви додаєте, +тому робіть це обережно і лише після консультації з цільовим валідатором. + +Ваш валідатор тепер повинен спілкуватися лише з чітко вказаними валідаторами і +лише через порти _Gossip_, _Repair_ та _ServeR_. ## Налаштування Депозитних Акаунтів -Акаунти Solana не потребують жодної ініціалізації в мережі; як тільки вони містять деяку кількість SOL, вони існують. Щоб налаштувати депозитний акаунт для вашої біржі, просто створіть ключову пару Solana за допомогою будь-якого з наших [інструментів для гаманців](https://docs.anza.xyz/cli/wallets). +Акаунти Solana не потребують жодної ініціалізації в мережі; як тільки вони +містять деяку кількість SOL, вони існують. Щоб налаштувати депозитний акаунт для +вашої біржі, просто створіть ключову пару Solana за допомогою будь-якого з наших +[інструментів для гаманців](https://docs.anza.xyz/cli/wallets). -Рекомендуємо використовувати унікальний депозитний акаунт для кожного з ваших користувачів. - -Акаунти Solana мають бути звільнені від оренди, містячи еквівалент 2-річної [оренди](/docs/uk/core/fees.md#rent) у SOL. Щоб визначити мінімальний баланс для звільнення від оренди для ваших депозитних акаунтів, виконайте запит до [ендпоінту `getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx): +Рекомендуємо використовувати унікальний депозитний акаунт для кожного з ваших +користувачів. +Акаунти Solana мають бути звільнені від оренди, містячи еквівалент 2-річної +[оренди](/docs/uk/core/fees.md#rent) у SOL. Щоб визначити мінімальний баланс для +звільнення від оренди для ваших депозитних акаунтів, виконайте запит до +[ендпоінту `getMinimumBalanceForRentExemption`](/docs/uk/rpc/http/getMinimumBalanceForRentExemption.mdx): ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -117,33 +187,56 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - ### Офлайн Акаунти -Ви можете залишити ключі для одного або декількох акаунтів колекції офлайн для підвищення безпеки. У цьому випадку вам потрібно буде переміщати SOL до "гарячих" акаунтів за допомогою наших [офлайн-методів](https://docs.anza.xyz/cli/examples/offline-signing). +Ви можете залишити ключі для одного або декількох акаунтів колекції офлайн для +підвищення безпеки. У цьому випадку вам потрібно буде переміщати SOL до +"гарячих" акаунтів за допомогою наших +[офлайн-методів](https://docs.anza.xyz/cli/examples/offline-signing). ## Відстеження Депозитів -Коли користувач хоче внести SOL на вашу біржу, інструктуйте його виконати переказ на відповідну депозитну адресу. +Коли користувач хоче внести SOL на вашу біржу, інструктуйте його виконати +переказ на відповідну депозитну адресу. ### Міграція Транзакцій із Версіями -Коли мережа Mainnet Beta почне обробляти транзакції із версіями, біржі **ЗОБОВ'ЯЗАНІ** внести зміни. Якщо не внести змін, виявлення депозитів працюватиме неправильно, оскільки отримання транзакції з версією або блоку, що містить такі транзакції, призведе до помилки. +Коли мережа Mainnet Beta почне обробляти транзакції із версіями, біржі +**ЗОБОВ'ЯЗАНІ** внести зміни. Якщо не внести змін, виявлення депозитів +працюватиме неправильно, оскільки отримання транзакції з версією або блоку, що +містить такі транзакції, призведе до помилки. - `{"maxSupportedTransactionVersion": 0}` - Параметр `maxSupportedTransactionVersion` потрібно додати до запитів `getBlock` і `getTransaction`, щоб уникнути порушення роботи виявлення депозитів. Остання версія транзакції — `0`, і саме її слід зазначати як максимальну підтримувану версію транзакції. + Параметр `maxSupportedTransactionVersion` потрібно додати до запитів + `getBlock` і `getTransaction`, щоб уникнути порушення роботи виявлення + депозитів. Остання версія транзакції — `0`, і саме її слід зазначати як + максимальну підтримувану версію транзакції. -Важливо розуміти, що транзакції з версіями дозволяють користувачам створювати транзакції, які використовують інший набір ключів акаунтів, завантажених з ончейн таблиць пошуку адрес. +Важливо розуміти, що транзакції з версіями дозволяють користувачам створювати +транзакції, які використовують інший набір ключів акаунтів, завантажених з +ончейн таблиць пошуку адрес. - `{"encoding": "jsonParsed"}` - При отриманні блоків і транзакцій тепер рекомендується використовувати кодування `"jsonParsed"`, оскільки воно включає всі ключі акаунтів транзакції (включаючи ті, що з таблиць пошуку) у список `"accountKeys"` повідомлення. Це спрощує розв'язання змін балансу, описаних у `preBalances` / `postBalances` і `preTokenBalances` / `postTokenBalances`. + При отриманні блоків і транзакцій тепер рекомендується використовувати + кодування `"jsonParsed"`, оскільки воно включає всі ключі акаунтів транзакції + (включаючи ті, що з таблиць пошуку) у список `"accountKeys"` повідомлення. Це + спрощує розв'язання змін балансу, описаних у `preBalances` / `postBalances` і + `preTokenBalances` / `postTokenBalances`. - Якщо використовується кодування `"json"`, записи у `preBalances` / `postBalances` і `preTokenBalances` / `postTokenBalances` можуть посилатися на ключі акаунтів, які **НЕ** входять до списку `"accountKeys"` і потребують розв'язання за допомогою записів `"loadedAddresses"` у метаданих транзакції. + Якщо використовується кодування `"json"`, записи у `preBalances` / + `postBalances` і `preTokenBalances` / `postTokenBalances` можуть посилатися на + ключі акаунтів, які **НЕ** входять до списку `"accountKeys"` і потребують + розв'язання за допомогою записів `"loadedAddresses"` у метаданих транзакції. ### Опитування Блоків -Для відстеження всіх депозитних акаунтів вашої біржі регулярно опитуйте кожен підтверджений блок і перевіряйте адреси, що вас цікавлять, використовуючи JSON-RPC сервіс вашої ноди API Solana. +Для відстеження всіх депозитних акаунтів вашої біржі регулярно опитуйте кожен +підтверджений блок і перевіряйте адреси, що вас цікавлять, використовуючи +JSON-RPC сервіс вашої ноди API Solana. -- Щоб визначити, які блоки доступні, надішліть запит [`getBlocks`](/docs/uk/rpc/http/getBlocks.mdx), передавши останній блок, який ви вже обробили, як параметр start-slot: +- Щоб визначити, які блоки доступні, надішліть запит + [`getBlocks`](/docs/uk/rpc/http/getBlocks.mdx), передавши останній блок, який + ви вже обробили, як параметр start-slot: ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -165,19 +258,25 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - "id": 1 } ``` + Не кожен слот створює блок, тому в послідовності чисел можуть бути прогалини. -- Для кожного блоку запитуйте його вміст за допомогою запиту [`getBlock`](/docs/uk/rpc/http/getBlock.mdx): +- Для кожного блоку запитуйте його вміст за допомогою запиту + [`getBlock`](/docs/uk/rpc/http/getBlock.mdx): ### Поради для Отримання Блоків - `{"rewards": false}` -За замовчуванням отримані блоки містять інформацію про комісії валідаторів за кожен блок і нагороди за стейкінг на межах епох. Якщо ця інформація вам не потрібна, вимкніть її за допомогою параметра `"rewards"`. +За замовчуванням отримані блоки містять інформацію про комісії валідаторів за +кожен блок і нагороди за стейкінг на межах епох. Якщо ця інформація вам не +потрібна, вимкніть її за допомогою параметра `"rewards"`. - `{"transactionDetails": "accounts"}` -За замовчуванням отримані блоки містять багато інформації про транзакції та метадані, які не потрібні для відстеження балансів акаунтів. Встановіть параметр `"transactionDetails"` для прискорення отримання блоків. +За замовчуванням отримані блоки містять багато інформації про транзакції та +метадані, які не потрібні для відстеження балансів акаунтів. Встановіть параметр +`"transactionDetails"` для прискорення отримання блоків. ```shell curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' -d '{ @@ -263,15 +362,29 @@ curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' - } ``` -Поля `preBalances` і `postBalances` дозволяють відстежувати зміни балансу кожного акаунта без необхідності аналізувати всю транзакцію. Вони містять початкові та кінцеві баланси кожного акаунта у [лампортах](/docs/uk/terminology.md#lamport), проіндексовані до списку `accountKeys`. Наприклад, якщо депозитна адреса, яка вас цікавить, — це `G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o`, то ця транзакція представляє переказ 1040000000 - 1030000000 = 10,000,000 лампортів = 0.01 SOL. +Поля `preBalances` і `postBalances` дозволяють відстежувати зміни балансу +кожного акаунта без необхідності аналізувати всю транзакцію. Вони містять +початкові та кінцеві баланси кожного акаунта у +[лампортах](/docs/uk/terminology.md#lamport), проіндексовані до списку +`accountKeys`. Наприклад, якщо депозитна адреса, яка вас цікавить, — це +`G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o`, то ця транзакція представляє +переказ 1040000000 - 1030000000 = 10,000,000 лампортів = 0.01 SOL. -Якщо вам потрібна додаткова інформація про тип транзакції або інші специфічні дані, ви можете запросити блок із RPC у бінарному форматі та проаналізувати його за допомогою нашого [Rust SDK](https://github.com/solana-labs/solana) або [JavaScript SDK](https://github.com/solana-labs/solana-web3.js). +Якщо вам потрібна додаткова інформація про тип транзакції або інші специфічні +дані, ви можете запросити блок із RPC у бінарному форматі та проаналізувати його +за допомогою нашого [Rust SDK](https://github.com/solana-labs/solana) або +[JavaScript SDK](https://github.com/solana-labs/solana-web3.js). ### Історія Адрес -Ви також можете запитати історію транзакцій для певної адреси. Це, як правило, _не_ є життєздатним методом для відстеження всіх ваших депозитних адрес за всіма слотами, але може бути корисним для аналізу кількох акаунтів за певний період часу. +Ви також можете запитати історію транзакцій для певної адреси. Це, як правило, +_не_ є життєздатним методом для відстеження всіх ваших депозитних адрес за всіма +слотами, але може бути корисним для аналізу кількох акаунтів за певний період +часу. -- Надішліть запит [`getSignaturesForAddress`](/docs/uk/rpc/http/getSignaturesForAddress.mdx) до API-ноди: +- Надішліть запит + [`getSignaturesForAddress`](/docs/uk/rpc/http/getSignaturesForAddress.mdx) до + API-ноди: ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -321,7 +434,9 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - "id": 1 } ``` -- Для кожного отриманого підпису отримайте деталі транзакції, надіславши запит [`getTransaction`](/docs/uk/rpc/http/getTransaction.mdx): + +- Для кожного отриманого підпису отримайте деталі транзакції, надіславши запит + [`getTransaction`](/docs/uk/rpc/http/getTransaction.mdx): ```shell curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' -d '{ @@ -420,44 +535,69 @@ curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' - ## Відправлення Виведення -Щоб виконати запит користувача на виведення SOL, ви повинні створити транзакцію переказу Solana та надіслати її на API-ноду для передачі в кластер. +Щоб виконати запит користувача на виведення SOL, ви повинні створити транзакцію +переказу Solana та надіслати її на API-ноду для передачі в кластер. ### Синхронний Переказ -Відправлення синхронного переказу до кластера Solana дозволяє легко переконатися, що переказ успішно завершено та підтверджено кластером. - -Інструмент командного рядка Solana пропонує просту команду `solana transfer` для створення, подання та підтвердження транзакцій переказу. За замовчуванням цей метод чекатиме та відстежуватиме прогрес через stderr, доки транзакція не буде підтверджена кластером. У разі невдачі транзакції буде повідомлено про будь-які помилки. +Відправлення синхронного переказу до кластера Solana дозволяє легко +переконатися, що переказ успішно завершено та підтверджено кластером. +Інструмент командного рядка Solana пропонує просту команду `solana transfer` для +створення, подання та підтвердження транзакцій переказу. За замовчуванням цей +метод чекатиме та відстежуватиме прогрес через stderr, доки транзакція не буде +підтверджена кластером. У разі невдачі транзакції буде повідомлено про будь-які +помилки. ```shell solana transfer --allow-unfunded-recipient --keypair --url http://localhost:8899 ``` -[Solana Javascript SDK](https://github.com/solana-labs/solana-web3.js) пропонує схожий підхід для екосистеми JS. Використовуйте `SystemProgram` для створення транзакції переказу та надсилайте її за допомогою методу `sendAndConfirmTransaction`. +[Solana Javascript SDK](https://github.com/solana-labs/solana-web3.js) пропонує +схожий підхід для екосистеми JS. Використовуйте `SystemProgram` для створення +транзакції переказу та надсилайте її за допомогою методу +`sendAndConfirmTransaction`. ### Асинхронний Переказ -Для більшої гнучкості ви можете надсилати перекази на виведення асинхронно. У цьому випадку саме ви несете відповідальність за перевірку успішності транзакції та її підтвердження кластером. +Для більшої гнучкості ви можете надсилати перекази на виведення асинхронно. У +цьому випадку саме ви несете відповідальність за перевірку успішності транзакції +та її підтвердження кластером. -**Примітка:** Кожна транзакція містить [recent blockhash](/docs/uk/core/transactions.md#recent-blockhash), що вказує на її актуальність. Важливо **дочекатися**, поки цей blockhash не стане недійсним, перш ніж повторювати спробу переказу, який, схоже, не було підтверджено або завершено кластером. Інакше ви ризикуєте створити подвійний витрату. Дивіться більше про [термін дії blockhash](#blockhash-expiration) нижче. +**Примітка:** Кожна транзакція містить +[recent blockhash](/docs/uk/core/transactions.md#recent-blockhash), що вказує на +її актуальність. Важливо **дочекатися**, поки цей blockhash не стане недійсним, +перш ніж повторювати спробу переказу, який, схоже, не було підтверджено або +завершено кластером. Інакше ви ризикуєте створити подвійний витрату. Дивіться +більше про [термін дії blockhash](#blockhash-expiration) нижче. -Спочатку отримайте недавній blockhash за допомогою ендпоінту [`getFees`](/docs/uk/rpc/deprecated/getFees.mdx) або команди CLI: +Спочатку отримайте недавній blockhash за допомогою ендпоінту +[`getFees`](/docs/uk/rpc/deprecated/getFees.mdx) або команди CLI: ```shell solana fees --url http://localhost:8899 ``` -У командному рядку передайте аргумент `--no-wait`, щоб відправити переказ асинхронно, і додайте ваш недавній blockhash за допомогою аргументу `--blockhash`: +У командному рядку передайте аргумент `--no-wait`, щоб відправити переказ +асинхронно, і додайте ваш недавній blockhash за допомогою аргументу +`--blockhash`: ```shell solana transfer --no-wait --allow-unfunded-recipient --blockhash --keypair --url http://localhost:8899 ``` -Ви також можете створити, підписати та серіалізувати транзакцію вручну, а потім надіслати її до кластера за допомогою ендпоінта JSON-RPC [`sendTransaction`](/docs/uk/rpc/http/sendTransaction.mdx). +Ви також можете створити, підписати та серіалізувати транзакцію вручну, а потім +надіслати її до кластера за допомогою ендпоінта JSON-RPC +[`sendTransaction`](/docs/uk/rpc/http/sendTransaction.mdx). #### Підтвердження Транзакцій та Фінальність -Отримайте статус групи транзакцій за допомогою ендпоінта JSON-RPC [`getSignatureStatuses`](/docs/uk/rpc/http/getSignatureStatuses.mdx). Поле `confirmations` вказує, скільки [підтверджених блоків](/docs/uk/terminology.md#confirmed-block) минуло з моменту обробки транзакції. Якщо `confirmations: null`, це означає, що транзакція є [фіналізованою](/docs/uk/terminology.md#finality). +Отримайте статус групи транзакцій за допомогою ендпоінта JSON-RPC +[`getSignatureStatuses`](/docs/uk/rpc/http/getSignatureStatuses.mdx). Поле +`confirmations` вказує, скільки +[підтверджених блоків](/docs/uk/terminology.md#confirmed-block) минуло з моменту +обробки транзакції. Якщо `confirmations: null`, це означає, що транзакція є +[фіналізованою](/docs/uk/terminology.md#finality). ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ @@ -507,33 +647,52 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - #### Термін Дії Blockhash -Ви можете перевірити, чи є конкретний blockhash ще дійсним, надіславши запит [`getFeeCalculatorForBlockhash`](/docs/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx) з blockhash як параметром. Якщо значення у відповіді `null`, blockhash недійсний, і транзакція на виведення, яка використовує цей blockhash, не має шансів на успіх. +Ви можете перевірити, чи є конкретний blockhash ще дійсним, надіславши запит +[`getFeeCalculatorForBlockhash`](/docs/uk/rpc/deprecated/getFeeCalculatorForBlockhash.mdx) +з blockhash як параметром. Якщо значення у відповіді `null`, blockhash +недійсний, і транзакція на виведення, яка використовує цей blockhash, не має +шансів на успіх. ### Перевірка Адрес Акаунтів, Наданих Користувачами, для Виведення -Оскільки транзакції на виведення є незворотними, хорошою практикою може бути перевірка адреси акаунта, наданої користувачем, перед авторизацією виведення, щоб запобігти випадковій втраті коштів користувача. +Оскільки транзакції на виведення є незворотними, хорошою практикою може бути +перевірка адреси акаунта, наданої користувачем, перед авторизацією виведення, +щоб запобігти випадковій втраті коштів користувача. #### Основна Перевірка -Адреси Solana — це 32-байтовий масив, закодований за допомогою алфавіту base58 від Bitcoin. Це призводить до отримання ASCII-рядка, що відповідає наступному регулярному виразу: +Адреси Solana — це 32-байтовий масив, закодований за допомогою алфавіту base58 +від Bitcoin. Це призводить до отримання ASCII-рядка, що відповідає наступному +регулярному виразу: ```text [1-9A-HJ-NP-Za-km-z]{32,44} ``` -Ця перевірка сама по собі є недостатньою, оскільки адреси Solana не мають контрольної суми, тому помилки друку не можуть бути виявлені. Для додаткової перевірки введення користувачем можна декодувати рядок і підтвердити, що довжина отриманого байтового масиву дорівнює 32. Однак існують адреси, які можуть декодуватися у 32 байти, незважаючи на помилки, наприклад, пропущений символ, перестановка символів або ігнорування регістру. +Ця перевірка сама по собі є недостатньою, оскільки адреси Solana не мають +контрольної суми, тому помилки друку не можуть бути виявлені. Для додаткової +перевірки введення користувачем можна декодувати рядок і підтвердити, що довжина +отриманого байтового масиву дорівнює 32. Однак існують адреси, які можуть +декодуватися у 32 байти, незважаючи на помилки, наприклад, пропущений символ, +перестановка символів або ігнорування регістру. #### Розширена Перевірка -Через вразливість до помилок друку, описану вище, рекомендується запитувати баланс для можливих адрес виведення та запитувати у користувача підтвердження, якщо буде виявлено ненульовий баланс. +Через вразливість до помилок друку, описану вище, рекомендується запитувати +баланс для можливих адрес виведення та запитувати у користувача підтвердження, +якщо буде виявлено ненульовий баланс. #### Перевірка Валідного ed25519 Публічного Ключа -Адреса звичайного акаунта в Solana — це Base58-кодований рядок 256-бітного публічного ключа ed25519. Не всі бітові патерни є валідними публічними ключами для кривої ed25519, тому можна забезпечити, що адреси акаунтів, надані користувачем, принаймні є правильними публічними ключами ed25519. +Адреса звичайного акаунта в Solana — це Base58-кодований рядок 256-бітного +публічного ключа ed25519. Не всі бітові патерни є валідними публічними ключами +для кривої ed25519, тому можна забезпечити, що адреси акаунтів, надані +користувачем, принаймні є правильними публічними ключами ed25519. #### Java -Ось приклад на Java для перевірки адреси, наданої користувачем, як валідного публічного ключа ed25519: +Ось приклад на Java для перевірки адреси, наданої користувачем, як валідного +публічного ключа ed25519: Наступний приклад коду передбачає використання Maven. @@ -590,11 +749,13 @@ public class PubkeyValidator ## Мінімальні Суми Депозиту та Виведення -Кожен депозит та виведення SOL повинні бути більшими або дорівнювати мінімальному балансу, звільненому від оренди, для акаунта за адресою гаманця (базовий акаунт SOL, який не містить даних), який наразі складає: **0.000890880 SOL**. +Кожен депозит та виведення SOL повинні бути більшими або дорівнювати +мінімальному балансу, звільненому від оренди, для акаунта за адресою гаманця +(базовий акаунт SOL, який не містить даних), який наразі складає: **0.000890880 +SOL**. Аналогічно, кожен депозитний акаунт повинен містити принаймні цей баланс. - ```shell curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{ "jsonrpc": "2.0", @@ -612,65 +773,99 @@ curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" - ## Пріоритетні Комісії та Обчислювальні Одиниці -У періоди високого попиту транзакція може стати недійсною до того, як валідатор включить її до блоку, оскільки були обрані інші транзакції з вищою економічною цінністю. Валідні транзакції в Solana можуть бути затримані або скасовані, якщо Пріоритетні Комісії не впроваджені належним чином. +У періоди високого попиту транзакція може стати недійсною до того, як валідатор +включить її до блоку, оскільки були обрані інші транзакції з вищою економічною +цінністю. Валідні транзакції в Solana можуть бути затримані або скасовані, якщо +Пріоритетні Комісії не впроваджені належним чином. -[Пріоритетні Комісії](/docs/uk/terminology.md#prioritization-fee) — це додаткові комісії, які можна додати до [базової комісії за транзакцію](/docs/uk/core/fees.md#transaction-fees), щоб забезпечити включення транзакцій у блоки і їх доставку. +[Пріоритетні Комісії](/docs/uk/terminology.md#prioritization-fee) — це додаткові +комісії, які можна додати до +[базової комісії за транзакцію](/docs/uk/core/fees.md#transaction-fees), щоб +забезпечити включення транзакцій у блоки і їх доставку. -Ці пріоритетні комісії додаються до транзакції шляхом додавання спеціальної інструкції `Compute Budget`, яка встановлює бажану суму комісії. +Ці пріоритетні комісії додаються до транзакції шляхом додавання спеціальної +інструкції `Compute Budget`, яка встановлює бажану суму комісії. -Якщо ці інструкції не впровадити, це може призвести до збоїв у роботі мережі та скасування транзакцій. Наполегливо рекомендується кожній біржі, що підтримує Solana, використовувати пріоритетні комісії для уникнення збоїв. +Якщо ці інструкції не впровадити, це може призвести до збоїв у роботі мережі та +скасування транзакцій. Наполегливо рекомендується кожній біржі, що підтримує +Solana, використовувати пріоритетні комісії для уникнення збоїв. ### Що таке Пріоритетна Комісія? -Пріоритетні комісії виражаються у мікролампортах за обчислювальну одиницю (наприклад, невеликі суми SOL) і додаються до транзакцій, щоб зробити їх економічно привабливими для валідаторів і забезпечити їх включення до блоків у мережі. +Пріоритетні комісії виражаються у мікролампортах за обчислювальну одиницю +(наприклад, невеликі суми SOL) і додаються до транзакцій, щоб зробити їх +економічно привабливими для валідаторів і забезпечити їх включення до блоків у +мережі. ### Якою має бути Пріоритетна Комісія? -Метод встановлення пріоритетної комісії має включати запити до недавніх значень пріоритетних комісій, щоб встановити розмір комісії, яка буде привабливою для мережі. Використовуючи метод RPC [`getRecentPrioritizationFees`](/docs/uk/rpc/http/getrecentprioritizationfees), можна отримати дані про пріоритетні комісії, необхідні для підтвердження транзакції в недавньому блоці. +Метод встановлення пріоритетної комісії має включати запити до недавніх значень +пріоритетних комісій, щоб встановити розмір комісії, яка буде привабливою для +мережі. Використовуючи метод RPC +[`getRecentPrioritizationFees`](/docs/uk/rpc/http/getrecentprioritizationfees), +можна отримати дані про пріоритетні комісії, необхідні для підтвердження +транзакції в недавньому блоці. -Стратегія ціноутворення пріоритетних комісій залежить від ваших потреб. Універсального підходу не існує. Однією зі стратегій може бути розрахунок рівня успішності ваших транзакцій і коригування пріоритетної комісії відповідно до даних з API про комісії. Ціноутворення на пріоритетні комісії є динамічним і залежить від активності в мережі та ставок інших учасників. +Стратегія ціноутворення пріоритетних комісій залежить від ваших потреб. +Універсального підходу не існує. Однією зі стратегій може бути розрахунок рівня +успішності ваших транзакцій і коригування пріоритетної комісії відповідно до +даних з API про комісії. Ціноутворення на пріоритетні комісії є динамічним і +залежить від активності в мережі та ставок інших учасників. ### Як Впровадити Пріоритетні Комісії -Додавання пріоритетних комісій до транзакції включає додавання двох інструкцій Compute Budget: +Додавання пріоритетних комісій до транзакції включає додавання двох інструкцій +Compute Budget: - для встановлення ціни за обчислювальну одиницю - для встановлення ліміту обчислювальних одиниць -> Детальний [посібник для розробників про використання пріоритетних комісій](/content/guides/advanced/how-to-use-priority-fees.md) доступний для додаткової інформації. +> Детальний +> [посібник для розробників про використання пріоритетних комісій](/content/guides/advanced/how-to-use-priority-fees.md) +> доступний для додаткової інформації. -Створіть інструкцію `setComputeUnitPrice`, щоб додати Пріоритетну Комісію понад Базову Комісію за Транзакцію (5,000 лампортів). +Створіть інструкцію `setComputeUnitPrice`, щоб додати Пріоритетну Комісію понад +Базову Комісію за Транзакцію (5,000 лампортів). ```typescript // import { ComputeBudgetProgram } from "@solana/web3.js" ComputeBudgetProgram.setComputeUnitPrice({ microLamports: number }); ``` -Значення, надане в мікролампортах, буде множитися на обчислювальний бюджет (Compute Unit, CU), щоб визначити Пріоритетну Комісію в лампортах. Наприклад, якщо ваш бюджет CU становить 1M CU, і ви додаєте `1 мікролампорта/CU`, Пріоритетна Комісія становитиме 1 лампорт (1M \* 0.000001). Загальна комісія складе 5001 лампорт. - -Щоб встановити новий обчислювальний бюджет для транзакції, створіть інструкцію `setComputeUnitLimit`. +Значення, надане в мікролампортах, буде множитися на обчислювальний бюджет +(Compute Unit, CU), щоб визначити Пріоритетну Комісію в лампортах. Наприклад, +якщо ваш бюджет CU становить 1M CU, і ви додаєте `1 мікролампорта/CU`, +Пріоритетна Комісія становитиме 1 лампорт (1M \* 0.000001). Загальна комісія +складе 5001 лампорт. +Щоб встановити новий обчислювальний бюджет для транзакції, створіть інструкцію +`setComputeUnitLimit`. ```typescript // import { ComputeBudgetProgram } from "@solana/web3.js" ComputeBudgetProgram.setComputeUnitLimit({ units: number }); ``` -Значення `units`, яке ви надаєте, замінить стандартне значення обчислювального бюджету (Compute Budget) в середовищі виконання Solana. +Значення `units`, яке ви надаєте, замінить стандартне значення обчислювального +бюджету (Compute Budget) в середовищі виконання Solana. -Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць (CU), необхідну для виконання, щоб максимізувати пропускну здатність і мінімізувати загальні комісії. +Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць (CU), +необхідну для виконання, щоб максимізувати пропускну здатність і мінімізувати +загальні комісії. -Ви можете дізнатися, скільки CU споживає транзакція, надіславши її в інший кластер Solana, наприклад, devnet. Наприклад, [простий переказ токенів](https://explorer.solana.com/tx/5scDyuiiEbLxjLUww3APE9X7i8LE3H63unzonUwMG7s2htpoAGG17sgRsNAhR1zVs6NQAnZeRVemVbkAct5myi17) займає 300 CU. +Ви можете дізнатися, скільки CU споживає транзакція, надіславши її в інший +кластер Solana, наприклад, devnet. Наприклад, +[простий переказ токенів](https://explorer.solana.com/tx/5scDyuiiEbLxjLUww3APE9X7i8LE3H63unzonUwMG7s2htpoAGG17sgRsNAhR1zVs6NQAnZeRVemVbkAct5myi17) +займає 300 CU. - ```typescript // import { ... } from "@solana/web3.js" @@ -697,33 +892,55 @@ const transaction = new Transaction() ### Пріоритетні Комісії та Транзакції з Durable Nonces -Якщо у вашій системі використовуються транзакції з Durable Nonces, важливо правильно впровадити Пріоритетні Комісії разом із Durable Transaction Nonces, щоб забезпечити успішне виконання транзакцій. Якщо цього не зробити, заплановані Durable Nonce транзакції не будуть розпізнані належним чином. +Якщо у вашій системі використовуються транзакції з Durable Nonces, важливо +правильно впровадити Пріоритетні Комісії разом із Durable Transaction Nonces, +щоб забезпечити успішне виконання транзакцій. Якщо цього не зробити, заплановані +Durable Nonce транзакції не будуть розпізнані належним чином. -Якщо ви ВИКОРИСТОВУЄТЕ Durable Transaction Nonces, інструкція `AdvanceNonceAccount` МАЄ бути зазначена ПЕРШОЮ у списку інструкцій, навіть якщо використовуються інструкції обчислювального бюджету для встановлення пріоритетних комісій. +Якщо ви ВИКОРИСТОВУЄТЕ Durable Transaction Nonces, інструкція +`AdvanceNonceAccount` МАЄ бути зазначена ПЕРШОЮ у списку інструкцій, навіть якщо +використовуються інструкції обчислювального бюджету для встановлення +пріоритетних комісій. -Специфічний приклад коду, що демонструє використання durable nonces і пріоритетних комісій разом, можна знайти у [керівництві для розробників](/content/guides/advanced/how-to-use-priority-fees.md#special-considerations). +Специфічний приклад коду, що демонструє використання durable nonces і +пріоритетних комісій разом, можна знайти у +[керівництві для розробників](/content/guides/advanced/how-to-use-priority-fees.md#special-considerations). ## Підтримка Стандарту SPL Token -[SPL Token](https://spl.solana.com/token) є стандартом для створення і обміну обгорнутих/синтетичних токенів у блокчейні Solana. +[SPL Token](https://spl.solana.com/token) є стандартом для створення і обміну +обгорнутих/синтетичних токенів у блокчейні Solana. -Робочий процес SPL Token схожий на той, що використовується для нативних SOL токенів, але є кілька відмінностей, які будуть розглянуті в цьому розділі. +Робочий процес SPL Token схожий на той, що використовується для нативних SOL +токенів, але є кілька відмінностей, які будуть розглянуті в цьому розділі. ### Токен Mints -Кожен _тип_ SPL Token декларується шляхом створення акаунта _mint_. Цей акаунт зберігає метадані, які описують характеристики токена, такі як пропозиція, кількість десяткових знаків і різні повноваження з контролю за mint. Кожен акаунт SPL Token посилається на відповідний mint і може взаємодіяти лише з SPL Token цього типу. +Кожен _тип_ SPL Token декларується шляхом створення акаунта _mint_. Цей акаунт +зберігає метадані, які описують характеристики токена, такі як пропозиція, +кількість десяткових знаків і різні повноваження з контролю за mint. Кожен +акаунт SPL Token посилається на відповідний mint і може взаємодіяти лише з SPL +Token цього типу. ### Встановлення CLI Інструменту `spl-token` -Акаунти SPL Token можна запитувати та змінювати за допомогою утиліти командного рядка `spl-token`. Приклади, наведені в цьому розділі, залежать від того, що вона встановлена на вашій локальній системі. +Акаунти SPL Token можна запитувати та змінювати за допомогою утиліти командного +рядка `spl-token`. Приклади, наведені в цьому розділі, залежать від того, що +вона встановлена на вашій локальній системі. -`spl-token` розповсюджується з Rust [crates.io](https://crates.io/crates/spl-token) через утиліту командного рядка Rust `cargo`. Останню версію `cargo` можна встановити за допомогою простого скрипта для вашої платформи на [rustup.rs](https://rustup.rs). Після встановлення `cargo`, утиліту `spl-token` можна отримати за допомогою такої команди: +`spl-token` розповсюджується з Rust +[crates.io](https://crates.io/crates/spl-token) через утиліту командного рядка +Rust `cargo`. Останню версію `cargo` можна встановити за допомогою простого +скрипта для вашої платформи на [rustup.rs](https://rustup.rs). Після +встановлення `cargo`, утиліту `spl-token` можна отримати за допомогою такої +команди: ```shell cargo install spl-token-cli ``` -Після цього ви можете перевірити встановлену версію, щоб переконатися у правильності встановлення: +Після цього ви можете перевірити встановлену версію, щоб переконатися у +правильності встановлення: ```shell spl-token --version @@ -734,12 +951,21 @@ spl-token --version ```text spl-token-cli 2.0.1 ``` + ### Створення Акаунтів -Акаунти SPL Token мають додаткові вимоги, яких не мають нативні акаунти System Program: +Акаунти SPL Token мають додаткові вимоги, яких не мають нативні акаунти System +Program: -1. Акаунти SPL Token мають бути створені до того, як у них можна буде внести токени. Акаунти токенів можна створити явно за допомогою команди `spl-token create-account` або неявно за допомогою команди `spl-token transfer --fund-recipient ...`. -2. Акаунти SPL Token повинні залишатися [звільненими від оренди](/docs/uk/core/fees.md#rent-exempt) протягом усього періоду їх існування, а отже, вимагають внесення невеликої кількості нативних SOL токенів під час створення акаунта. Для акаунтів SPL Token ця сума становить 0.00203928 SOL (2,039,280 лампортів). +1. Акаунти SPL Token мають бути створені до того, як у них можна буде внести + токени. Акаунти токенів можна створити явно за допомогою команди + `spl-token create-account` або неявно за допомогою команди + `spl-token transfer --fund-recipient ...`. +2. Акаунти SPL Token повинні залишатися + [звільненими від оренди](/docs/uk/core/fees.md#rent-exempt) протягом усього + періоду їх існування, а отже, вимагають внесення невеликої кількості нативних + SOL токенів під час створення акаунта. Для акаунтів SPL Token ця сума + становить 0.00203928 SOL (2,039,280 лампортів). #### Командний Рядок @@ -764,6 +990,7 @@ spl-token create-account AkUFCWTXb3w9nY2n6SFJvBV6VwvFUCe4KBMCcgLsa2ir Creating account 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV Signature: 4JsqZEPra2eDTHtHpB4FMWSfk3UgcCVmkKkP7zESZeMrKmFFkDkNd91pKP3vPVVZZPiu5XxyJwS73Vi5WsZL88D7 ``` + Або щоб створити акаунт SPL Token з конкретною ключовою парою: ```shell @@ -778,6 +1005,7 @@ spl-token create-account AkUFCWTXb3w9nY2n6SFJvBV6VwvFUCe4KBMCcgLsa2ir token-acco Creating account 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV Signature: 4JsqZEPra2eDTHtHpB4FMWSfk3UgcCVmkKkP7zESZeMrKmFFkDkNd91pKP3vPVVZZPiu5XxyJwS73Vi5WsZL88D7 ``` + ### Перевірка Балансу Акаунта #### Командний Рядок @@ -799,11 +1027,15 @@ solana balance 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV ``` 0 ``` + ### Переказ Токенів -Вихідним акаунтом для переказу є фактичний акаунт токенів, який містить необхідну суму. +Вихідним акаунтом для переказу є фактичний акаунт токенів, який містить +необхідну суму. -Однак адресою отримувача може бути звичайний гаманець. Якщо асоційований токен акаунт для вказаного mint ще не існує для цього гаманця, переказ створить його, якщо буде вказаний аргумент `--fund-recipient`. +Однак адресою отримувача може бути звичайний гаманець. Якщо асоційований токен +акаунт для вказаного mint ще не існує для цього гаманця, переказ створить його, +якщо буде вказаний аргумент `--fund-recipient`. #### Командний Рядок @@ -831,19 +1063,43 @@ Signature: 3R6tsog17QM8KfzbcbdP4aoMfwgo6hBggJDVy7dZPVmH2xbCWjEj31JKD53NzMrf25ChF ### Депозити -Оскільки кожна пара `(гаманець, mint)` потребує окремого акаунта в ончейні, рекомендується, щоб адреси для цих акаунтів були отримані з гаманців для депозиту SOL за допомогою схеми [Associated Token Account (ATA)](https://spl.solana.com/associated-token-account), і приймалися _лише_ депозити з ATA адрес. +Оскільки кожна пара `(гаманець, mint)` потребує окремого акаунта в ончейні, +рекомендується, щоб адреси для цих акаунтів були отримані з гаманців для +депозиту SOL за допомогою схеми +[Associated Token Account (ATA)](https://spl.solana.com/associated-token-account), +і приймалися _лише_ депозити з ATA адрес. -Відстеження транзакцій депозиту має використовувати метод [опитування блоків](#poll-for-blocks), описаний вище. Кожен новий блок слід сканувати на наявність успішних транзакцій, що посилаються на адреси акаунтів, отриманих для користувачів. Поля `preTokenBalance` і `postTokenBalance` з метаданих транзакцій необхідно використовувати для визначення ефективної зміни балансу. Ці поля ідентифікують mint токена та власника акаунта (основну адресу гаманця) відповідного акаунта. +Відстеження транзакцій депозиту має використовувати метод +[опитування блоків](#poll-for-blocks), описаний вище. Кожен новий блок слід +сканувати на наявність успішних транзакцій, що посилаються на адреси акаунтів, +отриманих для користувачів. Поля `preTokenBalance` і `postTokenBalance` з +метаданих транзакцій необхідно використовувати для визначення ефективної зміни +балансу. Ці поля ідентифікують mint токена та власника акаунта (основну адресу +гаманця) відповідного акаунта. -Зауважте, що якщо акаунт для отримання створюється під час транзакції, у нього не буде запису `preTokenBalance`, оскільки стан акаунта раніше не існував. У цьому випадку початковий баланс можна вважати нульовим. +Зауважте, що якщо акаунт для отримання створюється під час транзакції, у нього +не буде запису `preTokenBalance`, оскільки стан акаунта раніше не існував. У +цьому випадку початковий баланс можна вважати нульовим. ### Виведення Адреса для виведення, надана користувачем, має бути адресою їх SOL гаманця. -Перед виконанням [переказу](#token-transfers) для виведення біржа повинна перевірити адресу, як це [описано вище](#validating-user-supplied-account-addresses-for-withdrawals). Крім того, ця адреса має належати System Program і не мати даних акаунта. Якщо на цій адресі відсутній баланс SOL, перед виконанням виведення слід отримати підтвердження користувача. Усі інші адреси для виведення повинні бути відхилені. - -З адреси для виведення [Associated Token Account (ATA)](https://spl.solana.com/associated-token-account) для відповідного mint отримується, і переказ виконується на цей акаунт за допомогою інструкції [TransferChecked](https://github.com/solana-labs/solana-program-library/blob/fc0d6a2db79bd6499f04b9be7ead0c400283845e/token/program/src/instruction.rs#L268). Зауважте, що ATA адреса може ще не існувати, у цьому випадку біржа повинна профінансувати акаунт від імені користувача. Для акаунтів SPL Token фінансування акаунта для виведення потребує 0.00203928 SOL (2,039,280 лампортів). +Перед виконанням [переказу](#token-transfers) для виведення біржа повинна +перевірити адресу, як це +[описано вище](#validating-user-supplied-account-addresses-for-withdrawals). +Крім того, ця адреса має належати System Program і не мати даних акаунта. Якщо +на цій адресі відсутній баланс SOL, перед виконанням виведення слід отримати +підтвердження користувача. Усі інші адреси для виведення повинні бути відхилені. + +З адреси для виведення +[Associated Token Account (ATA)](https://spl.solana.com/associated-token-account) +для відповідного mint отримується, і переказ виконується на цей акаунт за +допомогою інструкції +[TransferChecked](https://github.com/solana-labs/solana-program-library/blob/fc0d6a2db79bd6499f04b9be7ead0c400283845e/token/program/src/instruction.rs#L268). +Зауважте, що ATA адреса може ще не існувати, у цьому випадку біржа повинна +профінансувати акаунт від імені користувача. Для акаунтів SPL Token фінансування +акаунта для виведення потребує 0.00203928 SOL (2,039,280 лампортів). Шаблон команди `spl-token transfer` для виведення: @@ -855,31 +1111,54 @@ spl-token transfer --fund-recipient #### Freeze Authority (Замороження Акаунтів) -Для дотримання регуляторних вимог емітент токенів SPL може опціонально мати "Freeze Authority" (повноваження замороження) для всіх акаунтів, створених у зв'язку з його mint. Це дозволяє йому [заморожувати](https://spl.solana.com/token#freezing-accounts) активи в певному акаунті за бажанням, роблячи акаунт недоступним до моменту його розморожування. Якщо ця функція використовується, публічний ключ freeze authority буде зареєстрований у акаунті mint токену SPL. +Для дотримання регуляторних вимог емітент токенів SPL може опціонально мати +"Freeze Authority" (повноваження замороження) для всіх акаунтів, створених у +зв'язку з його mint. Це дозволяє йому +[заморожувати](https://spl.solana.com/token#freezing-accounts) активи в певному +акаунті за бажанням, роблячи акаунт недоступним до моменту його розморожування. +Якщо ця функція використовується, публічний ключ freeze authority буде +зареєстрований у акаунті mint токену SPL. ### Основна Підтримка Стандарту SPL Token-2022 (Token-Extensions) -[SPL Token-2022](https://spl.solana.com/token-2022) є новим стандартом для створення й обміну обгорнутих/синтетичних токенів у блокчейні Solana. +[SPL Token-2022](https://spl.solana.com/token-2022) є новим стандартом для +створення й обміну обгорнутих/синтетичних токенів у блокчейні Solana. -Відомий також як "Token Extensions", цей стандарт включає багато нових функцій, які можуть бути опціонально увімкнені творцями токенів та власниками акаунтів. До таких функцій належать конфіденційні перекази, комісії за переказ, закриття mint, метадані, постійні делегати, незмінна власність тощо. Більше інформації дивіться в [керівництві з розширень](https://spl.solana.com/token-2022/extensions). +Відомий також як "Token Extensions", цей стандарт включає багато нових функцій, +які можуть бути опціонально увімкнені творцями токенів та власниками акаунтів. +До таких функцій належать конфіденційні перекази, комісії за переказ, закриття +mint, метадані, постійні делегати, незмінна власність тощо. Більше інформації +дивіться в +[керівництві з розширень](https://spl.solana.com/token-2022/extensions). -Якщо ваша біржа підтримує SPL Token, багато додаткових зусиль для підтримки SPL Token-2022 не знадобиться: +Якщо ваша біржа підтримує SPL Token, багато додаткових зусиль для підтримки SPL +Token-2022 не знадобиться: -- CLI інструмент безпроблемно працює з обома програмами, починаючи з версії 3.0.0. -- Поля `preTokenBalances` та `postTokenBalances` включають баланси SPL Token-2022. -- RPC індексує акаунти SPL Token-2022, але їх потрібно запитувати окремо за програмним ідентифікатором `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`. +- CLI інструмент безпроблемно працює з обома програмами, починаючи з версії + 3.0.0. +- Поля `preTokenBalances` та `postTokenBalances` включають баланси SPL + Token-2022. +- RPC індексує акаунти SPL Token-2022, але їх потрібно запитувати окремо за + програмним ідентифікатором `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`. -Програма Associated Token Account працює так само, і правильно розраховує необхідну суму депозиту SOL для нового акаунта. +Програма Associated Token Account працює так само, і правильно розраховує +необхідну суму депозиту SOL для нового акаунта. -Однак через розширення акаунти можуть бути більшими за 165 байтів, тому вони можуть потребувати більше ніж 0.00203928 SOL для фінансування. +Однак через розширення акаунти можуть бути більшими за 165 байтів, тому вони +можуть потребувати більше ніж 0.00203928 SOL для фінансування. -Наприклад, програма Associated Token Account завжди включає розширення "immutable owner", тому акаунти займають мінімум 170 байтів, що вимагає 0.00207408 SOL. +Наприклад, програма Associated Token Account завжди включає розширення +"immutable owner", тому акаунти займають мінімум 170 байтів, що вимагає +0.00207408 SOL. ### Міркування Щодо Розширень -Попередній розділ описує базову підтримку SPL Token-2022. Оскільки розширення змінюють поведінку токенів, біржам, можливо, доведеться змінити, як вони обробляють токени. +Попередній розділ описує базову підтримку SPL Token-2022. Оскільки розширення +змінюють поведінку токенів, біржам, можливо, доведеться змінити, як вони +обробляють токени. -Можливо побачити всі розширення на mint або токен акаунті за допомогою наступної команди: +Можливо побачити всі розширення на mint або токен акаунті за допомогою наступної +команди: ```shell spl-token display @@ -887,9 +1166,11 @@ spl-token display #### Комісія за Переказ -Токен може бути налаштований з комісією за переказ, при якій частина переданих токенів утримується на адресі отримувача для подальшого стягнення. +Токен може бути налаштований з комісією за переказ, при якій частина переданих +токенів утримується на адресі отримувача для подальшого стягнення. -Якщо ваша біржа здійснює переказ цих токенів, зверніть увагу, що не всі токени можуть надійти на адресу отримувача через утриману суму. +Якщо ваша біржа здійснює переказ цих токенів, зверніть увагу, що не всі токени +можуть надійти на адресу отримувача через утриману суму. Під час переказу можна вказати очікувану комісію, щоб уникнути несподіванок: @@ -899,9 +1180,11 @@ spl-token transfer --expected-fee --fund-recipient #### Конфіденційні Перекази -Mint може бути налаштований для конфіденційних переказів, при яких суми токенів шифруються, але власники акаунтів залишаються публічними. +Mint може бути налаштований для конфіденційних переказів, при яких суми токенів +шифруються, але власники акаунтів залишаються публічними. -Біржі можуть налаштувати токен акаунти для відправлення та отримання конфіденційних переказів, щоб приховати суми користувачів. Увімкнення конфіденційних переказів для токен акаунтів не є обов’язковим, тому біржі можуть змусити користувачів надсилати токени неконфіденційно. +Біржі можуть налаштувати токен акаунти для відправлення та отримання +конфіденційних переказів, щоб приховати суми користувачів. Увімкнення +конфіденційних переказів для токен акаунтів не є обов’язковим, тому біржі можуть +змусити користувачів надсилати токени неконфіденційно. -Щоб увімкнути конфіденційні перекази, акаунт має бути налаштований відповідним чином: +Щоб увімкнути конфіденційні перекази, акаунт має бути налаштований відповідним +чином: ```shell spl-token configure-confidential-transfer-account --address @@ -927,7 +1215,9 @@ spl-token configure-confidential-transfer-account --address spl-token transfer --confidential ``` -Під час конфіденційного переказу поля `preTokenBalance` та `postTokenBalance` не показуватимуть змін. Щоб виконати операцію з депозитними акаунтами, необхідно розшифрувати новий баланс, щоб вивести токени: +Під час конфіденційного переказу поля `preTokenBalance` та `postTokenBalance` не +показуватимуть змін. Щоб виконати операцію з депозитними акаунтами, необхідно +розшифрувати новий баланс, щоб вивести токени: ```shell spl-token apply-pending-balance --address @@ -936,7 +1226,9 @@ spl-token withdraw-confidential-tokens --address --transfer-hook-account ... ``` + #### Обов'язкова Нотатка (Memo) при Переказі -Користувачі можуть налаштувати свої токен акаунти так, щоб перекази вимагали нотатку (memo). +Користувачі можуть налаштувати свої токен акаунти так, щоб перекази вимагали +нотатку (memo). -Біржі можуть додавати інструкцію нотатки перед тим, як переказати токени користувачам, або вимагати, щоб користувачі додавали нотатку перед відправкою токенів на біржу: +Біржі можуть додавати інструкцію нотатки перед тим, як переказати токени +користувачам, або вимагати, щоб користувачі додавали нотатку перед відправкою +токенів на біржу: ```shell spl-token transfer --with-memo ``` -## Тестування Інтеграції -Обов'язково протестуйте весь свій робочий процес у кластерах Solana devnet та testnet [clusters](/docs/uk/core/clusters.md) перед переходом до продакшну на mainnet-beta. Devnet є найбільш відкритим і гнучким, і ідеально підходить для початкової розробки, тоді як testnet пропонує більш реалістичну конфігурацію кластера. Обидва кластери devnet та testnet підтримують faucet. Використовуйте команду `solana airdrop 1`, щоб отримати трохи SOL для devnet або testnet для розробки та тестування. +## Тестування Інтеграції +Обов'язково протестуйте весь свій робочий процес у кластерах Solana devnet та +testnet [clusters](/docs/uk/core/clusters.md) перед переходом до продакшну на +mainnet-beta. Devnet є найбільш відкритим і гнучким, і ідеально підходить для +початкової розробки, тоді як testnet пропонує більш реалістичну конфігурацію +кластера. Обидва кластери devnet та testnet підтримують faucet. Використовуйте +команду `solana airdrop 1`, щоб отримати трохи SOL для devnet або testnet для +розробки та тестування. diff --git a/docs/locales/uk/programs/anchor/client-typescript.md b/docs/locales/uk/programs/anchor/client-typescript.md index 42be6e41c..d53d54e12 100644 --- a/docs/locales/uk/programs/anchor/client-typescript.md +++ b/docs/locales/uk/programs/anchor/client-typescript.md @@ -1,15 +1,16 @@ --- title: JS/TS Client description: - Дізнайтеся, як використовувати клієнтську бібліотеку TypeScript для взаємодії з Solana + Дізнайтеся, як використовувати клієнтську бібліотеку TypeScript для взаємодії + з Solana sidebarLabel: JS/TS Client sidebarSortOrder: 3 --- Anchor надає бібліотеку клієнта TypeScript ([@coral-xyz/anchor](https://github.com/coral-xyz/anchor/tree/v0.30.1/ts/packages/anchor)) -Це спрощує процес взаємодії з програмами Solana від клієнта -у JavaScript або TypeScript. +Це спрощує процес взаємодії з програмами Solana від клієнта у JavaScript або +TypeScript. ## Клієнтська програма @@ -22,15 +23,15 @@ Anchor надає бібліотеку клієнта TypeScript `AnchorProvider` - це абстракція, яка поєднує дві речі: - `Підключення ' - з'єднання з [кластером Solana] (/docs/core/clusters.md) -(тобто localhost, devnet, mainnet) -- `Wallet` - (необов’язково) Гаманець за замовчуванням, який використовується для оплати та підписання транзакцій - - - + (тобто localhost, devnet, mainnet) +- `Wallet` - (необов’язково) Гаманець за замовчуванням, який використовується + для оплати та підписання транзакцій + + -При інтеграції з фронтендом за допомогою -[Адаптер гаманця] (https://solana.com/developers/guides/wallets/add-solana-wallet-adapter-to-nextjs), -Вам потрібно буде налаштувати `AnchorProvider` та `Program`. +При інтеграції з фронтендом за допомогою [Адаптер гаманця] +(https://solana.com/developers/guides/wallets/add-solana-wallet-adapter-to-nextjs), +Вам потрібно буде налаштувати `AnchorProvider` та `Program`. ```ts {9-10, 12-14} import { Program, AnchorProvider, setProvider } from "@coral-xyz/anchor"; @@ -52,13 +53,13 @@ export const program = new Program(idl as HelloAnchor, { У фрагменті коду вище: - `idl.json` - це файл IDL, створений якір, знайдено на -`/target/idl/ .json` в якорі. + `/target/idl/ .json` в якорі. - `idltype.ts` - це тип IDL (для використання з TS), знайдено в -`/target/type/ .ts` в якорі. + `/target/type/ .ts` в якорі. -Крім того, ви можете створити екземпляр, використовуючи лише IDL -і підключення до кластеру солани.Це означає, що немає за замовчуванням -`Wallet`, але дозволяє використовувати` Програму 'для отримання облікових записів або побудувати +Крім того, ви можете створити екземпляр, використовуючи лише IDL і підключення +до кластеру солани.Це означає, що немає за замовчуванням `Wallet`, але дозволяє +використовувати` Програму 'для отримання облікових записів або побудувати Інструкції без підключеного гаманця. ```ts {8-10} @@ -77,9 +78,10 @@ export const program = new Program(idl as HelloAnchor, { -Якір автоматично налаштовує екземпляр `Program` у тестовому файлі за замовчуванням -нові проекти.Однак ця установка відрізняється від того, як ви ініціалізуєте програму -Поза робочою областю якоря, наприклад, у програмах React або Node.js. +Якір автоматично налаштовує екземпляр `Program` у тестовому файлі за +замовчуванням нові проекти.Однак ця установка відрізняється від того, як ви +ініціалізуєте програму Поза робочою областю якоря, наприклад, у програмах React +або Node.js. ```typescript import * as anchor from "@coral-xyz/anchor"; @@ -105,20 +107,23 @@ describe("hello_anchor", () => { ## Виклик інструкцій -Після того як `Program` налаштовано за допомогою програмного IDL, ви можете використовувати якір +Після того як `Program` налаштовано за допомогою програмного IDL, ви можете +використовувати якір [`MethodsBuilder`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L155) для: + - Створіть окремі інструкції - Будуйте транзакції - Будуйте та надсилайте транзакції Основний формат виглядає як наступне: + -`program.methods` - Це API Builder для створення інструкційних дзвінків з -IDL програми +`program.methods` - Це API Builder для створення інструкційних дзвінків з IDL +програми ```ts /methods/ {1} await program.methods @@ -131,7 +136,8 @@ await program.methods -У розділі `.methods` вказуйте назву інструкції з IDL програми, передаючи будь-які необхідні аргументи як значення, розділені комами. +У розділі `.methods` вказуйте назву інструкції з IDL програми, передаючи +будь-які необхідні аргументи як значення, розділені комами. ```ts /instructionName/ /instructionData1/ /instructionData2/ {2} await program.methods @@ -144,7 +150,8 @@ await program.methods -`.accounts` - Вказуйте адресу облікових записів, необхідних для інструкції, як це зазначено в IDL. +`.accounts` - Вказуйте адресу облікових записів, необхідних для інструкції, як +це зазначено в IDL. ```ts /accounts/ {3} await program.methods @@ -153,7 +160,9 @@ await program.methods .signers([]) .rpc(); ``` -Зверніть увагу, що деякі адреси облікових записів не потрібно вказувати явно, оскільки клієнт Anchor може автоматично їх визначити. Це зазвичай стосується: + +Зверніть увагу, що деякі адреси облікових записів не потрібно вказувати явно, +оскільки клієнт Anchor може автоматично їх визначити. Це зазвичай стосується: - Загальних облікових записів (наприклад, Програма Системи) - Облікових записів, де адреса є PDA (Програма-Походження Адреси) @@ -161,7 +170,10 @@ await program.methods -`.signers` - Необов'язково передайте масив ключових пар, які потрібні як додаткові підписанти для інструкції. Це зазвичай використовується при створенні нових облікових записів, де адреса облікового запису є публічним ключем нещодавно згенерованої ключової пари. +`.signers` - Необов'язково передайте масив ключових пар, які потрібні як +додаткові підписанти для інструкції. Це зазвичай використовується при створенні +нових облікових записів, де адреса облікового запису є публічним ключем +нещодавно згенерованої ключової пари. ```ts /signers/ {4} await program.methods @@ -171,7 +183,9 @@ await program.methods .rpc(); ``` -Зверніть увагу, що `.signers` слід використовувати тільки при використанні `.rpc()`. Коли ви використовуєте `.transaction()` або `.instruction()`, підписанти повинні бути додані до транзакції перед її відправкою. +Зверніть увагу, що `.signers` слід використовувати тільки при використанні +`.rpc()`. Коли ви використовуєте `.transaction()` або `.instruction()`, +підписанти повинні бути додані до транзакції перед її відправкою. @@ -182,11 +196,13 @@ Anchor надає кілька методів для створення інст -Метод [`rpc()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L283) +Метод +[`rpc()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L283) [відправляє підписану транзакцію](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/rpc.ts#L29) з вказаною інструкцією та повертає `TransactionSignature`. -При використанні `.rpc` гаманець з `Provider` автоматично додається як підписант. +При використанні `.rpc` гаманець з `Provider` автоматично додається як +підписант. ```ts {13} // Generate keypair for the new account @@ -207,7 +223,8 @@ const transactionSignature = await program.methods -Метод [`transaction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L382) +Метод +[`transaction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L382) [створює `Transaction`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/transaction.ts#L18-L26) з вказаною інструкцією без відправки транзакції. @@ -234,9 +251,11 @@ const transactionSignature = await connection.sendTransaction(transaction, [ -Метод [`instruction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L348) +Метод +[`instruction()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/methods.ts#L348) [створює `TransactionInstruction`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/instruction.ts#L57-L61) -з вказаною інструкцією. Це корисно, якщо ви хочете вручну додати інструкцію до транзакції та поєднати її з іншими інструкціями. +з вказаною інструкцією. Це корисно, якщо ви хочете вручну додати інструкцію до +транзакції та поєднати її з іншими інструкціями. ```ts {12} /instruction()/ // Generate keypair for the new account @@ -265,16 +284,20 @@ const transactionSignature = await connection.sendTransaction(transaction, [ ## Отримання облікових записів -Клієнт `Program` спрощує процес отримання та десеріалізації облікових записів, створених вашою програмою Anchor. +Клієнт `Program` спрощує процес отримання та десеріалізації облікових записів, +створених вашою програмою Anchor. -Використовуйте `program.account`, за яким слідує назва типу облікового запису, визначеного в IDL. Anchor надає кілька методів для отримання облікових записів. +Використовуйте `program.account`, за яким слідує назва типу облікового запису, +визначеного в IDL. Anchor надає кілька методів для отримання облікових записів. -Використовуйте [`all()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L251) -для отримання всіх існуючих облікових записів для конкретного типу облікового запису. +Використовуйте +[`all()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L251) +для отримання всіх існуючих облікових записів для конкретного типу облікового +запису. ```ts /all/ const accounts = await program.account.newAccount.all(); @@ -283,9 +306,13 @@ const accounts = await program.account.newAccount.all(); -Використовуйте `memcmp` (порівняння пам'яті) для фільтрації облікових записів, дані яких відповідають конкретному значенню на вказаному зсуві. Для використання `memcmp` необхідно розуміти байтову структуру поля даних для типу облікового запису, який ви отримуєте. +Використовуйте `memcmp` (порівняння пам'яті) для фільтрації облікових записів, +дані яких відповідають конкретному значенню на вказаному зсуві. Для використання +`memcmp` необхідно розуміти байтову структуру поля даних для типу облікового +запису, який ви отримуєте. -При обчисленні зсуву пам'ятайте, що перші 8 байтів у облікових записах, створених програмою Anchor, зарезервовані для дискримінатора облікового запису. +При обчисленні зсуву пам'ятайте, що перші 8 байтів у облікових записах, +створених програмою Anchor, зарезервовані для дискримінатора облікового запису. ```ts /memcmp/ const accounts = await program.account.newAccount.all([ @@ -301,7 +328,8 @@ const accounts = await program.account.newAccount.all([ -Використовуйте [`fetch()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L165) +Використовуйте +[`fetch()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L165) для отримання даних облікового запису для одного облікового запису. ```ts /fetch/ @@ -311,8 +339,10 @@ const account = await program.account.newAccount.fetch(ACCOUNT_ADDRESS); -Використовуйте [`fetchMultiple()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L200) -для отримання даних облікових записів для кількох облікових записів, передавши масив адрес облікових записів. +Використовуйте +[`fetchMultiple()`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/program/namespace/account.ts#L200) +для отримання даних облікових записів для кількох облікових записів, передавши +масив адрес облікових записів. ```ts /fetchMultiple/ const accounts = await program.account.newAccount.fetchMultiple([ diff --git a/docs/locales/uk/programs/anchor/cpi.md b/docs/locales/uk/programs/anchor/cpi.md index 4e725d555..311a1444f 100644 --- a/docs/locales/uk/programs/anchor/cpi.md +++ b/docs/locales/uk/programs/anchor/cpi.md @@ -1,29 +1,30 @@ --- title: CPIs з Anchor description: - Дізнайтеся, як реалізувати Cross Program Invocations (CPI) в програмах на Anchor, - що дозволяє взаємодіяти між різними програмами на Solana + Дізнайтеся, як реалізувати Cross Program Invocations (CPI) в програмах на + Anchor, що дозволяє взаємодіяти між різними програмами на Solana sidebarLabel: CPIs з Anchor sidebarSortOrder: 5 --- [Cross Program Invocations (CPI)](/docs/core/cpi.md) означають процес, коли одна -програма викликає інструкції іншої програми, що дозволяє здійснювати композицію програм на Solana. +програма викликає інструкції іншої програми, що дозволяє здійснювати композицію +програм на Solana. -Цей розділ охоплює основи реалізації CPIs в програмі Anchor, -використовуючи інструкцію простого переказу SOL як практичний приклад. Після того, як ви -зрозумієте основи реалізації CPI, ви зможете застосувати ці ж концепції -для будь-якої інструкції. +Цей розділ охоплює основи реалізації CPIs в програмі Anchor, використовуючи +інструкцію простого переказу SOL як практичний приклад. Після того, як ви +зрозумієте основи реалізації CPI, ви зможете застосувати ці ж концепції для +будь-якої інструкції. ## Cross Program Invocations -Розглянемо програму, яка реалізує CPI для інструкції переказу в System Program. Ось приклад програми на +Розглянемо програму, яка реалізує CPI для інструкції переказу в System Program. +Ось приклад програми на [Solana Playground](https://beta.solpg.io/66df2751cffcf4b13384d35a). Файл `lib.rs` містить одну інструкцію `sol_transfer`. Коли інструкція -`sol_transfer` в програмі Anchor викликається, програма -внутрішньо викликає інструкцію переказу з System Program. - +`sol_transfer` в програмі Anchor викликається, програма внутрішньо викликає +інструкцію переказу з System Program. ```rs filename="lib.rs" /sol_transfer/ /transfer/ {23} use anchor_lang::prelude::*; @@ -63,8 +64,8 @@ pub struct SolTransfer<'info> { } ``` -Файл `cpi.test.ts` показує, як викликати інструкцію `sol_transfer` програми Anchor і реєструє посилання на деталі транзакції на SolanaFM. - +Файл `cpi.test.ts` показує, як викликати інструкцію `sol_transfer` програми +Anchor і реєструє посилання на деталі транзакції на SolanaFM. ```ts filename="cpi.test.ts" it("SOL Transfer Anchor", async () => { @@ -83,29 +84,30 @@ it("SOL Transfer Anchor", async () => { }); ``` -Ви можете побудувати, розгорнути та запустити тест для цього прикладу на Playground, щоб переглянути -деталі транзакції на [SolanaFM explorer](https://solana.fm/). +Ви можете побудувати, розгорнути та запустити тест для цього прикладу на +Playground, щоб переглянути деталі транзакції на +[SolanaFM explorer](https://solana.fm/). Деталі транзакції покажуть, що спочатку була викликана програма Anchor -(інструкція 1), яка потім викликає System Program (інструкція 1.1), -що призводить до успішного переказу SOL. +(інструкція 1), яка потім викликає System Program (інструкція 1.1), що +призводить до успішного переказу SOL. ![Деталі транзакції](/assets/docs/core/cpi/transaction-details.png) ### Пояснення прикладу 1 -Реалізація CPI слідує такому ж шаблону, як і створення інструкції для додавання в -транзакцію. Коли реалізуємо CPI, потрібно вказати ID програми, -рахунки та дані інструкції для викликаної інструкції. +Реалізація CPI слідує такому ж шаблону, як і створення інструкції для додавання +в транзакцію. Коли реалізуємо CPI, потрібно вказати ID програми, рахунки та дані +інструкції для викликаної інструкції. Інструкція переказу в System Program вимагає два рахунки: - `from`: Рахунок, що надсилає SOL. - `to`: Рахунок, що отримує SOL. -У прикладній програмі структура `SolTransfer` вказує рахунки, необхідні -для інструкції переказу. System Program також включена, оскільки CPI -викликає System Program. +У прикладній програмі структура `SolTransfer` вказує рахунки, необхідні для +інструкції переказу. System Program також включена, оскільки CPI викликає System +Program. ```rust /sender/ /recipient/ /system_program/ #[derive(Accounts)] @@ -127,13 +129,13 @@ CPI. -Інструкція `sol_transfer`, включена в прикладний код, показує типовий -підхід до побудови CPIs за допомогою фреймворку Anchor. +Інструкція `sol_transfer`, включена в прикладний код, показує типовий підхід до +побудови CPIs за допомогою фреймворку Anchor. Цей підхід передбачає створення [`CpiContext`](https://docs.rs/anchor-lang/latest/anchor_lang/context/struct.CpiContext.html), -який містить `program_id` та рахунки, необхідні для викликаної інструкції, а також допоміжну функцію (`transfer`) для виклику конкретної -інструкції. +який містить `program_id` та рахунки, необхідні для викликаної інструкції, а +також допоміжну функцію (`transfer`) для виклику конкретної інструкції. ```rust use anchor_lang::system_program::{transfer, Transfer}; @@ -158,8 +160,8 @@ pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { } ``` -Змінна `cpi_context` вказує ID програми (System Program) та -рахунки (відправник і отримувач), необхідні для інструкції переказу. +Змінна `cpi_context` вказує ID програми (System Program) та рахунки (відправник +і отримувач), необхідні для інструкції переказу. ```rust /program_id/ /from_pubkey/ /to_pubkey/ let cpi_context = CpiContext::new( @@ -171,8 +173,8 @@ let cpi_context = CpiContext::new( ); ``` -Змінні `cpi_context` та `amount` передаються в функцію `transfer` для -виконання CPI, що викликає інструкцію переказу з System Program. +Змінні `cpi_context` та `amount` передаються в функцію `transfer` для виконання +CPI, що викликає інструкцію переказу з System Program. ```rust transfer(cpi_context, amount)?; @@ -181,12 +183,13 @@ transfer(cpi_context, amount)?; -Цей приклад показує інший підхід до реалізації CPI за допомогою функції `invoke` та +Цей приклад показує інший підхід до реалізації CPI за допомогою функції `invoke` +та [`system_instruction::transfer`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L881), що зазвичай використовується в рідних програмах на Rust. -Під капотом попередній приклад є абстракцією цієї реалізації. -Нижче наведений приклад є функціонально еквівалентним попередньому. +Під капотом попередній приклад є абстракцією цієї реалізації. Нижче наведений +приклад є функціонально еквівалентним попередньому. ```rust use anchor_lang::solana_program::{program::invoke, system_instruction}; @@ -209,11 +212,13 @@ pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { -Ви також можете вручну створити інструкцію для передачі в функцію `invoke()`. -Це корисно, коли немає доступної бібліотеки, що допомагає побудувати -інструкцію, яку ви хочете викликати. Цей підхід вимагає вказати `AccountMeta` для інструкції та правильно створити буфер даних інструкції. +Ви також можете вручну створити інструкцію для передачі в функцію `invoke()`. Це +корисно, коли немає доступної бібліотеки, що допомагає побудувати інструкцію, +яку ви хочете викликати. Цей підхід вимагає вказати `AccountMeta` для інструкції +та правильно створити буфер даних інструкції. -Інструкція `sol_transfer` нижче є вручну реалізованим CPI для інструкції переказу в System Program. +Інструкція `sol_transfer` нижче є вручну реалізованим CPI для інструкції +переказу в System Program. ```rust /instruction/10,13 {28} pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { @@ -249,13 +254,13 @@ pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { ``` Інструкція `sol_transfer` вище повторює цей -[приклад](/docs/core/transactions.md#manual-sol-transfer) вручну побудованої інструкції переказу SOL. Вона слідує тому ж шаблону, що і створення +[приклад](/docs/core/transactions.md#manual-sol-transfer) вручну побудованої +інструкції переказу SOL. Вона слідує тому ж шаблону, що і створення [інструкції](/docs/core/transactions.md#instruction) для додавання в транзакцію. При створенні інструкції на Rust використовуйте наступний синтаксис для вказівки `AccountMeta` для кожного рахунку: - ```rust AccountMeta::new(account1_pubkey, true), // writable, signer AccountMeta::new(account2_pubkey, false), // writable, not signer @@ -272,12 +277,13 @@ AccountMeta::new_readonly(account4_pubkey, true), // writable, signer ## Cross Program Invocations з PDA підписами -Далі розглянемо програму, яка реалізує CPI для інструкції переказу в System Program, де відправником є Програма Походження Адреси (PDA), для якої програма повинна "підписати" транзакцію. Ось приклад програми на +Далі розглянемо програму, яка реалізує CPI для інструкції переказу в System +Program, де відправником є Програма Походження Адреси (PDA), для якої програма +повинна "підписати" транзакцію. Ось приклад програми на [Solana Playground](https://beta.solpg.io/66df2bd2cffcf4b13384d35b). Файл `lib.rs` містить наступну програму з єдиною інструкцією `sol_transfer`. - ```rust filename="lib.rs" use anchor_lang::prelude::*; use anchor_lang::system_program::{transfer, Transfer}; @@ -325,11 +331,11 @@ pub struct SolTransfer<'info> { } ``` -Файл `cpi.test.ts` показує, як викликати інструкцію `sol_transfer` програми Anchor і реєструє посилання на деталі транзакції на SolanaFM. +Файл `cpi.test.ts` показує, як викликати інструкцію `sol_transfer` програми +Anchor і реєструє посилання на деталі транзакції на SolanaFM. Він показує, як отримати PDA за допомогою насіння, вказаного в програмі: - ```ts /pda/ /wallet.publicKey/ const [PDA] = PublicKey.findProgramAddressSync( [Buffer.from("pda"), wallet.publicKey.toBuffer()], @@ -337,8 +343,8 @@ const [PDA] = PublicKey.findProgramAddressSync( ); ``` -Першим кроком у цьому прикладі є фінансування рахунку PDA за допомогою простого переказу SOL з гаманця Playground. - +Першим кроком у цьому прикладі є фінансування рахунку PDA за допомогою простого +переказу SOL з гаманця Playground. ```ts filename="cpi.test.ts" it("Fund PDA with SOL", async () => { @@ -364,8 +370,8 @@ it("Fund PDA with SOL", async () => { ``` Коли PDA буде фінансовано SOL, викликається інструкція `sol_transfer`. Ця -інструкція переказує SOL з рахунку PDA назад на рахунок `wallet` через -CPI до System Program, що "підписується" програмою. +інструкція переказує SOL з рахунку PDA назад на рахунок `wallet` через CPI до +System Program, що "підписується" програмою. ```ts it("SOL Transfer with PDA signer", async () => { @@ -383,12 +389,12 @@ it("SOL Transfer with PDA signer", async () => { }); ``` -Ви можете побудувати, розгорнути та запустити тест, щоб переглянути деталі транзакції на -[SolanaFM explorer](https://solana.fm/). +Ви можете побудувати, розгорнути та запустити тест, щоб переглянути деталі +транзакції на [SolanaFM explorer](https://solana.fm/). Деталі транзакції покажуть, що спочатку була викликана користувацька програма -(інструкція 1), яка потім викликає System Program (інструкція 1.1), -що призводить до успішного переказу SOL. +(інструкція 1), яка потім викликає System Program (інструкція 1.1), що +призводить до успішного переказу SOL. ![Деталі транзакції](/assets/docs/core/cpi/transaction-details-pda.png) @@ -397,10 +403,10 @@ it("SOL Transfer with PDA signer", async () => { У прикладному коді структура `SolTransfer` вказує рахунки, необхідні для інструкції переказу. -Відправником є PDA, для якого програма повинна підписати транзакцію. `seeds`, які використовуються для отримання -адреси для `pda_account`, включають зашитий рядок "pda" та адресу -рахунку `recipient`. Це означає, що адреса для `pda_account` є -унікальною для кожного `recipient`. +Відправником є PDA, для якого програма повинна підписати транзакцію. `seeds`, +які використовуються для отримання адреси для `pda_account`, включають зашитий +рядок "pda" та адресу рахунку `recipient`. Це означає, що адреса для +`pda_account` є унікальною для кожного `recipient`. ```rust /pda_account/ /recipient/2 /system_program/ #[derive(Accounts)] @@ -425,6 +431,7 @@ const [PDA] = PublicKey.findProgramAddressSync( program.programId, ); ``` + Наступні вкладки представляють два підходи до реалізації Cross Program Invocations (CPI), кожен з яких має різний рівень абстракції. Обидва приклади є функціонально еквівалентними. Основною метою є ілюстрація деталей реалізації @@ -434,13 +441,13 @@ CPI. -Інструкція `sol_transfer`, включена в прикладний код, показує типовий -підхід до побудови CPIs за допомогою фреймворку Anchor. +Інструкція `sol_transfer`, включена в прикладний код, показує типовий підхід до +побудови CPIs за допомогою фреймворку Anchor. Цей підхід передбачає створення [`CpiContext`](https://docs.rs/anchor-lang/latest/anchor_lang/context/struct.CpiContext.html), -який містить `program_id` та рахунки, необхідні для викликаної інструкції, а також допоміжну функцію (`transfer`) для виклику конкретної -інструкції. +який містить `program_id` та рахунки, необхідні для викликаної інструкції, а +також допоміжну функцію (`transfer`) для виклику конкретної інструкції. ```rust /cpi_context/ {19} pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { @@ -485,9 +492,8 @@ let cpi_context = CpiContext::new( .with_signer(signer_seeds); ``` -Змінні `cpi_context` та `amount` передаються в функцію `transfer` для -виконання CPI. - +Змінні `cpi_context` та `amount` передаються в функцію `transfer` для виконання +CPI. ```rust transfer(cpi_context, amount)?; @@ -495,19 +501,19 @@ transfer(cpi_context, amount)?; Коли обробляється CPI, середовище виконання Solana перевіряє, чи правильно наведені насіння та ID програми викликача для отримання дійсного PDA. Потім PDA -додається як підписант під час виклику. Цей механізм дозволяє програмам підписувати PDA, -які отримані з їхнього ID програми. +додається як підписант під час виклику. Цей механізм дозволяє програмам +підписувати PDA, які отримані з їхнього ID програми. -Під капотом попередній приклад є обгорткою для функції `invoke_signed()`, -яка використовує +Під капотом попередній приклад є обгорткою для функції `invoke_signed()`, яка +використовує [`system_instruction::transfer`](https://github.com/solana-labs/solana/blob/27eff8408b7223bb3c4ab70523f8a8dca3ca6645/sdk/program/src/system_instruction.rs#L881) для побудови інструкції. -Цей приклад показує, як використовувати функцію `invoke_signed()`, щоб зробити CPI -підписаним PDA. +Цей приклад показує, як використовувати функцію `invoke_signed()`, щоб зробити +CPI підписаним PDA. ```rust use anchor_lang::solana_program::{program::invoke_signed, system_instruction}; @@ -530,8 +536,9 @@ pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { Ok(()) } ``` -Ця реалізація функціонально еквівалентна попередньому прикладу. -`signer_seeds` передаються в функцію `invoke_signed`. + +Ця реалізація функціонально еквівалентна попередньому прикладу. `signer_seeds` +передаються в функцію `invoke_signed`. diff --git a/docs/locales/uk/programs/anchor/idl.md b/docs/locales/uk/programs/anchor/idl.md index 1f4024f89..080f030d6 100644 --- a/docs/locales/uk/programs/anchor/idl.md +++ b/docs/locales/uk/programs/anchor/idl.md @@ -7,19 +7,22 @@ sidebarLabel: Файл IDL sidebarSortOrder: 2 --- -Файл Interface Definition Language (IDL) надає стандартизований JSON-файл, -який описує інструкції та рахунки програми. Цей файл спрощує процес інтеграції -вашої програми на блокчейні з клієнтськими додатками. +Файл Interface Definition Language (IDL) надає стандартизований JSON-файл, який +описує інструкції та рахунки програми. Цей файл спрощує процес інтеграції вашої +програми на блокчейні з клієнтськими додатками. Основні переваги IDL: -- Стандартизація: Надає послідовний формат для опису інструкцій та рахунків програми -- Генерація клієнта: Використовується для генерації коду клієнта для взаємодії з програмою +- Стандартизація: Надає послідовний формат для опису інструкцій та рахунків + програми +- Генерація клієнта: Використовується для генерації коду клієнта для взаємодії з + програмою Команда `anchor build` генерує файл IDL, який знаходиться за адресою `/target/idl/.json`. -Нижче наведені фрагменти коду, що показують, як програма, IDL та клієнт взаємопов'язані. +Нижче наведені фрагменти коду, що показують, як програма, IDL та клієнт +взаємопов'язані. ## Інструкції програми @@ -31,8 +34,8 @@ sidebarSortOrder: 2 -Наведена програма включає інструкцію `initialize`, що вказує на рахунки -та параметри, які вона потребує. +Наведена програма включає інструкцію `initialize`, що вказує на рахунки та +параметри, які вона потребує. ```rust {8-12, 15-22} use anchor_lang::prelude::*; @@ -181,17 +184,16 @@ describe("hello_anchor", () => { ## Рахунки програми -Масив `accounts` у файлі IDL відповідає структурам у програмі, -позначеним макросом `#[account]`. Ці структури визначають дані, які зберігаються в +Масив `accounts` у файлі IDL відповідає структурам у програмі, позначеним +макросом `#[account]`. Ці структури визначають дані, які зберігаються в рахунках, створених програмою. -Наведена програма визначає структуру `NewAccount` з одним полем `data` -типу `u64`. - +Наведена програма визначає структуру `NewAccount` з одним полем `data` типу +`u64`. ```rust {24-27} use anchor_lang::prelude::*; @@ -229,7 +231,6 @@ pub struct NewAccount { Згенерований файл IDL включає рахунок у стандартизованому форматі JSON, включаючи його ім'я, дискримінатор та поля. - ```json filename="JSON" {39-40, 45-54} { "address": "BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd", @@ -341,23 +342,27 @@ describe("hello_anchor", () => { ## Дискримінатори -Anchor призначає унікальний 8-байтовий дискримінатор для кожної інструкції та типу рахунку в програмі. Ці дискримінатори служать як ідентифікатори для відрізнення різних інструкцій або типів рахунків. +Anchor призначає унікальний 8-байтовий дискримінатор для кожної інструкції та +типу рахунку в програмі. Ці дискримінатори служать як ідентифікатори для +відрізнення різних інструкцій або типів рахунків. -Дискримінатор генерується за допомогою перших 8 байтів хешу Sha256 префікса, поєднаного з ім'ям інструкції або рахунку. Починаючи з версії Anchor v0.30, ці дискримінатори включені в файл IDL. +Дискримінатор генерується за допомогою перших 8 байтів хешу Sha256 префікса, +поєднаного з ім'ям інструкції або рахунку. Починаючи з версії Anchor v0.30, ці +дискримінатори включені в файл IDL. Зверніть увагу, що при роботі з Anchor, вам зазвичай не потрібно взаємодіяти -безпосередньо з цими дискримінаторами. Цей розділ надає контекст щодо того, -як генерується і використовується дискримінатор. +безпосередньо з цими дискримінаторами. Цей розділ надає контекст щодо того, як +генерується і використовується дискримінатор. -Дискримінатор інструкції використовується програмою для визначення, яку конкретну -інструкцію виконати при виклику. +Дискримінатор інструкції використовується програмою для визначення, яку +конкретну інструкцію виконати при виклику. -Коли інструкція програми Anchor викликається, дискримінатор включається як -перші 8 байтів даних інструкції. Це робиться автоматично клієнтом Anchor. +Коли інструкція програми Anchor викликається, дискримінатор включається як перші +8 байтів даних інструкції. Це робиться автоматично клієнтом Anchor. ```json filename="IDL" {4} "instructions": [ @@ -369,7 +374,8 @@ Anchor призначає унікальний 8-байтовий дискрим ] ``` -Дискримінатор для інструкції — це перші 8 байтів хешу Sha256 префікса `global` плюс ім'я інструкції. +Дискримінатор для інструкції — це перші 8 байтів хешу Sha256 префікса `global` +плюс ім'я інструкції. Наприклад: @@ -404,8 +410,9 @@ ed = 237 -Дискримінатор рахунку використовується для ідентифікації конкретного типу рахунку при -десеріалізації даних з ланцюга та встановлюється при створенні рахунку. +Дискримінатор рахунку використовується для ідентифікації конкретного типу +рахунку при десеріалізації даних з ланцюга та встановлюється при створенні +рахунку. ```json filename="IDL" {4} "accounts": [ @@ -416,11 +423,11 @@ ed = 237 ] ``` -Дискримінатор для рахунку — це перші 8 байтів хешу Sha256 префікса `account` плюс ім'я рахунку. +Дискримінатор для рахунку — це перші 8 байтів хешу Sha256 префікса `account` +плюс ім'я рахунку. Наприклад: - ``` sha256("account:NewAccount") ``` @@ -447,13 +454,16 @@ e8 = 232 Реалізацію генерації дискримінатора ви можете знайти в кодовій базі Anchor [тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L101-L117). -Зверніть увагу, що різні програми, які використовують однакові імена рахунків, генеруватимуть той самий дискримінатор. При десеріалізації даних рахунків програми Anchor також перевірятимуть, що рахунок належить очікуваній програмі для заданого типу рахунку. +Зверніть увагу, що різні програми, які використовують однакові імена рахунків, +генеруватимуть той самий дискримінатор. При десеріалізації даних рахунків +програми Anchor також перевірятимуть, що рахунок належить очікуваній програмі +для заданого типу рахунку. -Дискримінатор події використовується для ідентифікації конкретного типу події при -десеріалізації даних з ланцюга при емісії події. +Дискримінатор події використовується для ідентифікації конкретного типу події +при десеріалізації даних з ланцюга при емісії події. ```json filename="IDL" {4} "events": [ @@ -464,7 +474,8 @@ e8 = 232 ] ``` -Дискримінатор для події — це перші 8 байтів хешу Sha256 префікса `event` плюс ім'я події. +Дискримінатор для події — це перші 8 байтів хешу Sha256 префікса `event` плюс +ім'я події. Наприклад: @@ -496,9 +507,10 @@ c9 = 201 Реалізацію генерації дискримінатора ви можете знайти в кодовій базі Anchor [тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/event/src/lib.rs#L23-L27). -Зверніть увагу, що різні програми, які використовують однакові імена подій, генеруватимуть той самий -дискримінатор. При десеріалізації даних подій програми Anchor також перевірятимуть, що -подія належить очікуваній програмі для заданого типу події. +Зверніть увагу, що різні програми, які використовують однакові імена подій, +генеруватимуть той самий дискримінатор. При десеріалізації даних подій програми +Anchor також перевірятимуть, що подія належить очікуваній програмі для заданого +типу події. - \ No newline at end of file + diff --git a/docs/locales/uk/programs/anchor/index.md b/docs/locales/uk/programs/anchor/index.md index 35be0c546..169686979 100644 --- a/docs/locales/uk/programs/anchor/index.md +++ b/docs/locales/uk/programs/anchor/index.md @@ -1,8 +1,9 @@ --- title: Початок роботи з Anchor description: - Дізнайтесь, як будувати програми для Solana за допомогою фреймворку Anchor. Цей - детальний посібник охоплює створення, збірку, тестування та розгортання смарт-контрактів Solana з використанням Anchor. + Дізнайтесь, як будувати програми для Solana за допомогою фреймворку Anchor. + Цей детальний посібник охоплює створення, збірку, тестування та розгортання + смарт-контрактів Solana з використанням Anchor. sidebarLabel: Фреймворк Anchor sidebarSortOrder: 0 altRoutes: @@ -11,9 +12,9 @@ altRoutes: - /docs/programs/overview --- -Фреймворк Anchor — це інструмент, який спрощує процес створення програм для Solana. -Неважливо, чи ви новачок у блокчейн-розробці, чи досвідчений програміст, Anchor спрощує процес написання, тестування та розгортання -програм для Solana. +Фреймворк Anchor — це інструмент, який спрощує процес створення програм для +Solana. Неважливо, чи ви новачок у блокчейн-розробці, чи досвідчений програміст, +Anchor спрощує процес написання, тестування та розгортання програм для Solana. У цьому розділі ми розглянемо: @@ -35,7 +36,6 @@ altRoutes: Щоб перевірити встановлення Anchor CLI, відкрийте термінал і виконайте: - ```shell filename="Terminal" anchor --version ``` @@ -48,13 +48,16 @@ anchor-cli 0.30.1 ## Початок роботи -Цей розділ охоплює основні кроки для створення, зборки та тестування вашої першої локальної програми на Anchor. +Цей розділ охоплює основні кроки для створення, зборки та тестування вашої +першої локальної програми на Anchor. ### Створення нового проекту -Щоб почати новий проект, використовуйте команду `anchor init`, після якої вкажіть назву вашого проекту. Ця команда створює нову директорію з вказаним ім'ям і налаштовує стандартну програму та тестовий файл. +Щоб почати новий проект, використовуйте команду `anchor init`, після якої +вкажіть назву вашого проекту. Ця команда створює нову директорію з вказаним +ім'ям і налаштовує стандартну програму та тестовий файл. ```shell filename="Terminal" anchor init my-project @@ -66,7 +69,8 @@ anchor init my-project cd my-project ``` -Стандартна програма Anchor знаходиться за адресою `programs/my-project/src/lib.rs`. +Стандартна програма Anchor знаходиться за адресою +`programs/my-project/src/lib.rs`. @@ -99,13 +103,14 @@ pub struct Initialize {} -Стандартний тестовий файл TypeScript знаходиться за адресою `/tests/my-project.ts`. +Стандартний тестовий файл TypeScript знаходиться за адресою +`/tests/my-project.ts`. -Цей файл демонструє, як викликати інструкцію `initialize` стандартної програми в TypeScript. - +Цей файл демонструє, як викликати інструкцію `initialize` стандартної програми в +TypeScript. ```ts filename="my-project.ts" import * as anchor from "@coral-xyz/anchor"; @@ -129,8 +134,8 @@ describe("my-project", () => { -Якщо ви віддаєте перевагу Rust для тестування, ініціалізуйте свій проект за допомогою прапорця -`--test-template rust`. +Якщо ви віддаєте перевагу Rust для тестування, ініціалізуйте свій проект за +допомогою прапорця `--test-template rust`. ```shell anchor init --test-template rust my-project @@ -183,9 +188,9 @@ fn test_initialize() { anchor build ``` -Зкомпільована програма буде знаходитися за адресою `/target/deploy/my_project.so`. Вміст -цього файлу буде збережено в мережі Solana (як виконуваний акаунт) -під час розгортання вашої програми. +Зкомпільована програма буде знаходитися за адресою +`/target/deploy/my_project.so`. Вміст цього файлу буде збережено в мережі Solana +(як виконуваний акаунт) під час розгортання вашої програми. ### Тестування програми @@ -195,24 +200,31 @@ anchor build anchor test ``` -За замовчуванням конфігураційний файл `Anchor.toml` вказує на кластер `localnet`. При розробці на `localnet`, команда `anchor test` автоматично: +За замовчуванням конфігураційний файл `Anchor.toml` вказує на кластер +`localnet`. При розробці на `localnet`, команда `anchor test` автоматично: 1. Запускає локальний валідатор Solana 2. Створює та розгортає вашу програму на локальному кластері 3. Виконує тести з папки `tests` 4. Зупиняє локальний валідатор Solana -Альтернативно, ви можете вручну запустити локальний валідатор Solana та виконувати тести проти нього. Це корисно, якщо ви хочете, щоб валідатор працював, поки ви працюєте над програмою. Це дозволяє вам перевіряти акаунти та журнали транзакцій на [Solana Explorer](https://explorer.solana.com/?cluster=custom) під час розробки локально. +Альтернативно, ви можете вручну запустити локальний валідатор Solana та +виконувати тести проти нього. Це корисно, якщо ви хочете, щоб валідатор +працював, поки ви працюєте над програмою. Це дозволяє вам перевіряти акаунти та +журнали транзакцій на +[Solana Explorer](https://explorer.solana.com/?cluster=custom) під час розробки +локально. -Відкрийте новий термінал і запустіть локальний валідатор Solana, виконуючи команду -`solana-test-validator`. +Відкрийте новий термінал і запустіть локальний валідатор Solana, виконуючи +команду `solana-test-validator`. ```shell filename="Terminal" copy solana-test-validator ``` -У окремому терміналі виконайте тести проти локального кластера. Використовуйте прапорець -`--skip-local-validator`, щоб пропустити запуск локального валідатора, оскільки він уже працює. +У окремому терміналі виконайте тести проти локального кластера. Використовуйте +прапорець `--skip-local-validator`, щоб пропустити запуск локального валідатора, +оскільки він уже працює. ```shell filename="Terminal" copy anchor test --skip-local-validator @@ -220,7 +232,8 @@ anchor test --skip-local-validator ### Розгортання на Devnet -За замовчуванням конфігураційний файл `Anchor.toml` у проекті Anchor вказує на кластер localnet. +За замовчуванням конфігураційний файл `Anchor.toml` у проекті Anchor вказує на +кластер localnet. ```toml filename="Anchor.toml" {14} [toolchain] @@ -243,7 +256,9 @@ wallet = "~/.config/solana/id.json" test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" ``` -Щоб розгорнути вашу програму на devnet, змініть значення `cluster` на `Devnet`. Зверніть увагу, що для цього ваш гаманець повинен мати достатньо SOL на Devnet для покриття вартості розгортання. +Щоб розгорнути вашу програму на devnet, змініть значення `cluster` на `Devnet`. +Зверніть увагу, що для цього ваш гаманець повинен мати достатньо SOL на Devnet +для покриття вартості розгортання. ```diff -cluster = "Localnet" @@ -256,13 +271,16 @@ cluster = "Devnet" wallet = "~/.config/solana/id.json" ``` -Тепер, коли ви виконаєте команду `anchor deploy`, ваша програма буде розгорнута на кластері devnet. Команда `anchor test` також використовуватиме кластер, вказаний у файлі `Anchor.toml`. +Тепер, коли ви виконаєте команду `anchor deploy`, ваша програма буде розгорнута +на кластері devnet. Команда `anchor test` також використовуватиме кластер, +вказаний у файлі `Anchor.toml`. ```shell anchor deploy ``` -Щоб розгорнути на mainnet, просто оновіть файл `Anchor.toml`, вказавши кластер mainnet. +Щоб розгорнути на mainnet, просто оновіть файл `Anchor.toml`, вказавши кластер +mainnet. ```toml filename="Anchor.toml" [provider] @@ -272,17 +290,18 @@ wallet = "~/.config/solana/id.json" ### Оновлення програми -Програми Solana можна оновити, повторно розгорнувши програму з тим самим ID програми. - -Щоб оновити програму, просто внесіть зміни в код вашої програми і виконайте команду -`anchor build` для генерації оновленого файлу `.so`. +Програми Solana можна оновити, повторно розгорнувши програму з тим самим ID +програми. +Щоб оновити програму, просто внесіть зміни в код вашої програми і виконайте +команду `anchor build` для генерації оновленого файлу `.so`. ```shell anchor build ``` -Потім виконайте команду `anchor deploy`, щоб повторно розгорнути оновлену програму. +Потім виконайте команду `anchor deploy`, щоб повторно розгорнути оновлену +програму. ```shell anchor deploy @@ -290,15 +309,18 @@ anchor deploy ### Закриття програми -Щоб повернути SOL, виділені на акаунт програми, ви можете закрити вашу програму Solana. +Щоб повернути SOL, виділені на акаунт програми, ви можете закрити вашу програму +Solana. -Для закриття програми використовуйте команду `solana program close `. Наприклад: +Для закриття програми використовуйте команду +`solana program close `. Наприклад: ```shell solana program close 3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg --bypass-warning ``` -Зверніть увагу, що після закриття програми, ID програми не можна буде використовувати для розгортання нової програми. +Зверніть увагу, що після закриття програми, ID програми не можна буде +використовувати для розгортання нової програми. @@ -334,11 +356,13 @@ solana program close 3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg --bypass-warni ### Папка Programs -Папка `/programs` містить програми Anchor вашого проекту. Один робочий простір може містити кілька програм. +Папка `/programs` містить програми Anchor вашого проекту. Один робочий простір +може містити кілька програм. ### Папка Tests -Папка `/tests` містить тестові файли для вашого проекту. Стандартний тестовий файл створюється автоматично під час створення вашого проекту. +Папка `/tests` містить тестові файли для вашого проекту. Стандартний тестовий +файл створюється автоматично під час створення вашого проекту. ### Папка Target @@ -354,8 +378,10 @@ solana program close 3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg --bypass-warni ### Папка .anchor -Містить файл `program-logs`, що містить журнали транзакцій з останнього виконання тестових файлів. +Містить файл `program-logs`, що містить журнали транзакцій з останнього +виконання тестових файлів. ### Папка App -Папка `/app` є порожньою і може бути опційно використана для вашого фронтенд-коду. \ No newline at end of file +Папка `/app` є порожньою і може бути опційно використана для вашого +фронтенд-коду. diff --git a/docs/locales/uk/programs/anchor/pda.md b/docs/locales/uk/programs/anchor/pda.md index 505698c82..5b80e71a7 100644 --- a/docs/locales/uk/programs/anchor/pda.md +++ b/docs/locales/uk/programs/anchor/pda.md @@ -1,50 +1,55 @@ --- title: PDAs з Anchor description: - Дізнайтеся, як використовувати Program Derived Addresses (PDA) в програмах Anchor, використовуючи - обмеження та реалізуючи поширені шаблони PDA + Дізнайтеся, як використовувати Program Derived Addresses (PDA) в програмах + Anchor, використовуючи обмеження та реалізуючи поширені шаблони PDA sidebarLabel: PDAs з Anchor sidebarSortOrder: 4 --- -[Program Derived Addresses (PDA)](/docs/core/pda) — це функція розробки на Solana, -яка дозволяє створювати унікальну адресу, що отримується детерміновано -з попередньо визначених вхідних значень (насіння) та ID програми. +[Program Derived Addresses (PDA)](/docs/core/pda) — це функція розробки на +Solana, яка дозволяє створювати унікальну адресу, що отримується детерміновано з +попередньо визначених вхідних значень (насіння) та ID програми. Цей розділ охоплює базові приклади використання PDA в програмі Anchor. ## Обмеження Anchor для PDA -При використанні PDA в програмі Anchor, зазвичай використовуються обмеження акаунтів Anchor -для визначення насіння, що використовуються для отримання PDA. Ці обмеження служать -як перевірки безпеки, щоб переконатися, що правильна адреса була отримана. +При використанні PDA в програмі Anchor, зазвичай використовуються обмеження +акаунтів Anchor для визначення насіння, що використовуються для отримання PDA. +Ці обмеження служать як перевірки безпеки, щоб переконатися, що правильна адреса +була отримана. Обмеження, які використовуються для визначення насіння PDA, включають: -- `seeds`: Масив необов'язкових насінь, що використовуються для отримання PDA. Насіння можуть бути - статичними значеннями або динамічними посиланнями на дані акаунтів. -- `bump`: Bump seed, що використовується для отримання PDA. Використовується для забезпечення того, - щоб адреса не потрапляла на криву Ed25519 і була дійсним PDA. -- `seeds::program` - (Необов'язково) ID програми, що використовується для отримання адреси PDA. - Це обмеження використовується лише для отримання PDA, де ID програми не є - поточною програмою. +- `seeds`: Масив необов'язкових насінь, що використовуються для отримання PDA. + Насіння можуть бути статичними значеннями або динамічними посиланнями на дані + акаунтів. +- `bump`: Bump seed, що використовується для отримання PDA. Використовується для + забезпечення того, щоб адреса не потрапляла на криву Ed25519 і була дійсним + PDA. +- `seeds::program` - (Необов'язково) ID програми, що використовується для + отримання адреси PDA. Це обмеження використовується лише для отримання PDA, де + ID програми не є поточною програмою. Обмеження `seeds` та `bump` повинні використовуватися разом. ### Приклади використання -Нижче наведені приклади, що демонструють, як використовувати обмеження PDA в програмі Anchor. +Нижче наведені приклади, що демонструють, як використовувати обмеження PDA в +програмі Anchor. -Обмеження `seeds` визначає необов'язкові значення, що використовуються для отримання PDA. +Обмеження `seeds` визначає необов'язкові значення, що використовуються для +отримання PDA. #### Без необов'язкових сідів -- Використовуйте порожній масив `[]`, щоб визначити PDA без необов'язкових насінь. - +- Використовуйте порожній масив `[]`, щоб визначити PDA без необов'язкових + насінь. ```rs #[derive(Accounts)] @@ -74,8 +79,8 @@ pub struct InstructionAccounts<'info> { #### Кілька насінь та посилань на акаунти -- Можна вказати кілька насінь в обмеженні `seeds`. Обмеження `seeds` - також може посилатися на інші адреси акаунтів або дані акаунтів. +- Можна вказати кілька насінь в обмеженні `seeds`. Обмеження `seeds` також може + посилатися на інші адреси акаунтів або дані акаунтів. ```rs #[derive(Accounts)] @@ -89,8 +94,8 @@ pub struct InstructionAccounts<'info> { } ``` -Приклад вище використовує як статичне насіння (`b"hello_world"`), так і динамічне насіння -(публічний ключ підписанта). +Приклад вище використовує як статичне насіння (`b"hello_world"`), так і +динамічне насіння (публічний ключ підписанта). @@ -115,7 +120,9 @@ pub struct InstructionAccounts<'info> { #### Вказати значення Bump -Ви можете явно вказати значення bump, що корисно для оптимізації використання обчислювальних одиниць. Це передбачає, що акаунт PDA вже був створений і bump seed зберігається як поле в існуючому акаунті. +Ви можете явно вказати значення bump, що корисно для оптимізації використання +обчислювальних одиниць. Це передбачає, що акаунт PDA вже був створений і bump +seed зберігається як поле в існуючому акаунті. ```rs #[derive(Accounts)] @@ -133,16 +140,19 @@ pub struct CustomAccount { } ``` -Зберігаючи значення bump у даних акаунту, програма не потребує його повторного обчислення, що дозволяє заощадити обчислювальні одиниці. Збережене значення bump може бути збережено в самому акаунті або в іншому акаунті. +Зберігаючи значення bump у даних акаунту, програма не потребує його повторного +обчислення, що дозволяє заощадити обчислювальні одиниці. Збережене значення bump +може бути збережено в самому акаунті або в іншому акаунті. -Обмеження `seeds::program` визначає ID програми, що використовується для отримання PDA. -Це обмеження використовується лише при отриманні PDA з іншої програми. +Обмеження `seeds::program` визначає ID програми, що використовується для +отримання PDA. Це обмеження використовується лише при отриманні PDA з іншої +програми. -Використовуйте це обмеження, коли ваша інструкція повинна взаємодіяти з акаунтами PDA, -створеними іншою програмою. +Використовуйте це обмеження, коли ваша інструкція повинна взаємодіяти з +акаунтами PDA, створеними іншою програмою. ```rs #[derive(Accounts)] @@ -160,8 +170,8 @@ pub struct InstructionAccounts<'info> { -Обмеження `init` зазвичай використовується разом з `seeds` та `bump` для створення нового -акаунту з адресою, яка є PDA. Під капотом обмеження `init` +Обмеження `init` зазвичай використовується разом з `seeds` та `bump` для +створення нового акаунту з адресою, яка є PDA. Під капотом обмеження `init` викликає System Program для створення акаунту. ```rs @@ -191,7 +201,9 @@ pub struct CustomAccount { ## Насіння PDA в IDL -Насіння Program Derived Address (PDA), визначені в обмеженні `seeds`, включені в IDL файл програми. Це дозволяє клієнту Anchor автоматично вирішувати акаунти, використовуючи ці насіння під час побудови інструкцій. +Насіння Program Derived Address (PDA), визначені в обмеженні `seeds`, включені в +IDL файл програми. Це дозволяє клієнту Anchor автоматично вирішувати акаунти, +використовуючи ці насіння під час побудови інструкцій. Наведений нижче приклад показує взаємозв'язок між програмою, IDL та клієнтом. @@ -199,8 +211,8 @@ pub struct CustomAccount { -Програма нижче визначає `pda_account`, використовуючи статичне насіння (`b"hello_world"`) -та публічний ключ підписанта як динамічне насіння. +Програма нижче визначає `pda_account`, використовуючи статичне насіння +(`b"hello_world"`) та публічний ключ підписанта як динамічне насіння. ```rs {18} /signer/ use anchor_lang::prelude::*; @@ -280,7 +292,10 @@ IDL файл програми включає насіння PDA, визначе Клієнт Anchor може автоматично визначити адресу PDA, використовуючи IDL файл. -У наведеному нижче прикладі Anchor автоматично визначає адресу PDA, використовуючи гаманець постачальника як підписанта, а його публічний ключ як динамічне насіння для отримання PDA. Це усуває необхідність явного отримання PDA під час побудови інструкції. +У наведеному нижче прикладі Anchor автоматично визначає адресу PDA, +використовуючи гаманець постачальника як підписанта, а його публічний ключ як +динамічне насіння для отримання PDA. Це усуває необхідність явного отримання PDA +під час побудови інструкції. ```ts {13} import * as anchor from "@coral-xyz/anchor"; @@ -301,7 +316,8 @@ describe("hello_anchor", () => { }); ``` -Коли інструкція викликається, PDA виводиться в журнали програми, як це визначено в інструкції програми. +Коли інструкція викликається, PDA виводиться в журнали програми, як це визначено +в інструкції програми. ```{3} Program BZLiJ62bzRryYp9mRobz47uA66WDgtfTXhhgM25tJyx5 invoke [1] diff --git a/docs/locales/uk/programs/anchor/program-structure.md b/docs/locales/uk/programs/anchor/program-structure.md index 3fc534b6c..e37a5eac7 100644 --- a/docs/locales/uk/programs/anchor/program-structure.md +++ b/docs/locales/uk/programs/anchor/program-structure.md @@ -1,8 +1,8 @@ --- title: Структура програми Anchor description: - Дізнайтеся про структуру програм Anchor, включаючи основні макроси та їх - роль у спрощенні розробки програм для Solana + Дізнайтеся про структуру програм Anchor, включаючи основні макроси та їх роль + у спрощенні розробки програм для Solana sidebarLabel: Структура програми sidebarSortOrder: 1 --- @@ -15,16 +15,17 @@ sidebarSortOrder: 1 Основні макроси, які використовуються в програмі Anchor, включають: - [`declare_id`](#declare-id-macro): Визначає on-chain адресу програми -- [`#[program]`](#program-macro): Визначає модуль, що містить логіку інструкцій програми -- [`#[derive(Accounts)]`](#derive-accounts-macro): Застосовується до структур для - вказівки списку акаунтів, необхідних для інструкції +- [`#[program]`](#program-macro): Визначає модуль, що містить логіку інструкцій + програми +- [`#[derive(Accounts)]`](#derive-accounts-macro): Застосовується до структур + для вказівки списку акаунтів, необхідних для інструкції - [`#[account]`](#account-macro): Застосовується до структур для створення користувацьких типів акаунтів для програми ## Приклад програми -Давайте розглянемо просту програму, яка демонструє використання вищезгаданих макросів, -щоб зрозуміти основну структуру програми Anchor. +Давайте розглянемо просту програму, яка демонструє використання вищезгаданих +макросів, щоб зрозуміти основну структуру програми Anchor. Наведена нижче програма створює новий акаунт (`NewAccount`), який зберігає значення `u64`, передане в інструкцію `initialize`. @@ -71,8 +72,8 @@ use anchor_lang::prelude::*; declare_id!("11111111111111111111111111111111"); ``` -За замовчуванням, ID програми — це публічний ключ ключової пари, згенерованої за адресою -`/target/deploy/your_program_name.json`. +За замовчуванням, ID програми — це публічний ключ ключової пари, згенерованої за +адресою `/target/deploy/your_program_name.json`. Щоб оновити значення ID програми в макросі `declare_id` за допомогою публічного ключа ключової пари з файлу `/target/deploy/your_program_name.json`, виконайте @@ -83,15 +84,16 @@ anchor keys sync ``` Команда `anchor keys sync` корисна для виконання при клонуванні репозиторію, де -значення ID програми в макросі `declare_id` клонованого репозиторію не буде співпадати -з тим, що генерується при виконанні команди `anchor build` локально. +значення ID програми в макросі `declare_id` клонованого репозиторію не буде +співпадати з тим, що генерується при виконанні команди `anchor build` локально. ## Макрос `#[program]` Макрос [`#[program]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/program/src/lib.rs#L12) -визначає модуль, що містить усі обробники інструкцій для вашої програми. Кожна публічна функція -в межах цього модуля відповідає інструкції, яку можна викликати. +визначає модуль, що містить усі обробники інструкцій для вашої програми. Кожна +публічна функція в межах цього модуля відповідає інструкції, яку можна +викликати. ```rust filename="lib.rs" {5, 8-12} use anchor_lang::prelude::*; @@ -125,7 +127,10 @@ pub struct NewAccount { ### Контекст інструкції -Обробники інструкцій — це функції, які визначають логіку, що виконується, коли інструкція викликається. Перший параметр кожного обробника має тип `Context`, де `T` — це структура, яка реалізує трейд `Accounts` і вказує на акаунти, які потрібні для інструкції. +Обробники інструкцій — це функції, які визначають логіку, що виконується, коли +інструкція викликається. Перший параметр кожного обробника має тип `Context`, +де `T` — це структура, яка реалізує трейд `Accounts` і вказує на акаунти, які +потрібні для інструкції. Тип [`Context`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/context.rs#L24) @@ -151,12 +156,14 @@ pub struct Context<'a, 'b, 'c, 'info, T> { - `ctx.accounts`: Акаунти, необхідні для інструкції - `ctx.program_id`: Публічний ключ програми (адреса) -- `ctx.remaining_accounts`: Додаткові акаунти, які не вказані в структурі `Accounts`. +- `ctx.remaining_accounts`: Додаткові акаунти, які не вказані в структурі + `Accounts`. - `ctx.bumps`: Bump seed для будь-яких акаунтів [Program Derived Address (PDA)](/docs/core/pda.md), вказаних у структурі `Accounts` -Додаткові параметри є необов'язковими та можуть бути включені для вказівки аргументів, які повинні бути надані при виклику інструкції. +Додаткові параметри є необов'язковими та можуть бути включені для вказівки +аргументів, які повинні бути надані при виклику інструкції. ```rust filename="lib.rs" /Context/ /data/1 pub fn initialize(ctx: Context, data: u64) -> Result<()> { @@ -166,8 +173,8 @@ pub fn initialize(ctx: Context, data: u64) -> Result<()> { } ``` -У цьому прикладі структура `Initialize` реалізує трейд `Accounts`, де -кожне поле в структурі представляє акаунт, необхідний для інструкції `initialize`. +У цьому прикладі структура `Initialize` реалізує трейд `Accounts`, де кожне поле +в структурі представляє акаунт, необхідний для інструкції `initialize`. ```rust filename="lib.rs" /Initialize/ /Accounts/ #[program] @@ -194,9 +201,11 @@ pub struct Initialize<'info> { Макрос [`#[derive(Accounts)]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/derive/accounts/src/lib.rs#L630) -застосовується до структури для вказівки акаунтів, які повинні бути надані під час виклику інструкції. Цей макрос реалізує трейд +застосовується до структури для вказівки акаунтів, які повинні бути надані під +час виклику інструкції. Цей макрос реалізує трейд [`Accounts`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/lib.rs#L105), -що спрощує перевірку акаунтів, а також серіалізацію та десеріалізацію даних акаунтів. +що спрощує перевірку акаунтів, а також серіалізацію та десеріалізацію даних +акаунтів. ```rust /Accounts/ {1} #[derive(Accounts)] @@ -209,7 +218,9 @@ pub struct Initialize<'info> { } ``` -Кожне поле в структурі представляє акаунт, необхідний для інструкції. Іменування кожного поля є довільним, але рекомендується використовувати описове ім'я, яке вказує на призначення акаунту. +Кожне поле в структурі представляє акаунт, необхідний для інструкції. Іменування +кожного поля є довільним, але рекомендується використовувати описове ім'я, яке +вказує на призначення акаунту. ```rust /signer/2 /new_account/ /system_program/ #[derive(Accounts)] @@ -224,10 +235,15 @@ pub struct Initialize<'info> { ### Перевірка акаунтів -Для запобігання вразливостям безпеки важливо перевіряти, що акаунти, надані інструкції, є очікуваними. Акаунти перевіряються в програмах Anchor двома способами, які зазвичай використовуються разом: +Для запобігання вразливостям безпеки важливо перевіряти, що акаунти, надані +інструкції, є очікуваними. Акаунти перевіряються в програмах Anchor двома +способами, які зазвичай використовуються разом: - [Обмеження акаунтів](https://www.anchor-lang.com/docs/account-constraints): - Обмеження визначають додаткові умови, які акаунт повинен задовольняти, щоб вважатися дійсним для інструкції. Обмеження застосовуються за допомогою атрибута `#[account(..)]`, який розміщується над полем у структурі, що реалізує трейд `Accounts`. + Обмеження визначають додаткові умови, які акаунт повинен задовольняти, щоб + вважатися дійсним для інструкції. Обмеження застосовуються за допомогою + атрибута `#[account(..)]`, який розміщується над полем у структурі, що + реалізує трейд `Accounts`. Реалізацію обмежень можна знайти [тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/syn/src/parser/accounts/constraints.rs). @@ -243,8 +259,9 @@ pub struct Initialize<'info> { } ``` -- [Типи акаунтів](https://www.anchor-lang.com/docs/account-types): Anchor - надає різні типи акаунтів, щоб допомогти гарантувати, що акаунт, наданий клієнтом, відповідає тому, що очікує програма. +- [Типи акаунтів](https://www.anchor-lang.com/docs/account-types): Anchor надає + різні типи акаунтів, щоб допомогти гарантувати, що акаунт, наданий клієнтом, + відповідає тому, що очікує програма. Реалізацію типів акаунтів можна знайти [тут](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/src/accounts). @@ -261,7 +278,8 @@ pub struct Initialize<'info> { ``` Коли інструкція в програмі Anchor викликається, програма спочатку перевіряє -надані акаунти перед виконанням логіки інструкції. Після перевірки ці акаунти можна отримати в інструкції за допомогою синтаксису `ctx.accounts`. +надані акаунти перед виконанням логіки інструкції. Після перевірки ці акаунти +можна отримати в інструкції за допомогою синтаксису `ctx.accounts`. ```rust filename="lib.rs" /ctx.accounts.new_account/ /new_account/ /Initialize/ use anchor_lang::prelude::*; @@ -297,8 +315,8 @@ pub struct NewAccount { Макрос [`#[account]`](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L66) -застосовується до структур, які визначають дані, що зберігаються в користувацьких акаунтах, -створених вашою програмою. +застосовується до структур, які визначають дані, що зберігаються в +користувацьких акаунтах, створених вашою програмою. ```rust #[account] @@ -319,8 +337,8 @@ pub struct NewAccount { перші 8 байтів даних акаунту під час його ініціалізації. Це допомагає відрізняти типи акаунтів і використовується для перевірки акаунтів. - [Серіалізація та десеріалізація даних](https://github.com/coral-xyz/anchor/blob/v0.30.1/lang/attribute/account/src/lib.rs#L202-L246): - Дані акаунту автоматично серіалізуються та десеріалізуються відповідно до типу акаунту. - + Дані акаунту автоматично серіалізуються та десеріалізуються відповідно до типу + акаунту. ```rust filename="lib.rs" /data/2,6 /NewAccount/ {24-27} use anchor_lang::prelude::*; @@ -356,9 +374,11 @@ pub struct NewAccount { Дискримінатор акаунту в програмі Anchor — це 8-байтовий ідентифікатор, унікальний для кожного типу акаунту. Він отримується з перших 8 байтів SHA256 -хешу рядка `account:`. Цей дискримінатор зберігається як перші 8 байтів даних акаунту під час його створення. +хешу рядка `account:`. Цей дискримінатор зберігається як перші 8 +байтів даних акаунту під час його створення. -При створенні акаунту в програмі Anchor для дискримінатора повинно бути виділено 8 байтів. +При створенні акаунту в програмі Anchor для дискримінатора повинно бути виділено +8 байтів. ```rust /8/1 #[account(init, payer = signer, space = 8 + 8)] @@ -367,7 +387,11 @@ pub new_account: Account<'info, NewAccount>, Дискримінатор використовується в наступних двох сценаріях: -- Ініціалізація: Коли акаунт створюється, дискримінатор встановлюється як перші 8 байтів даних акаунту. -- Десеріалізація: Коли дані акаунту десеріалізуються, перші 8 байтів даних акаунту перевіряються на відповідність дискримінатору очікуваного типу акаунту. +- Ініціалізація: Коли акаунт створюється, дискримінатор встановлюється як перші + 8 байтів даних акаунту. +- Десеріалізація: Коли дані акаунту десеріалізуються, перші 8 байтів даних + акаунту перевіряються на відповідність дискримінатору очікуваного типу + акаунту. -Якщо є невідповідність, це вказує на те, що клієнт надав неочікуваний акаунт. Цей механізм служить перевіркою валідності акаунтів у програмах Anchor. +Якщо є невідповідність, це вказує на те, що клієнт надав неочікуваний акаунт. +Цей механізм служить перевіркою валідності акаунтів у програмах Anchor. diff --git a/docs/locales/uk/programs/deploying.md b/docs/locales/uk/programs/deploying.md index 7486f9866..c4b2bd845 100644 --- a/docs/locales/uk/programs/deploying.md +++ b/docs/locales/uk/programs/deploying.md @@ -1,19 +1,20 @@ --- title: "Розгортання програм" description: - Розгортання програм на ланцюгу можна здійснити за допомогою Solana CLI, використовуючи - Upgradable BPF loader для завантаження скомпільованого байт-коду на блокчейн Solana. + Розгортання програм на ланцюгу можна здійснити за допомогою Solana CLI, + використовуючи Upgradable BPF loader для завантаження скомпільованого + байт-коду на блокчейн Solana. sidebarSortOrder: 2 --- -Програми Solana зберігаються в "виконуваних" акаунтах в мережі. Ці -акаунти містять скомпільований байт-код програми, який визначає інструкції, -які користувачі викликають для взаємодії з програмою. +Програми Solana зберігаються в "виконуваних" акаунтах в мережі. Ці акаунти +містять скомпільований байт-код програми, який визначає інструкції, які +користувачі викликають для взаємодії з програмою. ## Команди CLI -Цей розділ призначений як довідник для базових команд CLI для створення -та розгортання програм Solana. Для покрокового посібника зі створення вашої першої +Цей розділ призначений як довідник для базових команд CLI для створення та +розгортання програм Solana. Для покрокового посібника зі створення вашої першої програми почніть з [Розробки програм на Rust](/docs/programs/rust). ### Збірка програми @@ -28,30 +29,47 @@ cargo build-sbf 1. Скомпілює вашу програму 2. Створить директорію `target/deploy` -3. Згенерує файл `.so`, де `` відповідає імені вашої програми у файлі `Cargo.toml` +3. Згенерує файл `.so`, де `` відповідає імені вашої + програми у файлі `Cargo.toml` -Вивантажений файл `.so` містить скомпільований байт-код вашої програми, який буде -збережено в акаунті Solana під час розгортання вашої програми. +Вивантажений файл `.so` містить скомпільований байт-код вашої програми, який +буде збережено в акаунті Solana під час розгортання вашої програми. ### Розгортання програми -Щоб розгорнути вашу програму, використовуйте команду `solana program deploy`, вказавши шлях до файлу `.so`, який був створений командою `cargo build-sbf`. +Щоб розгорнути вашу програму, використовуйте команду `solana program deploy`, +вказавши шлях до файлу `.so`, який був створений командою `cargo build-sbf`. ```shell solana program deploy ./target/deploy/your_program.so ``` -Під час періодів завантаження є кілька додаткових прапорців, які можна використовувати для полегшення розгортання програми. - -- `--with-compute-unit-price`: Встановіть ціну за обчислювальні одиниці для транзакції, в increments 0.000001 лампортів (мікро-лампорти) за обчислювальну одиницю. -- `--max-sign-attempts`: Максимальна кількість спроб підписати або повторно підписати транзакції після закінчення терміну дії blockhash. Якщо будь-які транзакції, надіслані під час розгортання програми, залишаються непідтвердженими після закінчення терміну дії початково вибраного останнього blockhash, ці транзакції будуть повторно підписані з новим blockhash і відправлені знову. Використовуйте цей параметр для налаштування максимальної кількості спроб підписання транзакцій. Кожен blockhash є дійсним близько 60 секунд, що означає, що використання значення за замовчуванням 5 призведе до надсилання транзакцій щонайменше 5 хвилин або до тих пір, поки всі транзакції не будуть підтверджені, залежно від того, що відбудеться раніше. [за замовчуванням: 5] -- `--use-rpc`: Надсилайте транзакції запису до налаштованого RPC замість TPU валідатора. Цей прапорець вимагає RPC з урахуванням ставки. +Під час періодів завантаження є кілька додаткових прапорців, які можна +використовувати для полегшення розгортання програми. + +- `--with-compute-unit-price`: Встановіть ціну за обчислювальні одиниці для + транзакції, в increments 0.000001 лампортів (мікро-лампорти) за обчислювальну + одиницю. +- `--max-sign-attempts`: Максимальна кількість спроб підписати або повторно + підписати транзакції після закінчення терміну дії blockhash. Якщо будь-які + транзакції, надіслані під час розгортання програми, залишаються + непідтвердженими після закінчення терміну дії початково вибраного останнього + blockhash, ці транзакції будуть повторно підписані з новим blockhash і + відправлені знову. Використовуйте цей параметр для налаштування максимальної + кількості спроб підписання транзакцій. Кожен blockhash є дійсним близько 60 + секунд, що означає, що використання значення за замовчуванням 5 призведе до + надсилання транзакцій щонайменше 5 хвилин або до тих пір, поки всі транзакції + не будуть підтверджені, залежно від того, що відбудеться раніше. [за + замовчуванням: 5] +- `--use-rpc`: Надсилайте транзакції запису до налаштованого RPC замість TPU + валідатора. Цей прапорець вимагає RPC з урахуванням ставки. Ви можете використовувати ці прапорці окремо або поєднувати їх разом. Наприклад: ```shell solana program deploy ./target/deploy/your_program.so --with-compute-unit-price 10000 --max-sign-attempts 1000 --use-rpc ``` + - Використовуйте [Priority Fee API від Helius](https://docs.helius.dev/guides/priority-fee-api) для отримання оцінки пріоритетної плати, яку потрібно встановити за допомогою @@ -59,18 +77,19 @@ solana program deploy ./target/deploy/your_program.so --with-compute-unit-price - Отримайте [RPC з урахуванням ставки](https://solana.com/developers/guides/advanced/stake-weighted-qos) - від [Helius](https://www.helius.dev/) або - [Triton](https://triton.one/) для використання з прапорцем `--use-rpc`. Прапорець - `--use-rpc` повинен використовуватись тільки з RPC з урахуванням ставки. + від [Helius](https://www.helius.dev/) або [Triton](https://triton.one/) для + використання з прапорцем `--use-rpc`. Прапорець `--use-rpc` повинен + використовуватись тільки з RPC з урахуванням ставки. -Щоб оновити ваш за умовчанням RPC URL за допомогою власної точки доступу RPC, використовуйте команду -`solana config set`. +Щоб оновити ваш за умовчанням RPC URL за допомогою власної точки доступу RPC, +використовуйте команду `solana config set`. ```shell solana config set --url ``` -Ви можете переглянути список програм, які ви розгорнули, використовуючи підкоманду `program show`: +Ви можете переглянути список програм, які ви розгорнули, використовуючи +підкоманду `program show`: ```shell solana program show --programs @@ -85,18 +104,18 @@ Program Id | Slot | Authority ### Оновлення програми -Авторизація на оновлення програми може змінювати існуючу програму Solana, розгортаючи -новий файл `.so` на той самий ID програми. +Авторизація на оновлення програми може змінювати існуючу програму Solana, +розгортаючи новий файл `.so` на той самий ID програми. Щоб оновити існуючу програму Solana: - Змініть вихідний код вашої програми - Виконайте команду `cargo build-sbf`, щоб згенерувати оновлений файл `.so` -- Виконайте команду `solana program deploy ./target/deploy/your_program.so`, щоб розгорнути - оновлений файл `.so` +- Виконайте команду `solana program deploy ./target/deploy/your_program.so`, щоб + розгорнути оновлений файл `.so` -Авторизацію на оновлення можна змінити за допомогою підкоманди `set-upgrade-authority` -наступним чином: +Авторизацію на оновлення можна змінити за допомогою підкоманди +`set-upgrade-authority` наступним чином: ```shell solana program set-upgrade-authority --new-upgrade-authority @@ -104,14 +123,15 @@ solana program set-upgrade-authority --new-upgrade-authority < ### Незмінна програма -Програму можна зробити незмінною, видаливши її авторизацію на оновлення. Це незворотна дія. +Програму можна зробити незмінною, видаливши її авторизацію на оновлення. Це +незворотна дія. ```shell solana program set-upgrade-authority --final ``` -Ви можете вказати, що програма має бути незмінною при розгортанні, встановивши прапорець -`--final` під час розгортання програми. +Ви можете вказати, що програма має бути незмінною при розгортанні, встановивши +прапорець `--final` під час розгортання програми. ```shell solana program deploy ./target/deploy/your_program.so --final @@ -135,15 +155,18 @@ Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOL reclaimed ``` -Зверніть увагу, що після закриття програми її ID програми не можна буде використовувати знову. Спроба розгорнути програму з раніше закритим ID програми призведе до помилки. +Зверніть увагу, що після закриття програми її ID програми не можна буде +використовувати знову. Спроба розгорнути програму з раніше закритим ID програми +призведе до помилки. ``` Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, use a new Program Id ``` -Якщо вам потрібно повторно розгорнути програму після її закриття, ви повинні згенерувати новий -ID програми. Щоб згенерувати нову ключову пару для програми, виконайте наступну команду: +Якщо вам потрібно повторно розгорнути програму після її закриття, ви повинні +згенерувати новий ID програми. Щоб згенерувати нову ключову пару для програми, +виконайте наступну команду: ```shell filename="Terminal" solana-keygen new -o ./target/deploy/your_program-keypair.json --force @@ -154,8 +177,9 @@ solana-keygen new -o ./target/deploy/your_program-keypair.json --force ### Акаунти буфера програми -Розгортання програми вимагає кількох транзакцій через обмеження в 1232 байти -для транзакцій на Solana. Проміжним кроком процесу розгортання є запис байт-коду програми в тимчасовий "акаунт буфера". +Розгортання програми вимагає кількох транзакцій через обмеження в 1232 байти для +транзакцій на Solana. Проміжним кроком процесу розгортання є запис байт-коду +програми в тимчасовий "акаунт буфера". Цей акаунт буфера автоматично закривається після успішного розгортання програми. Однак, якщо розгортання не вдалося, акаунт буфера залишається, і ви можете: @@ -163,7 +187,8 @@ solana-keygen new -o ./target/deploy/your_program-keypair.json --force - Продовжити розгортання, використовуючи існуючий акаунт буфера - Закрити акаунт буфера, щоб повернути виділений SOL (оренду) -Ви можете перевірити, чи є відкриті акаунти буфера, використовуючи підкоманду `program show`, наступним чином: +Ви можете перевірити, чи є відкриті акаунти буфера, використовуючи підкоманду +`program show`, наступним чином: ```shell solana program show --buffers @@ -176,7 +201,8 @@ Buffer Address | Authority 5TRm1DxYcXLbSEbbxWcQbEUCce7L4tVgaC6e2V4G82pM | 4kh6HxYZiAebF8HWLsUWod2EaQQ6iWHpHYCz8UcmFbM1 | 0.57821592 SOL ``` -Ви можете продовжити до розгортання за допомогою підкоманди `program deploy` наступним чином: +Ви можете продовжити до розгортання за допомогою підкоманди `program deploy` +наступним чином: ```shell solana program deploy --buffer 5TRm1DxYcXLbSEbbxWcQbEUCce7L4tVgaC6e2V4G82pM @@ -198,11 +224,13 @@ solana program close --buffers ### ELF Dump -Внутрішні дані SBF shared object можна вивести в текстовий файл, щоб отримати більше -інформації про склад програми та те, що вона може виконувати під час виконання. Вивантаження -містить як ELF інформацію, так і список всіх символів та інструкцій, що їх реалізують. Деякі з повідомлень журналу помилок BPF loader -будуть посилатися на конкретні номери інструкцій, де сталася помилка. -Ці посилання можна знайти у вивантаженні ELF, щоб ідентифікувати помилкову інструкцію та її контекст. +Внутрішні дані SBF shared object можна вивести в текстовий файл, щоб отримати +більше інформації про склад програми та те, що вона може виконувати під час +виконання. Вивантаження містить як ELF інформацію, так і список всіх символів та +інструкцій, що їх реалізують. Деякі з повідомлень журналу помилок BPF loader +будуть посилатися на конкретні номери інструкцій, де сталася помилка. Ці +посилання можна знайти у вивантаженні ELF, щоб ідентифікувати помилкову +інструкцію та її контекст. ```shell cargo build-bpf --dump @@ -213,14 +241,17 @@ cargo build-bpf --dump ## Процес розгортання програми Розгортання програми на Solana вимагає кількох транзакцій через максимальний -ліміт розміру транзакцій у 1232 байти. Solana CLI надсилає ці транзакції за допомогою підкоманди `solana program deploy`. Процес можна розділити на наступні 3 фази: +ліміт розміру транзакцій у 1232 байти. Solana CLI надсилає ці транзакції за +допомогою підкоманди `solana program deploy`. Процес можна розділити на наступні +3 фази: 1. [Ініціалізація буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2113): Спочатку CLI надсилає транзакцію, яка [створює акаунт буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1903) достатнього розміру для байт-коду, що розгортається. Також викликається [інструкція ініціалізації буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L320), - щоб встановити право власності на буфер і обмежити записи на вибрану адресу розробника. + щоб встановити право власності на буфер і обмежити записи на вибрану адресу + розробника. 2. [Запис буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L2129): Після ініціалізації акаунту буфера CLI [розбиває байт-код програми](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1940) @@ -228,7 +259,9 @@ cargo build-bpf --dump [відправляє транзакції зі швидкістю 100 транзакцій за секунду](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/client/src/tpu_client.rs#L133), щоб записати кожен шматок за допомогою [інструкції запису буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L334). - Ці транзакції надсилаються безпосередньо до порту обробки транзакцій (TPU) поточного лідера і обробляються паралельно. Після того, як всі транзакції будуть надіслані, CLI + Ці транзакції надсилаються безпосередньо до порту обробки транзакцій (TPU) + поточного лідера і обробляються паралельно. Після того, як всі транзакції + будуть надіслані, CLI [опитує RPC API партіями підписів транзакцій](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/client/src/tpu_client.rs#L216), щоб переконатися, що кожен запис був успішним і підтвердженим. 3. [Фіналізація](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/cli/src/program.rs#L1807): @@ -238,8 +271,8 @@ cargo build-bpf --dump [розгорнути нову програму](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L362) або [оновити існуючу програму](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/programs/bpf_loader/src/lib.rs#L513). - В будь-якому випадку байт-код, записаний в акаунт буфера, буде скопійовано - в акаунт даних програми і перевірено. + В будь-якому випадку байт-код, записаний в акаунт буфера, буде скопійовано в + акаунт даних програми і перевірено. ## Оновлювана програма BPF Loader @@ -252,48 +285,49 @@ Solana. Коли ви розгортаєте програму, власник а Оновлювана програма BPF loader підтримує три різні типи акаунтів стану: 1. [Акаунт програми](https://github.com/solana-labs/solana/blob/master/sdk/program/src/bpf_loader_upgradeable.rs#L34): - Це основний акаунт програми на ланцюгу, і його адреса зазвичай - називається "ID програми". ID програми — це те, на що посилаються інструкції транзакцій - для виклику програми. Акаунти програми незмінні після розгортання, тому ви можете вважати їх проксі-акаунтами для байт-коду та - стану, що зберігаються в інших акаунтах. + Це основний акаунт програми на ланцюгу, і його адреса зазвичай називається + "ID програми". ID програми — це те, на що посилаються інструкції транзакцій + для виклику програми. Акаунти програми незмінні після розгортання, тому ви + можете вважати їх проксі-акаунтами для байт-коду та стану, що зберігаються в + інших акаунтах. 2. [Акаунт даних програми](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/bpf_loader_upgradeable.rs#L39): - Цей акаунт зберігає виконуваний байт-код програми на ланцюгу. - Коли програма оновлюється, дані цього акаунту оновлюються новим - байт-кодом. Крім байт-коду, акаунти даних програми також - відповідають за зберігання слоту, коли вони були востаннє змінені, та адреси - єдиного акаунту, авторизованого для зміни акаунту (ця адреса може бути - очищена, щоб зробити програму незмінною). + Цей акаунт зберігає виконуваний байт-код програми на ланцюгу. Коли програма + оновлюється, дані цього акаунту оновлюються новим байт-кодом. Крім байт-коду, + акаунти даних програми також відповідають за зберігання слоту, коли вони були + востаннє змінені, та адреси єдиного акаунту, авторизованого для зміни акаунту + (ця адреса може бути очищена, щоб зробити програму незмінною). 3. [Акаунти буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/bpf_loader_upgradeable.rs#L27): - Ці акаунти тимчасово зберігають байт-код під час активного - розгортання програми через серію транзакцій. Вони також зберігають адресу - єдиного акаунту, який авторизований для виконання записів. + Ці акаунти тимчасово зберігають байт-код під час активного розгортання + програми через серію транзакцій. Вони також зберігають адресу єдиного + акаунту, який авторизований для виконання записів. ### Інструкції -Акаунти стану, перераховані вище, можуть бути змінені лише за допомогою однієї з наступних -інструкцій, що підтримуються програмою Upgradeable BPF Loader: +Акаунти стану, перераховані вище, можуть бути змінені лише за допомогою однієї з +наступних інструкцій, що підтримуються програмою Upgradeable BPF Loader: 1. [Ініціалізація буфера](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L21): - Створює акаунт буфера і зберігає адресу авторизації, яка дозволена - змінювати буфер. + Створює акаунт буфера і зберігає адресу авторизації, яка дозволена змінювати + буфер. 2. [Запис](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L28): Записує байт-код на вказаний байтовий офсет в акаунті буфера. Записи обробляються маленькими шматками через обмеження транзакцій Solana, максимальний розмір яких складає 1232 байти. 3. [Розгортання](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L77): - Створює акаунт програми та акаунт даних програми. Він заповнює - акаунт даних програми, копіюючи байт-код, що зберігається в акаунті буфера. Якщо - байт-код є дійсним, акаунт програми буде встановлений як виконуваний, - дозволяючи його викликати. Якщо байт-код недійсний, інструкція не вдасться, і всі зміни будуть скасовані. + Створює акаунт програми та акаунт даних програми. Він заповнює акаунт даних + програми, копіюючи байт-код, що зберігається в акаунті буфера. Якщо байт-код + є дійсним, акаунт програми буде встановлений як виконуваний, дозволяючи його + викликати. Якщо байт-код недійсний, інструкція не вдасться, і всі зміни + будуть скасовані. 4. [Оновлення](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L102): - Заповнює існуючий акаунт даних програми, копіюючи виконуваний байт-код з акаунта - буфера. Подібно до інструкції розгортання, вона буде успішною лише в тому випадку, якщо - байт-код є дійсним. + Заповнює існуючий акаунт даних програми, копіюючи виконуваний байт-код з + акаунта буфера. Подібно до інструкції розгортання, вона буде успішною лише в + тому випадку, якщо байт-код є дійсним. 5. [Встановлення авторизації](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L114): Оновлює авторизацію акаунта даних програми або акаунта буфера, якщо поточний - власник акаунту підписав транзакцію, що обробляється. Якщо авторизація буде видалена без заміни, - її можна буде встановити лише один раз і акаунт більше не можна буде закрити. + власник акаунту підписав транзакцію, що обробляється. Якщо авторизація буде + видалена без заміни, її можна буде встановити лише один раз і акаунт більше + не можна буде закрити. 6. [Закриття](https://github.com/solana-labs/solana/blob/7409d9d2687fba21078a745842c25df805cdf105/sdk/program/src/loader_upgradeable_instruction.rs#L127): - Очищає дані акаунта програми або акаунта буфера та повертає SOL, - використані для депозиту звільнення від оренди. - + Очищає дані акаунта програми або акаунта буфера та повертає SOL, використані + для депозиту звільнення від оренди. diff --git a/docs/locales/uk/programs/examples.md b/docs/locales/uk/programs/examples.md index be25a95dd..e20f39553 100644 --- a/docs/locales/uk/programs/examples.md +++ b/docs/locales/uk/programs/examples.md @@ -1,8 +1,9 @@ --- title: "Приклади програм" description: - "Список прикладів програм для Solana на різних мовах і фреймворках, - які можуть допомогти вам вивчити та використовувати їх як посилання для ваших власних проектів." + "Список прикладів програм для Solana на різних мовах і фреймворках, які можуть + допомогти вам вивчити та використовувати їх як посилання для ваших власних + проектів." tags: - quickstart - program @@ -28,19 +29,19 @@ sidebarSortOrder: 3 Репозиторій [Solana Program Examples](https://github.com/solana-developers/program-examples) -на GitHub пропонує кілька підпапок, кожна з яких містить приклади коду -для різних парадигм програмування Solana та мов, створених, щоб допомогти +на GitHub пропонує кілька підпапок, кожна з яких містить приклади коду для +різних парадигм програмування Solana та мов, створених, щоб допомогти розробникам вивчати та експериментувати з розробкою на блокчейні Solana. Ви можете знайти приклади в репозиторії `solana-developers/program-examples` разом з файлами README, що пояснюють, як запускати різні приклади. Більшість прикладів є самодостатніми та доступні на рідному Rust (тобто без використання -фреймворку) та [Anchor](https://www.anchor-lang.com/docs/installation). Також -є список прикладів, які ми з радістю б +фреймворку) та [Anchor](https://www.anchor-lang.com/docs/installation). Також є +список прикладів, які ми з радістю б [побачили як внески](https://github.com/solana-developers/program-examples?tab=readme-ov-file#examples-wed-love-to-see). -У репозиторії ви знайдете наступну підпапку, кожну з яких з різними -прикладами програм: +У репозиторії ви знайдете наступну підпапку, кожну з яких з різними прикладами +програм: - [Основи](#basics) - [Стиснення](#compression) @@ -52,26 +53,26 @@ sidebarSortOrder: 3 ## Основи -Містить серію прикладів, які демонструють основні кроки для -створення програм Solana, використовуючи рідні бібліотеки Rust. Ці приклади -призначені для того, щоб допомогти розробникам зрозуміти основні концепції програмування Solana. - -| Назва прикладу | Опис | Мова | -| ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------ | -| [Дані акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/account-data) | Збереження адреси з ім'ям, номером будинку, вулицею та містом в акаунті. | Native, Anchor | -| [Перевірка акаунтів](https://github.com/solana-developers/program-examples/tree/main/basics/checking-accounts) | Уроки безпеки, що показують, як виконувати перевірки акаунтів | Native, Anchor | -| [Закриття акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/close-account) | Показує, як закривати акаунти, щоб повернути оренду. | Native, Anchor | -| [Лічильник](https://github.com/solana-developers/program-examples/tree/main/basics/counter) | Простий програмний лічильник на всіх різних архітектурах. | Native, Anchor, mpl-stack| -| [Створення акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/create-account) | Як створити системний акаунт в межах програми. | Native, Anchor | -| [Перехресний виклик програми](https://github.com/solana-developers/program-examples/tree/main/basics/cross-program-invocation) | Використовуючи аналогію з рукою та важелем, показує, як викликати іншу програму з програми. | Native, Anchor | -| [Hello Solana](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana) | Приклад "Hello world", який просто виводить hello world у журналах транзакцій. | Native, Anchor | -| [Pda Rent payer](https://github.com/solana-developers/program-examples/tree/main/basics/pda-rent-payer) | Показує, як можна використовувати лампорти з PDA для оплати нового акаунта. | Native, Anchor | -| [Обробка інструкцій](https://github.com/solana-developers/program-examples/tree/main/basics/processing-instructions) | Показує, як обробляти рядкові дані інструкцій та u32. | Native, Anchor | -| [Програма з похідними адресами](https://github.com/solana-developers/program-examples/tree/main/basics/program-derived-addresses) | Показує, як використовувати насіння для посилання на PDA та збереження даних в ньому. | Native, Anchor | -| [Перерозподіл](https://github.com/solana-developers/program-examples/tree/main/basics/realloc) | Показує, як збільшувати та зменшувати розмір існуючого акаунта. | Native, Anchor | -| [Оренда](https://github.com/solana-developers/program-examples/tree/main/basics/rent) | Тут ви дізнаєтесь, як обчислювати вимоги оренди в межах програми. | Native, Anchor | -| [Розташування репозиторію](https://github.com/solana-developers/program-examples/tree/main/basics/repository-layout) | Рекомендації щодо структурування вашого макету програми. | Native, Anchor | -| [Передача SOL](https://github.com/solana-developers/program-examples/tree/main/basics/transfer-sol) | Різні методи передачі SOL для системних акаунтів та PDA. | Native, Anchor, Seahorse | +Містить серію прикладів, які демонструють основні кроки для створення програм +Solana, використовуючи рідні бібліотеки Rust. Ці приклади призначені для того, +щоб допомогти розробникам зрозуміти основні концепції програмування Solana. + +| Назва прикладу | Опис | Мова | +| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------- | +| [Дані акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/account-data) | Збереження адреси з ім'ям, номером будинку, вулицею та містом в акаунті. | Native, Anchor | +| [Перевірка акаунтів](https://github.com/solana-developers/program-examples/tree/main/basics/checking-accounts) | Уроки безпеки, що показують, як виконувати перевірки акаунтів | Native, Anchor | +| [Закриття акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/close-account) | Показує, як закривати акаунти, щоб повернути оренду. | Native, Anchor | +| [Лічильник](https://github.com/solana-developers/program-examples/tree/main/basics/counter) | Простий програмний лічильник на всіх різних архітектурах. | Native, Anchor, mpl-stack | +| [Створення акаунта](https://github.com/solana-developers/program-examples/tree/main/basics/create-account) | Як створити системний акаунт в межах програми. | Native, Anchor | +| [Перехресний виклик програми](https://github.com/solana-developers/program-examples/tree/main/basics/cross-program-invocation) | Використовуючи аналогію з рукою та важелем, показує, як викликати іншу програму з програми. | Native, Anchor | +| [Hello Solana](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana) | Приклад "Hello world", який просто виводить hello world у журналах транзакцій. | Native, Anchor | +| [Pda Rent payer](https://github.com/solana-developers/program-examples/tree/main/basics/pda-rent-payer) | Показує, як можна використовувати лампорти з PDA для оплати нового акаунта. | Native, Anchor | +| [Обробка інструкцій](https://github.com/solana-developers/program-examples/tree/main/basics/processing-instructions) | Показує, як обробляти рядкові дані інструкцій та u32. | Native, Anchor | +| [Програма з похідними адресами](https://github.com/solana-developers/program-examples/tree/main/basics/program-derived-addresses) | Показує, як використовувати насіння для посилання на PDA та збереження даних в ньому. | Native, Anchor | +| [Перерозподіл](https://github.com/solana-developers/program-examples/tree/main/basics/realloc) | Показує, як збільшувати та зменшувати розмір існуючого акаунта. | Native, Anchor | +| [Оренда](https://github.com/solana-developers/program-examples/tree/main/basics/rent) | Тут ви дізнаєтесь, як обчислювати вимоги оренди в межах програми. | Native, Anchor | +| [Розташування репозиторію](https://github.com/solana-developers/program-examples/tree/main/basics/repository-layout) | Рекомендації щодо структурування вашого макету програми. | Native, Anchor | +| [Передача SOL](https://github.com/solana-developers/program-examples/tree/main/basics/transfer-sol) | Різні методи передачі SOL для системних акаунтів та PDA. | Native, Anchor, Seahorse | ## Стиснення @@ -79,62 +80,67 @@ sidebarSortOrder: 3 [стиснення стану](/docs/advanced/state-compression.md) на Solana. Головним чином фокусується на стиснених NFT (cNFT). -| Назва прикладу | Опис | Мова | -| -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------- | -| [cNFT-burn](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-burn) | Для знищення cNFT він може бути спалений. Цей приклад показує, як це зробити в програмі. | Anchor | -| [cNFT-Vault](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-vault/anchor) | Як зберігати cNFT в програмі та відправляти його знову. | Anchor | -| [cutils](https://github.com/solana-developers/program-examples/tree/main/compression/cutils) | Набір утиліт для, наприклад, мінтування та перевірки cNFT в програмі. | Anchor | +| Назва прикладу | Опис | Мова | +| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------ | +| [cNFT-burn](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-burn) | Для знищення cNFT він може бути спалений. Цей приклад показує, як це зробити в програмі. | Anchor | +| [cNFT-Vault](https://github.com/solana-developers/program-examples/tree/main/compression/cnft-vault/anchor) | Як зберігати cNFT в програмі та відправляти його знову. | Anchor | +| [cutils](https://github.com/solana-developers/program-examples/tree/main/compression/cutils) | Набір утиліт для, наприклад, мінтування та перевірки cNFT в програмі. | Anchor | ## Оракули Оракули дозволяють використовувати дані поза ланцюгом в програмах. -| Назва прикладу | Опис | Мова | -| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------ | -| [Pyth](https://github.com/solana-developers/program-examples/tree/main/oracles/pyth) | Pyth надає дані про ціни токенів для використання в програмах на ланцюгу. | Anchor | +| Назва прикладу | Опис | Мова | +| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- | ------ | +| [Pyth](https://github.com/solana-developers/program-examples/tree/main/oracles/pyth) | Pyth надає дані про ціни токенів для використання в програмах на ланцюгу. | Anchor | ## Токени -Більшість токенів на Solana використовують стандарт токенів Solana Program Library (SPL). Тут -ви знайдете багато прикладів, як створювати, передавати, спалювати токени та навіть як взаємодіяти з ними в програмах. +Більшість токенів на Solana використовують стандарт токенів Solana Program +Library (SPL). Тут ви знайдете багато прикладів, як створювати, передавати, +спалювати токени та навіть як взаємодіяти з ними в програмах. -| Назва прикладу | Опис | Мова | -| --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------ | -| [Створення токена](https://github.com/solana-developers/program-examples/tree/main/tokens/create-token) | Як створити токен та додати метадані метаплекса до нього. | Anchor, Native | -| [NFT Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/nft-minter) | Мінтування тільки однієї кількості токену, а потім видалення права на мінтинг. | Anchor, Native | -| [PDA Mint Authority](https://github.com/solana-developers/program-examples/tree/main/tokens/pda-mint-authority) | Показує, як змінити право на мінтинг токенів через PDA. | Anchor, Native | -| [SPL Token Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/spl-token-minter) | Пояснює, як використовувати Associated Token Accounts для відслідковування токен акаунтів. | Anchor, Native | -| [Token Swap](https://github.com/solana-developers/program-examples/tree/main/tokens/token-swap) | Розширений приклад, який показує, як побудувати AMM (автоматизований маркет-мейкер) пул для SPL токенів. | Anchor | -| [Передача токенів](https://github.com/solana-developers/program-examples/tree/main/tokens/transfer-tokens) | Показує, як передавати SPL токени за допомогою CPIs у програму токенів. | Anchor, Native | -| [Token-2022](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022) | Див. Token 2022 (Розширення токенів). | Anchor, Native | +| Назва прикладу | Опис | Мова | +| --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -------------- | +| [Створення токена](https://github.com/solana-developers/program-examples/tree/main/tokens/create-token) | Як створити токен та додати метадані метаплекса до нього. | Anchor, Native | +| [NFT Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/nft-minter) | Мінтування тільки однієї кількості токену, а потім видалення права на мінтинг. | Anchor, Native | +| [PDA Mint Authority](https://github.com/solana-developers/program-examples/tree/main/tokens/pda-mint-authority) | Показує, як змінити право на мінтинг токенів через PDA. | Anchor, Native | +| [SPL Token Minter](https://github.com/solana-developers/program-examples/tree/main/tokens/spl-token-minter) | Пояснює, як використовувати Associated Token Accounts для відслідковування токен акаунтів. | Anchor, Native | +| [Token Swap](https://github.com/solana-developers/program-examples/tree/main/tokens/token-swap) | Розширений приклад, який показує, як побудувати AMM (автоматизований маркет-мейкер) пул для SPL токенів. | Anchor | +| [Передача токенів](https://github.com/solana-developers/program-examples/tree/main/tokens/transfer-tokens) | Показує, як передавати SPL токени за допомогою CPIs у програму токенів. | Anchor, Native | +| [Token-2022](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022) | Див. Token 2022 (Розширення токенів). | Anchor, Native | ## Token 2022 (Розширення токенів) -Token 2022 — це новий стандарт для токенів на Solana. Це більш гнучкий стандарт, який -дозволяє додавати до токену 16 різних розширень для додавання більшої функціональності. - -| Назва прикладу | Опис | Мова | -| ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------ | -| [Основи](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/basics/anchor) | Як створити токен, мінтувати та передавати його. | Anchor | -| [Стандартний стан акаунта](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/default-account-state/native) | Це розширення дозволяє створювати акаунти токенів з певним станом, наприклад замороженими. | Native | -| [Право закриття мінта](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/mint-close-authority) | З старою програмою токенів не було можливості закривати мінт. Тепер це можливо. | Native | -| [Багато розширень](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/multiple-extensions) | Показує, як додавати кілька розширень до одного мінта | Native | -| [Вказівник метаданих NFT](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/nft-meta-data-pointer) | Можна використовувати розширення метаданих для створення NFT та додавання динамічних метаданих на ланцюг. | Anchor | -| [Не передаваємий](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/non-transferable/native) | Корисно, наприклад, для досягнень, програм рефералів або будь-яких токенів, які не можна передавати. | Native | -| [Плата за передачу](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-fees) | Кожна передача токенів утримує певну кількість токенів у акаунті токена, яку потім можна забрати. | Native | -| [Transfer Hook](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-hook) | Чотири приклади для додавання додаткової функціональності до вашого токена за допомогою CPI з програми токенів. | Anchor | +Token 2022 — це новий стандарт для токенів на Solana. Це більш гнучкий стандарт, +який дозволяє додавати до токену 16 різних розширень для додавання більшої +функціональності. + +| Назва прикладу | Опис | Мова | +| ------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- | ------ | +| [Основи](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/basics/anchor) | Як створити токен, мінтувати та передавати його. | Anchor | +| [Стандартний стан акаунта](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/default-account-state/native) | Це розширення дозволяє створювати акаунти токенів з певним станом, наприклад замороженими. | Native | +| [Право закриття мінта](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/mint-close-authority) | З старою програмою токенів не було можливості закривати мінт. Тепер це можливо. | Native | +| [Багато розширень](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/multiple-extensions) | Показує, як додавати кілька розширень до одного мінта | Native | +| [Вказівник метаданих NFT](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/nft-meta-data-pointer) | Можна використовувати розширення метаданих для створення NFT та додавання динамічних метаданих на ланцюг. | Anchor | +| [Не передаваємий](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/non-transferable/native) | Корисно, наприклад, для досягнень, програм рефералів або будь-яких токенів, які не можна передавати. | Native | +| [Плата за передачу](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-fees) | Кожна передача токенів утримує певну кількість токенів у акаунті токена, яку потім можна забрати. | Native | +| [Transfer Hook](https://github.com/solana-developers/program-examples/tree/main/tokens/token-2022/transfer-hook) | Чотири приклади для додавання додаткової функціональності до вашого токена за допомогою CPI з програми токенів. | Anchor | ## Break -[Break](https://break.solana.com/) — це додаток на React, який дає користувачам можливість -відчути, наскільки швидко і ефективно працює мережа Solana. Чи зможете ви _зламати_ блокчейн Solana? Протягом 15 секунд кожне натискання кнопки або клавіші -відправляє нову транзакцію в кластер. Ударте по клавіатурі так швидко, як можете, і дивіться, -як ваші транзакції підтверджуються в реальному часі, поки мережа справляється з усім! +[Break](https://break.solana.com/) — це додаток на React, який дає користувачам +можливість відчути, наскільки швидко і ефективно працює мережа Solana. Чи +зможете ви _зламати_ блокчейн Solana? Протягом 15 секунд кожне натискання кнопки +або клавіші відправляє нову транзакцію в кластер. Ударте по клавіатурі так +швидко, як можете, і дивіться, як ваші транзакції підтверджуються в реальному +часі, поки мережа справляється з усім! -Break можна грати на наших мережах Devnet, Testnet та Mainnet Beta. Ігри безкоштовні на Devnet і Testnet, -де сесія фінансується мережевим фонтаном. На Mainnet Beta користувачі платять 0,08 SOL за гру. Сесійний акаунт можна -фінансувати через локальний гаманець keystore або скануючи QR-код з Trust Wallet для -переміщення токенів. +Break можна грати на наших мережах Devnet, Testnet та Mainnet Beta. Ігри +безкоштовні на Devnet і Testnet, де сесія фінансується мережевим фонтаном. На +Mainnet Beta користувачі платять 0,08 SOL за гру. Сесійний акаунт можна +фінансувати через локальний гаманець keystore або скануючи QR-код з Trust Wallet +для переміщення токенів. [Клацніть тут, щоб зіграти в Break](https://break.solana.com/) @@ -142,10 +148,10 @@ Break можна грати на наших мережах Devnet, Testnet та Спочатку отримайте останню версію прикладів коду: - ```shell git clone https://github.com/solana-labs/break.git cd break ``` -Дотримуйтесь кроків у файлі [README](https://github.com/solana-labs/break/blob/main/README.md) репозиторію. +Дотримуйтесь кроків у файлі +[README](https://github.com/solana-labs/break/blob/main/README.md) репозиторію. diff --git a/docs/locales/uk/programs/faq.md b/docs/locales/uk/programs/faq.md index d11a5f914..7514d785e 100644 --- a/docs/locales/uk/programs/faq.md +++ b/docs/locales/uk/programs/faq.md @@ -15,65 +15,68 @@ sidebarSortOrder: 7 [Berkeley Packet Filter (BPF)](https://en.wikipedia.org/wiki/Berkeley_Packet_Filter) байткоду. -Оскільки Solana використовує інфраструктуру компілятора LLVM, програму можна написати -на будь-якій мові програмування, яка підтримує компіляцію в BPF бекенд LLVM. +Оскільки Solana використовує інфраструктуру компілятора LLVM, програму можна +написати на будь-якій мові програмування, яка підтримує компіляцію в BPF бекенд +LLVM. BPF надає ефективний [набір інструкцій](https://github.com/iovisor/bpf-docs/blob/master/eBPF.md), -який можна виконувати в інтерпретованій віртуальній машині або як ефективно згенеровані -нативні інструкції за допомогою just-in-time компіляції. +який можна виконувати в інтерпретованій віртуальній машині або як ефективно +згенеровані нативні інструкції за допомогою just-in-time компіляції. ## Карта пам'яті -Віртуальна адресна карта пам'яті, яку використовують програми Solana SBF, є фіксованою -та має наступне розташування: +Віртуальна адресна карта пам'яті, яку використовують програми Solana SBF, є +фіксованою та має наступне розташування: - Код програми починається з адреси 0x100000000 - Дані стека починаються з адреси 0x200000000 - Дані купи починаються з адреси 0x300000000 - Вхідні параметри програми починаються з адреси 0x400000000 -Вищезазначені віртуальні адреси є початковими адресами, але програми отримують доступ до -підмножини карти пам'яті. Програма викликає паніку, якщо вона намагається читати або -записувати в віртуальну адресу, до якої не було надано доступу, і повертається помилка -`AccessViolation`, яка містить адресу та розмір спроби порушення. +Вищезазначені віртуальні адреси є початковими адресами, але програми отримують +доступ до підмножини карти пам'яті. Програма викликає паніку, якщо вона +намагається читати або записувати в віртуальну адресу, до якої не було надано +доступу, і повертається помилка `AccessViolation`, яка містить адресу та розмір +спроби порушення. ## InvalidAccountData Ця помилка програми може статися з багатьох причин. Зазвичай це викликано передачею акаунта в програму, якого програма не очікує, або через неправильне -положення акаунта в інструкції або акаунт, який не сумісний з виконуваною інструкцією. +положення акаунта в інструкції або акаунт, який не сумісний з виконуваною +інструкцією. -Реалізація програми може також спричинити цю помилку при виконанні -перехресної інструкції між програмами, якщо забули надати акаунт для програми, -яку ви викликаєте. +Реалізація програми може також спричинити цю помилку при виконанні перехресної +інструкції між програмами, якщо забули надати акаунт для програми, яку ви +викликаєте. ## InvalidInstructionData -Ця помилка програми може статися при спробі десеріалізувати інструкцію, перевірте, -чи структура, передана в інструкцію, точно відповідає вимогам програми. Між полями -може бути деяке додаткове заповнення. Якщо програма реалізує трейти Rust `Pack`, спробуйте -упакувати і розпакувати тип інструкції `T`, щоб визначити точне кодування, -яке програма очікує. +Ця помилка програми може статися при спробі десеріалізувати інструкцію, +перевірте, чи структура, передана в інструкцію, точно відповідає вимогам +програми. Між полями може бути деяке додаткове заповнення. Якщо програма +реалізує трейти Rust `Pack`, спробуйте упакувати і розпакувати тип інструкції +`T`, щоб визначити точне кодування, яке програма очікує. ## MissingRequiredSignature -Деякі інструкції вимагають, щоб акаунт був підписантом; ця помилка повертається, якщо -очікується підпис акаунта, але він відсутній. +Деякі інструкції вимагають, щоб акаунт був підписантом; ця помилка повертається, +якщо очікується підпис акаунта, але він відсутній. Реалізація програми може також викликати цю помилку при виконанні -[перехресного виклику програми](/docs/core/cpi.md), який вимагає підписаного адреси програми, -але передані насіння підписувача до `invoke_signed` не збігаються з -насіннями підписувача, що використовуються для створення адреси програми -[`create_program_address`](/docs/core/pda.md#createprogramaddress). +[перехресного виклику програми](/docs/core/cpi.md), який вимагає підписаного +адреси програми, але передані насіння підписувача до `invoke_signed` не +збігаються з насіннями підписувача, що використовуються для створення адреси +програми [`create_program_address`](/docs/core/pda.md#createprogramaddress). ## Стек -SBF використовує стекові кадри замість змінного покажчика стеку. Кожен стековий кадр -має розмір 4 КБ. +SBF використовує стекові кадри замість змінного покажчика стеку. Кожен стековий +кадр має розмір 4 КБ. -Якщо програма порушує розмір цього стекового кадру, компілятор повідомить -про перевищення розміру як попередження. +Якщо програма порушує розмір цього стекового кадру, компілятор повідомить про +перевищення розміру як попередження. Наприклад: @@ -81,82 +84,92 @@ SBF використовує стекові кадри замість змінн Error: Function _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E Stack offset of -30728 exceeded max offset of -4096 by 26632 bytes, please minimize large stack variables ``` -Повідомлення вказує, який символ перевищує розмір свого стекового кадру, але ім'я може бути змінене. +Повідомлення вказує, який символ перевищує розмір свого стекового кадру, але +ім'я може бути змінене. -> Щоб деманглювати символ Rust, використовуйте [rustfilt](https://github.com/luser/rustfilt). - -Вищезазначене попередження походить від програми на Rust, тому демангльоване ім'я символу: +> Щоб деманглювати символ Rust, використовуйте +> [rustfilt](https://github.com/luser/rustfilt). +Вищезазначене попередження походить від програми на Rust, тому демангльоване +ім'я символу: ```shell rustfilt _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E curve25519_dalek::edwards::EdwardsBasepointTable::create ``` -Причина того, що виводиться попередження, а не помилка, полягає в тому, що деякі залежні -пакети можуть містити функціональність, яка порушує обмеження розміру стекового кадру, навіть -якщо програма не використовує цю функціональність. Якщо програма порушить розмір стеку під час виконання, -то буде виведено помилку `AccessViolation`. -Стекові кадри SBF займають діапазон віртуальних адрес, починаючи з `0x200000000`. +Причина того, що виводиться попередження, а не помилка, полягає в тому, що деякі +залежні пакети можуть містити функціональність, яка порушує обмеження розміру +стекового кадру, навіть якщо програма не використовує цю функціональність. Якщо +програма порушить розмір стеку під час виконання, то буде виведено помилку +`AccessViolation`. + +Стекові кадри SBF займають діапазон віртуальних адрес, починаючи з +`0x200000000`. ## Розмір купи Програми мають доступ до купи часу виконання через API Rust `alloc`. Для -швидкого виділення пам'яті використовується проста купа на 32 КБ. Куча не підтримує -`free` або `realloc`. +швидкого виділення пам'яті використовується проста купа на 32 КБ. Куча не +підтримує `free` або `realloc`. -Програми мають доступ до пам'яті об'ємом 32 КБ, починаючи з віртуальної -адреси 0x300000000, і можуть реалізувати власну купу на основі специфічних потреб програми. +Програми мають доступ до пам'яті об'ємом 32 КБ, починаючи з віртуальної адреси +0x300000000, і можуть реалізувати власну купу на основі специфічних потреб +програми. Програми на Rust реалізують купу безпосередньо, визначаючи власний [`global_allocator`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/entrypoint.rs#L72) ## Завантажувачі -Програми розгортаються і виконуються через завантажувачі часу виконання, наразі підтримуються -два завантажувачі: +Програми розгортаються і виконуються через завантажувачі часу виконання, наразі +підтримуються два завантажувачі: + - [BPF Loader](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader.rs#L17) - [BPF loader (deprecated)](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader_deprecated.rs#L14) -Завантажувачі можуть підтримувати різні інтерфейси бінарних додатків, тому розробники повинні -пишуть свої програми для одного завантажувача і розгортають їх на тому ж завантажувачі. Якщо програма, -написана для одного завантажувача, буде розгорнута на іншому, це зазвичай призведе до -помилки `AccessViolation` через невідповідність десеріалізації вхідних параметрів програми. +Завантажувачі можуть підтримувати різні інтерфейси бінарних додатків, тому +розробники повинні пишуть свої програми для одного завантажувача і розгортають +їх на тому ж завантажувачі. Якщо програма, написана для одного завантажувача, +буде розгорнута на іншому, це зазвичай призведе до помилки `AccessViolation` +через невідповідність десеріалізації вхідних параметрів програми. -Для практичних цілей програми завжди повинні бути написані для останнього -BPF завантажувача, і останній завантажувач є за умовчанням для інтерфейсу командного рядка -та JavaScript API. +Для практичних цілей програми завжди повинні бути написані для останнього BPF +завантажувача, і останній завантажувач є за умовчанням для інтерфейсу командного +рядка та JavaScript API. - [Точки входу програми Rust](/docs/programs/lang-rust.md#program-entrypoint) ### Розгортання -Розгортання програми SBF — це процес завантаження спільного об'єкта BPF в -дані акаунта програми та позначення акаунта як виконуваного. Клієнт розбиває -спільний об'єкт SBF на менші частини і надсилає їх як дані інструкцій +Розгортання програми SBF — це процес завантаження спільного об'єкта BPF в дані +акаунта програми та позначення акаунта як виконуваного. Клієнт розбиває спільний +об'єкт SBF на менші частини і надсилає їх як дані інструкцій [`Write`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/loader_instruction.rs#L13) -до завантажувача, де завантажувач записує ці дані в акаунт програми. -Якщо всі частини отримані, клієнт надсилає +до завантажувача, де завантажувач записує ці дані в акаунт програми. Якщо всі +частини отримані, клієнт надсилає [`Finalize`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/loader_instruction.rs#L30) -інструкцію до завантажувача, завантажувач потім перевіряє, чи є дані SBF дійсними -і позначає акаунт програми як _виконуваний_. Після того, як акаунт програми -буде позначено як виконуваний, подальші транзакції можуть видавати інструкції для цієї -програми для обробки. +інструкцію до завантажувача, завантажувач потім перевіряє, чи є дані SBF +дійсними і позначає акаунт програми як _виконуваний_. Після того, як акаунт +програми буде позначено як виконуваний, подальші транзакції можуть видавати +інструкції для цієї програми для обробки. -Коли інструкція спрямована до виконуваної програми SBF, завантажувач -конфігурує середовище виконання програми, серіалізує вхідні параметри програми, -викликає точку входу програми і повідомляє про будь-які помилки. +Коли інструкція спрямована до виконуваної програми SBF, завантажувач конфігурує +середовище виконання програми, серіалізує вхідні параметри програми, викликає +точку входу програми і повідомляє про будь-які помилки. -Додаткову інформацію див. в розділі [розгортання програм](/docs/programs/deploying.md). +Додаткову інформацію див. в розділі +[розгортання програм](/docs/programs/deploying.md). ### Серіалізація вхідних параметрів -Завантажувачі SBF серіалізують вхідні параметри програми в масив байтів, який потім передається -в точку входу програми, де програма відповідає за їх десеріалізацію на ланцюгу. Одна з змін між -депрецованим завантажувачем і поточним полягає в тому, що вхідні параметри серіалізуються так, -що різні параметри потрапляють на вирівняні офсети в межах вирівняного байтового -масиву. Це дозволяє реалізаціям десеріалізації безпосередньо посилатися на -байтовий масив і надавати вирівняні вказівники до програми. +Завантажувачі SBF серіалізують вхідні параметри програми в масив байтів, який +потім передається в точку входу програми, де програма відповідає за їх +десеріалізацію на ланцюгу. Одна з змін між депрецованим завантажувачем і +поточним полягає в тому, що вхідні параметри серіалізуються так, що різні +параметри потрапляють на вирівняні офсети в межах вирівняного байтового масиву. +Це дозволяє реалізаціям десеріалізації безпосередньо посилатися на байтовий +масив і надавати вирівняні вказівники до програми. - [Десеріалізація параметрів програми на Rust](/docs/programs/lang-rust.md#parameter-deserialization) @@ -165,8 +178,8 @@ BPF завантажувача, і останній завантажувач є - 8 байт беззнакового числа акаунтів - Для кожного акаунта: - - 1 байт, що вказує, чи є цей акаунт дублікатом, якщо ні — значення 0xff, - в іншому випадку значення — це індекс акаунта, з яким він є дублікатом. + - 1 байт, що вказує, чи є цей акаунт дублікатом, якщо ні — значення 0xff, в + іншому випадку значення — це індекс акаунта, з яким він є дублікатом. - Якщо дублікати: 7 байт заповнювальної пам'яті - Якщо не дублікати: - 1 байт булевого типу, true, якщо акаунт є підписантом diff --git a/docs/locales/uk/programs/limitations.md b/docs/locales/uk/programs/limitations.md index a2e33411f..955549850 100644 --- a/docs/locales/uk/programs/limitations.md +++ b/docs/locales/uk/programs/limitations.md @@ -3,15 +3,20 @@ title: "Обмеження" sidebarSortOrder: 6 --- -Розробка програм на блокчейні Solana має деякі вроджені обмеження. Нижче наведено список поширених обмежень, з якими ви можете зіткнутися. +Розробка програм на блокчейні Solana має деякі вроджені обмеження. Нижче +наведено список поширених обмежень, з якими ви можете зіткнутися. ## Бібліотеки Rust -Оскільки програми Rust на блокчейні повинні бути детермінованими і виконуватись у середовищі з обмеженими ресурсами та одночасною обробкою, вони мають деякі обмеження щодо використання бібліотек. +Оскільки програми Rust на блокчейні повинні бути детермінованими і виконуватись +у середовищі з обмеженими ресурсами та одночасною обробкою, вони мають деякі +обмеження щодо використання бібліотек. -Програми Rust на блокчейні підтримують більшість бібліотек Rust, таких як libstd, libcore, liballoc, а також багато сторонніх бібліотек. +Програми Rust на блокчейні підтримують більшість бібліотек Rust, таких як +libstd, libcore, liballoc, а також багато сторонніх бібліотек. -Проте існують певні обмеження через обмежені ресурси середовища та необхідність детермінованості: +Проте існують певні обмеження через обмежені ресурси середовища та необхідність +детермінованості: - Немає доступу до: - `rand` @@ -28,41 +33,62 @@ sidebarSortOrder: 6 - `std::os` - Використання Bincode є дуже ресурсомістким і його слід уникати. - Форматування рядків також є ресурсомістким і повинно бути мінімізоване. -- Відсутня підтримка для `println!` та `print!`, замість цього використовуйте макрос +- Відсутня підтримка для `println!` та `print!`, замість цього використовуйте + макрос [`msg!`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/log.rs#L33). -- Під час виконання встановлено обмеження на кількість інструкцій, які програма може виконати під час обробки однієї інструкції. Дивіться [бюджет обчислень](/docs/core/fees.md#compute-budget) для більш детальної інформації. +- Під час виконання встановлено обмеження на кількість інструкцій, які програма + може виконати під час обробки однієї інструкції. Дивіться + [бюджет обчислень](/docs/core/fees.md#compute-budget) для більш детальної + інформації. ## Бюджет обчислень -Для запобігання зловживанню обчислювальними ресурсами блокчейну кожна транзакція отримує [бюджет обчислень](/docs/terminology.md#compute-budget). Перевищення цього бюджету призведе до провалу транзакції. +Для запобігання зловживанню обчислювальними ресурсами блокчейну кожна транзакція +отримує [бюджет обчислень](/docs/terminology.md#compute-budget). Перевищення +цього бюджету призведе до провалу транзакції. -Дивіться документацію про [обмеження обчислень](/docs/core/fees.md#compute-budget) для більш детальної інформації. +Дивіться документацію про +[обмеження обчислень](/docs/core/fees.md#compute-budget) для більш детальної +інформації. ## Глибина стеку викликів — помилка `CallDepthExceeded` Програми Solana мають обмежену глибину стеку викликів до **64 кадрів**. -Якщо програма перевищує дозволену глибину стеку викликів, вона отримує помилку `CallDepthExceeded`. +Якщо програма перевищує дозволену глибину стеку викликів, вона отримує помилку +`CallDepthExceeded`. ## Глибина викликів CPI — помилка `CallDepth` -Перехресні виклики між програмами дозволяють програмам викликати інші програми безпосередньо, але наразі глибина обмежена до `4`. +Перехресні виклики між програмами дозволяють програмам викликати інші програми +безпосередньо, але наразі глибина обмежена до `4`. -Якщо програма перевищує дозволену [глибину викликів між програмами](/docs/core/cpi.md), вона отримує помилку `CallDepth`. +Якщо програма перевищує дозволену +[глибину викликів між програмами](/docs/core/cpi.md), вона отримує помилку +`CallDepth`. ## Підтримка типів float у Rust -Програми підтримують обмежений набір операцій із типами float у Rust. Якщо програма намагається використовувати операцію із float, яка не підтримується, виконання викликає помилку про нерозв’язаний символ. +Програми підтримують обмежений набір операцій із типами float у Rust. Якщо +програма намагається використовувати операцію із float, яка не підтримується, +виконання викликає помилку про нерозв’язаний символ. -Операції із float виконуються через програмні бібліотеки (LLVM's float built-ins) і споживають більше обчислювальних одиниць, ніж операції з цілими числами. Загалом рекомендується використовувати фіксовану точку там, де це можливо. +Операції із float виконуються через програмні бібліотеки (LLVM's float +built-ins) і споживають більше обчислювальних одиниць, ніж операції з цілими +числами. Загалом рекомендується використовувати фіксовану точку там, де це +можливо. -[Математичні тести Solana Program Library](https://github.com/solana-labs/solana-program-library/tree/master/libraries/math) демонструють продуктивність деяких математичних операцій. Для запуску тесту синхронізуйте репозиторій і виконайте: +[Математичні тести Solana Program Library](https://github.com/solana-labs/solana-program-library/tree/master/libraries/math) +демонструють продуктивність деяких математичних операцій. Для запуску тесту +синхронізуйте репозиторій і виконайте: ```shell cargo test-sbf -- --nocapture --test-threads=1 ``` -Недавні результати показують, що операції із float споживають більше інструкцій порівняно з еквівалентами для цілих чисел. Реалізації з фіксованою точкою також будуть менш ресурсомісткими, ніж float: +Недавні результати показують, що операції із float споживають більше інструкцій +порівняно з еквівалентами для цілих чисел. Реалізації з фіксованою точкою також +будуть менш ресурсомісткими, ніж float: ```text u64 f32 @@ -72,7 +98,11 @@ Divide 9 219 ## Статичні змінні, які можна змінювати -Спільні об’єкти програм не підтримують змінювані спільні дані. Програми спільно використовують один і той самий код та дані лише для читання, що означає, що розробники не повинні включати статичні змінювані або глобальні змінні в програми. У майбутньому може бути додано механізм копіювання при записі для підтримки змінюваних даних. +Спільні об’єкти програм не підтримують змінювані спільні дані. Програми спільно +використовують один і той самий код та дані лише для читання, що означає, що +розробники не повинні включати статичні змінювані або глобальні змінні в +програми. У майбутньому може бути додано механізм копіювання при записі для +підтримки змінюваних даних. ## Ділення зі знаком diff --git a/docs/locales/uk/programs/rust/index.md b/docs/locales/uk/programs/rust/index.md index bfc459af9..16c3c79c3 100644 --- a/docs/locales/uk/programs/rust/index.md +++ b/docs/locales/uk/programs/rust/index.md @@ -1,28 +1,31 @@ --- title: Розробка програм на Rust description: - Дізнайтеся, як розробляти програми для Solana, використовуючи Rust, включаючи покрокові - інструкції для створення, збірки, тестування та розгортання смарт-контрактів на - блокчейні Solana. + Дізнайтеся, як розробляти програми для Solana, використовуючи Rust, включаючи + покрокові інструкції для створення, збірки, тестування та розгортання + смарт-контрактів на блокчейні Solana. sidebarLabel: Програми на Rust sidebarSortOrder: 1 altRoutes: - /docs/programs/lang-rust --- -Програми для Solana в основному розробляються за допомогою мови програмування Rust. -Ця сторінка зосереджена на написанні програм для Solana на Rust без використання фреймворку Anchor, -метод, який часто називають написанням "рідних програм на Rust". +Програми для Solana в основному розробляються за допомогою мови програмування +Rust. Ця сторінка зосереджена на написанні програм для Solana на Rust без +використання фреймворку Anchor, метод, який часто називають написанням "рідних +програм на Rust". Розробка рідних програм на Rust дає розробникам повний контроль над їхніми програмами для Solana. Однак цей підхід вимагає більше ручної налаштування та -шаблонного коду порівняно з використанням фреймворку Anchor. Цей метод рекомендований для розробників, які: +шаблонного коду порівняно з використанням фреймворку Anchor. Цей метод +рекомендований для розробників, які: - Шукають детальний контроль над логікою програми та оптимізаціями -- Хочуть зрозуміти основні концепції, перш ніж переходити до фреймворків вищого рівня +- Хочуть зрозуміти основні концепції, перш ніж переходити до фреймворків вищого + рівня -Для початківців ми рекомендуємо почати з фреймворку Anchor. Для отримання додаткової інформації див. розділ -[Anchor](/docs/programs/anchor). +Для початківців ми рекомендуємо почати з фреймворку Anchor. Для отримання +додаткової інформації див. розділ [Anchor](/docs/programs/anchor). ## Попередні вимоги @@ -36,37 +39,38 @@ altRoutes: ## Початок роботи -Наведений приклад охоплює основні кроки для створення вашої першої програми для Solana, -написаної на Rust. Ми створимо мінімальну програму, яка виводить "Hello, world!" в -журнали програми. +Наведений приклад охоплює основні кроки для створення вашої першої програми для +Solana, написаної на Rust. Ми створимо мінімальну програму, яка виводить "Hello, +world!" в журнали програми. ### Створення нової програми -Спочатку створіть новий проект на Rust, використовуючи стандартну команду `cargo init` з -прапорцем `--lib`. +Спочатку створіть новий проект на Rust, використовуючи стандартну команду +`cargo init` з прапорцем `--lib`. ```shell filename="Terminal" cargo init hello_world --lib ``` -Перейдіть до директорії проекту. Ви повинні побачити стандартні файли `src/lib.rs` та -`Cargo.toml`. +Перейдіть до директорії проекту. Ви повинні побачити стандартні файли +`src/lib.rs` та `Cargo.toml`. ```shell filename="Terminal" cd hello_world ``` -Далі додайте залежність `solana-program`. Це мінімальна залежність, -необхідна для побудови програми Solana. +Далі додайте залежність `solana-program`. Це мінімальна залежність, необхідна +для побудови програми Solana. ```shell filename="Terminal" cargo add solana-program@1.18.26 ``` Далі додайте наступний фрагмент до файлу `Cargo.toml`. Якщо ви не включите цю -конфігурацію, директорія `target/deploy` не буде згенерована під час збірки програми. +конфігурацію, директорія `target/deploy` не буде згенерована під час збірки +програми. ```toml filename="Cargo.toml" [lib] @@ -88,9 +92,12 @@ crate-type = ["cdylib", "lib"] solana-program = "1.18.26" ``` -Далі замініть вміст файлу `src/lib.rs` на наступний код. Це мінімальна програма для Solana, яка виводить "Hello, world!" в журнал програми, коли програма викликається. +Далі замініть вміст файлу `src/lib.rs` на наступний код. Це мінімальна програма +для Solana, яка виводить "Hello, world!" в журнал програми, коли програма +викликається. -Макрос `msg!` використовується в програмах Solana для виведення повідомлення в журнал програми. +Макрос `msg!` використовується в програмах Solana для виведення повідомлення в +журнал програми. ```rs filename="lib.rs" use solana_program::{ @@ -121,11 +128,11 @@ cargo build-sbf 1. Файл `.so` (наприклад, `hello_world.so`): Це зкомпільована програма Solana, яка буде розгорнута в мережі як "смарт-контракт". -2. Файл ключової пари (наприклад, `hello_world-keypair.json`): Публічний ключ цієї - ключової пари використовується як ID програми при розгортанні програми. +2. Файл ключової пари (наприклад, `hello_world-keypair.json`): Публічний ключ + цієї ключової пари використовується як ID програми при розгортанні програми. -Щоб переглянути ID програми, виконайте наступну команду у вашому терміналі. Ця команда -виводить публічний ключ ключової пари за вказаним шляхом до файлу: +Щоб переглянути ID програми, виконайте наступну команду у вашому терміналі. Ця +команда виводить публічний ключ ключової пари за вказаним шляхом до файлу: ```shell filename="Terminal" solana address -k ./target/deploy/hello_world-keypair.json @@ -139,8 +146,8 @@ Example output: ### Тестування програми -Далі протестуйте програму за допомогою crate `solana-program-test`. Додайте наступні -залежності до файлу `Cargo.toml`. +Далі протестуйте програму за допомогою crate `solana-program-test`. Додайте +наступні залежності до файлу `Cargo.toml`. ```shell filename="Terminal" cargo add solana-program-test@1.18.26 --dev @@ -181,8 +188,8 @@ mod test { } ``` -Запустіть тест за допомогою команди `cargo test-sbf`. У журналі програми буде виведено -"Hello, world!". +Запустіть тест за допомогою команди `cargo test-sbf`. У журналі програми буде +виведено "Hello, world!". ```shell filename="Terminal" cargo test-sbf @@ -223,8 +230,8 @@ Keypair Path: /.config/solana/id.json Commitment: confirmed ``` -Відкрийте новий термінал і виконайте команду `solana-test-validator`, щоб запустити -локальний валідатор. +Відкрийте новий термінал і виконайте команду `solana-test-validator`, щоб +запустити локальний валідатор. ```shell filename="Terminal" solana-test-validator @@ -247,8 +254,9 @@ Signature: Ви можете перевірити ID програми та підпис транзакції на [Solana Explorer](https://explorer.solana.com/?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899). -Зверніть увагу, що кластер на Solana Explorer також повинен бути localhost. Опція "Custom RPC -URL" на Solana Explorer за замовчуванням встановлюється на `http://localhost:8899`. +Зверніть увагу, що кластер на Solana Explorer також повинен бути localhost. +Опція "Custom RPC URL" на Solana Explorer за замовчуванням встановлюється на +`http://localhost:8899`. ### Виклик програми @@ -276,7 +284,8 @@ cargo add solana-client@1.18.26 --dev ``` Додайте наступний код до файлу `examples/client.rs`. Це Rust клієнтський скрипт, -який фінансує нову ключову пару для оплати зборів за транзакцію і потім викликає програму hello world. +який фінансує нову ключову пару для оплати зборів за транзакцію і потім викликає +програму hello world. ```rs filename="example/client.rs" use solana_client::rpc_client::RpcClient; @@ -334,7 +343,8 @@ async fn main() { } ``` -Перед виконанням скрипту замініть ID програми в наведеному коді на той, що відповідає вашій програмі. +Перед виконанням скрипту замініть ID програми в наведеному коді на той, що +відповідає вашій програмі. Ви можете отримати свій ID програми, виконавши наступну команду. @@ -369,8 +379,9 @@ Transaction Signature: 54TWxKi3Jsi3UTeZbhLGUFX6JQH7TspRJjRRFZ8NFnwG5BXM9udxiX77b ### Оновлення програми -Програми Solana можна оновити, повторно розгорнувши їх на той самий ID програми. Оновіть -програму в `src/lib.rs`, щоб виводити "Hello, Solana!" замість "Hello, world!". +Програми Solana можна оновити, повторно розгорнувши їх на той самий ID програми. +Оновіть програму в `src/lib.rs`, щоб виводити "Hello, Solana!" замість "Hello, +world!". ```diff filename="lib.rs" pub fn process_instruction( @@ -428,7 +439,8 @@ cargo run --example client Ви можете закрити свою програму Solana, щоб повернути SOL, виділені для акаунту. Закриття програми є незворотним, тому це слід робити обережно. -Щоб закрити програму, використовуйте команду `solana program close `. Наприклад: +Щоб закрити програму, використовуйте команду +`solana program close `. Наприклад: ```shell filename="Terminal" solana program close 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz @@ -442,21 +454,25 @@ Closed Program Id 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz, 0.1350588 SOL reclaimed ``` -Зверніть увагу, що після закриття програми її ID програми не можна буде використовувати знову. Спроба розгорнути програму з раніше закритим ID програми призведе до помилки. +Зверніть увагу, що після закриття програми її ID програми не можна буде +використовувати знову. Спроба розгорнути програму з раніше закритим ID програми +призведе до помилки. ``` Error: Program 4Ujf5fXfLx2PAwRqcECCLtgDxHKPznoJpa43jUBxFfMz has been closed, use a new Program Id ``` -Якщо вам потрібно повторно розгорнути програму з тим самим вихідним кодом після закриття програми, ви повинні згенерувати новий ID програми. Щоб згенерувати нову ключову пару для програми, виконайте наступну команду: +Якщо вам потрібно повторно розгорнути програму з тим самим вихідним кодом після +закриття програми, ви повинні згенерувати новий ID програми. Щоб згенерувати +нову ключову пару для програми, виконайте наступну команду: ```shell filename="Terminal" solana-keygen new -o ./target/deploy/hello_world-keypair.json --force ``` Альтернативно, ви можете видалити існуючий файл ключової пари (наприклад, -`./target/deploy/hello_world-keypair.json`) і знову виконати команду `cargo build-sbf`, -що згенерує новий файл ключової пари. +`./target/deploy/hello_world-keypair.json`) і знову виконати команду +`cargo build-sbf`, що згенерує новий файл ключової пари. diff --git a/docs/locales/uk/programs/rust/program-structure.md b/docs/locales/uk/programs/rust/program-structure.md index 96955bdbf..e8d172094 100644 --- a/docs/locales/uk/programs/rust/program-structure.md +++ b/docs/locales/uk/programs/rust/program-structure.md @@ -2,14 +2,14 @@ title: Структура програми на Rust sidebarLabel: Структура програми description: - Дізнайтесь, як структуровані програми Solana на Rust, включаючи точки входу, управління станом, - обробку інструкцій та тестування. + Дізнайтесь, як структуровані програми Solana на Rust, включаючи точки входу, + управління станом, обробку інструкцій та тестування. sidebarSortOrder: 1 --- Програми Solana, написані на Rust, мають мінімальні вимоги до структури, що дає -гнучкість у тому, як організовувати код. Єдина вимога — програма повинна мати `entrypoint`, -який визначає точку початку виконання програми. +гнучкість у тому, як організовувати код. Єдина вимога — програма повинна мати +`entrypoint`, який визначає точку початку виконання програми. ## Структура програми @@ -28,14 +28,16 @@ sidebarSortOrder: 1 ## Приклад програми -Щоб продемонструвати, як побудувати рідну програму на Rust з кількома інструкціями, -ми розглянемо просту програму лічильника, яка реалізує дві інструкції: +Щоб продемонструвати, як побудувати рідну програму на Rust з кількома +інструкціями, ми розглянемо просту програму лічильника, яка реалізує дві +інструкції: -1. `InitializeCounter`: Створює і ініціалізує новий акаунт з початковим значенням. +1. `InitializeCounter`: Створює і ініціалізує новий акаунт з початковим + значенням. 2. `IncrementCounter`: Збільшує значення, що зберігається в існуючому акаунті. -Для простоти програма буде реалізована в одному файлі `lib.rs`, -хоча на практиці вам, можливо, захочеться розділити більші програми на кілька файлів. +Для простоти програма буде реалізована в одному файлі `lib.rs`, хоча на практиці +вам, можливо, захочеться розділити більші програми на кілька файлів. @@ -315,28 +317,30 @@ tokio = "1.41.0" ### Створення нової програми -Спочатку створіть новий проект на Rust, використовуючи стандартну команду `cargo init` з прапорцем `--lib`. +Спочатку створіть новий проект на Rust, використовуючи стандартну команду +`cargo init` з прапорцем `--lib`. ```shell filename="Terminal" cargo init counter_program --lib ``` -Перейдіть до директорії проекту. Ви повинні побачити стандартні файли `src/lib.rs` та -`Cargo.toml`. +Перейдіть до директорії проекту. Ви повинні побачити стандартні файли +`src/lib.rs` та `Cargo.toml`. ```shell filename="Terminal" cd counter_program ``` -Далі додайте залежність `solana-program`. Це мінімальна залежність, -необхідна для побудови програми Solana. +Далі додайте залежність `solana-program`. Це мінімальна залежність, необхідна +для побудови програми Solana. ```shell filename="Terminal" cargo add solana-program@1.18.26 ``` Далі додайте наступний фрагмент до файлу `Cargo.toml`. Якщо ви не включите цю -конфігурацію, директорія `target/deploy` не буде згенерована під час збірки програми. +конфігурацію, директорія `target/deploy` не буде згенерована під час збірки +програми. ```toml filename="Cargo.toml" [lib] @@ -361,8 +365,8 @@ solana-program = "1.18.26" ### Точка входу програми Точка входу програми Solana — це функція, яка викликається, коли програма -активується. Точка входу має наступне сире визначення, і розробники можуть створювати власну -реалізацію функції точки входу. +активується. Точка входу має наступне сире визначення, і розробники можуть +створювати власну реалізацію функції точки входу. Для простоти використовуйте макрос [`entrypoint!`](https://github.com/solana-labs/solana/blob/v2.0/sdk/program/src/entrypoint.rs#L124-L140) @@ -422,24 +426,32 @@ pub type ProcessInstruction = - `program_id`: Публічний ключ викликаної програми (поточна програма) - `accounts`: `AccountInfo` для акаунтів, необхідних для викликаної інструкції -- `instruction_data`: Додаткові дані, передані програмі, які вказують інструкцію для виконання та її необхідні аргументи +- `instruction_data`: Додаткові дані, передані програмі, які вказують інструкцію + для виконання та її необхідні аргументи Ці три параметри безпосередньо відповідають даним, які клієнти повинні надати при побудові інструкції для виклику програми. ### Визначення стану програми -При створенні програми Solana зазвичай починають з визначення стану програми — даних, які будуть зберігатися в акаунтах, створених і належних вашій програмі. +При створенні програми Solana зазвичай починають з визначення стану програми — +даних, які будуть зберігатися в акаунтах, створених і належних вашій програмі. -Стан програми визначається за допомогою структур Rust, які представляють макет даних акаунтів програми. Ви можете визначити кілька структур для представлення різних типів акаунтів вашої програми. +Стан програми визначається за допомогою структур Rust, які представляють макет +даних акаунтів програми. Ви можете визначити кілька структур для представлення +різних типів акаунтів вашої програми. -При роботі з акаунтами вам потрібен спосіб перетворювати типи даних вашої програми в і з сирих байтів, що зберігаються в полі даних акаунту: +При роботі з акаунтами вам потрібен спосіб перетворювати типи даних вашої +програми в і з сирих байтів, що зберігаються в полі даних акаунту: -- Серіалізація: Перетворення ваших типів даних у байти для збереження в полі даних акаунту -- Десеріалізація: Перетворення байтів, збережених в акаунті, назад у ваші типи даних +- Серіалізація: Перетворення ваших типів даних у байти для збереження в полі + даних акаунту +- Десеріалізація: Перетворення байтів, збережених в акаунті, назад у ваші типи + даних -Хоча ви можете використовувати будь-який формат серіалізації для розробки програм Solana, -[Borsh](https://borsh.io/) є загальноприйнятим. Щоб використовувати Borsh у вашій програмі Solana: +Хоча ви можете використовувати будь-який формат серіалізації для розробки +програм Solana, [Borsh](https://borsh.io/) є загальноприйнятим. Щоб +використовувати Borsh у вашій програмі Solana: 1. Додайте crate `borsh` як залежність до вашого `Cargo.toml`: @@ -447,8 +459,8 @@ pub type ProcessInstruction = cargo add borsh ``` -2. Імпортуйте трейди Borsh і використовуйте макрос `derive`, щоб реалізувати трейди для - ваших структур: +2. Імпортуйте трейди Borsh і використовуйте макрос `derive`, щоб реалізувати + трейди для ваших структур: ```rust use borsh::{BorshSerialize, BorshDeserialize}; @@ -460,8 +472,9 @@ pub struct CounterAccount { } ``` -Додайте структуру `CounterAccount` до файлу `lib.rs` для визначення стану програми. Ця -структура буде використовуватися як в інструкції ініціалізації, так і в інструкції збільшення. +Додайте структуру `CounterAccount` до файлу `lib.rs` для визначення стану +програми. Ця структура буде використовуватися як в інструкції ініціалізації, так +і в інструкції збільшення. ```rs filename="lib.rs" {12} {25-29} use solana_program::{ @@ -496,7 +509,9 @@ pub struct CounterAccount { ### Визначення інструкцій -Інструкції позначають різні операції, які ваша програма Solana може виконувати. Вважайте їх публічними API вашої програми — вони визначають, які дії користувачі можуть виконувати при взаємодії з вашою програмою. +Інструкції позначають різні операції, які ваша програма Solana може виконувати. +Вважайте їх публічними API вашої програми — вони визначають, які дії користувачі +можуть виконувати при взаємодії з вашою програмою. Інструкції зазвичай визначаються за допомогою enum на Rust, де: @@ -515,12 +530,14 @@ pub enum CounterInstruction { } ``` -Коли клієнт викликає вашу програму, він повинен надати дані інструкції (як буфер байтів), де: +Коли клієнт викликає вашу програму, він повинен надати дані інструкції (як буфер +байтів), де: - Перший байт вказує, який варіант інструкції потрібно виконати (0, 1 і т.д.) - Решта байтів містить серіалізовані параметри інструкції (якщо це необхідно) -Для перетворення даних інструкції (байтів) у варіант enum зазвичай реалізують допоміжний метод. Цей метод: +Для перетворення даних інструкції (байтів) у варіант enum зазвичай реалізують +допоміжний метод. Цей метод: 1. Розділяє перший байт, щоб отримати варіант інструкції 2. Зіставляє варіант і парсить будь-які додаткові параметри з решти байтів @@ -553,7 +570,8 @@ impl CounterInstruction { } ``` -Додайте наступний код до файлу `lib.rs` для визначення інструкцій для програми лічильника. +Додайте наступний код до файлу `lib.rs` для визначення інструкцій для програми +лічильника. ```rs filename="lib.rs" {18-46} use borsh::{BorshDeserialize, BorshSerialize}; @@ -605,12 +623,14 @@ impl CounterInstruction { ### Обробники інструкцій -Обробники інструкцій — це функції, які містять бізнес-логіку для кожної інструкції. Зазвичай функції обробників називаються як -`process_`, але ви вільні вибрати будь-яку конвенцію найменувань. +Обробники інструкцій — це функції, які містять бізнес-логіку для кожної +інструкції. Зазвичай функції обробників називаються як +`process_`, але ви вільні вибрати будь-яку конвенцію +найменувань. -Додайте наступний код до файлу `lib.rs`. Цей код використовує enum `CounterInstruction` -та метод `unpack`, визначений на попередньому кроці, для маршрутизації вхідних інструкцій -до відповідних функцій обробників: +Додайте наступний код до файлу `lib.rs`. Цей код використовує enum +`CounterInstruction` та метод `unpack`, визначений на попередньому кроці, для +маршрутизації вхідних інструкцій до відповідних функцій обробників: ```rs filename="lib.rs" {8-17} {20-32} /process_initialize_counter/1 /process_increment_counter/1 entrypoint!(process_instruction); @@ -647,8 +667,8 @@ fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> P } ``` -Далі додайте реалізацію функції `process_initialize_counter`. Цей -обробник інструкції: +Далі додайте реалізацію функції `process_initialize_counter`. Цей обробник +інструкції: 1. Створює і виділяє місце для нового акаунту для збереження даних лічильника 2. Ініціалізує дані акаунту з `initial_value`, переданим в інструкцію @@ -663,13 +683,13 @@ fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> P 3. System Program, який ми викликаємо для створення нового акаунту Для визначення акаунтів, необхідних для інструкції, ми створюємо ітератор по -масиву `accounts` та використовуємо функцію `next_account_info`, щоб отримати кожен -акаунт. Кількість акаунтів, яку ви визначаєте, є кількістю акаунтів, необхідних для -інструкції. +масиву `accounts` та використовуємо функцію `next_account_info`, щоб отримати +кожен акаунт. Кількість акаунтів, яку ви визначаєте, є кількістю акаунтів, +необхідних для інструкції. Порядок акаунтів має значення — при побудові інструкції на стороні клієнта, -акаунти повинні надаватися в тому ж порядку, в якому вони визначені в -програмі, щоб інструкція виконалася успішно. +акаунти повинні надаватися в тому ж порядку, в якому вони визначені в програмі, +щоб інструкція виконалася успішно. Хоча змінні імена акаунтів не впливають на функціональність програми, рекомендується використовувати описові імена. @@ -692,9 +712,12 @@ fn process_initialize_counter( Перед створенням акаунту нам потрібно: -1. Вказати простір (у байтах), який потрібно виділити для поля даних акаунту. Оскільки ми зберігаємо значення типу u64 (`count`), нам потрібно 8 байтів. +1. Вказати простір (у байтах), який потрібно виділити для поля даних акаунту. + Оскільки ми зберігаємо значення типу u64 (`count`), нам потрібно 8 байтів. -2. Обчислити мінімальний баланс "ренту", необхідний для акаунту. На Solana акаунти повинні підтримувати мінімальний баланс лампортів (ренту), що залежить від кількості даних, що зберігаються в акаунті. +2. Обчислити мінімальний баланс "ренту", необхідний для акаунту. На Solana + акаунти повинні підтримувати мінімальний баланс лампортів (ренту), що + залежить від кількості даних, що зберігаються в акаунті. ```rs filename="lib.rs" {12-17} fn process_initialize_counter( @@ -722,22 +745,23 @@ fn process_initialize_counter( Після того, як простір визначено і рент обчислений, створіть акаунт, викликавши інструкцію `create_account` з System Program. -На Solana нові акаунти можуть бути створені тільки через System Program. При створенні -акаунту ми вказуємо кількість байтів для виділення та програму-власника -нового акаунту. System Program: +На Solana нові акаунти можуть бути створені тільки через System Program. При +створенні акаунту ми вказуємо кількість байтів для виділення та +програму-власника нового акаунту. System Program: 1. Створює новий акаунт 2. Виділяє вказаний простір для поля даних акаунту 3. Передає право власності на вказану програму -Цей перехід права власності важливий, оскільки тільки власник акаунту може змінювати -дані акаунту. У цьому випадку ми встановлюємо нашу програму як власника, що дозволить нам змінювати -дані акаунту для збереження значення лічильника. +Цей перехід права власності важливий, оскільки тільки власник акаунту може +змінювати дані акаунту. У цьому випадку ми встановлюємо нашу програму як +власника, що дозволить нам змінювати дані акаунту для збереження значення +лічильника. Щоб викликати System Program з інструкції нашої програми, ми робимо Cross Program Invocation (CPI) через функцію `invoke`. CPI дозволяє одній програмі -викликати інструкції інших програм — в цьому випадку інструкцію `create_account` з System Program. - +викликати інструкції інших програм — в цьому випадку інструкцію `create_account` +з System Program. ```rs filename="lib.rs" {19-33} fn process_initialize_counter( @@ -780,10 +804,11 @@ fn process_initialize_counter( Після того, як акаунт створено, ми ініціалізуємо дані акаунту за допомогою: -1. Створення нової структури `CounterAccount` з переданим значенням `initial_value`. +1. Створення нової структури `CounterAccount` з переданим значенням + `initial_value`. 2. Отримання змінної посилання на поле даних нового акаунту. -3. Серіалізації структури `CounterAccount` в поле даних акаунту, - що ефективно зберігає значення `initial_value` в акаунті. +3. Серіалізації структури `CounterAccount` в поле даних акаунту, що ефективно + зберігає значення `initial_value` в акаунті. ```rs filename="lib.rs" {35-44} /initial_value/ fn process_initialize_counter( @@ -893,22 +918,24 @@ fn process_initialize_counter( } ``` -Далі додайте реалізацію функції `process_increment_counter`. Ця -інструкція збільшує значення існуючого акаунту лічильника. +Далі додайте реалізацію функції `process_increment_counter`. Ця інструкція +збільшує значення існуючого акаунту лічильника. -Так само, як і в функції `process_initialize_counter`, ми починаємо з створення ітератора -по акаунтах. У цьому випадку ми очікуємо лише один акаунт, який є акаунтом, що має бути оновлений. +Так само, як і в функції `process_initialize_counter`, ми починаємо з створення +ітератора по акаунтах. У цьому випадку ми очікуємо лише один акаунт, який є +акаунтом, що має бути оновлений. -Зверніть увагу, що на практиці розробник повинен реалізувати різні перевірки безпеки для -валідності акаунтів, переданих до програми. Оскільки всі акаунти надаються викликачем інструкції, -немає гарантії, що надані акаунти — це саме ті акаунти, які програма очікує. Відсутність перевірок -валідності акаунтів є поширеним джерелом вразливостей програми. +Зверніть увагу, що на практиці розробник повинен реалізувати різні перевірки +безпеки для валідності акаунтів, переданих до програми. Оскільки всі акаунти +надаються викликачем інструкції, немає гарантії, що надані акаунти — це саме ті +акаунти, які програма очікує. Відсутність перевірок валідності акаунтів є +поширеним джерелом вразливостей програми. -Наведений приклад містить перевірку для того, щоб переконатися, що акаунт, на який ми посилаємось як -`counter_account`, належить виконуючій програмі. +Наведений приклад містить перевірку для того, щоб переконатися, що акаунт, на +який ми посилаємось як `counter_account`, належить виконуючій програмі. ```rs filename="lib.rs" {6-9} // Update an existing counter's value @@ -999,8 +1026,8 @@ fn process_increment_counter(program_id: &Pubkey, accounts: &[AccountInfo]) -> P ### Тестування інструкцій -Для тестування інструкцій програми додайте наступні залежності до -файлу `Cargo.toml`. +Для тестування інструкцій програми додайте наступні залежності до файлу +`Cargo.toml`. ```shell filename="Terminal" cargo add solana-program-test@1.18.26 --dev @@ -1008,9 +1035,9 @@ cargo add solana-sdk@1.18.26 --dev cargo add tokio --dev ``` -Далі додайте наступний тестовий модуль до файлу `lib.rs` і виконайте команду `cargo test-sbf` для -запуску тестів. За бажанням, використовуйте прапорець `--nocapture`, щоб побачити -виведені дані в результатах. +Далі додайте наступний тестовий модуль до файлу `lib.rs` і виконайте команду +`cargo test-sbf` для запуску тестів. За бажанням, використовуйте прапорець +`--nocapture`, щоб побачити виведені дані в результатах. ```shell filename="Термінал" cargo test-sbf -- --nocapture @@ -1040,9 +1067,9 @@ mod test { } ``` -Далі налаштуйте тест за допомогою `ProgramTest`. Потім створіть нову ключову пару, яку будемо використовувати як -адресу для акаунту лічильника, який ми ініціалізуємо, і визначте початкове значення, -яке встановимо для лічильника. +Далі налаштуйте тест за допомогою `ProgramTest`. Потім створіть нову ключову +пару, яку будемо використовувати як адресу для акаунту лічильника, який ми +ініціалізуємо, і визначте початкове значення, яке встановимо для лічильника. ```rs filename="lib.rs" #[cfg(test)] @@ -1091,7 +1118,8 @@ AccountMeta::new_readonly(account4_pubkey, true), // writable, signer Для тестування інструкції ініціалізації: -- Створіть дані інструкції з варіантом 0 (`InitializeCounter`) та початковим значенням +- Створіть дані інструкції з варіантом 0 (`InitializeCounter`) та початковим + значенням - Побудуйте інструкцію з ID програми, даними інструкції та необхідними акаунтами - Відправте транзакцію з інструкцією ініціалізації - Перевірте, що акаунт був створений з правильним початковим значенням @@ -1160,8 +1188,8 @@ AccountMeta::new_readonly(account4_pubkey, true), // writable, signer - Перевірте, що акаунт був збільшений до правильного значення Зверніть увагу, що дані інструкції для інструкції збільшення — це `[1]`, що -відповідає варіанту 1 (`IncrementCounter`). Оскільки інструкція збільшення не має додаткових -параметрів, дані — це просто варіант інструкції. +відповідає варіанту 1 (`IncrementCounter`). Оскільки інструкція збільшення не +має додаткових параметрів, дані — це просто варіант інструкції. ```rs filename="lib.rs" {55-82} #[tokio::test] diff --git a/docs/locales/uk/programs/testing.md b/docs/locales/uk/programs/testing.md index dbd7711fa..3ceacb648 100644 --- a/docs/locales/uk/programs/testing.md +++ b/docs/locales/uk/programs/testing.md @@ -1,42 +1,69 @@ ## Тестування з NodeJS -Коли ви розробляєте програми на Solana, важливо забезпечити їхню правильність і надійність. До цього часу розробники використовували `solana-test-validator` для тестування. Цей документ описує тестування вашої програми Solana за допомогою Node.js і бібліотеки `solana-bankrun`. +Коли ви розробляєте програми на Solana, важливо забезпечити їхню правильність і +надійність. До цього часу розробники використовували `solana-test-validator` для +тестування. Цей документ описує тестування вашої програми Solana за допомогою +Node.js і бібліотеки `solana-bankrun`. ## Огляд Є два способи тестування програм на Solana: -1. [solana-test-validator](https://docs.anza.xyz/cli/examples/test-validator): Локальний емулятор блокчейна Solana, який обробляє транзакції, що надсилаються на валідацію. -2. Різні фреймворки для тестування програм SBF (Solana Bytecode Format) на базі BanksClient: - - `Bankrun` — це фреймворк, що імітує роботу Solana bank, дозволяючи розробникам розгортати програми, взаємодіяти з ними та оцінювати їх поведінку у тестових умовах, що нагадують mainnet. - - Підтримуються фреймворки як [solana-program-test](https://docs.rs/solana-program-test) (Rust), [solana-bankrun](https://github.com/kevinheavey/solana-bankrun) (Rust, JavaScript), [anchor-bankrun](https://www.npmjs.com/package/anchor-bankrun) (Anchor, JavaScript), [solders.bankrun](https://kevinheavey.github.io/solders/api_reference/bankrun.html) (Python). +1. [solana-test-validator](https://docs.anza.xyz/cli/examples/test-validator): + Локальний емулятор блокчейна Solana, який обробляє транзакції, що + надсилаються на валідацію. +2. Різні фреймворки для тестування програм SBF (Solana Bytecode Format) на базі + BanksClient: + - `Bankrun` — це фреймворк, що імітує роботу Solana bank, дозволяючи + розробникам розгортати програми, взаємодіяти з ними та оцінювати їх + поведінку у тестових умовах, що нагадують mainnet. + - Підтримуються фреймворки як + [solana-program-test](https://docs.rs/solana-program-test) (Rust), + [solana-bankrun](https://github.com/kevinheavey/solana-bankrun) (Rust, + JavaScript), [anchor-bankrun](https://www.npmjs.com/package/anchor-bankrun) + (Anchor, JavaScript), + [solders.bankrun](https://kevinheavey.github.io/solders/api_reference/bankrun.html) + (Python). > [`pnpm create solana-program`](https://github.com/solana-program/create-solana-program) -> може допомогти створити клієнти для JS і Rust, включаючи тести. Anchor ще не підтримується. +> може +> допомогти створити клієнти для JS і Rust, включаючи тести. Anchor ще не +> підтримується. У цьому керівництві ми використовуємо `Solana Bankrun`. -`Bankrun` — це дуже швидкий, потужний та легкий фреймворк для тестування програм Solana у Node.js. +`Bankrun` — це дуже швидкий, потужний та легкий фреймворк для тестування програм +Solana у Node.js. -- Основна перевага використання `Solana Bankrun` полягає в тому, що вам не потрібно налаштовувати середовище для тестування програм, як це потрібно при використанні `solana-test-validator`. Це можна зробити за допомогою коду всередині тестів. -- `Bankrun` динамічно встановлює час та дані акаунтів, що неможливо при використанні `solana-test-validator`. +- Основна перевага використання `Solana Bankrun` полягає в тому, що вам не + потрібно налаштовувати середовище для тестування програм, як це потрібно при + використанні `solana-test-validator`. Це можна зробити за допомогою коду + всередині тестів. +- `Bankrun` динамічно встановлює час та дані акаунтів, що неможливо при + використанні `solana-test-validator`. ## Інсталяція -Додайте `solana-bankrun` як dev-залежність до вашого Node.js проекту. Якщо ваша Solana програма ще не є Node.js проектом, ви можете ініціалізувати її за допомогою команди `npm init`: +Додайте `solana-bankrun` як dev-залежність до вашого Node.js проекту. Якщо ваша +Solana програма ще не є Node.js проектом, ви можете ініціалізувати її за +допомогою команди `npm init`: ```bash npm i -D solana-bankrun ``` + ## Використання ### Директорія для Програми -Перш за все, `.so` файл вашої програми повинен бути присутнім в одній із наступних директорій: +Перш за все, `.so` файл вашої програми повинен бути присутнім в одній із +наступних директорій: - `./tests/fixtures` (створіть цю директорію, якщо її ще не існує). - Ваша поточна робоча директорія. -- Директорія, яку ви визначите в змінних середовища `BPF_OUT_DIR` або `SBF_OUT_DIR`. - Наприклад: +- Директорія, яку ви визначите в змінних середовища `BPF_OUT_DIR` або + `SBF_OUT_DIR`. + Наприклад: + ```json { "scripts": { @@ -44,9 +71,12 @@ npm i -D solana-bankrun } } ``` + ### Початок Роботи -Функція `start` з бібліотеки `solana-bankrun` запускає `BanksServer` і `BanksClient`, розгортає програми та додає акаунти відповідно до ваших інструкцій. +Функція `start` з бібліотеки `solana-bankrun` запускає `BanksServer` і +`BanksClient`, розгортає програми та додає акаунти відповідно до ваших +інструкцій. Приклад використання: @@ -63,12 +93,22 @@ test("testing program instruction", async () => { // write tests }); ``` + ### `context` у Bankrun -- Ми отримуємо доступ до `context` з функції `start`. `context` містить `BanksClient`, останній blockhash та профінансовану keypair для підпису транзакцій. -- У `context` є `payer`, який є профінансованою парою ключів і може використовуватися для підпису транзакцій. -- `context` також містить `context.lastBlockhash` або `context.getLatestBlockhash`, що спрощує отримання [Blockhash](https://solana.com/docs/terminology#blockhash) під час тестів. -- `context.banksClient` використовується для надсилання транзакцій і отримання даних акаунтів зі стану реєстру. Наприклад, іноді потрібна [оренда (Rent)](https://solana.com/docs/terminology#rent) (в лампортах) для створення транзакції, наприклад, при використанні інструкції `createAccount()` з `SystemProgram`. Це можна зробити за допомогою `BanksClient`: +- Ми отримуємо доступ до `context` з функції `start`. `context` містить + `BanksClient`, останній blockhash та профінансовану keypair для підпису + транзакцій. +- У `context` є `payer`, який є профінансованою парою ключів і може + використовуватися для підпису транзакцій. +- `context` також містить `context.lastBlockhash` або + `context.getLatestBlockhash`, що спрощує отримання + [Blockhash](https://solana.com/docs/terminology#blockhash) під час тестів. +- `context.banksClient` використовується для надсилання транзакцій і отримання + даних акаунтів зі стану реєстру. Наприклад, іноді потрібна + [оренда (Rent)](https://solana.com/docs/terminology#rent) (в лампортах) для + створення транзакції, наприклад, при використанні інструкції `createAccount()` + з `SystemProgram`. Це можна зробити за допомогою `BanksClient`: ```typescript const rent = await client.getRent(); @@ -79,7 +119,9 @@ test("testing program instruction", async () => { //.... }); ``` -- Ви можете зчитувати дані акаунта з `BanksClient`, використовуючи функцію `getAccount`. + +- Ви можете зчитувати дані акаунта з `BanksClient`, використовуючи функцію + `getAccount`. ```typescript AccountInfo = await client.getAccount(counter); @@ -87,17 +129,19 @@ test("testing program instruction", async () => { ### Обробка Транзакції -Функція `processTransaction()` виконує транзакцію з використанням завантажених програм і акаунтів, отриманих із функції `start`. Вона повертає результат виконаної транзакції. +Функція `processTransaction()` виконує транзакцію з використанням завантажених +програм і акаунтів, отриманих із функції `start`. Вона повертає результат +виконаної транзакції. ```typescript let transaction = await client.processTransaction(tx); ``` + ## Приклад Ось приклад тесту для програми [hello world](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/native): - ```typescript import { PublicKey, @@ -152,6 +196,7 @@ describe("hello-solana", async () => { }); }); ``` + Ось як виглядає результат після запуску тестів для [hello world програми](https://github.com/solana-developers/program-examples/tree/main/basics/hello-solana/native): diff --git a/docs/locales/uk/rpc.md b/docs/locales/uk/rpc.md index e8e6582a6..d63508930 100644 --- a/docs/locales/uk/rpc.md +++ b/docs/locales/uk/rpc.md @@ -4,7 +4,7 @@ sidebarSortOrder: 1 isSkippedInNav: true --- -Цей файл не повинен редагуватися, оскільки він не призначений для відображення. Він існує лише для створення посилання в головній бічній панелі документації. +Цей файл не повинен редагуватися, оскільки він не призначений для відображення. +Він існує лише для створення посилання в головній бічній панелі документації. -Документація JSON RPC для Solana доступна в -[`rpc` каталозі](./rpc/) +Документація JSON RPC для Solana доступна в [`rpc` каталозі](./rpc/) diff --git a/docs/locales/uk/terminology.md b/docs/locales/uk/terminology.md index 39d74a750..5a06d576d 100644 --- a/docs/locales/uk/terminology.md +++ b/docs/locales/uk/terminology.md @@ -11,23 +11,28 @@ keywords: isSkippedInNav: true --- -Наведені нижче терміни використовуються в документації Solana та екосистемі розробки. +Наведені нижче терміни використовуються в документації Solana та екосистемі +розробки. ## Обліковий запис (account) Запис у реєстрі Solana, який або зберігає дані, або є виконуваною програмою. -Як і обліковий запис у традиційному банку, обліковий запис Solana може зберігати кошти, які називаються [лампортами](#lamport). Як файл у Linux, він адресується ключем, часто згадуваним як [публічний ключ](#public-key-pubkey) або pubkey. +Як і обліковий запис у традиційному банку, обліковий запис Solana може зберігати +кошти, які називаються [лампортами](#lamport). Як файл у Linux, він адресується +ключем, часто згадуваним як [публічний ключ](#public-key-pubkey) або pubkey. Ключ може бути одним із таких: - Публічний ключ ed25519 -- Адреса облікового запису, отримана програмно (32-байтне значення поза кривою ed25519) +- Адреса облікового запису, отримана програмно (32-байтне значення поза кривою + ed25519) - Хеш публічного ключа ed25519 із рядком із 32 символів ## Власник облікового запису (account owner) -Адреса програми, якій належить обліковий запис. Тільки програма-власник може змінювати обліковий запис. +Адреса програми, якій належить обліковий запис. Тільки програма-власник може +змінювати обліковий запис. Див. також [Повноваження](#authority). @@ -41,28 +46,39 @@ isSkippedInNav: true Наприклад: -- Можливість карбування нових токенів надається обліковому запису, який є "владою карбування" токена. -- Можливість оновлювати програму надається обліковому запису, який є "владою оновлення" програми. +- Можливість карбування нових токенів надається обліковому запису, який є + "владою карбування" токена. +- Можливість оновлювати програму надається обліковому запису, який є "владою + оновлення" програми. ## Стан банку (bank state) -Результат виконання всіх програм у реєстрі на певній [висоті тікання](#tick-height). Він включає щонайменше набір усіх [облікових записів](#account), які зберігають ненульові [нативні токени](#native-token). +Результат виконання всіх програм у реєстрі на певній +[висоті тікання](#tick-height). Він включає щонайменше набір усіх +[облікових записів](#account), які зберігають ненульові +[нативні токени](#native-token). ## Блок (block) -Неперервний набір [записів](#entry) у реєстрі, підтверджений [голосуванням](#ledger-vote). [Лідер](#leader) створює не більше одного блоку за [слот](#slot). +Неперервний набір [записів](#entry) у реєстрі, підтверджений +[голосуванням](#ledger-vote). [Лідер](#leader) створює не більше одного блоку за +[слот](#slot). ## Блокхеш (blockhash) -Унікальне значення ([хеш](#hash)), яке ідентифікує запис (блок). Solana обчислює блокхеш із останнього [ідентифікатора запису](#entry-id) блоку. +Унікальне значення ([хеш](#hash)), яке ідентифікує запис (блок). Solana обчислює +блокхеш із останнього [ідентифікатора запису](#entry-id) блоку. ## Висота блоку (block height) -Кількість [блоків](#block) під поточним блоком. Перший блок після [генезис-блоку](#genesis-block) має висоту один. +Кількість [блоків](#block) під поточним блоком. Перший блок після +[генезис-блоку](#genesis-block) має висоту один. ## Завантажувач BPF (BPF loader) -Програма Solana, яка завантажує [програми на основі BPF](/docs/uk/core/programs#berkeley-packet-filter-bpf) в [блокчейн](#onchain-program), дозволяючи їм взаємодіяти з середовищем виконання. +Програма Solana, яка завантажує +[програми на основі BPF](/docs/uk/core/programs#berkeley-packet-filter-bpf) в +[блокчейн](#onchain-program), дозволяючи їм взаємодіяти з середовищем виконання. ## Клієнт (client) @@ -78,7 +94,8 @@ isSkippedInNav: true ## Бюджет обчислень (compute budget) -Максимальна кількість [обчислювальних одиниць](#compute-units), спожитих за транзакцію. +Максимальна кількість [обчислювальних одиниць](#compute-units), спожитих за +транзакцію. ## Обчислювальні одиниці (compute units) @@ -86,11 +103,13 @@ isSkippedInNav: true ## Час підтвердження (confirmation time) -Час, який пройшов між створенням [тікового запису](#tick) [лідером](#leader) та створенням [підтвердженого блоку](#confirmed-block). +Час, який пройшов між створенням [тікового запису](#tick) [лідером](#leader) та +створенням [підтвердженого блоку](#confirmed-block). ## Підтверджений блок (confirmed block) -[Блок](#block), який отримав [супербільшість](#supermajority) [голосів реєстру](#ledger-vote). +[Блок](#block), який отримав [супербільшість](#supermajority) +[голосів реєстру](#ledger-vote). ## Площина керування (control plane) @@ -98,7 +117,9 @@ isSkippedInNav: true ## Період охолодження (cooldown period) -Декілька [епох](#epoch) після деактивації [ставки](#stake), протягом яких вона поступово стає доступною для зняття. Під час цього періоду ставка вважається "деактивованою". Докладніше: +Декілька [епох](#epoch) після деактивації [ставки](#stake), протягом яких вона +поступово стає доступною для зняття. Під час цього періоду ставка вважається +"деактивованою". Докладніше: [періоди прогріву та охолодження](https://docs.anza.xyz/implemented-proposals/staking-rewards#stake-warmup-cooldown-withdrawal). ## Кредит (credit) @@ -107,23 +128,28 @@ isSkippedInNav: true ## Виклик між програмами (CPI) -Виклик однієї [програми на блокчейні](#onchain-program) до іншої. Докладніше див. [Виклик між програмами](/docs/uk/core/cpi.md). +Виклик однієї [програми на блокчейні](#onchain-program) до іншої. Докладніше +див. [Виклик між програмами](/docs/uk/core/cpi.md). ## Площина даних (data plane) -Мультикаст-мережа, яка використовується для ефективної перевірки [записів](#entry) і досягнення консенсусу. +Мультикаст-мережа, яка використовується для ефективної перевірки +[записів](#entry) і досягнення консенсусу. ## Дрон (drone) -Зовнішній сервіс, який виступає в ролі хранителя приватного ключа користувача. Зазвичай використовується для перевірки та підпису транзакцій. +Зовнішній сервіс, який виступає в ролі хранителя приватного ключа користувача. +Зазвичай використовується для перевірки та підпису транзакцій. ## Запис (entry) -Запис у [реєстрі](#ledger), який може бути або [тіком](#tick), або [записом транзакції](#transactions-entry). +Запис у [реєстрі](#ledger), який може бути або [тіком](#tick), або +[записом транзакції](#transactions-entry). ## Ідентифікатор запису (entry id) -Хеш ([hash](#hash)), стійкий до попереднього зображення, який є унікальним ідентифікатором [запису](#entry). Хеш слугує доказом: +Хеш ([hash](#hash)), стійкий до попереднього зображення, який є унікальним +ідентифікатором [запису](#entry). Хеш слугує доказом: - Генерації запису після певного проміжку часу - Включення зазначених [транзакцій](#transaction) у запис @@ -133,19 +159,25 @@ isSkippedInNav: true ## Епоха (epoch) -Проміжок часу, визначений кількістю [слотів](#slot), протягом яких діє [розклад лідерів](#leader-schedule). +Проміжок часу, визначений кількістю [слотів](#slot), протягом яких діє +[розклад лідерів](#leader-schedule). ## Обліковий запис для комісій (fee account) -Обліковий запис у транзакції, який оплачує вартість включення транзакції до реєстру. Це перший обліковий запис у транзакції. Він має бути оголошений як читально-записуваний (writable), оскільки оплата транзакції зменшує баланс облікового запису. +Обліковий запис у транзакції, який оплачує вартість включення транзакції до +реєстру. Це перший обліковий запис у транзакції. Він має бути оголошений як +читально-записуваний (writable), оскільки оплата транзакції зменшує баланс +облікового запису. ## Фінальність (finality) -Стан, коли вузли, що представляють 2/3 [ставки](#stake), мають спільний [корінь](#root). +Стан, коли вузли, що представляють 2/3 [ставки](#stake), мають спільний +[корінь](#root). ## Форк (fork) -[Реєстр](#ledger), створений на основі загальних записів, але який розійшовся у своєму розвитку. +[Реєстр](#ledger), створений на основі загальних записів, але який розійшовся у +своєму розвитку. ## Генезис-блок (genesis block) @@ -153,7 +185,8 @@ isSkippedInNav: true ## Генезис-конфігурація (genesis config) -Файл конфігурації, який підготовлює [реєстр](#ledger) для [генезис-блоку](#genesis-block). +Файл конфігурації, який підготовлює [реєстр](#ledger) для +[генезис-блоку](#genesis-block). ## Хеш (hash) @@ -161,7 +194,8 @@ isSkippedInNav: true ## Інфляція (inflation) -Збільшення кількості токенів із часом, яке використовується для фінансування винагород за валідацію та подальшого розвитку Solana. +Збільшення кількості токенів із часом, яке використовується для фінансування +винагород за валідацію та подальшого розвитку Solana. ## Внутрішня інструкція (inner instruction) @@ -169,66 +203,96 @@ isSkippedInNav: true ## Інструкція (instruction) -Виклик для запуску конкретного [обробника інструкцій](#instruction-handler) у [програмі](#program). Інструкція також вказує, які облікові записи потрібно прочитати або змінити, та додаткові дані, які слугують допоміжним вхідним параметром для [обробника інструкцій](#instruction-handler). Кожна [транзакція](#transaction) має містити принаймні одну інструкцію. +Виклик для запуску конкретного [обробника інструкцій](#instruction-handler) у +[програмі](#program). Інструкція також вказує, які облікові записи потрібно +прочитати або змінити, та додаткові дані, які слугують допоміжним вхідним +параметром для [обробника інструкцій](#instruction-handler). Кожна +[транзакція](#transaction) має містити принаймні одну інструкцію. ## Обробник інструкцій (instruction handler) -Функції [програм](#program), які обробляють [інструкції](#instruction) із [транзакцій](#transaction). Обробник інструкцій може містити одну або кілька [викликів між програмами](#cross-program-invocation-cpi). +Функції [програм](#program), які обробляють [інструкції](#instruction) із +[транзакцій](#transaction). Обробник інструкцій може містити одну або кілька +[викликів між програмами](#cross-program-invocation-cpi). ## Пара ключів (keypair) -[Публічний ключ](#public-key-pubkey) і відповідний [приватний ключ](#private-key), які використовуються для доступу до облікового запису. +[Публічний ключ](#public-key-pubkey) і відповідний +[приватний ключ](#private-key), які використовуються для доступу до облікового +запису. ## Лампорти (lamport) -Дробова одиниця [нативного токена](#native-token) із вартістю 0.000000001 [SOL](#sol). +Дробова одиниця [нативного токена](#native-token) із вартістю 0.000000001 +[SOL](#sol). > У межах бюджету обчислень використовується кількість -> _[мікролампортів](https://github.com/solana-labs/solana/blob/ced8f6a512c61e0dd5308095ae8457add4a39e94/program-runtime/src/prioritization_fee.rs#L1-L2)_ для розрахунку [пріоритетної комісії](#prioritization-fee). +> _[мікролампортів](https://github.com/solana-labs/solana/blob/ced8f6a512c61e0dd5308095ae8457add4a39e94/program-runtime/src/prioritization_fee.rs#L1-L2)_ +> для розрахунку [пріоритетної комісії](#prioritization-fee). ## Лідер (leader) -Роль [валідатора](#validator), який додає [записи](#entry) до [реєстру](#ledger). +Роль [валідатора](#validator), який додає [записи](#entry) до +[реєстру](#ledger). ## Розклад лідерів (leader schedule) -Послідовність [публічних ключів](#public-key-pubkey) [валідаторів](#validator), пов’язаних із [слотами](#slot). Кластер використовує цей розклад, щоб визначити, який валідатор є [лідером](#leader) у певний момент часу. +Послідовність [публічних ключів](#public-key-pubkey) [валідаторів](#validator), +пов’язаних із [слотами](#slot). Кластер використовує цей розклад, щоб визначити, +який валідатор є [лідером](#leader) у певний момент часу. ## Реєстр (ledger) -Список [записів](#entry), що містять [транзакції](#transaction), підписані [клієнтами](#client). Концептуально це можна простежити до [генезис-блоку](#genesis-block), але реєстр конкретного [валідатора](#validator) може містити лише новіші [блоки](#block), щоб зменшити обсяг зберігання, оскільки старіші блоки не потрібні для перевірки майбутніх блоків за задумом. +Список [записів](#entry), що містять [транзакції](#transaction), підписані +[клієнтами](#client). Концептуально це можна простежити до +[генезис-блоку](#genesis-block), але реєстр конкретного [валідатора](#validator) +може містити лише новіші [блоки](#block), щоб зменшити обсяг зберігання, +оскільки старіші блоки не потрібні для перевірки майбутніх блоків за задумом. ## Голос у реєстрі (ledger vote) -[Хеш](#hash) стану [валідатора](#validator) на певній [висоті тікання](#tick-height). Він включає підтвердження валідатора, що [блок](#block), який він отримав, був перевірений, а також обіцянку не голосувати за конфліктуючий [блок](#block) (тобто [форк](#fork)) протягом певного часу, відомого як період [блокування](#lockout). +[Хеш](#hash) стану [валідатора](#validator) на певній +[висоті тікання](#tick-height). Він включає підтвердження валідатора, що +[блок](#block), який він отримав, був перевірений, а також обіцянку не +голосувати за конфліктуючий [блок](#block) (тобто [форк](#fork)) протягом +певного часу, відомого як період [блокування](#lockout). ## Легкий клієнт (light client) -Тип [клієнта](#client), який може перевірити, що він підключений до валідного [кластеру](#cluster). Він виконує більше перевірок реєстру, ніж [тонкий клієнт](#thin-client), але менше, ніж [валідатор](#validator). +Тип [клієнта](#client), який може перевірити, що він підключений до валідного +[кластеру](#cluster). Він виконує більше перевірок реєстру, ніж +[тонкий клієнт](#thin-client), але менше, ніж [валідатор](#validator). ## Завантажувач (loader) -[Програма](#program) із можливістю інтерпретувати двійкове кодування інших програм на блокчейні. +[Програма](#program) із можливістю інтерпретувати двійкове кодування інших +програм на блокчейні. ## Блокування (lockout) -Тривалість часу, протягом якої [валідатор](#validator) не може [голосувати](#ledger-vote) за інший [форк](#fork). +Тривалість часу, протягом якої [валідатор](#validator) не може +[голосувати](#ledger-vote) за інший [форк](#fork). ## Повідомлення (message) -Структурований вміст [транзакції](#transaction), зазвичай містить заголовок, масив адрес облікових записів, недавній [блокхеш](#blockhash) та масив [інструкцій](#instruction). +Структурований вміст [транзакції](#transaction), зазвичай містить заголовок, +масив адрес облікових записів, недавній [блокхеш](#blockhash) та масив +[інструкцій](#instruction). Докладніше про [форматування повідомлень у транзакціях](/docs/uk/core/transactions.md#message-header). ## Коефіцієнт Накамото (Nakamoto coefficient) -Міра децентралізації, яка визначає найменшу кількість незалежних суб’єктів, що можуть колективно зупинити блокчейн. Термін запропонований Балажі С. Срінівасаном і Леландом Лі у статті +Міра децентралізації, яка визначає найменшу кількість незалежних суб’єктів, що +можуть колективно зупинити блокчейн. Термін запропонований Балажі С. +Срінівасаном і Леландом Лі у статті [Quantifying Decentralization](https://news.earn.com/quantifying-decentralization-e39db233c28e). ## Нативний токен (native token) -[Токен](#token), що використовується для відстеження роботи [вузлів](#node) у кластері. +[Токен](#token), що використовується для відстеження роботи [вузлів](#node) у +кластері. ## Вузол (node) @@ -240,7 +304,10 @@ isSkippedInNav: true ## Програма на блокчейні (onchain program) -Виконуваний код у блокчейні Solana, який інтерпретує [інструкції](#instruction), надіслані в кожній [транзакції](#transaction), щоб читати та змінювати облікові записи, якими він управляє. Ці програми часто називають "[розумними контрактами](/docs/uk/core/programs.md)" на інших блокчейнах. +Виконуваний код у блокчейні Solana, який інтерпретує [інструкції](#instruction), +надіслані в кожній [транзакції](#transaction), щоб читати та змінювати облікові +записи, якими він управляє. Ці програми часто називають +"[розумними контрактами](/docs/uk/core/programs.md)" на інших блокчейнах. ## PoH (Proof of History) @@ -248,7 +315,10 @@ isSkippedInNav: true ## Окуляр (point) -Зважений [кредит](#credit) у системі винагород. У системі [винагород валідатора](https://docs.anza.xyz/consensus/stake-delegation-and-rewards) кількість очок, що належить [ставці](#stake), є добутком [голосових кредитів](#vote-credit) і кількості лампортів, що були поставлені. +Зважений [кредит](#credit) у системі винагород. У системі +[винагород валідатора](https://docs.anza.xyz/consensus/stake-delegation-and-rewards) +кількість очок, що належить [ставці](#stake), є добутком +[голосових кредитів](#vote-credit) і кількості лампортів, що були поставлені. ## Програма (program) @@ -256,7 +326,8 @@ isSkippedInNav: true ## Програмно отриманий обліковий запис (PDA) -Обліковий запис, підписуючою владою якого є програма, і тому він не контролюється приватним ключем, як інші облікові записи. +Обліковий запис, підписуючою владою якого є програма, і тому він не +контролюється приватним ключем, як інші облікові записи. ## Ідентифікатор програми (program id) @@ -264,15 +335,22 @@ isSkippedInNav: true ## Доказ історії (Proof of History, PoH) -Стек доказів, кожен із яких підтверджує, що певні дані існували до моменту створення доказу і що пройшов точний проміжок часу до попереднього доказу. Як і [перевірювана функція затримки (VDF)](#verifiable-delay-function-vdf), Proof of History може бути перевірений швидше, ніж його створення. +Стек доказів, кожен із яких підтверджує, що певні дані існували до моменту +створення доказу і що пройшов точний проміжок часу до попереднього доказу. Як і +[перевірювана функція затримки (VDF)](#verifiable-delay-function-vdf), Proof of +History може бути перевірений швидше, ніж його створення. ## Пріоритетна комісія (prioritization fee) -Додаткова комісія, яку користувач може вказати в інструкції бюджету обчислень, щоб пріоритизувати свої [транзакції](#transaction). +Додаткова комісія, яку користувач може вказати в інструкції бюджету обчислень, +щоб пріоритизувати свої [транзакції](#transaction). -Пріоритетна комісія розраховується шляхом множення запитаного максимуму обчислювальних одиниць на ціну обчислювальної одиниці (вказується в інтервалах 0.000001 лампорта за одиницю), округлену до найближчого лампорта. +Пріоритетна комісія розраховується шляхом множення запитаного максимуму +обчислювальних одиниць на ціну обчислювальної одиниці (вказується в інтервалах +0.000001 лампорта за одиницю), округлену до найближчого лампорта. -Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць, необхідних для виконання, щоб зменшити комісію. +Транзакції повинні запитувати мінімальну кількість обчислювальних одиниць, +необхідних для виконання, щоб зменшити комісію. ## Публічний ключ (public key, pubkey) @@ -280,49 +358,80 @@ isSkippedInNav: true ## Оренда (rent) -Комісія, яку сплачують [облікові записи](#account) і [програми](#program) за зберігання даних у блокчейні. Якщо на рахунку недостатньо балансу для оплати оренди, він може бути видалений. +Комісія, яку сплачують [облікові записи](#account) і [програми](#program) за +зберігання даних у блокчейні. Якщо на рахунку недостатньо балансу для оплати +оренди, він може бути видалений. -Див. також [звільнення від оренди](#rent-exempt). Докладніше про оренду: [Що таке оренда?](/docs/uk/intro/rent.md). +Див. також [звільнення від оренди](#rent-exempt). Докладніше про оренду: +[Що таке оренда?](/docs/uk/intro/rent.md). ## Звільнення від оренди (rent exempt) -Облікові записи, які підтримують мінімальний баланс лампортів, пропорційний кількості даних, що зберігаються в обліковому записі. Усі нові облікові записи зберігаються на блокчейні постійно, доки обліковий запис не буде закрито. Неможливо створити обліковий запис, який не відповідає порогу звільнення від оренди. +Облікові записи, які підтримують мінімальний баланс лампортів, пропорційний +кількості даних, що зберігаються в обліковому записі. Усі нові облікові записи +зберігаються на блокчейні постійно, доки обліковий запис не буде закрито. +Неможливо створити обліковий запис, який не відповідає порогу звільнення від +оренди. ## Корінь (root) -[Блок](#block) або [слот](#slot), який досяг максимального [блокування](#lockout) у [валідатора](#validator). Корінь є найвищим блоком, який є предком усіх активних форків у валідатора. Усі предкові блоки кореня також транзитивно є коренями. Блоки, які не є предками чи нащадками кореня, виключаються з розгляду для консенсусу і можуть бути відкинуті. +[Блок](#block) або [слот](#slot), який досяг максимального +[блокування](#lockout) у [валідатора](#validator). Корінь є найвищим блоком, +який є предком усіх активних форків у валідатора. Усі предкові блоки кореня +також транзитивно є коренями. Блоки, які не є предками чи нащадками кореня, +виключаються з розгляду для консенсусу і можуть бути відкинуті. ## Середовище виконання (runtime) -Компонент [валідатора](#validator), відповідальний за виконання [програм](#program). +Компонент [валідатора](#validator), відповідальний за виконання +[програм](#program). ## Sealevel -Паралельне середовище виконання Solana для [програм на блокчейні](#onchain-program). +Паралельне середовище виконання Solana для +[програм на блокчейні](#onchain-program). ## Шред (shred) -Фрагмент [блоку](#block); найменша одиниця, яка передається між [валідаторами](#validator). +Фрагмент [блоку](#block); найменша одиниця, яка передається між +[валідаторами](#validator). ## Підпис (signature) -64-байтний підпис ed25519, що складається з R (32 байти) і S (32 байти). Цей підпис забезпечує відсутність можливості модифікації (мальованості). Кожна транзакція повинна мати щонайменше один підпис для [облікового запису комісій](#fee-account). Таким чином, перший підпис у транзакції може використовуватися як [ідентифікатор транзакції](#transaction-id). +64-байтний підпис ed25519, що складається з R (32 байти) і S (32 байти). Цей +підпис забезпечує відсутність можливості модифікації (мальованості). Кожна +транзакція повинна мати щонайменше один підпис для +[облікового запису комісій](#fee-account). Таким чином, перший підпис у +транзакції може використовуватися як +[ідентифікатор транзакції](#transaction-id). ## Рівень пропуску (skip rate) -Відсоток [пропущених слотів](#skipped-slot) від загальної кількості слотів лідера в поточній епосі. Ця метрика може бути оманливою через високу варіативність після межі епохи, коли вибірка невелика, а також для валідаторів із малою кількістю слотів лідера. Однак вона може бути корисною для виявлення неправильних конфігурацій вузлів. +Відсоток [пропущених слотів](#skipped-slot) від загальної кількості слотів +лідера в поточній епосі. Ця метрика може бути оманливою через високу +варіативність після межі епохи, коли вибірка невелика, а також для валідаторів +із малою кількістю слотів лідера. Однак вона може бути корисною для виявлення +неправильних конфігурацій вузлів. ## Пропущений слот (skipped slot) -Минулий [слот](#slot), у якому не було створено [блоку](#block), тому що лідер був офлайн або [форк](#fork), що містить цей слот, був залишений на користь кращого варіанту за консенсусом кластера. Пропущений слот не з’явиться як предок для блоків у наступних слотах, не збільшить [висоту блоку](#block-height) і не призведе до прострочення найстарішого `recent_blockhash`. +Минулий [слот](#slot), у якому не було створено [блоку](#block), тому що лідер +був офлайн або [форк](#fork), що містить цей слот, був залишений на користь +кращого варіанту за консенсусом кластера. Пропущений слот не з’явиться як предок +для блоків у наступних слотах, не збільшить [висоту блоку](#block-height) і не +призведе до прострочення найстарішого `recent_blockhash`. -Чи було пропущено слот, можна визначити лише тоді, коли він стає старішим за останній [корінний](#root) (а отже, не пропущений) слот. +Чи було пропущено слот, можна визначити лише тоді, коли він стає старішим за +останній [корінний](#root) (а отже, не пропущений) слот. ## Слот (slot) -Проміжок часу, протягом якого кожен [лідер](#leader) приймає транзакції та створює [блок](#block). +Проміжок часу, протягом якого кожен [лідер](#leader) приймає транзакції та +створює [блок](#block). -Колективно слоти створюють логічний годинник. Слоти упорядковані послідовно та не перекриваються, охоплюючи приблизно однакові інтервали реального часу відповідно до [PoH](#proof-of-history-poh). +Колективно слоти створюють логічний годинник. Слоти упорядковані послідовно та +не перекриваються, охоплюючи приблизно однакові інтервали реального часу +відповідно до [PoH](#proof-of-history-poh). ## Розумний контракт (smart contract) @@ -334,15 +443,18 @@ isSkippedInNav: true ## Бібліотека програм Solana (SPL) -[Бібліотека програм](https://spl.solana.com/) на Solana, таких як spl-token, що сприяють виконанню завдань, як-от створення та використання токенів. +[Бібліотека програм](https://spl.solana.com/) на Solana, таких як spl-token, що +сприяють виконанню завдань, як-от створення та використання токенів. ## Ставка (stake) -Токени, які можуть бути конфісковані [кластером](#cluster), якщо буде доведено зловмисну поведінку [валідатора](#validator). +Токени, які можуть бути конфісковані [кластером](#cluster), якщо буде доведено +зловмисну поведінку [валідатора](#validator). ## Якість обслуговування з урахуванням ставки (stake-weighted quality of service, SWQoS) -SWQoS дозволяє [надавати перевагу транзакціям, які надходять від валідаторів із поставленими токенами](https://solana.com/developers/guides/advanced/stake-weighted-qos). +SWQoS дозволяє +[надавати перевагу транзакціям, які надходять від валідаторів із поставленими токенами](https://solana.com/developers/guides/advanced/stake-weighted-qos). ## Супербільшість (supermajority) @@ -350,11 +462,16 @@ SWQoS дозволяє [надавати перевагу транзакціям ## Системна змінна (sysvar) -Системний [обліковий запис](#account). [Системні змінні (Sysvars)](https://docs.anza.xyz/runtime/sysvars) надають інформацію про стан кластера, наприклад поточну висоту тіку, значення винагород [очок](#point) тощо. Програми можуть отримати доступ до системних змінних через обліковий запис Sysvar (публічний ключ) або запитати через системний виклик. +Системний [обліковий запис](#account). +[Системні змінні (Sysvars)](https://docs.anza.xyz/runtime/sysvars) надають +інформацію про стан кластера, наприклад поточну висоту тіку, значення винагород +[очок](#point) тощо. Програми можуть отримати доступ до системних змінних через +обліковий запис Sysvar (публічний ключ) або запитати через системний виклик. ## Тонкий клієнт (thin client) -Тип [клієнта](#client), який довіряє, що він підключений до дійсного [кластеру](#cluster). +Тип [клієнта](#client), який довіряє, що він підключений до дійсного +[кластеру](#cluster). ## Тік (tick) @@ -370,15 +487,21 @@ N-тий [тік](#tick) у [реєстрі](#ledger). ## Програма розширення токенів (Token Extensions Program) -[Програма розширення токенів](https://spl.solana.com/token-2022) має ідентифікатор `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` і включає всі ті самі функції, що й [Програма токенів](#token-program), але додає розширення, як-от конфіденційні перекази, кастомна логіка переказу, розширені метадані тощо. +[Програма розширення токенів](https://spl.solana.com/token-2022) має +ідентифікатор `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` і включає всі ті +самі функції, що й [Програма токенів](#token-program), але додає розширення, +як-от конфіденційні перекази, кастомна логіка переказу, розширені метадані тощо. ## Карбування токенів (token mint) -Обліковий запис, який може створювати токени. Різні токени відрізняються за унікальними адресами карбування токенів. +Обліковий запис, який може створювати токени. Різні токени відрізняються за +унікальними адресами карбування токенів. ## Програма токенів (Token Program) -[Програма токенів](https://spl.solana.com/token) має ідентифікатор `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` і надає базові можливості передачі, заморожування та карбування токенів. +[Програма токенів](https://spl.solana.com/token) має ідентифікатор +`TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` і надає базові можливості +передачі, заморожування та карбування токенів. ## TPS @@ -390,15 +513,21 @@ N-тий [тік](#tick) у [реєстрі](#ledger). ## Транзакція (transaction) -Одна або кілька [інструкцій](#instruction), підписаних [клієнтом](#client) за допомогою однієї або кількох [пар ключів](#keypair), виконуються атомарно з двома можливими результатами: успіх або невдача. +Одна або кілька [інструкцій](#instruction), підписаних [клієнтом](#client) за +допомогою однієї або кількох [пар ключів](#keypair), виконуються атомарно з +двома можливими результатами: успіх або невдача. ## Ідентифікатор транзакції (transaction id) -Перший [підпис](#signature) у [транзакції](#transaction), який можна використовувати для унікальної ідентифікації транзакції у повному [реєстрі](#ledger). +Перший [підпис](#signature) у [транзакції](#transaction), який можна +використовувати для унікальної ідентифікації транзакції у повному +[реєстрі](#ledger). ## Підтвердження транзакції (transaction confirmations) -Кількість [підтверджених блоків](#confirmed-block) з моменту прийняття транзакції до [реєстру](#ledger). Транзакція завершується, коли її блок стає [коренем](#root). +Кількість [підтверджених блоків](#confirmed-block) з моменту прийняття +транзакції до [реєстру](#ledger). Транзакція завершується, коли її блок стає +[коренем](#root). ## Запис транзакцій (transactions entry) @@ -410,7 +539,8 @@ N-тий [тік](#tick) у [реєстрі](#ledger). ## Валідатор (validator) -Повноцінний учасник мережі Solana, який створює нові [блоки](#block). Валідатор перевіряє транзакції, додані до [реєстру](#ledger). +Повноцінний учасник мережі Solana, який створює нові [блоки](#block). Валідатор +перевіряє транзакції, додані до [реєстру](#ledger). ## VDF @@ -418,7 +548,9 @@ N-тий [тік](#tick) у [реєстрі](#ledger). ## Перевірювана функція затримки (VDF) -Функція, яка займає фіксований проміжок часу для виконання та генерує доказ, що вона виконалася. Цей доказ можна перевірити швидше, ніж час, необхідний для його створення. +Функція, яка займає фіксований проміжок часу для виконання та генерує доказ, що +вона виконалася. Цей доказ можна перевірити швидше, ніж час, необхідний для його +створення. ## Голос (vote) @@ -426,13 +558,18 @@ N-тий [тік](#tick) у [реєстрі](#ledger). ## Кредит голосування (vote credit) -Нарахування винагороди для [валідаторів](#validator). Кредит голосування присуджується валідатору на його рахунок голосування, коли він досягає [кореня](#root). +Нарахування винагороди для [валідаторів](#validator). Кредит голосування +присуджується валідатору на його рахунок голосування, коли він досягає +[кореня](#root). ## Гаманець (wallet) -Набір [пар ключів](#keypair), який дозволяє користувачам керувати своїми коштами. +Набір [пар ключів](#keypair), який дозволяє користувачам керувати своїми +коштами. ## Період прогріву (warmup period) -Декілька [епох](#epoch) після делегування [ставки](#stake), протягом яких вона поступово стає активною. Під час цього періоду ставка вважається "активованою". Докладніше: +Декілька [епох](#epoch) після делегування [ставки](#stake), протягом яких вона +поступово стає активною. Під час цього періоду ставка вважається "активованою". +Докладніше: [періоди прогріву та охолодження](https://docs.anza.xyz/consensus/stake-delegation-and-rewards#stake-warmup-cooldown-withdrawal). From d72f897ce87529589505883cb80ae77cf837b7fe Mon Sep 17 00:00:00 2001 From: "DESKTOP-AI3KLJL\\Alex Colba" Date: Wed, 15 Jan 2025 21:34:56 +0200 Subject: [PATCH 14/14] prettier fix client-typescript --- docs/locales/uk/programs/anchor/client-typescript.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/locales/uk/programs/anchor/client-typescript.md b/docs/locales/uk/programs/anchor/client-typescript.md index d53d54e12..a2ff868f0 100644 --- a/docs/locales/uk/programs/anchor/client-typescript.md +++ b/docs/locales/uk/programs/anchor/client-typescript.md @@ -22,15 +22,14 @@ TypeScript. [`AnchorProvider`](https://github.com/coral-xyz/anchor/blob/v0.30.1/ts/packages/anchor/src/provider.ts#L55). `AnchorProvider` - це абстракція, яка поєднує дві речі: -- `Підключення ' - з'єднання з [кластером Solana] (/docs/core/clusters.md) - (тобто localhost, devnet, mainnet) +- `Підключення ' - з'єднання з [кластером Solana] (/docs/core/clusters.md) (тобто + localhost, devnet, mainnet) - `Wallet` - (необов’язково) Гаманець за замовчуванням, який використовується для оплати та підписання транзакцій -При інтеграції з фронтендом за допомогою [Адаптер гаманця] -(https://solana.com/developers/guides/wallets/add-solana-wallet-adapter-to-nextjs), +При інтеграції з фронтендом за допомогою [Адаптер гаманця] (https://solana.com/developers/guides/wallets/add-solana-wallet-adapter-to-nextjs), Вам потрібно буде налаштувати `AnchorProvider` та `Program`. ```ts {9-10, 12-14}