diff --git a/docs/.vuepress/config.ts b/docs/.vuepress/config.ts index 3a9ebdc0b..c4c2e9491 100644 --- a/docs/.vuepress/config.ts +++ b/docs/.vuepress/config.ts @@ -502,6 +502,79 @@ export default defineUserConfig({ ], }, }, + "/de/": { + selectLanguageName: "Deutsch", + navbar: [ + { + text: "Beitragen", + link: "https://github.com/solana-developers/solana-cookbook", + }, + { + text: "Integrationen", + link: "/de/integrations", + }, + ], + sidebar: { + "/": [ + { + text: "Installation", + children: ["/de/", "/de/getting-started/installation.md"], + }, + { + text: "Kernkonzepte", + children: [ + "/de/core-concepts/accounts.md", + "/de/core-concepts/programs.md", + "/de/core-concepts/transactions.md", + "/de/core-concepts/pdas.md", + ], + }, + { + text: "Leitfäden", + children: [ + "/de/guides/get-program-accounts.md", + "/de/guides/serialization.md", + "/de/guides/data-migration.md", + "/de/guides/account-maps.md", + "/de/guides/retrying-transactions.md", + "/de/guides/debugging-solana-programs.md", + "/de/guides/feature-parity-testing.md", + ], + }, + { + text: "Referenzen", + children: [ + "/de/references/local-development.md", + "/de/references/keypairs-and-wallets.md", + "/de/references/basic-transactions.md", + "/de/references/accounts.md", + "/de/references/programs.md", + "/de/references/token.md", + "/de/references/staking.md", + "/de/references/nfts.md", + "/de/references/offline-transactions.md", + "/de/references/name-service.md", + ], + }, + ], + "/id/integrations": [ + { + text: "Integrationen", + children: [ + "/de/integrations", + "/de/integrations/serum.md", + "/de/integrations/pyth.md", + "/de/integrations/switchboard.md", + "/de/integrations/mango.md", + "/de/integrations/strata.md", + "/de/integrations/web3auth.md", + "/de/integrations/react-native.md", + "/de/integrations/jupiter.md", + ], + }, + ], + }, + }, }, }, locales: { @@ -535,6 +608,10 @@ export default defineUserConfig({ lang: "id-ID", title: "Buku Panduan Solana", }, + "/de/": { + lang: "de-DE", + title: "Solana Kochbuch", + }, }, markdown: { importCode: { @@ -571,6 +648,9 @@ export default defineUserConfig({ "/id/": { placeholder: "Cari", }, + "/de/": { + placeholder: "Suchen", + }, }, maxSuggestions: 10, }, @@ -639,6 +719,14 @@ export default defineUserConfig({ }, }, }, + "/de/": { + placeholder: "Suchen", + translations: { + button: { + buttonText: "Suchen", + }, + }, + }, }, }, ], diff --git a/docs/de/README.md b/docs/de/README.md new file mode 100644 index 000000000..662769ea6 --- /dev/null +++ b/docs/de/README.md @@ -0,0 +1,67 @@ +--- +title: Kochen mit Solana +head: + - - meta + - name: title + content: Solana Kochbuch| Solana-Referenzen + - - meta + - name: og:title + content: Solana Kochbuch| Solana-Referenzen + - - meta + - name: description + content: Das Solana Kochbuch ist eine Ansammlung an nützlichen Beispielen und Referenzen für die Softwareentwicklung mit Solana + - - meta + - name: og:description + content: Das Solana Kochbuch ist eine Ansammlung an nützlichen Beispielen und Referenzen für die Softwareentwicklung mit Solana + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +footer: MIT Licensed +--- + +# Kochen mit Solana + +Das *Solana Kochbuch* ist eine Ressource für +Entickler und beschreibt die wesentlichen Konzepte +und Referenzen für das Entwickeln von Anwendungen +auf Solana. Jedes Konzept und Beispiel konzentriert sich +auf bestimmte Aspekte von Solana, während zusätzliche +Details und Verwendungsbeispiele bereitgestellt werden. + +## Beitragen + +Das Kochbuch ist so strukturiert, dass es von +neuen Solanaentwicklern einfach mitgestalted +werden kann. Auch wenn man noch nicht weiß wie +etwas in Solana funktioniert, dem Kochbuch beizutragen +ist ein großartiger Weg neues zu lernen. + +Offenen Issues findest du [hier](https://github.com/solana-developers/solana-cookbook/issues). Die Richtlinien zum Beitragen findest du [hier](https://github.com/solana-developers/solana-cookbook#contributing). Wenn du denkst, dass im Kochbuch etwas fehlt, dann füge bitte eine neue Issue hinzu. + +## Wie du das Kochbuch lesen solltest + +Das Solana Kochbuch ist in verschiedene Abschnitte eingeteilt. Jeder dieser Abschnitte verfolgt ein eigenes Lernziel. + +| Abschnitt | Beschreibung | +|---------------|-----------------------------------------------------------------------------| +| Kernkonzepte | Die Bausteine von Solana die du kennen solltest | +| Leitfäden | Leitfäden in Snackgröße zu verschiedenen Tools für die Entwicklung mit Solana | +| Referenzen | Referenzen für gängige Code Snippets | \ No newline at end of file diff --git a/docs/de/core-concepts/account-matrix.png b/docs/de/core-concepts/account-matrix.png new file mode 100644 index 000000000..b5dc9bab2 Binary files /dev/null and b/docs/de/core-concepts/account-matrix.png differ diff --git a/docs/de/core-concepts/account_example.jpeg b/docs/de/core-concepts/account_example.jpeg new file mode 100644 index 000000000..a9cea6f23 Binary files /dev/null and b/docs/de/core-concepts/account_example.jpeg differ diff --git a/docs/de/core-concepts/accounts.md b/docs/de/core-concepts/accounts.md new file mode 100644 index 000000000..f180423d0 --- /dev/null +++ b/docs/de/core-concepts/accounts.md @@ -0,0 +1,130 @@ +--- +title: Accounts +head: + - - meta + - name: title + content: Solana Cookbook | Accounts + - - meta + - name: og:title + content: Solana Cookbook | Accounts + - - meta + - name: description + content: Accounts are an essential building block for developing on Solana. Learn about Accounts and more Core Concepts at The Solana cookbook. + - - meta + - name: og:description + content: Accounts are an essential building block for developing on Solana. Learn about Accounts and more Core Concepts at The Solana cookbook. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +footer: MIT Licensed +--- + +# Accounts + +Accounts within Solana are used to store state. They are an essential +building block for developing on Solana. + +## Facts + +::: tip Fact Sheet + +- Accounts are used to store data +- Each account has a unique address +- Accounts have a max size of 10MB (10 Mega Bytes) +- PDA accounts have a max size of 10KB (10 Kilo Bytes) +- PDA accounts can be used to sign on behalf of a program +- Accounts size are fixed at creation time, but can be adjusted using [realloc](https://solanacookbook.com/references/programs.html#how-to-change-account-size) +- Account data storage is paid with rent +- Default account owner is the System Program + ::: + +## Deep Dive + +### Account Model + +There are 3 kinds of accounts on Solana: + +- Data accounts store data +- Program accounts store executable programs +- Native accounts that indicate native programs on Solana such as System, Stake, and Vote + +Within data accounts, there are 2 types: + +- System owned accounts +- PDA (Program Derived Address) accounts + +Each account has an address (usually a public key) and an owner +(address of a program account). The full field list an account stores +is found below. + +| Field | Description | +| ---------- | ---------------------------------------------- | +| lamports | The number of lamports owned by this account | +| owner | The program owner of this account | +| executable | Whether this account can process instructions | +| data | The raw data byte array stored by this account | +| rent_epoch | The next epoch that this account will owe rent | + +There are a few important ownership rules: + +- Only a data account's owner can modify its data and debit lamports +- Anyone is allowed to credit lamports to a data account +- The owner of an account may assign a new owner if the account's data is zeroed out + +Program accounts do not store state. + +For example, if you have a counter program that lets you increment a counter, you +must create two accounts, one account to store the program's code, and one to store +the counter. + +![](./account_example.jpeg) + +To prevent an account from being deleted, you must pay rent. + +### Rent + +Storing data on accounts costs SOL to maintain, and it is funded by what is called +rent. If you maintain a minimum balance equivalent to 2 years of rent payments in an +account, your account will be exempt from paying rent. You can retrieve rent by closing +the account and sending the lamports back to your wallet. + +Rent is paid during two different timings: + +1. When referenced by a transaction +2. Once an epoch + +A percentage of rent collected by accounts is destroyed, while the rest is distributed +to vote accounts at the end of every slot. + +If the account does not have enough to pay rent, the account will be deallocated and the data +removed. + +It is also important to note that new accounts must be rent exempt. + +## Other Resources + +- [Solana Account Model](https://solana.wiki/zh-cn/docs/account-model/#account-storage) +- [Official Documentation](https://docs.solana.com/developing/programming-model/accounts) +- [pencilflip account thread](https://twitter.com/pencilflip/status/1452402100470644739) + +### Credit + +This core concept is credited to Pencilflip. [Follow him on Twitter](https://twitter.com/intent/user?screen_name=pencilflip). diff --git a/docs/de/core-concepts/pda-curve.png b/docs/de/core-concepts/pda-curve.png new file mode 100644 index 000000000..e1d32ef37 Binary files /dev/null and b/docs/de/core-concepts/pda-curve.png differ diff --git a/docs/de/core-concepts/pdas.md b/docs/de/core-concepts/pdas.md new file mode 100644 index 000000000..4d69db9af --- /dev/null +++ b/docs/de/core-concepts/pdas.md @@ -0,0 +1,79 @@ +--- +title: Program Derived Addresses (PDAs) +head: + - - meta + - name: title + content: Solana Cookbook | PDAs + - - meta + - name: og:title + content: Solana Cookbook | PDAs + - - meta + - name: description + content: PDAs are home to accounts that are designed to be controlled by a specific program. Learn about PDAs and more Core Concepts at The Solana cookbook. + - - meta + - name: og:description + content: PDAs are home to accounts that are designed to be controlled by a specific program. Learn about PDAs and more Core Concepts at The Solana cookbook. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +footer: MIT Licensed +--- + +# Program Derived Addresses (PDAs) + +Program Derived Addresses (PDAs) are home to accounts that are designed to be controlled by a specific program. With PDAs, programs can programmatically sign for certain addresses without needing a private key. PDAs serve as the foundation for [Cross-Program Invocation](https://docs.solana.com/developing/programming-model/calling-between-programs#cross-program-invocations), which allows Solana apps to be composable with one another. + +## Facts + +::: tip Fact Sheet +- PDAs are 32 byte strings that look like public keys, but don’t have corresponding private keys +- `findProgramAddress` will deterministically derive a PDA from a programId and seeds (collection of bytes) +- A bump (one byte) is used to push a potential PDA off the ed25519 elliptic curve +- Programs can sign for their PDAs by providing the seeds and bump to [invoke_signed](https://docs.solana.com/developing/programming-model/calling-between-programs#program-signed-accounts) +- A PDA can only be signed by the program from which it was derived +- In addition to allowing for programs to sign for different instructions, PDAs also provide a hashmap-like interface for [indexing accounts](../guides/account-maps.md) +::: + +## Deep Dive + +PDAs are an essential building block for developing programs on Solana. With PDAs, programs can sign for accounts while guaranteeing that no external user could also generate a valid signature for the same account. In addition to signing for accounts, certain programs can also modify accounts held at their PDAs. + +![Accounts matrix](./account-matrix.png) + +Image courtesy of Pencilflip + +### Generating PDAs + +To understand the concept behind PDAs, it may be helpful to consider that PDAs are not technically created, but rather found. PDAs are generated from a combination of seeds (such as the string `“vote_account”`) and a program id. This combination of seeds and program id is then run through a sha256 hash function to see whether or not they generate a public key that lies on the ed25519 elliptic curve. + +In running our program id and seeds through a hash function, there is a ~50% chance that we actually end up with a valid public key that does lie on the elliptic curve. In this case, we simply add something to fudge our input a little bit and try again. The technical term for this fudge factor is a bump. In Solana, we start with bump = 255 and simply iterate down through bump = 254, bump = 253, etc. until we get an address that is not on the elliptic curve. This may seem rudimentary, but once found it gives us a deterministic way of deriving the same PDA over and over again. + +![PDA on the ellipitic curve](./pda-curve.png) + +### Interacting with PDAs + +When a PDA is generated, `findProgramAddress` will return both the address and the bump used to kick the address off of the elliptic curve. Armed with this bump, a program can then [sign](../references/accounts.md#sign-with-a-pda) for any instruction that requires its PDA. In order to sign, programs should pass the instruction, the list of accounts, and the seeds and bump used to derive the PDA to `invoke_signed`. In addition to signing for instructions, PDAs must also sign for their own creation via `invoke_signed`. + +When building with PDAs, it is common to [store the bump seed](https://github.com/solana-labs/solana-program-library/blob/78e29e9238e555967b9125799d7d420d7d12b959/token-swap/program/src/state.rs#L100) in the account data itself. This allows developers to easily validate a PDA without having to pass in the bump as an instruction argument. + +## Other Resources +- [Official Documentation](https://docs.solana.com/developing/programming-model/calling-between-programs#program-derived-addresses) +- [Understanding Program Derived Addresses](https://www.brianfriel.xyz/understanding-program-derived-addresses/) diff --git a/docs/de/core-concepts/programs.md b/docs/de/core-concepts/programs.md new file mode 100644 index 000000000..9a10cc64a --- /dev/null +++ b/docs/de/core-concepts/programs.md @@ -0,0 +1,123 @@ +--- +title: Programs +head: + - - meta + - name: title + content: Solana Cookbook | Programs + - - meta + - name: og:title + content: Solana Cookbook | Programs + - - meta + - name: description + content: Programs (also known as smart contracts) serve as the foundation for on-chain activity. Learn about Programs and more Core Concepts at The Solana cookbook. + - - meta + - name: og:description + content: Programs (also known as smart contracts) serve as the foundation for on-chain activity. Learn about Programs and more Core Concepts at The Solana cookbook. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +footer: MIT Licensed +--- + +# Programs + +Any developer can write and deploy programs to the Solana blockchain. Programs (known as smart contracts on other protocols) serve as the foundation for on-chain activity, powering anything from DeFi and NFTs to Social Media and Gaming. + +## Facts + +::: tip Fact Sheet +- Programs process [instructions](./transactions) from both end users and other programs +- All programs are *stateless*: any data they interact with is stored in separate [accounts](./accounts.md) that are passed in via instructions +- Programs themselves are stored in accounts marked as `executable` +- All programs are owned by the [BPF Loader](https://docs.solana.com/developing/runtime-facilities/programs#bpf-loader) and executed by the [Solana Runtime](https://docs.solana.com/developing/programming-model/runtime) +- Developers most commonly write programs in Rust or C++, but can choose any language that targets the [LLVM](https://llvm.org/)'s [BPF](https://en.wikipedia.org/wiki/Berkeley_Packet_Filter) backend +- All programs have a single entry point where instruction processing takes place (i.e. `process_instruction`); parameters always include: + - `program_id`: `pubkey` + - `accounts`: `array`, + - `instruction_data`: `byte array` +::: + +## Deep Dive + +Unlike most other blockchains, Solana completely separates code from data. All data that programs interact with are stored in separate accounts and passed in as references via instructions. This model allows for a single generic program to operate across various accounts without requiring additional deployments. Common examples of this pattern are seen across the Native and SPL Programs. + +### Native Programs & The Solana Program Library (SPL) + +Solana comes equipped with a number of programs that serve as core building blocks for on-chain interactions. These programs are divided into [Native Programs](https://docs.solana.com/developing/runtime-facilities/programs#bpf-loader) and [Solana Program Library (SPL) Programs](https://spl.solana.com/). + +Native Programs provide the base functionality that is required to operate validators. Among these programs, the most well known is the [System Program](https://docs.solana.com/developing/runtime-facilities/programs#system-program) which is responsible for administering new accounts and transferring SOL between two parties. + +SPL Programs support a number of on-chain activities, including creating, swapping, and lending tokens, as well as generating stake pools and maintaining an on-chain name service. The [SPL Token Program](https://spl.solana.com/token) can be invoked directly via the CLI, while others like the [Associated Token Account Program](https://spl.solana.com/associated-token-account) are usually composed with custom programs. + +### Writing Programs + +Programs are most commonly developed with Rust or C++, but can be developed with any language that targets the LLVM’s BPF backend. Recent initiatives by [Neon Labs](https://neon-labs.org/) and [Solang](https://solang.readthedocs.io/en/latest/) enable [EVM](https://ethereum.org/en/developers/docs/evm/) compatibility and allow developers to write programs in Solidity. + +Most Rust-based programs adhere to the following architecture: + +| File | Description | +|----------------|-----------------------------------------------| +| lib.rs | Registering modules | +| entrypoint.rs | Entrypoint to the program | +| instruction.rs | Program API, (de)serializing instruction data | +| processor.rs | Program logic | +| state.rs | Program objects, (de)serializing state | +| error.rs | Program-specific errors | + +Recently, [Anchor](https://github.com/coral-xyz/anchor) has emerged as a popular framework for developing programs. Anchor is an opinionated framework, akin to Ruby on Rails, that reduces boilerplate and streamlines the (de)serialization process for Rust-based development. + +Programs are usually developed and tested against Localhost and Devnet environments before being deployed to Testnet or Mainnet. Solana supports the following environments: + +| Cluster Environment | RPC Connection URL | +|----------------------|---------------------------------------------------------------------------| +| Mainnet-beta | https://api.mainnet-beta.solana.com | +| Testnet | https://api.testnet.solana.com | +| Devnet | https://api.devnet.solana.com | +| Localhost | Default port: 8899 (e.g. http://localhost:8899, http://192.168.1.88:8899) | + +Once deployed to an environment, clients can interact with on-chain programs via [RPC connections](https://docs.solana.com/developing/clients/jsonrpc-api) to the respective cluster. + +### Deploying Programs + +Developers can deploy their programs via the [CLI](https://docs.solana.com/cli/deploy-a-program): + +```bash +solana program deploy +``` + +When a program is deployed, it is compiled to an [ELF shared object](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) (containing BPF bytecode) and uploaded to the Solana cluster. Programs live in accounts (much like everything else on Solana), except these accounts are marked as `executable` and assigned to the BPF Loader. The address of this account is referred to as the `program_id` and is used to reference the program in all future transactions. + +Solana supports multiple BPF Loaders, with the latest being the [Upgradable BPF Loader](https://explorer.solana.com/address/BPFLoaderUpgradeab1e11111111111111111111111). The BPF Loader is responsible for administering the program’s account and making it available to clients via the `program_id`. All programs have a single entry point where instruction processing takes place (i.e. `process_instruction`) and parameters always include: +- `program_id`: `pubkey` +- `accounts`: `array`, +- `instruction_data`: `byte array` + +Once invoked, programs are executed by the Solana Runtime. + +## Other Resources + +- [Official Documentation](https://docs.solana.com/developing/on-chain-programs/overview) +- [SPL Documentation](https://spl.solana.com/) +- [Program Deploys by Justin Starry](https://jstarry.notion.site/Program-deploys-29780c48794c47308d5f138074dd9838) +- [Solana Starter Kit by Iron Addicted Dog](https://book.solmeet.dev/notes/solana-starter-kit) +- [Programming on Solana by Paulx](https://paulx.dev/blog/2021/01/14/programming-on-solana-an-introduction/) +- [An Introduction to the Solana Blockchain by Hana](https://2501babe.github.io/posts/solana101.html) +- [Anchor](https://github.com/coral-xyz/anchor) diff --git a/docs/de/core-concepts/transactions.md b/docs/de/core-concepts/transactions.md new file mode 100644 index 000000000..d6af1505e --- /dev/null +++ b/docs/de/core-concepts/transactions.md @@ -0,0 +1,92 @@ +--- +title: Transactions +head: + - - meta + - name: title + content: Solana Cookbook | Transactions + - - meta + - name: og:title + content: Solana Cookbook | Transactions + - - meta + - name: description + content: Transaction are bundles of Multiple operational units on Solana. Learn more about Transaction and Core Concepts at The Solana cookbook. + - - meta + - name: og:description + content: Multiple operational units on Solana can be bundled into a single unit called Transaction. Learn more about Core Concepts at The Solana cookbook. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +footer: MIT Licensed +--- + +# Transactions + +Clients can invoke [programs](./programs.md) by submitting a transaction to a cluster. A single transaction can include multiple instructions, each targeting its own program. When a transaction is submitted, the Solana [Runtime](https://docs.solana.com/developing/programming-model/runtime) will process its instructions in order and atomically. If any part of an instruction fails, the entire transaction will fail. + +## Facts + +::: tip Fact Sheet +- Instructions are the most basic operational unit on Solana +- Each instruction contains: + - The `program_id` of the intended program + - An array of all `accounts` it intends to read from or write to + - An `instruction_data` byte array that is specific to the intended program +- Multiple instructions can be bundled into a single transaction +- Each transaction contains: + - An array of all `accounts` it intends to read from or write to + - One or more `instructions` + - A recent `blockhash` + - One or more `signatures` +- Instructions are processed in order and atomically +- If any part of an instruction fails, the entire transaction fails. +- Transactions are limited to 1232 bytes +::: + +## Deep Dive + +The Solana Runtime requires both instructions and transactions to specify a list of all accounts they intended to read from or write to. By requiring these accounts in advance, the runtime is able to parallelize execution across all transactions. + +When a transaction is submitted to a cluster, the runtime will process its instructions in order and atomically. For each instruction, the receiving program will interpret its data array and operate on its specified accounts. The program will either return successfully or with an error code. If an error is returned, the entire transaction will fail immediately. + +Any transaction that aims to debit an account or modify its data requires the signature of its account holder. Any account that will be modified is marked as `writable`. An account can be credited without the holder’s permission so long as the transaction fee payer covers the necessary rent and transaction fees. + +Before submission, all transactions must reference a [recent blockhash](https://docs.solana.com/developing/programming-model/transactions#recent-blockhash). The blockhash is used to prevent duplications and eliminate stale transactions. The max age of a transaction's blockhash is 150 blocks, or about ~1 minute 19 seconds as of the time of this writing. + +### Fees + +The Solana network collects two types of fees: +- [Transaction fees](https://docs.solana.com/transaction_fees) for propagating transactions (aka “gas fees”) +- [Rent fees](https://docs.solana.com/developing/programming-model/accounts#rent) for storing data on-chain + +In Solana, transaction fees are deterministic: there is no concept of a fee market in which users can pay higher fees to increase their chances of being included in the next block. At the time of this writing, transaction fees are determined only by the number of signatures required (i.e. `lamports_per_signature`), not by the amount of resources used. This is because there is currently a hard cap of 1232 bytes on all transactions. + +All transactions require at least one `writable` account to sign the transaction. Once submitted, the writable signer account that is serialized first will be the fee payer. This account will pay for the cost of the transaction regardless of whether the transaction succeeds or fails. If the fee payer does not have a sufficient balance to pay the transaction fee, the transaction will be dropped. + +At the time of this writing, 50% of all transaction fees are collected by the validator that produces the block, while the remaining 50% are burned. This structure works to incentivize validators to process as many transactions as possible during their slots in the leader schedule. + +## Other Resources + +- [Official Documentation](https://docs.solana.com/developing/programming-model/transactions) +- [Transaction Structure](https://solana.wiki/docs/solidity-guide/transactions/#solana-transaction-structure) +- [Transaction Fees by Justin Starry](https://jstarry.notion.site/Transaction-Fees-f09387e6a8d84287aa16a34ecb58e239) +- [An Introduction to Solana by Hana](https://2501babe.github.io/posts/solana101.html) +- [Transaction Processing by Jito Labs](https://jito-labs.medium.com/solana-validator-101-transaction-processing-90bcdc271143) +- [Solana Transaction in Depth by Alex Miller](https://medium.com/@asmiller1989/solana-transactions-in-depth-1f7f7fe06ac2) diff --git a/docs/de/getting-started/installation.md b/docs/de/getting-started/installation.md new file mode 100644 index 000000000..75cfdcf9c --- /dev/null +++ b/docs/de/getting-started/installation.md @@ -0,0 +1,330 @@ +--- +title: Installation +head: + - - meta + - name: title + content: Solana Cookbook | Installation + - - meta + - name: og:title + content: Solana Cookbook | Installation + - - meta + - name: description + content: Learn how to get started on Solana with tutorials, guides, and examples. + - - meta + - name: og:description + content: Learn how to get started on Solana with tutorials, guides, and examples. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +footer: MIT Licensed +--- + +## Install Web3.js + +There are a few libraries that you can use to get started with javascript or typescript on Solana.
+ +### Web3.js + +[`@solana/web3.js`](https://solana-labs.github.io/solana-web3.js/) is a library that has a lot of the basic Solana tools to interact, send transactions, and read from the blockchain. + +You can install with the following: + + + + +```bash +yarn add @solana/web3.js +``` + + + + + +```bash +npm install --save @solana/web3.js +``` + + + + + +```html + + + + + +``` + + + + +--- + +### SPL-Token + +`@solana/spl-token` is a library that contains many of the javascript/typescript bindings needed to interact with SPL tokens. +You can use this library to mint new SPL tokens, transfer tokens, and more. + +You can install this library with the following: + + + + +```bash +yarn add @solana/spl-token +``` + + + + + +```bash +npm install --save @solana/spl-token +``` + + + + + +```html + + + + + +``` + + + + +--- + +### Wallet-Adapter + +There is a collection of libraries that can help bootstrap wallet connections within Solana called wallet-adapter. +Currently the package supports use within Svelte, Angular, Vue.js, and React. Wallet-adapter can quickstart your dApp +integration with wallets like [Phantom](https://phantom.app/), [Solflare](https://solflare.com/), and more. + +You can install this library with the following: + + + + +```bash +yarn add @solana/wallet-adapter-wallets \ + @solana/wallet-adapter-base +``` + + + + + +```bash +npm install --save @solana/wallet-adapter-wallets \ + @solana/wallet-adapter-base +``` + + + + +## Install Rust + + + + +```bash +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + + + + +```bash +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + + + + +For Windows, please visit the [Rust installation site](https://www.rust-lang.org/tools/install). + +## Install CLI + +### macOS & Linux + +Open your favorite Terminal application. + +Replace `LATEST_RELEASE` with your desired version and install the [latest Solana release](https://github.com/solana-labs/solana/releases) on your machine by running: + +```bash +sh -c "$(curl -sSfL https://release.solana.com/LATEST_RELEASE/install)" +``` + +You can replace `LATEST_RELEASE` with the release tag matching +the software version of your desired release, or use one of the three symbolic +channel names: `stable`, `beta`, or `edge`. To find the latest release, check +versions available [here](https://github.com/solana-labs/solana/releases). + +The following output indicates a successful update: + +```text +downloading LATEST_RELEASE installer +Configuration: /home/solana/.config/solana/install/config.yml +Active release directory: /home/solana/.local/share/solana/install/active_release +* Release version: LATEST_RELEASE +* Release URL: https://github.com/solana-labs/solana/releases/download/LATEST_RELEASE/solana-release-x86_64-unknown-linux-gnu.tar.bz2 +Update successful +``` + +Depending on your system, the end of the installer messaging may prompt you +to + +```bash +Please update your PATH environment variable to include the solana programs: +``` + +If you get the above message, copy and paste the recommended command below +it to update `PATH`. + +Confirm you have the desired version of `solana` installed by running: + +```bash +solana --version +``` + +After a successful install, `solana-install update` may be used to easily +update the Solana software to a newer version at any time. + +#### Downloading Binaries (Linux) + +Alternatively, you can install from binaries instead of using solana-install. + +Download the binaries by navigating to +[https://github.com/solana-labs/solana/releases/latest](https://github.com/solana-labs/solana/releases/latest), +download **solana-release-x86_64-unknown-linux-msvc.tar.bz2**, then extract the +archive: + +```bash +tar jxf solana-release-x86_64-unknown-linux-gnu.tar.bz2 +cd solana-release/ +export PATH=$PWD/bin:$PATH +``` + +#### Downloading Binaries (macOS) + +Alternatively, you can install from binaries instead of using solana-install. + +Download the binaries by navigating to +[https://github.com/solana-labs/solana/releases/latest](https://github.com/solana-labs/solana/releases/latest), +download **solana-release-x86_64-apple-darwin.tar.bz2**, then extract the +archive: + +```bash +tar jxf solana-release-x86_64-apple-darwin.tar.bz2 +cd solana-release/ +export PATH=$PWD/bin:$PATH +``` + +--- + +### Windows + +Open a Command Prompt (`cmd.exe`) as an Administrator. + +Search for Command Prompt in the Windows search bar. When the Command +Prompt app appears, right-click and select “Open as Administrator”. +If you are prompted by a pop-up window asking “Do you want to allow this app to +make changes to your device?”, click 'Yes'. + +Copy and paste the following command, then press Enter to download the Solana +installer into a temporary directory: + +```bash +curl https://release.solana.com/v1.9.16/solana-install-init-x86_64-pc-windows-msvc.exe --output C:\solana-install-tmp\solana-install-init.exe --create-dirs +``` + +If `v1.9.16` is not your desired version, find the latest release [here](https://github.com/solana-labs/solana/releases). + +Copy and paste the following command, then press Enter to install the latest +version of Solana. If you see a security pop-up by your system, please select +to allow the program to run. + +```bash +C:\solana-install-tmp\solana-install-init.exe v1.9.16 +``` + +To find the latest release, check +versions available [here](https://github.com/solana-labs/solana/releases). + +When the installer is finished, press Enter. + +Close the command prompt window and re-open a new command prompt window as a +normal user. + +Search for "Command Prompt" in the search bar, then left-click on the +Command Prompt app icon (no need to run as Administrator). + +Confirm you have the desired version of `solana` installed by entering: + +```bash +solana --version +``` + +After a successful install, `solana-install update` may be used to easily +update the Solana software to a newer version at any time. + +#### Downloading Binaries + +Alternatively, you can install from binaries instead of using solana-install. + +Download the binaries by navigating to +[https://github.com/solana-labs/solana/releases/latest](https://github.com/solana-labs/solana/releases/latest), +download **solana-release-x86_64-pc-windows-msvc.tar.bz2**, then extract the +archive using WinZip or similar. + +Open a Command Prompt and navigate to the directory into which you extracted +the binaries and run: + +```bash +cd solana-release/ +set PATH=%cd%/bin;%PATH% +``` + +### Build From Source + +If you are unable to use the prebuilt binaries or prefer to build it yourself +from source, navigate to +[https://github.com/solana-labs/solana/releases/latest](https://github.com/solana-labs/solana/releases/latest), +and download the **Source Code** archive. Extract the code and build the +binaries with: + +```bash +./scripts/cargo-install-all.sh . +export PATH=$PWD/bin:$PATH +``` + +You can then run the following command to obtain the same result as with +prebuilt binaries: + +```bash +solana-install init +``` diff --git a/docs/de/guides/account-maps.md b/docs/de/guides/account-maps.md new file mode 100644 index 000000000..35ae4a649 --- /dev/null +++ b/docs/de/guides/account-maps.md @@ -0,0 +1,147 @@ +--- +title: Account Maps +--- + +# Account Maps + +Maps are data structures we frequently use in programming to associate a **key** with a **value** of some kind. The key and value could be any arbitrary type and the key acts as an identifier for a given value that is being saved. It then, given its key, allows us to efficiently insert, retrieve and update these values efficiently. + +Solana's Account model, as we know, requires program data and its relevant state data to be stored in different accounts. These accounts have an address associated with them. This, in itself, acts as a map! Learn more about Solana's Account mode [here][AccountCookbook]. + +So, it would make sense to store your **values** in separate accounts, with its address being the **key** required to retrieve the value. But this brings up a few issues, such as, + +* The addresses mentioned above are most probably not going to be ideal **keys**, which you could remember and retrieve the required value. + +* The addresses mentioned above, referred to public keys of different **Keypairs**, where each public key (or *address*) would have a **private key** associated with it as well. This private key would be required to sign different instructions if and when needed, requiring us to store the private key somewhere, which is most definitely **not** recommended! + +This presents a problem many Solana developers face, which is implementing a `Map`-like logic into their programs. Let's look at a couple of way how we would go about this problem, + +## Deriving PDAs + +PDA stands for [Program Derived Address][PDA], and are in short, addresses **derived** from a set of seeds, and a program id (or _address_). + +The unique thing about PDAs is that, these addresses are **not** associated with any private key. This is because these addresses do not lie on the ED25519 curve. Hence, **only** the program, from which this _address_ was derived, can sign an instruction with the key, provided the seeds as well. Learn more about this [here][CPI]. + +Now that we have an idea about what PDAs are, let's use them to map some accounts! We'll take an example of a **Blog** program to demonstrate how this would be implemented. + +In this Blog program, we would like each `User` to have a single `Blog`. This blog could have any number of `Posts`. That would mean that we are **mapping** each user to a blog, and each post is **mapped** to a certain blog. + +In short, there is a `1:1` mapping between a user and his/her blog, whereas a `1:N` mapping between a blog and its posts. + +For the `1:1` mapping, we would want a blog's address to be derived **only** from its user, which would allow us to retrieve a blog, given its authority (or _user_). Hence, the seeds for a blog would consist of its **authority's key**, and possibly a prefix of **"blog"**, to act as a type identifier. + +For the `1:N` mapping, we would want each post's address to be derived **not only** from the blog which it is associated with, but also another **identifier**, allowing us to differentiate between the `N` number of posts in the blog. In the example below, each post's address is derived from the **blog's key**, a **slug** to identify each post, and a prefix of **"post"**, to act as a type identifier. + +The code is as shown below, + + + + + + + + + + + + + + + + + + + + +On the client-side, you can use `PublicKey.findProgramAddress()` to obtain the required `Blog` and `Post` account address, which you can pass into `connection.getAccountInfo()` to fetch the account data. An example is shown below, + + + + + + + + + + + + +## Single Map Account + +Another way to implement mapping would be to have a `BTreeMap` data structure explicitly stored in a single account. This account's address itself could be a PDA, or the public key of a generated Keypair. + +This method of mapping accounts is not ideal because of the following reasons, + +* You will have to first initialize the account storing the `BTreeMap`, before you can insert the necessary key-value pairs to it. Then, you will also have to store the address of this account somewhere, so as to update it every time. + +* There are memory limitations to an account, where an account can have a maximum size of **10 megabytes**, which restricts the `BTreeMap` from storing a large number of key-value pairs. + +Hence, after considering your use-case, you can implement this method as shown below, + + + + + + + + + + + +The client-side code to test the above program would look like something as shown below, + + + + + + + + + + + + + +[AccountCookbook]: https://solanacookbook.com/core-concepts/accounts.html +[PDA]: https://solanacookbook.com/references/accounts.html#program-derived-address +[CPI]: https://solanacookbook.com/references/programs.html#create-a-program-derived-address \ No newline at end of file diff --git a/docs/de/guides/data-migration.md b/docs/de/guides/data-migration.md new file mode 100644 index 000000000..37ac6b5d5 --- /dev/null +++ b/docs/de/guides/data-migration.md @@ -0,0 +1,190 @@ +--- +title: Migrating Program Data Accounts +head: + - - meta + - name: title + content: Solana Cookbook | Program Accounts Data Migration + - - meta + - name: og:title + content: Solana Cookbook | Program Accounts Data Migration + - - meta + - name: description + content: Fundamentally to version data in support of migration means to create a unique reference for a collection of data. This reference can take the form of a query, an ID, or also commonly a datetime identifier. Learn about Serialization and more Ingredients for your dish at The Solana cookbook. + - - meta + - name: og:description + content: Fundamentally to version data in support of migration means to create a unique reference for a collection of data. This reference can take the form of a query, an ID, or also commonly a datetime identifier. Learn about Serialization and more Ingredients for your dish at The Solana cookbook. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +footer: MIT Licensed +--- + +# Migrating a Programs Data Accounts + +## How can you migrate a program's data accounts? + +When you create a program, each data account associated with that +program will have a specific data structure. If you ever need +to upgrade a program derived account, you end up having a bunch +of leftover program derived accounts with the old structure. + +With account versioning, you can upgrade your old accounts to +the new structure. + +:::tip Note +This is only one of many ways to migrate data in Program Owned Accounts (POA). +::: + +## Scenario + +To version and migrate our account data, we will be providing an **id** for each +account. This id will allow us to identify the account version when +we pass it to the program, and thus handle the account correctly. + +Take the following account state and program: + +Program Account v1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +In our first version of an account, we are doing the following: + +| ID | Action | +| - | - | +|1| Include a 'data version' field in your data. It can be a simple incrementing ordinal (e.g. u8) or something more sophisticated +|2| Allocating enough space for data growth +|3| Initializing a number of constants to be used across program versions +|4| Add an update account function under `fn conversion_logic` for future upgrades + +Let's say we want to upgrade our program's accounts now to include +a new required field, the `somestring` field. + +If we didn't allocate extra space on the previous account, we could +not upgrade the account and be stuck. + +## Upgrading the Account + +In our new program we want to add a new property for the content state. +The changes that follow are how we leveraged the initial program +constructs as they come into use now. + +### 1. Add account conversion logic + + + + + + + + + + + +| Line(s) | Note | +| ------- | - | +| 6 | We've added Solana's `solana_program::borsh::try_from_slice_unchecked` to simplify reading subsets of data from the larger data block +| 13-26| Here we've preserved the old content structure, `AccountContentOld` line 24, before extending the `AccountContentCurrent` starting in line 17. +| 60 | We bump the `DATA_VERSION` constant +| 71 | We now have a 'previous' version and we want to know it's size +| 86 | The Coup de grâce is adding the plumbing to upgrade the previous content state to the new (current) content state + +We then update our instructions, to add a new one for updating `somestring`, and processor for handling the new instruction. Note that the 'upgrading' the data structure is encapsulated behind `pack/unpack` + + + + +@[code](@/code/data-migration/rust.instruction1.en.rs) + + + + + +@[code](@/code/data-migration/rust.processor1.en.rs) + + + + +After building and submitting an instruction: `VersionProgramInstruction::SetString(String)` we now have the following 'upgraded' account data layout + +Program Account v2 + +## Resources + +* [Borsh Specification](https://borsh.io/) +* [Solana `try_from_slice_unchecked`](https://github.com/solana-labs/solana/blob/master/sdk/program/src/borsh.rs#L67) +* [Reference Implementation](https://github.com/FrankC01/versioning-solana) \ No newline at end of file diff --git a/docs/de/guides/data-migration/pav1.png b/docs/de/guides/data-migration/pav1.png new file mode 100644 index 000000000..e7158e9c0 Binary files /dev/null and b/docs/de/guides/data-migration/pav1.png differ diff --git a/docs/de/guides/data-migration/pav2.png b/docs/de/guides/data-migration/pav2.png new file mode 100644 index 000000000..3417d2576 Binary files /dev/null and b/docs/de/guides/data-migration/pav2.png differ diff --git a/docs/de/guides/debugging-solana-programs.md b/docs/de/guides/debugging-solana-programs.md new file mode 100644 index 000000000..fbfbcb368 --- /dev/null +++ b/docs/de/guides/debugging-solana-programs.md @@ -0,0 +1,159 @@ +--- +title: Debugging Solana Programs +head: + - - meta + - name: title + content: Solana Cookbook | Debugging Solana Programs + - - meta + - name: og:title + content: Solana Cookbook | Debugging Solana Programs + - - meta + - name: description + content: There are a number of options and supporting tools for testing and debugging a Solana BPF program. + - - meta + - name: og:description + content: There are a number of options and supporting tools for testing and debugging a Solana BPF program. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +footer: MIT Licensed +--- + +# Debugging Solana Programs + +There are a number of options and supporting tools for testing and debugging a Solana program. + +## Facts + +::: tip Fact Sheet +- The crate `solana-program-test` enables use of bare bones **_local runtime_** where you can test and debug +your program interactively (e.g. in vscode). +- The crate `solana-validator` enables use of the `solana-test-validator` implementation for more robust +testing that occurs on a **_local validator node_**. You can run from the editor **_but breakpoints in the +program are ignored_**. +- The CLI tool `solana-test-validator` runs and loads your program and processes transaction execution from +command line Rust applications or Javascript/Typescript applications using web3. +- For all the above, liberal use of `msg!` macro in your program is recommended at the start and then +removing them as you test and ensure rock solid behavior. Remember that `msg!` consumes Compute Units which +can eventually fail your program by hitting the Compute Unit budget caps. +::: + +The steps in the following sections use the [solana-program-bpf-template](#resources). Clone that to your +machine: +```bash +git clone git@github.com:mvines/solana-bpf-program-template.git +cd solana-bpf-program-template +code . +``` +## Runtime Testing and Debugging in editor + +Open the file `src/lib.rs` + +You'll see that the program is a pretty simple and basically just logs the content received by +the program entrypoint function: `process_instruction` + +1. Go to the `#[cfg(test)]` section and click `Run Tests`. This will build the program and then +execute the `async fn test_transaction()` test. You will see the log messages (simplified) in the vscode terminal below +the source. +```bash +running 1 test +"bpf_program_template" program loaded as native code +Program 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM invoke [1] +Program log: process_instruction: 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM: 1 accounts, data=[1, 2, 3] +Program 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM success +test test::test_transaction ... ok +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 33.41s +``` +2. Set a breakpoint on the programs `msg!` line (11) +3. Back in the test module, click `Debug` and within seconds the debugger will stop on the breakpoint and +now you can examine data, step through functions, etc., etc.. + +These tests are also run from the command line with: +`cargo test` or `cargo test-bpf`. Of course any breakpoints will be ignored. + +How groovy can you get! + +:::tip Note +Keep in mind you are not using a validator node so default programs, blockhashes, etc. are not represented or +will not behave as they would when running in validator node. This is why the gang at Solana gave us +Local Validator Node testing! +::: + + +## Local Validator Node Testing in editor + +Integration testing using programmatic loading of a local validator node is defined in the +`tests/integration.rs` file. + +By default, the template repo integration tests will only be runnable from the command line +using `cargo test-bpf`. The following steps will enable you to run within the editor as well +as displaying program validator logs and `msg!` outputs from your program: + +1. In the repo directory run `cargo build-bpf` to build the sample program +2. In the editor, open `tests/integration.rs` +3. Comment out line 1 -> `// #![cfg(feature = "test-bpf")]` +4. On line 19 change it to read: `.add_program("target/deploy/bpf_program_template", program_id)` +5. Insert the following at line 22 `solana_logger::setup_with_default("solana_runtime::message=debug");` +6. Click `Run Test` above the `test_validator_transaction()` function + +This will load the validator node then allowing you to construct a transaction (the Rust way) and +submit to the node using the `RcpClient`. + +The program's output will also print out in the editor terminal. For example (simplified): +```bash +running 1 test +Waiting for fees to stabilize 1... +Waiting for fees to stabilize 2... +Program 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM invoke [1] +Program log: process_instruction: 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM: 1 accounts, data=[1, 2, 3] +Program 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM consumed 13027 of 200000 compute units +Program 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM success + +test test_validator_transaction ... ok +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 6.40s +``` +Debugging here will allow you to debug the functions and methods used in the **_test body_** but will +not breakpoint in your program. + +The bee's knees eh? + +## Local Validator Node Testing from Client Apps +Lastly, you can start a local validating node and load your program and any accounts using the `solana-test-validator` +from the command line. + +In this approach, you will need a client application either using Rust [RcpClient](#resources) or in +[JavaScript or Typescript clients](#resources) + +See `solana-test-validator --help` for more details and options. For the example program here is vanilla setup: +1. Open a terminal in the repo folder +2. Run `solana config set -ul` to set the configuration to point to local +3. Run `solana-test-validator --bpf-program target/deploy/bpf_program_template-keypair.json target/deploy/bpf_program_template.so` +4. Open another terminal and run `solana logs` to start the log streamer +5. You can then run your client program and observe program output in the terminal where you started the log streamer + +Now that is the cat's pajamas YO! + +## Resources +[solana-program-bpf-template](https://github.com/mvines/solana-bpf-program-template) + +[RcpClient](https://docs.rs/solana-client/latest/solana_client/rpc_client/struct.RpcClient.html) + +[JavaScript/Typescript Library](https://solana-labs.github.io/solana-web3.js/) diff --git a/docs/de/guides/feature-parity-testing.md b/docs/de/guides/feature-parity-testing.md new file mode 100644 index 000000000..c15cf9ab2 --- /dev/null +++ b/docs/de/guides/feature-parity-testing.md @@ -0,0 +1,240 @@ +--- +title: Feature Parity Testing +head: + - - meta + - name: title + content: Solana Cookbook | Feature Parity Testing + - - meta + - name: og:title + content: Solana Cookbook | Feature Parity Testing + - - meta + - name: description + content: Features vary by Solana cluster. Feature testing ensures predictable results. + - - meta + - name: og:description + content: Features vary by Solana cluster. Feature testing ensures predictable results. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +footer: MIT Licensed +--- + +# Feature Parity Testing + +When testing your program, assurances that it will run the same in various clusters is essential to both quality and +producing expected outcomes. + +## Facts + +::: tip Fact Sheet +- Features are capabilities that are introduced to Solana validators and require activation to be used. +- Features may be activated in one cluster (e.g. testnet) but not so in another (e.g. mainnet-beta). +- However; when running default `solana-test-validator` locally, all available features in your +Solana version are automagically activated. The result is that when testing locally, the capabilities and results of +your testing may not be the same when deploying and running in a different cluster! +::: + +## Scenario +Assume you have a Transaction that contained three (3) instructions and each instruction consumes approximately +100_000 Compute Units (CU). When running in a Solana 1.8.x version, you would observe your instruction CU consumption similar to: + +| Instruction | Starting CU | Execution | Remaining CU| +| - | - | - | - | +| 1 | 200_000 | -100_000| 100_000 +| 2 | 200_000 | -100_000| 100_000 +| 3 | 200_000 | -100_000| 100_000 + +In Solana 1.9.2 a feature called 'transaction wide compute cap' was introduced where a Transaction, by default, +has a 200_000 CU budget and the encapsulated instructions **_draw down_** from that Transaction budget. Running the same +transaction as noted above would have very different behavior: + +| Instruction | Starting CU | Execution | Remaining CU| +| - | - | - | - | +| 1 | 200_000 | -100_000| 100_000 +| 2 | 100_000 | -100_000| 0 +| 3 | 0 | FAIL!!! | FAIL!!! + +Yikes! If you were unaware of this you'd likely be frustrated as there was no change to your instruction behavior that +would cause this. In devnet it worked fine, but locally it was failing?!? + +There is the ability to increase the overall Transaction budget, to lets say 300_000 CU, and salvage your sanity +but this demonstrates why testing with **_Feature Parity_** provides a proactive way to avoid any confusion. + +## Feature Status +It is fairly easy to check what features are enabled for a particular cluster with the `solana feature status` command. +```console +solana feature status -ud // Displays by feature status for devnet +solana feature status -ut // Displays for testnet +solana feature status -um // Displays for mainnet-beta +solana feature status -ul // Displays for local, requires running solana-test-validator +``` + +Alternatively, you could use a tool like [scfsd](#resources) to observe all feature state across clusters +which would display, partial screen shown here, and does not require `solana-test-validator` to be running: + +Feature Status Heatmap + +## Parity Testing +As noted above, the `solana-test-validator` activates **all** features automagically. +So to answer the question "How can I test locally in an environment that has parity with devnet, +testnet or even mainnet-beta?". + +Solution: PRs were added to Solana 1.9.6 to allow deactivation of features: + +```console +solana-test-validator --deactivate-feature ... +``` + +## Simple Demonstration +Suppose you have a simple program that logs the data it receives in it's entry-point. And you are +testing a transaction that adds two (2) instructions for your program. + +### All features activated +1. You start the test validator in one terminal: + +```console +solana config set -ul +solana-test-validator -l ./ledger --bpf-program ADDRESS target/deploy/PROGNAME.so --reset` +``` + +2. In another terminal you start the log streamer: +```console +solana logs +``` + +3. You then run your transaction. You would see something similar in the log terminal (edited for clarity): +```console +Program PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc invoke [1] +Program log: process_instruction: PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc: 0 accounts, data=[0] +Program PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc consumed 12843 of 200000 compute units +Program PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc success +Program PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc invoke [1] +Program log: process_instruction: PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc: 0 accounts, data=[1] +Program PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc consumed 12843 of 187157 compute units +Program PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc success[ +``` +Because our feature 'transaction wide compute cap' is automatically activated by default, we observe each +instruction drawing down CU from the starting Transaction budget of 200_000 CU. + +### Selective features deactivated +1. For this run, we want to run so that the CU budget behavior is in parity with what is running in devnet. Using +the tool(s) described in [Feature Status](#feature-status) we isolate the `transaction wide compute cap` public key +and use the `--deactivate-feature` on the test validator startup + +```console +solana-test-validator -l ./ledger --deactivate-feature 5ekBxc8itEnPv4NzGJtr8BVVQLNMQuLMNQQj7pHoLNZ9 --bpf-program target/deploy/PROGNAME.so --reset` +``` +2. We now see in our logs that our instructions now have their own 200_000 CU budget (edited for clarity) which is +currently the state in all upstream clusters: +```console +Program PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc invoke [1] +Program log: process_instruction: PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc: 0 accounts, data=[0] +Program PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc consumed 12843 of 200000 compute units +Program PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc success +Program PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc invoke [1] +Program log: process_instruction: PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc: 0 accounts, data=[0] +Program PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc consumed 12843 of 200000 compute units +Program PWDnx8LkjJUn9bAVzG6Fp6BuvB41x7DkBZdo9YLMGcc success +``` + +## Full Parity Testing +You can be in full parity with a specific cluster by identifying each feature that is not +yet activated and add a `--deactivate-feature ` for each when invoking `solana-test-validator`: +```console +solana-test-validator --deactivate-feature PUBKEY_1 --deactivate-feature PUBKEY_2 ... +``` + +Alternatively, [scfsd](#resources) provides a command switch to output the complete deactivated feature +set for a cluster to feed directly into the `solana-test-validator` startup: +```console +solana-test-validator -l ./.ledger $(scfsd -c devnet -k -t) +``` + +If you open another terminal, while the validator is running, and `solana feature status` you will see +features deactivated that were found deactivated in devnet + +## Full Parity Testing Programmatically +For those who control running the test validator within their test code, modifying +the test validator activated/deactivated features is possible using TestValidatorGenesis. With +Solana 1.9.6 a function has been added to the validator builder to support this. + +At the root of your program folder, create a new folder called `tests` and add a `parity_test.rs` +file. Here is the boiler place functions (boiler-plate if you will) used by each test + + + + + + + + + + + + +We can now add test functions in the body of `mod test {...}` to demonstrate default +validator setup (all features enabled) and then disabling the `transaction wide compute cap` as +per previous examples running `solana-test-validator` from the command line. + + + + + @[code](@/code/feature-parity-testing/deactivate_one.rs) + + + + + + @[code](@/code/feature-parity-testing/deactivate_two.rs) + + + + + +Alternatively, the [scfs engine gadget](#resources) can produce a full vector of deactivated +features for a cluster. The following demonstrates using that engine to get a list +of all deactivated features for devnet. + + + + + @[code](@/code/feature-parity-testing/deactivate_scfs.rs) + + + + + + +Happy Testing! + + +## Resources +[scfsd](https://github.com/FrankC01/solana-gadgets/tree/main/rust/scfsd) + +[gadget-scfs](https://github.com/FrankC01/solana-gadgets/tree/main/rust/gadgets-scfs) \ No newline at end of file diff --git a/docs/de/guides/feature-parity-testing/scfsd.png b/docs/de/guides/feature-parity-testing/scfsd.png new file mode 100644 index 000000000..fe5852cd0 Binary files /dev/null and b/docs/de/guides/feature-parity-testing/scfsd.png differ diff --git a/docs/de/guides/get-program-accounts.md b/docs/de/guides/get-program-accounts.md new file mode 100644 index 000000000..75702dc43 --- /dev/null +++ b/docs/de/guides/get-program-accounts.md @@ -0,0 +1,169 @@ +--- +title: Get Program Accounts +head: + - - meta + - name: title + content: Solana Cookbook | Get Program Accounts + - - meta + - name: og:title + content: Solana Cookbook | Get Program Accounts + - - meta + - name: description + content: Learn how to query data on Solana using getProgramAccounts and accountsDB + - - meta + - name: og:description + content: Learn how to query data on Solana using getProgramAccounts and accountsDB + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +--- + +# Get Program Accounts + +An RPC method that returns all accounts owned by a program. Currently pagination is not supported. Requests to `getProgramAccounts` should include the `dataSlice` and/or `filters` parameters to improve response time and return only intended results. + +## Facts + +::: tip Parameters + +- `programId`: `string` - Pubkey of the program to query, provided as a base58 encoded string +- (optional) `configOrCommitment`: `object` - Configuration parameters containing the following optional fields: + - (optional) `commitment`: `string` - [State commitment](https://docs.solana.com/developing/clients/jsonrpc-api#configuring-state-commitment) + - (optional) `encoding`: `string` - Encoding for account data, either: `base58`, `base64`, or `jsonParsed`. Note, web3js users should instead use [getParsedProgramAccounts](https://solana-labs.github.io/solana-web3.js/classes/Connection.html#getParsedProgramAccounts) + - (optional) `dataSlice`: `object` - Limit the returned account data based on: + - `offset`: `number` - Number of bytes into account data to begin returning + - `length`: `number` - Number of bytes of account data to return + - (optional) `filters`: `array` - Filter results using the following filter objects: + - `memcmp`: `object` - Match a series of bytes to account data: + - `offset`: `number` - Number of bytes into account data to begin comparing + - `bytes`: `string` - Data to match, as base58 encoded string limited to 129 bytes + - `dataSize`: `number` - Compares the account data length with the provided data size + - (optional) `withContext`: `boolean` - Wrap the result in an [RpcResponse JSON object](https://docs.solana.com/developing/clients/jsonrpc-api#rpcresponse-structure) + +##### Response + +By default `getProgramAccounts` will return an array of JSON objects with the following structure: + +- `pubkey`: `string` - The account pubkey as a base58 encoded string +- `account`: `object` - a JSON object, with the following sub fields: + - `lamports`: `number`, number of lamports assigned to the account + - `owner`: `string`, The base58 encoded pubkey of the program the account has been assigned to + - `data`: `string` | `object` - data associated with the account, either as encoded binary data or JSON format depending on the provided encoding parameter + - `executable`: `boolean`, Indication if the account contains a program + - `rentEpoch`: `number`, The epoch at which this account will next owe rent +::: + +## Deep Dive + +`getProgramAccounts` is a versatile RPC method that returns all accounts owned by a program. We can use `getProgramAccounts` for a number of useful queries, such as finding: + +- All token accounts for a particular wallet +- All token accounts for a particular mint (i.e. All [SRM](https://www.projectserum.com/) holders) +- All custom accounts for a particular program (i.e. All [Mango](https://mango.markets/) users) + +Despite its usefulness, `getProgramAccounts` is often misunderstood due to its current constraints. Many of the queries supported by `getProgramAccounts` require RPC nodes to scan large sets of data. These scans are both memory and resource intensive. As a result, calls that are too frequent or too large in scope can result in connection timeouts. Furthermore, at the time of this writing, the `getProgramAccounts` endpoint does not support pagination. If the results of a query are too large, the response will be truncated. + +To get around these current constraints, `getProgramAccounts` offers a number of useful parameters: namely, `dataSlice` and the `filters` options `memcmp` and `dataSize`. By providing combinations of these parameters, we can reduce the scope of our queries down to manageable and predictable sizes. + +A common example of `getProgramAccounts` involves interacting with the [SPL-Token Program](https://spl.solana.com/token). Requesting all accounts owned by the Token Program with a [basic call](../references/accounts.md#get-program-accounts) would involve an enormous amount of data. By providing parameters, however, we can efficiently request just the data we intend to use. + +### `filters` +The most common parameter to use with `getProgramAccounts` is the `filters` array. This array accepts two types of filters,`dataSize` and `memcmp`. Before using either of these filters, we should be familiar with how the data we are requesting is laid out and serialized. + +#### `dataSize` +In the case of the Token Program, we can see that [token accounts are 165 bytes in length](https://github.com/solana-labs/solana-program-library/blob/08d9999f997a8bf38719679be9d572f119d0d960/token/program/src/state.rs#L86-L106). Specifically, a token account has eight different fields, with each field requiring a predictable number of bytes. We can visualize how this data is laid out using the below illustration. + +![Account Size](./get-program-accounts/account-size.png) + +If we wanted to find all token accounts owned by our wallet address, we could add `{ dataSize: 165 }` to our `filters` array to narrow the scope of our query to just accounts that are exactly 165 bytes in length. This alone, however, would be insufficient. We would also need to add a filter that looks for accounts owned by our address. We can achieve this with the `memcmp` filter. + +#### `memcmp` +The `memcmp` filter, or "memory comparison" filter, allows us to compare data at any field stored on our account. Specifically, we can query only for accounts that match a particular set of bytes at a particular position. `memcmp` requires two arguments: + +- `offset`: The position at which to begin comparing data. This position is measured in bytes and is expressed as an integer. +- `bytes`: The data that should match the account's data. This is represented as a base-58 encoded string should be limited to less than 129 bytes. + +It's important to note that `memcmp` will only return results that are an exact match on `bytes`. Currently, it does not support comparisons for values that are less than or greater than the `bytes` we provide. + +In keeping with our Token Program example, we can amend our query to only return token accounts that are owned by our wallet address. When looking at a token account, we can see the first two fields stored on a token account are both pubkeys, and that each pubkey is 32 bytes in length. Given that `owner` is the second field, we should begin our `memcmp` at an `offset` of 32 bytes. From here, we’ll be looking for accounts whose owner field matches our wallet address. + +![Account Size](./get-program-accounts/memcmp.png) + +We can invoke this query via the following example: + + + + +@[code](@/code/get-program-accounts/memcmp/memcmp.en.ts) + + + + + +@[code](@/code/get-program-accounts/memcmp/memcmp.en.rs) + + + + + +@[code](@/code/get-program-accounts/memcmp/memcmp.en.sh) + + + + +### `dataSlice` + +Outside of the two filter parameters, the third most common parameter for `getProgramAccounts` is `dataSlice`. Unlike the `filters` parameter, `dataSlice` will not reduce the number of accounts returned by a query. Instead, `dataSlice` will limit the amount of data for each account. + +Much like `memcmp`, `dataSlice` accepts two arguments: + +- `offset`: The position (in number of bytes) at which to begin returning account data +- `length`: The number of bytes which should be returned + +`dataSlice` is particularly useful when we run queries on a large dataset but don’t actually care about the account data itself. An example of this would be if we wanted to find the number of token accounts (i.e. number of token holders) for a particular token mint. + + + + +@[code](@/code/get-program-accounts/dataSlice/dataSlice.en.ts) + + + + + +@[code](@/code/get-program-accounts/dataSlice/dataSlice.en.rs) + + + + + +@[code](@/code/get-program-accounts/dataSlice/dataSlice.en.sh) + + + + +By combining all three parameters (`dataSlice`, `dataSize`, and `memcmp`) we can limit the scope of our query and efficiently return only the data we’re interested in. + +## Other Resources + +- [RPC API Documentation](https://docs.solana.com/developing/clients/jsonrpc-api#getprogramaccounts) +- [Web3js Documentation](https://solana-labs.github.io/solana-web3.js/classes/Connection.html#getProgramAccounts) +- [JSON-parsed Web3js Documentation](https://solana-labs.github.io/solana-web3.js/classes/Connection.html#getParsedProgramAccounts) diff --git a/docs/de/guides/get-program-accounts/account-size.png b/docs/de/guides/get-program-accounts/account-size.png new file mode 100644 index 000000000..69e10127b Binary files /dev/null and b/docs/de/guides/get-program-accounts/account-size.png differ diff --git a/docs/de/guides/get-program-accounts/memcmp.png b/docs/de/guides/get-program-accounts/memcmp.png new file mode 100644 index 000000000..16b53a922 Binary files /dev/null and b/docs/de/guides/get-program-accounts/memcmp.png differ diff --git a/docs/de/guides/retrying-transactions.md b/docs/de/guides/retrying-transactions.md new file mode 100644 index 000000000..88fae9034 --- /dev/null +++ b/docs/de/guides/retrying-transactions.md @@ -0,0 +1,178 @@ +--- +title: Retrying Transactions +head: + - - meta + - name: title + content: Solana Cookbook | Retrying Transactions + - - meta + - name: og:title + content: Solana Cookbook | Retrying Transactions + - - meta + - name: description + content: On some occasions, a seemingly valid transaction may be dropped before it is included in a block. To combat this, application developers are able to develop their own custom rebroadcasting logic. Learn about retrying transactions and more at The Solana cookbook. + - - meta + - name: og:description + content: On some occasions, a seemingly valid transaction may be dropped before it is included in a block. To combat this, application developers are able to develop their own custom rebroadcasting logic. Learn about retrying transactions and more at The Solana cookbook. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +footer: MIT Licensed +--- + +# 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](https://docs.solana.com/terminology#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. + +## Facts + +::: tip Fact Sheet +- 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](https://docs.solana.com/developing/clients/jsonrpc-api#sendtransaction) JSON-RPC method +2. Directly to leaders via a [TPU Client](https://docs.rs/solana-client/1.7.3/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. + +![Transaction Journey](./retrying-transactions/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](https://docs.solana.com/terminology#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) + +![TPU Overview](./retrying-transactions/tpu-jito-labs.png) +Image Courtesy of Jito Labs + +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](https://docs.solana.com/developing/programming-model/transactions#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](https://docs.solana.com/developing/clients/jsonrpc-api#sendtransaction) on `sendTransaction`. + +![Dropped via RPC Pool](./retrying-transactions/dropped-via-rpc-pool.png) + +Temporarily 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. + +![Dropped due to Minority Fork (Before Processed)](./retrying-transactions/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. + +![Dropped due to Minority Fork (After Processed)](./retrying-transactions/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. + +:::tip +#### 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](https://docs.solana.com/developing/clients/jsonrpc-api#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](https://docs.solana.com/developing/clients/jsonrpc-api#getsignaturestatuses) 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](https://docs.solana.com/developing/clients/jsonrpc-api#getlatestblockhash). Once stashed, an application can then [poll the cluster’s blockheight](https://docs.solana.com/developing/clients/jsonrpc-api#getblockheight) 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. + + + + + + + + + + + + +When polling via `getLatestBlockhash`, applications should specify their intended [commitment](https://docs.solana.com/developing/clients/jsonrpc-api#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](./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`](https://docs.solana.com/developing/clients/jsonrpc-api#getepochinfo) and comparing with `blockHeight` in the response. Once a blockhash is invalidated, clients may re-sign with a newly-queried blockhash. + +## Acknowledgements + +Many thanks to Trent Nelson, [Jacob Creech](https://twitter.com/jacobvcreech), White Tiger, Le Yafo, [Buffalu](https://twitter.com/buffalu__), and [Jito Labs](https://twitter.com/jito_labs) for their review and feedback. diff --git a/docs/de/guides/retrying-transactions/dropped-minority-fork-post-process.png b/docs/de/guides/retrying-transactions/dropped-minority-fork-post-process.png new file mode 100644 index 000000000..ba56d1ccc Binary files /dev/null and b/docs/de/guides/retrying-transactions/dropped-minority-fork-post-process.png differ diff --git a/docs/de/guides/retrying-transactions/dropped-minority-fork-pre-process.png b/docs/de/guides/retrying-transactions/dropped-minority-fork-pre-process.png new file mode 100644 index 000000000..10f08dfed Binary files /dev/null and b/docs/de/guides/retrying-transactions/dropped-minority-fork-pre-process.png differ diff --git a/docs/de/guides/retrying-transactions/dropped-via-rpc-pool.png b/docs/de/guides/retrying-transactions/dropped-via-rpc-pool.png new file mode 100644 index 000000000..8020ebd87 Binary files /dev/null and b/docs/de/guides/retrying-transactions/dropped-via-rpc-pool.png differ diff --git a/docs/de/guides/retrying-transactions/tpu-jito-labs.png b/docs/de/guides/retrying-transactions/tpu-jito-labs.png new file mode 100644 index 000000000..934e1dcdc Binary files /dev/null and b/docs/de/guides/retrying-transactions/tpu-jito-labs.png differ diff --git a/docs/de/guides/retrying-transactions/tx-journey.png b/docs/de/guides/retrying-transactions/tx-journey.png new file mode 100644 index 000000000..faa8b6e22 Binary files /dev/null and b/docs/de/guides/retrying-transactions/tx-journey.png differ diff --git a/docs/de/guides/serialization.md b/docs/de/guides/serialization.md new file mode 100644 index 000000000..ce8e051f6 --- /dev/null +++ b/docs/de/guides/serialization.md @@ -0,0 +1,308 @@ +--- +title: Serializing Data +head: + - - meta + - name: title + content: Solana Cookbook | Serializing Data + - - meta + - name: og:title + content: Solana Cookbook | Serializing Data + - - meta + - name: description + content: Learn how to serialize and deserialize data on Solana + - - meta + - name: og:description + content: Learn how to serialize and deserialize data on Solana + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +footer: MIT Licensed +--- + +# Serializing Data + +When we talk about serialization we mean both serializing data as well as deserialization of data. + +Serialization comes into play at a few points along Solana program and program accounts lifecycle: + +1. Serializing instruction data on to client +2. Deserializing instruction data on the program +3. Serializing Account data on the program +4. Deserializing Account Data on the client + +It is important that the above actions are all supported by the same serialization approach. The +included snippets are demonstrating serialization using [Borsh](#resources). + +The samples in the remainder of this document are excerpts as taken from the [Solana CLI Program Template](#resources) + +## Setting up for Borsh Serialization + +Libraries for Borsh must be setup for the Rust program, Rust client, Node and/or Python client. + + + + +@[code](@/code/serialization/setup/Cargo.program.en.toml) + + + + + +@[code](@/code/serialization/setup/Cargo.cli.en.toml) + + + + + +@[code](@/code/serialization/setup/Node.package.en.json) + + + + + +@[code](@/code/serialization/setup/requirements.txt) + + + + + +## How to serialize instruction data on the client + +Serialize Instruction Data + +If you are serializing outbound instruction data to send to a program it must mirror how the program deserializes the +inbound instruction data. + +In this template, an instruction data block is a serialized array containing, with examples: + +| Instruction (Variant index) | Serialized Key | Serialized Value | +| --------------------------- | ------------------------------ | ------------------------------ | +| Initialize (0) | not applicable for instruction | not applicable for instruction | +| Mint (1) | "foo" | "bar" | +| Transfer (2) | "foo" | not applicable for instruction | +| Burn (2) | "foo" | not applicable for instruction | + +In the following example we assume the program owned account has been initialized + + + + +@[code](@/code/serialization/instruction/ts.client.mint.en.ts) + + + + + +@[code](@/code/serialization/instruction/python.client.py) + + + + + +@[code](@/code/serialization/instruction/rust.client.mint.en.rs) + + + + +## How to deserialize instruction data on the program + +Deserialize Instruction Data + + + +@[code](@/code/serialization/instruction/rust.program.instruction.en.rs) + + + + +## How to serialize account data on the program + +Account Data Serialization + +The program account data block (from the sample repo) is layed out as + +| Byte 0 | Bytes 1-4 | Remaining Byte up to 1019 | +| ---------------- | ----------------------------- | ------------------------------------------- | +| Initialized flag | length of serialized BTreeMap | BTreeMap (where key value pairs are stored) | + +### Pack + +A word about the [Pack][1] trait + +The Pack trait makes it easier to hide the details of account data serialization/deserialization +from your core Program instruction processing. So instead of putting all the serialize/deserialize +log in the program processing code, it encapsulates the details behind (3) functions: + +1. `unpack_unchecked` - Allows you to deserialize an account without checking if it has been initialized. This + is useful when you are actually processing the Initialization function (variant index 0) +2. `unpack` - Calls your Pack implementation of `unpack_from_slice` and checks if account has been initialized. +3. `pack` - Calls your Pack implementation of `pack_into_slice` + +Here is the implementation of the Pack trait for our sample program. This is followed with the actual +processing of the account data using borsh. + + + + +@[code](@/code/serialization/program/rust.program.packimpl.en.rs) + + + + +### Serialization/Deserialization + +To complete the underlying serialization and deserialization: + +1. `sol_template_shared::pack_into_slice` - Where the actual serialization occurs +2. `sol_template_shared::unpack_from_slice` - Where the actual deserialization occurs + +**Note** that in the following we have a `u32` (4 bytes) partition in the data layout for +`BTREE_LENGTH` preceding the `BTREE_STORAGE`. This is because borsh, during deserialization, +checks that the length of the slice you are deserializing agrees with the amount of +data it reads prior to actually recombobulation of the receiving object. The approach +demonstrated below first reads the `BTREE_LENGTH` to get the size to `slice` out of the +`BTREE_STORAGE` pointer. + + + + +@[code](@/code/serialization/program/rust.program.serdeser.en.rs) + + + + +### Usage + +The following pulls it all together and demonstrates how the program interacts with the `ProgramAccountState` +which encapsulates the initialization flag as well as the underlying `BTreeMap` for our key/value pairs. + +First when we want to initialize a brand new account: + + + + +@[code](@/code/serialization/program/rust.program.initialize.en.rs) + + + + +Now we can operate on our other instructions as the following demonstrates minting a new +key value pair that we demonstrated above when sending instructions from a client: + + + + +@[code](@/code/serialization/program/rust.program.mint.en.rs) + + + + +[1]: https://github.com/solana-labs/solana/blob/22a18a68e3ee68ae013d647e62e12128433d7230/sdk/program/src/program_pack.rs + +## How to deserialize account data on the client + +Clients can call Solana to fetch program owned account, in which the serialized +data block is a part of the return. Deserializing requires knowing the data block +layout. + +The layout of the account data was described [Here](#account-data-serialization) + + + + +@[code](@/code/serialization/clientdata/ts.client.data.en.ts) + + + + + +@[code](@/code/serialization/clientdata/python.client.data.py) + + + + + +@[code](@/code/serialization/clientdata/rust.client.data.en.rs) + + + + +## Common Solana TS/JS Mappings + +The [Borsh Specification](#resources) contains most mappings for primitive and +compound data types. + +The key to TS/JS and Python is creating a Borsh Schema with a proper definition so the serialize +and deserialize can generate or walk the respective inputs. + +Here we demonstrate serialization of primitives (numbers, strings) and compound types (fixed size array, Map) +first in Typescript, then in Python and then equivalent deserialization on the Rust side: + + + + +@[code](@/code/serialization/primitives/demo_primitives.en.ts) + + + + + +@[code](@/code/serialization/primitives/python.demo_primitives.py) + + + + + +@[code](@/code/serialization/primitives/src/main.rs) + + + + +## Advanced Constructs + +We've shown how to create simple Payloads in previous examples. Sometimes +Solana throws a fastball with certain types. This section will demonstrate +proper mapping between TS/JS and Rust to handle those + +### COption + + + + +@[code](@/code/serialization/coption/demo_coption.en.ts) + + + + + +@[code](@/code/serialization/coption/src/main.rs) + + + + +## Resources + +- [Borsh Specification](https://borsh.io/) +- [Rust Borsh](https://github.com/near/borsh-rs) +- [TS/JS Borsh](https://github.com/near/borsh-js) +- [Python Borsh](https://github.com/near/borsh-construct-py) +- [Python Borsh Documentation](https://near.github.io/borsh-construct-py/) +- [Solana CLI Program Template2](https://github.com/hashblock/solana-cli-program-template) diff --git a/docs/de/guides/serialization/ser1.png b/docs/de/guides/serialization/ser1.png new file mode 100644 index 000000000..a903c9f7a Binary files /dev/null and b/docs/de/guides/serialization/ser1.png differ diff --git a/docs/de/guides/serialization/ser2.png b/docs/de/guides/serialization/ser2.png new file mode 100644 index 000000000..087e10fc2 Binary files /dev/null and b/docs/de/guides/serialization/ser2.png differ diff --git a/docs/de/guides/serialization/ser3.png b/docs/de/guides/serialization/ser3.png new file mode 100644 index 000000000..c959a92e1 Binary files /dev/null and b/docs/de/guides/serialization/ser3.png differ diff --git a/docs/de/integrations/README.md b/docs/de/integrations/README.md new file mode 100644 index 000000000..59d95cbeb --- /dev/null +++ b/docs/de/integrations/README.md @@ -0,0 +1,58 @@ +--- +title: Getting Started +head: + - - meta + - name: title + content: Solana Cookbook | Composability and Integrations + - - meta + - name: og:title + content: Solana Cookbook | Composability and Integrations + - - meta + - name: description + content: Composability is innovation. Building on top of protocols on Solana unlocks new capabilities and possibilities. + - - meta + - name: og:description + content: Composability is innovation. Building on top of protocols on Solana unlocks new capabilities and possibilities. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +--- + +# Getting Started with Integrations + +The Solana Cookbook integrations provides a set of examples and references for anyone +to build on top of other protocols on Solana. + +The power of Solana comes from the ability to integrate with other protocols, +building on top of existing infrastructure to make something better. + +## Composability is Key + +Making your program easy to use and extend will grow both your program and the +entire Solana ecosystem. Don't reinvent the wheel, build on top of existing protocols +and bootstrap your userbase. + +Adapt and build on top of other programs or libraries and unlock new capabilities for Solana. + +## Contributing + +If you are interested in contributing to integrations, please checkout the [contribution +guidelines](https://github.com/solana-developers/solana-cookbook/blob/master/CONTRIBUTING.md). diff --git a/docs/de/integrations/assets/Web3Auth/login-modal.png b/docs/de/integrations/assets/Web3Auth/login-modal.png new file mode 100644 index 000000000..e38f88045 Binary files /dev/null and b/docs/de/integrations/assets/Web3Auth/login-modal.png differ diff --git a/docs/de/integrations/jupiter.md b/docs/de/integrations/jupiter.md new file mode 100644 index 000000000..6570a2fad --- /dev/null +++ b/docs/de/integrations/jupiter.md @@ -0,0 +1,417 @@ +--- +title: Jupiter +head: + - - meta + - name: title + content: Solana Cookbook | Swap tokens using Jupiter + - - meta + - name: og:title + content: Solana Cookbook | Swap tokens using Jupiter + - - meta + - name: description + content: Jupiter is the key liquidity aggregator for Solana, offering the widest range of tokens and best route discovery between any token pair. + - - meta + - name: og:description + content: Jupiter is the key liquidity aggregator for Solana, offering the widest range of tokens and best route discovery between any token pair. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +--- + +# Jupiter + +Jupiter is the key liquidity aggregator for Solana, offering the widest range of tokens and best route discovery between any token pair. + +### Installation + +@jup-ag/core is the Core package used to interact with jupiter on-chain programs to perform swaps between two possible token pairs. + + + + +```bash +yarn add @jup-ag/core +``` + + + + + +```bash +npm install @jup-ag/core +``` + + + + +### Fetching Token list from Jupiter + +All the possible tokens that can be swapped with jupiter for a given network is being fetched. + + + + + + + + + + + + +### Loading the Jupiter instance + +Jupiter instance is being created with the provided configurations. There are many optional parameters that the instance takes to know more about it go [here](https://docs.jup.ag/jupiter-core/full-guide) + + + + + + + + + + + + +### Getting the RouteMap + +The RouteMap identifies what tokens can be swapped for a given input token. The route map only contains token mint addresses and no metadata. + + + + + + + + + + + + +### Getting the routes for given Input and Output token +The `computeRoutes` methods takes in the input Mint address and the output Mint address and gives all the possibles routes in order of best price first. + + + + + + + + + + + + +### Execute the Token Swap +The `exchange` method is called here which constructs the transaction for a given route. + + + + + + + + + + + + +## How to use Jupiter in a React Application + +### Installation + + + + +```bash +yarn add @jup-ag/react-hook +``` + + + + + +```bash +npm install @jup-ag/react-hook +``` + + + + +### Adding the Provider + +We are setting up the JupiterProvider here in order to use the useJupiter Hook Through out the React App. The cluster parameter is set as **mainnet-beta** in order to get a wide variety of tokens but if you wish you could change it to **devnet** as well + + + + + + + + + + + + +### Fetching the List of Tokens + +All the possible Tokens that can be swapped in a Given Network is fetched stored in the state. + + + + + + + + + + + + +### Setting up the State + +InputMint and OutputMint are state that is added in order for it to be swapped among each other or can be taken from the user as well. + + + + + + + + + + + + +### Using the useJupiter react hook + +The useJupiter Hook takes all the parameters required for it to find the routes through which Tokens of both InputMint and OutputMint can be swapped. To learn more about it go [here](https://docs.jup.ag/jupiter-react/using-the-react-hook) + + + + + + + + + + + + +### Performing the Swap + +After providing all the data to the useJupiter Hook. We can use the jupiter instance to perform a swap using the `exchange` method + + + + + + + + + + + + +## How to use Jupiter API + +This is the easiest way to interact with jupiter programs to swap any 2 provided tokens. + +### Installation + + + + +```bash +yarn i @solana/web3.js +yarn i cross-fetch +yarn i @project-serum/anchor +yarn i bs58 +``` + + + + + +```bash +npm i @solana/web3.js +npm i cross-fetch +npm i @project-serum/anchor +npm i bs58 +``` + + + + +### Getting the Route Map + +This API retrieves all the available tokens that can be swapped using the jupiter API. A list of all possible token routes is being fetched here and `allInputMints` contains the list of all possible Input Tokens by mint address and `swappableOutputForSol` contains all the possible tokens that can be swapped for SOL in this case. + + + + + + + + + + + + +### Getting the Serialized Transaction to perform Swap +POST API request is done with the route that we wish to go with and the wallet address of the user there are few optional parameters that can be added to this api like **wrapUnwrapSOL** and **feeAccount** to learn more about it go through the offical docs here [link](https://docs.jup.ag/jupiter-api/swap-api-for-solana) + + + + + + + + + + + + +### Executing the Swap Transaction +A Transaction object is created and then its getting signed by the user. + + + + + + + + + + + + +## Other Resources + +- [Main Docs](https://docs.jup.ag/) +- [Jupiter Core Example Code](https://github.com/jup-ag/jupiter-core-example) +- [Jupiter React Example Code](https://github.com/jup-ag/jupiter-api-nextjs-example) +- [Jupiter API Example Code](https://github.com/jup-ag/api-arbs-example) diff --git a/docs/de/integrations/mango.md b/docs/de/integrations/mango.md new file mode 100644 index 000000000..7f43040e0 --- /dev/null +++ b/docs/de/integrations/mango.md @@ -0,0 +1,232 @@ +--- +title: Mango Markets +head: + - - meta + - name: title + content: Solana Cookbook | Building on Mango Markets + - - meta + - name: og:title + content: Solana Cookbook | Building on Mango Markets + - - meta + - name: description + content: Mango Markets offers the industry standard for decentralized, cross-margin trading. Learn how to use and build on top of Mango Markets. + - - meta + - name: og:description + content: Mango Markets offers the industry standard for decentralized, cross-margin trading. Learn how to use and build on top of Mango Markets. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +--- + +# Mango Markets + +Mango provides a single venue to lend, borrow, swap, and leverage +trade cryptoassets through an on-chain risk engine. +You can connect to Mango's on-chain program using the Client API libraries. +You'll also need the Solana javascript API library. + + + + +``` +"@blockworks-foundation/mango-client": "^3.3.27", +"@solana/web3.js": "^1.37.0" +``` + + + +## How to get a Mango Group + +A mango group is a basket of cross-margined tokens. It holds broad market info about tokens, serum dex markets, perp markets, oracles, insurance fund and fees vaults. Each version +of Mango Markets uses a different Mango Group containing different +tokens. The current v3 group is `mainnet.1`. Here's a table showing the various groups: + + +| Group | Version | Cluster | +|----------------------|-------------|------------------| +| mainnet.1 | v3 | mainnet | +| devnet.2 | v3 | devnet | +| devnet.3 | v3 | devnet | +| BTC_ETH_SOL_SRM_USDC | v2 | mainnet & devnet | +| BTC_ETH_USDT | v2 | devnet | +| BTC_ETH_USDC | v2 | testnet | + + +:::tip Note +If you wish to use the v2 groups, you'll have to use the v2 client library. You can find it [here](https://github.com/blockworks-foundation/mango-client-ts) +::: + + + + + + + + + + + + + +## How to create a Mango Account + +A Mango Account is associated with a Mango Group, and it holds your tokens and allows +you to trade that Group’s markets. You can find the reference [here](https://blockworks-foundation.github.io/mango-client-v3/classes/MangoClient.html#createMangoAccount). + + + + + + + + + + + + + + + + + + + +## How to deposit USDC into a Mango Account +After creating a mango account, you'll need to fund it with tokens for trading. +You can find the reference for the deposit method [here](https://blockworks-foundation.github.io/mango-client-v3/classes/MangoClient.html#deposit). + + + + + + + + + + + +## How to place a spot order +Mango interacts with Serum Protocol to place spot orders on markets. You can place a spot +order by doing this. You can find the reference for the placeSpotOrder function [here](https://blockworks-foundation.github.io/mango-client-v3/classes/MangoClient.html#placeSpotOrder). +Mango has a config file that contains information on groups, markets, tokens and oracles, +you can find it [here](https://github.com/blockworks-foundation/mango-client-v3/blob/main/src/ids.json). We use information from that file to find the right group and market. + + + + + + + + + + + +## How to load bids +Mango uses the market information from Serum Protocol to load bids. You can load +them directly from Serum to work with on Mango. You can find out more about Serum's +markets [here](https://github.com/project-serum/serum-ts/tree/master/packages/serum) + + + + + + + + + + + +## How to load asks +Mango uses the market information from Serum Protocol to load asks. +You can load them directly from Serum to work with on Mango. You can find out more +about Serum's markets [here](https://github.com/project-serum/serum-ts/tree/master/packages/serum) + + + + + + + + + + + +## Other Resources + +- [Client Libraries](https://docs.mango.markets/development-resources/client-libraries) +- [Mango Docs](https://docs.mango.markets) +- [Technical Intro](https://mango-markets.notion.site/Technical-Intro-to-Mango-Markets-15a650e4799e41c8bfc043fbf079e6f9) diff --git a/docs/de/integrations/pyth.md b/docs/de/integrations/pyth.md new file mode 100644 index 000000000..7474d92db --- /dev/null +++ b/docs/de/integrations/pyth.md @@ -0,0 +1,94 @@ +--- +title: Pyth +head: + - - meta + - name: title + content: Solana Cookbook | Using Pyth to get OnChain data + - - meta + - name: og:title + content: Solana Cookbook | Using Pyth to get OnChain data + - - meta + - name: description + content: Pyth is an Oracle used to get real-word financial data onChain. + - - meta + - name: og:description + content: Pyth is an Oracle used to get real-word financial data onChain. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +--- + +# Pyth + +Pyth is an Oracle used to get real-world financial and crypto market data. Pyth Oracle can be used by on-chain programs in consuming data for a variety of use cases. + +## How to use Pyth in Client + +Pyth provides a JavaScript/TypeScript library called **@pythnetwork/client**. This library can be used to read on-chain Pyth Data for off-chain applications, such as displaying the Pyth price on a website. Learn more about this [here](https://www.npmjs.com/package/@pythnetwork/client) + + + + + + + + + + + + +## How to use Pyth in Anchor + +Pyth provides a Rust Crate which can be used by on-chain programs or off-chain application's to consume pyth's data. + + + + + + + + + + + + +## Other Resources + +- [Client Libraries](https://docs.pyth.network/consumers/client-libraries) +- [JS Example Code](https://github.dev/solana-labs/solana/tree/master/web3.js/examples) +- [Rust Example Code](https://github.com/project-serum/anchor/tree/master/tests/pyth) +- [Anchor Example Code](https://github.com/0xPratik/pyth-anchor-example) diff --git a/docs/de/integrations/react-native.md b/docs/de/integrations/react-native.md new file mode 100644 index 000000000..5217d1193 --- /dev/null +++ b/docs/de/integrations/react-native.md @@ -0,0 +1,187 @@ +--- +title: React Native +head: + - - meta + - name: title + content: Solana Cookbook | Using React Native with Solana + - - meta + - name: og:title + content: Solana Cookbook | Using React Native with Solana + - - meta + - name: description + content: In this tutorial, you learn how to use Solana in your React Native apps. + - - meta + - name: og:description + content: In this tutorial, you learn how to use Solana in your React Native apps. + - - meta + - name: og:image + content: https://solanacookbook.com/cookbook-sharing-card.png + - - meta + - name: og:image:alt + content: Solana splash card + - - meta + - name: twitter:card + content: summary + - - meta + - name: twitter:site + content: "@solanacookbook" + - - meta + - name: twitter:image + content: "https://solanacookbook.com/cookbook-sharing-card.png" + - - meta + - name: robots + content: index,follow,noodp + - - meta + - name: googlebot + content: index,follow +--- + +# React Native and Solana + +React Native is an open-source UI software framework used to develop mobile, web and desktop applications by enabling developers to use the React framework along with native platform capabilities. Powered with the Solana SDK, this is a great platform to quickly build performant native Crypto apps. + +The fastest way to start with React Native and Solana is by using the [Solana DApp Scaffold for React Native](#solana-dapp-scaffold-for-react-native). + +## How to use @solana/web3.js in a React Native app + +In this tutorial you will learn how to create a new React Native app and install and configure the `@solana/web3.js` SDK, and its dependencies. + +If you already have an existing app, skip to [installing the dependencies](#install-dependencies). + +### Create a new app + +We start a new React Native application that uses TypeScript, then `cd` into the project directory, where we will execute the rest of the commands. + +```shell +npx react-native@0.70.0 init SolanaReactNative --template react-native-template-typescript +cd SolanaReactNative +``` + +### Install dependencies + +Next, we install the dependencies. The Solana JavaScript SDK, a package to patch the React Native build system (Metro), a secure random number generator, and a fix to patch React Native's missing `URL` class. + +```shell +yarn add \ + @solana/web3.js \ + react-native-get-random-values \ + react-native-url-polyfill +``` + +### Patch Babel to use the Hermes transforms + +As of August 2022 the template from which new React Native apps are made enables the Hermes JavaScript engine by default but not the Hermes code transforms. Enable them by making the following change to `babel.config.js`: + +```diff + module.exports = { +- presets: ['module:metro-react-native-babel-preset'], ++ presets: [ ++ [ ++ 'module:metro-react-native-babel-preset', ++ {unstable_transformProfile: 'hermes-stable'}, ++ ], ++ ], +}; +``` + +### Update `index.js` + +To load the polyfills, we open the file `index.js` in the root of the project and add the following two lines to the top of the file: + +```javascript +import 'react-native-get-random-values'; +import 'react-native-url-polyfill/auto'; +``` + +### Update `App.tsx` + +Let's add a web3.js example into our app! + +Open the file `App.tsx` and add the following code inside the `App` function: + +In this example, we set up a connection to Solana Devnet and when the components load, we get the version of the cluster we connected to and store the version in the component state. + +Additionally, this example shows how to generate and store a keypair. + +```typescript +const [keypair, setKeypair] = useState(() => Keypair.generate()); +const randomKeypair = () => { + setKeypair(() => Keypair.generate()); +}; + +const [version, setVersion] = useState(''); +useEffect(() => { + const conn = new Connection(clusterApiUrl('devnet')); + conn.getVersion().then(r => { + setVersion(r); + }); +}, []); +``` + +Lastly, in the template (or `render function`) add the following markup: + + +```tsx +{version ? ( +
{JSON.stringify(version, null, 2)}
+) : null} +{keypair ? ( +
{JSON.stringify(keypair?.publicKey?.toBase58(), null, 2)}
+) : null} +