diff --git a/api/README.mdx b/api/README.mdx new file mode 100644 index 00000000..9d399874 --- /dev/null +++ b/api/README.mdx @@ -0,0 +1,9 @@ +--- +title: Introduction +--- + +import DocCardList from "@theme/DocCardList"; + +A public discussion about the design of soroban-rpc. + + diff --git a/api/goals.mdx b/api/goals.mdx index 096b6ea4..1b88c326 100644 --- a/api/goals.mdx +++ b/api/goals.mdx @@ -15,4 +15,4 @@ Soroban-RPC should provide all the basic data that a dapp developer would need, Soroban-RPC should support the developer from local testing (via the quickstart image), all the way through to production deployments. - This implies it should be easy to deploy, and easy to maintain; with low cost, and little "admin" needed. -- The developer should be able to simply run the quickstart docker image, and quickly be ready to serve requests without needing to set up or maintain dependent infrastructure. \ No newline at end of file +- The developer should be able to simply run the quickstart docker image, and quickly be ready to serve requests without needing to set up or maintain dependent infrastructure. diff --git a/api/json-rpc.mdx b/api/json-rpc.mdx index 01d7aed9..d2004ce3 100644 --- a/api/json-rpc.mdx +++ b/api/json-rpc.mdx @@ -16,10 +16,10 @@ When XDR is passed as a parameter or returned, it is always a string encoded usi Soroban-RPC provides an [OpenRPC] specification document that can be used to mock, build, and/or validate both server and client software implementations. This document is used to generate all of our [methods] documentation pages. You can view the full [specification document here]. Additionally, you can experiment with this specificaiton document in the [OpenRPC Playground]. -[JSON-RPC 2.0]: -[jsonrpc error object]: -[JavaScript SDK]: -[OpenRPC]: -[methods]: <./methods> -[specification document here]: -[OpenRPC Playground]: +[JSON-RPC 2.0]: https://www.jsonrpc.org/specification +[jsonrpc error object]: https://www.jsonrpc.org/specification#error_object +[JavaScript SDK]: https://github.com/stellar/js-stellar-sdk +[OpenRPC]: https://open-rpc.org/ +[methods]: ./methods +[specification document here]: https://raw.githubusercontent.com/stellar/soroban-docs/main/static/openrpc.json +[OpenRPC Playground]: https://playground.open-rpc.org/?schemaUrl=https://raw.githubusercontent.com/stellar/soroban-docs/main/static/openrpc.json diff --git a/api/methods/getEvents.mdx b/api/methods/getEvents.mdx index 6417fd75..e46cee2b 100644 --- a/api/methods/getEvents.mdx +++ b/api/methods/getEvents.mdx @@ -5,4 +5,4 @@ description: Returns contract events import { RpcMethod } from "@site/src/components/RpcMethod"; - + diff --git a/api/methods/getHealth.mdx b/api/methods/getHealth.mdx index 826bef45..980418e9 100644 --- a/api/methods/getHealth.mdx +++ b/api/methods/getHealth.mdx @@ -5,4 +5,4 @@ description: Returns node health import { RpcMethod } from "@site/src/components/RpcMethod"; - + diff --git a/api/methods/getLatestLedger.mdx b/api/methods/getLatestLedger.mdx index 825f8088..6cc788c7 100644 --- a/api/methods/getLatestLedger.mdx +++ b/api/methods/getLatestLedger.mdx @@ -5,4 +5,4 @@ description: Returns latest known ledger import { RpcMethod } from "@site/src/components/RpcMethod"; - + diff --git a/api/methods/getLedgerEntries.mdx b/api/methods/getLedgerEntries.mdx index 4e9f9446..2d5ae1e4 100644 --- a/api/methods/getLedgerEntries.mdx +++ b/api/methods/getLedgerEntries.mdx @@ -5,7 +5,7 @@ description: Returns ledger entries import { RpcMethod } from "@site/src/components/RpcMethod"; - + ### Generating `keys` Parameters @@ -55,23 +55,23 @@ yarn add @stellar/stellar-sdk ``` ```js -import { xdr, StrKey } from '@stellar/stellar-sdk'; +import { xdr, StrKey } from "@stellar/stellar-sdk"; const getLedgerKeySymbol = (contractId, symbolText) => { const ledgerKey = xdr.LedgerKey.contractData( new xdr.LedgerKeyContractData({ contractId: StrKey.decodeContract(contractId), - key: xdr.ScVal.scvSymbol(symbolText) - }) + key: xdr.ScVal.scvSymbol(symbolText), + }), ); - return ledgerKey.toXDR('base64'); + return ledgerKey.toXDR("base64"); }; console.log( getLedgerKeySymbol( - 'CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE', - 'COUNTER' - ) + "CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE", + "COUNTER", + ), ); ``` @@ -105,7 +105,6 @@ console.log(getLedgerKeyAccount( # OUTPUT: AAAAAAAAAACp3BPIqFxM9XSnW6aHvavD3GWlJGfuylOt5tZL6CQtdQ== ``` - We then take our output from this function, and use it as the element in the `keys` array parameter in our call to the `getLedgerEntries` method. ```json @@ -126,7 +125,7 @@ And the response we get contains the `LedgerEntryData` with the current informat "jsonrpc": "2.0", "id": 8675309, "result": { - "entries":[ + "entries": [ { "key": "AAAAAAAAAACp3BPIqFxM9XSnW6aHvavD3GWlJGfuylOt5tZL6CQtdQ==", "xdr": "AAAAAAAAAACp3BPIqFxM9XSnW6aHvavD3GWlJGfuylOt5tZL6CQtdQAAABdIdugAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA", @@ -142,9 +141,9 @@ We can then parse this result as an `xdr.LedgerEntryData` type. ```js const parsed = xdr.LedgerEntryData.fromXDR( - 'AAAAAAAAAACp3BPIqFxM9XSnW6aHvavD3GWlJGfuylOt5tZL6CQtdQAAABdIdugAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA', - 'base64' -) + "AAAAAAAAAACp3BPIqFxM9XSnW6aHvavD3GWlJGfuylOt5tZL6CQtdQAAABdIdugAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA", + "base64", +); console.log(parsed); ``` @@ -192,18 +191,18 @@ print( ##### JavaScript ```javascript -import { Address, xdr } from '@stellar/stellar-sdk'; +import { Address, xdr } from "@stellar/stellar-sdk"; function getLedgerKeyContractCode(contractId) { const instance = new ContractId(contractId).getFootprint(); - return instance.toXDR('base64'); + return instance.toXDR("base64"); } console.log( getLedgerKeyContractCode( - "CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE" - ) -) + "CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE", + ), +); // OUTPUT: AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFA== ``` @@ -215,9 +214,7 @@ We then take our output from this function, and use it as the element in the `ke "id": 8675309, "method": "getLedgerEntries", "params": { - "keys": [ - "AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFA==" - ] + "keys": ["AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFA=="] } } ``` @@ -280,31 +277,30 @@ const { xdr } = require("@stellar/stellar-sdk"); function getLedgerKeyWasmId(contractCodeLedgerEntryData) { const entry = xdr.LedgerEntryData.fromXDR( contractCodeLedgerEntryData, - "base64" + "base64", ); const instance = entry.contractData().val().instance(); let ledgerKey = xdr.LedgerKey.contractCode( new xdr.LedgerKeyContractCode({ - hash: instance.wasmHash() - }) + hash: instance.wasmHash(), + }), ); - return ledgerKey.toXDR('base64'); + return ledgerKey.toXDR("base64"); } console.log( getLedgerKeyWasmId( - "AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFAAAABIAAAAAZBYoEJT3IaPMMk3FoRmnEQHoDxewPZL+Uor+xWI4uII=" - ) -) + "AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFAAAABIAAAAAZBYoEJT3IaPMMk3FoRmnEQHoDxewPZL+Uor+xWI4uII=", + ), +); // OUTPUT: AAAAB2QWKBCU9yGjzDJNxaEZpxEB6A8XsD2S/lKK/sViOLiC ``` Now, finally we have a `LedgerKey` that correspond to the Wasm byte-code that has been deployed under the `ContractId` we started out with so very long ago. This `LedgerKey` can be used in a final request to the Soroban-RPC endpoint. - ```json { "jsonrpc": "2.0", @@ -337,4 +333,4 @@ And the response we get contains (even more) `LedgerEntryData` that we can decod ``` [`increment` example contract]: /docs/getting-started/storing-data -["View XDR" page of the Stellar Laboratory]: +["View XDR" page of the Stellar Laboratory]: https://laboratory.stellar.org/#xdr-viewer?type=LedgerEntryData&network=testnet diff --git a/api/methods/getNetwork.mdx b/api/methods/getNetwork.mdx index d9de0e50..1d986434 100644 --- a/api/methods/getNetwork.mdx +++ b/api/methods/getNetwork.mdx @@ -5,4 +5,4 @@ description: Returns network config import { RpcMethod } from "@site/src/components/RpcMethod"; - + diff --git a/api/methods/getTransaction.mdx b/api/methods/getTransaction.mdx index cceeec44..d3ccda69 100644 --- a/api/methods/getTransaction.mdx +++ b/api/methods/getTransaction.mdx @@ -5,4 +5,4 @@ description: Returns transaction details import { RpcMethod } from "@site/src/components/RpcMethod"; - + diff --git a/api/methods/sendTransaction.mdx b/api/methods/sendTransaction.mdx index b16d93e6..72549de2 100644 --- a/api/methods/sendTransaction.mdx +++ b/api/methods/sendTransaction.mdx @@ -5,4 +5,4 @@ description: Submits a transaction import { RpcMethod } from "@site/src/components/RpcMethod"; - + diff --git a/api/methods/simulateTransaction.mdx b/api/methods/simulateTransaction.mdx index 1e08d5e6..ba486f18 100644 --- a/api/methods/simulateTransaction.mdx +++ b/api/methods/simulateTransaction.mdx @@ -5,4 +5,4 @@ description: Submits a trial contract invocation transaction import { RpcMethod } from "@site/src/components/RpcMethod"; - + diff --git a/api/pagination.mdx b/api/pagination.mdx index 69023bb2..4a9e0cfa 100644 --- a/api/pagination.mdx +++ b/api/pagination.mdx @@ -8,8 +8,8 @@ Pagination in soroban-rpc is similar to pagination in Horizon. For methods which support it, the pagination arguments are passed as a final object argument with two values: -- `cursor`: string - (optional) A string ID that points to a specific location in a collection of responses and is pulled from the paging_token value of a record. When a cursor is provided Soroban-RPC will *not* include the element whose id matches the cursor in the response. Only elements which appear *after* the cursor are included. -- `limit`: number - (optional) The maximum number of records returned. The limit for [getEvents](methods/getEvents) can range from 1 to 10000 - an upper limit that is hardcoded in Soroban-RPC for performance reasons. If this argument isn't designated, it defaults to 100. +- `cursor`: string - (optional) A string ID that points to a specific location in a collection of responses and is pulled from the paging*token value of a record. When a cursor is provided Soroban-RPC will \_not* include the element whose id matches the cursor in the response. Only elements which appear _after_ the cursor are included. +- `limit`: number - (optional) The maximum number of records returned. The limit for [getEvents](methods/getEvents.mdx) can range from 1 to 10000 - an upper limit that is hardcoded in Soroban-RPC for performance reasons. If this argument isn't designated, it defaults to 100. For example, calling a method with pagination parameter set: @@ -18,10 +18,6 @@ For example, calling a method with pagination parameter set: "jsonrpc": "2.0", "Id": "1", "method": "exampleMethod", - "params": [ - "other", - "arguments", - { "cursor": "1234-1", "limit": 100 } - ] + "params": ["other", "arguments", { "cursor": "1234-1", "limit": 100 }] } ``` diff --git a/dapps/index.mdx b/dapps/README.mdx similarity index 98% rename from dapps/index.mdx rename to dapps/README.mdx index 192ac74b..6c087990 100644 --- a/dapps/index.mdx +++ b/dapps/README.mdx @@ -11,18 +11,17 @@ While the course specifically focuses on the Soroban platform, the knowledge you Through The Soroban Dapps Challenge, you'll have hands-on experience using Soroban's initial versions of the smart contracts environment, a Rust SDK, a CLI, and an RPC server. You'll learn how to write, test, and deploy smart contracts, and you'll get to see your code in action on Futurenet. -# What This Course Entails +## What This Course Entails We've designed this course as a learning adventure. It's a way for developers from the Stellar ecosystem and other blockchain communities to experiment, provide feedback, and contribute to the Soroban development process. As you progress through The Soroban Dapps Challenge, anticipate your code to break and updates to shift things. We invite you to experiment and build but also remind you that changes are afoot as we prepare for the production release. - ## Getting Started To get started, simply head over to the [Dashboard](/dashboard), connect your wallet, and see what challenges await you! -# Giving Your Feedback +## Giving Your Feedback We value your input. Feel free to file issues in the Soroban repos or raise them in the soroban channel in the Stellar Developer [Discord](https://discord.gg/3qrBhbwE). diff --git a/dapps/dapp-challenges/challenge-0-crowdfund.mdx b/dapps/dapp-challenges/challenge-0-crowdfund.mdx index 0c54fb91..adff7075 100644 --- a/dapps/dapp-challenges/challenge-0-crowdfund.mdx +++ b/dapps/dapp-challenges/challenge-0-crowdfund.mdx @@ -116,7 +116,7 @@ npm run dev Now open your browser and visit [http://localhost:3000](http://localhost:3000). You should be able to see the frontend of your dapp. -> Note: Follow the instructions below and ensure that you have funded your wallet address that you intend to use from browser, otherwise the dapp display will be blank and a 'Account not found' will be printed on browser's console only. If you are using Freighter, be sure that you have properly configured the Freighter Wallet by following the instructions [here](../guides/wallets#connect-a-wallet-freighter). +> Note: Follow the instructions below and ensure that you have funded your wallet address that you intend to use from browser, otherwise the dapp display will be blank and a 'Account not found' will be printed on browser's console only. If you are using Freighter, be sure that you have properly configured the Freighter Wallet by following the instructions [here](../guides/wallets.mdx#connect-a-wallet-freighter). Now that you have the frontend running, it's time to connect it with the backend, your smart contract, that defines the rules and logic of the crowdfund campaign, including the function for accepting contributions. If you want to dig into the specifics of the contract, take a look at the video walkthrough of the contract code [here](https://youtu.be/vTz0CQYnMRQ?t=260&feature=shared). @@ -225,7 +225,7 @@ You should see an updated balance reflecting the amount you have pledged in the ## Checkpoint 4: 🚢 Ship it! 🚁 -Now that your dapp is fully functional, its time to deploy it to a production environment. In this step, you will learn how to deploy your dapp to Vercel, a cloud platform for static sites that offers a quick and effective way to deploy the frontend of your dapp. This section requires that you have a [Vercel account] and the Vercel cli installed. +Now that your dapp is fully functional, its time to deploy it to a production environment. In this step, you will learn how to deploy your dapp to Vercel, a cloud platform for static sites that offers a quick and effective way to deploy the frontend of your dapp. This section requires that you have a [Vercel account] and the Vercel cli installed. If you don't have the Vercel cli installed, run the following command to install it globally: @@ -241,7 +241,7 @@ Next, you will need to remove the `target` directory to save space for the the d rm -rf target ``` ->Note: You can build this directory again by running `soroban contract build` in the `contracts/abundance` directory. +> Note: You can build this directory again by running `soroban contract build` in the `contracts/abundance` directory. Then, remove any existing `.vercel` directory in your project to ensure that you are starting with a clean slate: @@ -255,7 +255,7 @@ Then, run the following command to deploy your example dapp: vercel --prod ``` -Vercel will prompt you to link your local project to a new Vercel project. +Vercel will prompt you to link your local project to a new Vercel project. Follow the answers to the prompts below to ensure that your local project is correctly linked to a new Vercel project: ```bash @@ -286,7 +286,6 @@ You can now visit the preview link to see your deployed dapp! 🎉 Remember, you must add Futurenet network lumens to your Freighter wallet to interact with the deployed example dapp. Visit https://laboratory.stellar.org/#account-creator?network=futurenet, and follow the instructions to create your Freighter account on Futurenet. - ## Checkpoint 5: 💪 Pass the Challenge! Now it's time to submit your work! @@ -313,6 +312,7 @@ In order to successfully complete this challenge, your work needs to be checked. ```sh Public Key: GBSXUXZSA2VEXN5VGOWE5ODAJLC575JCMWRJ4FFRDWSTRCJ123456789 ``` + 3. Create a Pull Request to the `stellar/soroban-dapps-challenge/crowdfund` branch. When the PR is created, CI actions will check the `crowdfund/challenge/output.txt` file data and update your progress. 4. Wait for the CI/CD pipeline results. 5. Fix errors if present: @@ -371,4 +371,4 @@ Then via the web UI, you should be able to: ## 🛡️🗡️ Take On More Challenges -View your progress and take on more challenges by visiting your [User Dashboard!](/dashboard) \ No newline at end of file +View your progress and take on more challenges by visiting your [User Dashboard!](/dashboard) diff --git a/dapps/dapp-challenges/challenge-1-payment.mdx b/dapps/dapp-challenges/challenge-1-payment.mdx index d78a8c89..41bbf31c 100644 --- a/dapps/dapp-challenges/challenge-1-payment.mdx +++ b/dapps/dapp-challenges/challenge-1-payment.mdx @@ -42,12 +42,12 @@ import { ParentChallengeContractForm } from "../../src/components/atoms/challeng import CompleteStepButton from "../../src/components/atoms/complete-step-button"; import StartChallengeButton from "../../src/components/atoms/start-challenge-button"; import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem" -import './styles.css'; +import TabItem from "@theme/TabItem"; +import "./styles.css"; -This challenge will guide you through the process of setting up, customizing, and deploying a Soroban Payment dapp, a blockchain-powered payment application designed to work with the Freighter wallet. Payment dapps are powerful because they offer users equitable and accessible means to send and receive payments. Transactions via a payment dapp are peer-to-peer, which means that no central authority, third-party, or bank oversees or controls the payment. This decentralization reduces payment fees, which are comparatively minimal on a blockchain, and transaction time, which is, via a payment dapp, almost instantaneous. What's more, the wallet integration in a payment dapp, like Freighter in this case, means that anyone with a smartphone and the wallet installed can use the payment dapp, no matter where they are in the world. +This challenge will guide you through the process of setting up, customizing, and deploying a Soroban Payment dapp, a blockchain-powered payment application designed to work with the Freighter wallet. Payment dapps are powerful because they offer users equitable and accessible means to send and receive payments. Transactions via a payment dapp are peer-to-peer, which means that no central authority, third-party, or bank oversees or controls the payment. This decentralization reduces payment fees, which are comparatively minimal on a blockchain, and transaction time, which is, via a payment dapp, almost instantaneous. What's more, the wallet integration in a payment dapp, like Freighter in this case, means that anyone with a smartphone and the wallet installed can use the payment dapp, no matter where they are in the world. ## Checkpoint 0: 📦 Install Dependencies @@ -177,7 +177,7 @@ $ webpack-dev-server --config config/webpack.dev.js Now open your browser and navigate to [`http://localhost:9000`](http://localhost:9000). You should see the Payment Dapp running in your browser. - connect + connect ## Checkpoint 4: 🚀 Token Transfer Odyssey @@ -201,15 +201,19 @@ Strap in and get ready to send some tokens! In this step, you will use the Payme #### 📡 Connect Freighter to Payment Dapp Follow the steps in the [Connect a Wallet: Freighter](../guides/wallets.mdx) guide to connect Freighter to the Payment Dapp. + #### Add Soroban Token + To add the newly minted DT token type to your wallet, open your Freighter wallet and click on the `Manage Assets` button at the bottom of the screen. + manage assets Then click on the `Add Soroban token ` button and enter the token contract ID that was returned when you deployed the token smart contract. + add token
new token @@ -218,7 +222,9 @@ Then click on the `Add Soroban token ` button and enter the token contract ID th #### Check Token Addition + You should now see the Soroban token in your Freighter wallet. + added balance @@ -235,7 +241,9 @@ You should now see the Soroban token in your Freighter wallet. #### Connect Freighter and Select Account + Back on your dapp's frontend webpage, make sure Freighter is connected and then select the account that will be used to send Soroban tokens. Click "next" to continue. + next @@ -244,31 +252,40 @@ Back on your dapp's frontend webpage, make sure Freighter is connected and then #### Provide Token Transfer Details To send DT tokens via the Payment dapp, provide the public key of the account that will receive the Soroban tokens. (This could be another of your own Freighter accounts.) -payment destination + +payment destination Input the token ID of the Soroban token. -choose token + +choose token Input the amount of Soroban tokens to send. -select token + +select token Confirm the payment settings, which include the option to add a memo and show the transaction fee. + payment settings
#### Confirm and Submit Transaction + Review the transaction details to ensure accuracy and then click "Sign with Freighter". Freighter will prompt you to sign the transaction with your wallet's private key. -confirm payment + +confirm payment Once signed, click "Submit Payment." The transaction will be submitted to the network. -submit payment + +submit payment The Payment Dapp will show a confirmation message once the transaction has been successfully submitted. This includes the XDR response, which can be decoded using [stellar laboratory](https://laboratory.stellar.org/#xdr-viewer?type=TransactionResult&network=futurenet). -end + +end You can now check the balance of the receiving account to ensure that the transaction was successful. + balance receiver As stated before, you can also check the balance of an account with the soroban-cli by running the following command: @@ -283,7 +300,6 @@ As stated before, you can also check the balance of an account with the soroban- --id ``` - Output: ```bash diff --git a/dapps/dapp-challenges/challenge-2-liquidity-pool.mdx b/dapps/dapp-challenges/challenge-2-liquidity-pool.mdx index 85ca637a..638d8112 100644 --- a/dapps/dapp-challenges/challenge-2-liquidity-pool.mdx +++ b/dapps/dapp-challenges/challenge-2-liquidity-pool.mdx @@ -21,7 +21,6 @@ import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; import "./styles.css"; - Liquidity Pool Dapp Challenge. @@ -43,7 +42,7 @@ import "./styles.css"; A liquidity pool is a collection of tokens or digital assets deposited by users and held in a smart contract or dapp that can be used to provide essential liquidity to decentralized exchanges (DEXs) and other decentralized finance (DeFi) protocols. Since liquidity plays a crucial role in enabling DeFi systems, liquidity pools, where assets can be held, lent, borrowed, swapped, or traded (depending on dapp functionality), are fundamental to these systems. -The functionality of this liquidity pool dapp will allow users to mint tokens, deposit liquidity, swap between asset types, and withdraw funds from the liquidity pool. This dapp challenge will walk you through the step-by-step process of creating and launching a liquidity pool dapp on Stellar using Soroban smart contracts. You will learn how to deploy smart contracts to a sandbox environment and interact with them through a web frontend. In this context, the term "ship" refers to finalizing the development process of your dapp, ensuring that it functions as expected and is accessible for user interaction and testing through a hosted frontend. Despite the end-to-end functionality of this challenge, this dapp is not promoted nor intended for deployment in a production-level setting on Futurenet, but rather is designed for educational purposes. +The functionality of this liquidity pool dapp will allow users to mint tokens, deposit liquidity, swap between asset types, and withdraw funds from the liquidity pool. This dapp challenge will walk you through the step-by-step process of creating and launching a liquidity pool dapp on Stellar using Soroban smart contracts. You will learn how to deploy smart contracts to a sandbox environment and interact with them through a web frontend. In this context, the term "ship" refers to finalizing the development process of your dapp, ensuring that it functions as expected and is accessible for user interaction and testing through a hosted frontend. Despite the end-to-end functionality of this challenge, this dapp is not promoted nor intended for deployment in a production-level setting on Futurenet, but rather is designed for educational purposes. ## Checkpoint 0: 📦 Install 📚 @@ -71,10 +70,9 @@ cargo install_soroban Soroban CLI is the command line interface to Soroban. It allows you to build, deploy, and interact with smart contracts, configure identities, generate key pairs, manage networks, and more. The soroban-cli alias that is used in this challenge is a pinned version of the soroban-cli that is used in the Soroban Dapps Challenge. Using the soroban-cli alias ensures that the challenge is reproducible and that all participants are using the same version of Soroban. - ## Checkpoint 1: 🎬 Deploy Smart Contracts -Deploying a smart contract in a production setting involves submitting the contract code to the blockchain's main network (Mainnet), where it becomes part of the chain's immutable ledger. When you deploy the smart contracts in this challenge, you'll instead deploy to Futurenet, a test network with more cutting-edge features that have not yet been implemented in the Mainnet. Deploying smart contracts to a sandbox environment simulates the production-level deployment process without actually affecting Mainnet. +Deploying a smart contract in a production setting involves submitting the contract code to the blockchain's main network (Mainnet), where it becomes part of the chain's immutable ledger. When you deploy the smart contracts in this challenge, you'll instead deploy to Futurenet, a test network with more cutting-edge features that have not yet been implemented in the Mainnet. Deploying smart contracts to a sandbox environment simulates the production-level deployment process without actually affecting Mainnet. Now that you have the Liquidity Pool branch checked out, load the contracts and initialize them in the sandbox environment by running the following commands in your terminal: @@ -132,7 +130,7 @@ You will need to add some Futurenet network lumens to your wallet to interact wi ## Checkpoint 3: 🌊 Dive into the Liquidity Pool -Embark on a tidal journey! In this step you will mint, deposit, swap, and withdraw tokens from the liquidity pool. Minting tokens, depositing liquidity, swapping between asset types, and withdrawing funds from the liquidity pool constitute the basic lifecycle of interacting with a DeFi protocol. +Embark on a tidal journey! In this step you will mint, deposit, swap, and withdraw tokens from the liquidity pool. Minting tokens, depositing liquidity, swapping between asset types, and withdrawing funds from the liquidity pool constitute the basic lifecycle of interacting with a DeFi protocol. In the context of liquidity pools, depositing and withdrawing assets involve connecting a digital wallet and submitting deposit/withdraw transactions. In this liquidity pool dapp challenge specifically, you will also need to mint the test tokens that you will then use to make deposits to the liquidity pool. (This minting of test tokens is different from liquidity pools where depositors may receive minted tokens in exchange for their deposited funds.) Perhaps one of the most important actions a user can take through liquidity pool dapps is swapping tokens. In fact, the ability to swap from one asset to another through a liqudity pool is a powerful feature of DeFi protocols: instead of exchanging assets through traditional financial institutions and intermediaries, users can have direct access to decentralized asset exchange via liquidity pool dapps, without needing a bank account or other traditional financial instruments. @@ -194,7 +192,7 @@ You should see an updated balance in the account balance component. #### Deposit into the Liquidity Pool -Depositing assets into the liquidity pool involves users submitting deposit transactions via the frontend to deposit tokens from their wallet into the liquidity pool. In this dapp you will make a deposit of two asset types in order to swap between those asset types. In other DeFi protocols, users may also deposit liquidity into a liquidity pool in order to earn yields on their deposits. The intial deposit of liquidity into a liquidity pool is what sets the initial price of the tokens in the pool. For example, if a user deposits 37000 USDC and 1 BTC, the price of each BTC token will be 37000 USDC. +Depositing assets into the liquidity pool involves users submitting deposit transactions via the frontend to deposit tokens from their wallet into the liquidity pool. In this dapp you will make a deposit of two asset types in order to swap between those asset types. In other DeFi protocols, users may also deposit liquidity into a liquidity pool in order to earn yields on their deposits. The intial deposit of liquidity into a liquidity pool is what sets the initial price of the tokens in the pool. For example, if a user deposits 37000 USDC and 1 BTC, the price of each BTC token will be 37000 USDC. Open the frontend, enter the desired token amounts, and click the "Deposit" button. You should see a popup from Freighter asking you to sign the transaction. @@ -241,7 +239,6 @@ This liquidity pool dapp challenge uses a [specific formula] in its smart contra [specific formula]: https://github.com/stellar/soroban-dapps-challenge/blob/f7cde6fc6cfce5470ebab9b7489c367c3306317f/contracts/liquidity-pool/src/lib.rs#L251 - Also important to note is how slippage works in this dapp. Slippage refers to the maximum variation percentage accepted for the desired deposit amounts. The higher the percentage, the greater the chance of a successful transaction, but you may not get such a good price. Here, users can set the max slippage to their desired amount. To complete a swap between USDC and BTC test tokens, open the swap tab of the frontend, input the desired token swap amounts, and click the "Swap" button. You should see a popup from Freighter asking you to sign the transaction. @@ -323,7 +320,8 @@ Once the transaction is confirmed, you should see updated balances on the fronte ## Checkpoint 4: 🚢 Ship It! 🚁 -Now that your dapp is fully functional, its time to deploy it to a production environment. In this step, you will learn how to deploy your dapp to Vercel, a cloud platform for static sites that offers a quick and effective way to deploy the frontend of your dapp. This section requires that you have a [Vercel account] and install the Vercel CLI. + +Now that your dapp is fully functional, its time to deploy it to a production environment. In this step, you will learn how to deploy your dapp to Vercel, a cloud platform for static sites that offers a quick and effective way to deploy the frontend of your dapp. This section requires that you have a [Vercel account] and install the Vercel CLI. [Vercel account]: https://vercel.com/login @@ -333,7 +331,7 @@ First, you will remove the target directory, as it is not used by Vercel to depl rm -rf target ``` ->Note: You can build this directory again by running `soroban contract build` in the `contracts/abundance` directory. +> Note: You can build this directory again by running `soroban contract build` in the `contracts/abundance` directory. Next, you must move your `.soroban` directory to the frontend directory. @@ -370,13 +368,14 @@ Then, remove any existing `.vercel` directory in your project to ensure that you ```bash rm -rf .vercel ``` + Then, run the following command to deploy your example dapp: ```bash vercel --prod ``` -Vercel will prompt you to link your local project to a new Vercel project. +Vercel will prompt you to link your local project to a new Vercel project. Follow the answers to the prompts below to ensure that your local project is correctly linked to a new Vercel project: ```bash @@ -476,4 +475,4 @@ Then, via the web UI, you should be able to: ## 🛡️🗡️ Take On More Challenges -View your progress and take on more challenges by visiting your [User Dashboard!](/dashboard) \ No newline at end of file +View your progress and take on more challenges by visiting your [User Dashboard!](/dashboard) diff --git a/dapps/guides/wallets.mdx b/dapps/guides/wallets.mdx index d8f965b5..4b133871 100644 --- a/dapps/guides/wallets.mdx +++ b/dapps/guides/wallets.mdx @@ -3,6 +3,7 @@ sidebar_position: 4 title: Wallets description: Learn how to use wallets on Soroban --- + import freighter_settings from "../../static/img/freighter_settings.png"; import gear_icon from "../../static/img/gear_icon.png"; import preferences_menu from "../../static/img/preferences_menu.png"; @@ -16,7 +17,7 @@ This page will teach you how to connect and code with wallets on Soroban Dapps. To use Freighter with Soroban Dapps, you will need to enable exmperimental mode. Below are instructions on how to do this: -First, click on the Freighter extension icon in your browser and click on the gear icon in the bottom right corner. +First, click on the Freighter extension icon in your browser and click on the gear icon in the bottom right corner. `(Settings(⚙️)>Preferences>ENABLE EXPERIMENTAL MODE).` @@ -30,18 +31,21 @@ Then, enable experimental mode by toggling the switch. freighter settings -
+
Finally, in the case of the example dapps in the Soroban Dapps Challenge, there will often be a "Connect" button on the frontend of the dapps. Ensure that you are connected to the proper network and click on this button to connect your wallet. -connect freighter example +connect freighter example -
-
+
+
> Note: You will use Futurenet and the Standalone network throughout these challenges. - ## Wallet Integration: React Wallets are an essential part of any dapp. They allow users to interact with the blockchain and sign transactions. In this section, you'll learn how to integrate wallets into your React dapps. @@ -114,4 +118,4 @@ Here's a breakdown of the code: ## Conclusion -In this section, you learned how to integrate wallets into your dapps. You also learned how to use the `useAccount` and `useNetwork` hooks to access account and network data. If you want to learn more about Soroban Dapp development, please reach out to us on [Discord](https://discord.com/channels/897514728459468821/1037073682599780494). We'd love to hear from you! \ No newline at end of file +In this section, you learned how to integrate wallets into your dapps. You also learned how to use the `useAccount` and `useNetwork` hooks to access account and network data. If you want to learn more about Soroban Dapp development, please reach out to us on [Discord](https://discord.com/channels/897514728459468821/1037073682599780494). We'd love to hear from you! diff --git a/dapps/scaffold-soroban.mdx b/dapps/scaffold-soroban.mdx index edf07d1f..15c4960b 100644 --- a/dapps/scaffold-soroban.mdx +++ b/dapps/scaffold-soroban.mdx @@ -4,9 +4,9 @@ title: Scaffold Soroban description: Dive into the simple implementations of Soroban dapps to understand and learn the Soroban ecosystem. --- -import ReactPlayer from 'react-player' +## Demonstrative Soroban Dapps -# Scaffold Soroban: Demonstrative Soroban Dapps +import ReactPlayer from "react-player"; The **Soroban** team has invested considerable effort into contract implementation. They’ve built CLI’s and libraries, enabling contract builders to create and invoke using Rust, which forms the “backend” of Soroban. However, the “frontend”, which involves JS client libraries, required attention. @@ -17,32 +17,43 @@ During the Soroban Hackathon, we recognized that while the frontend libraries we To tackle this, the **Wallet Engineering** team, in collaboration with the Soroban team, has decided to launch “Scaffold Soroban”, a collection of demo dapps. These dapps demonstrate basic functionalities in a structured, easy-to-follow manner, primarily focusing on how to construct/deploy Soroban contract invocations. ## Dapp Demos + For easy accessibility, we have compiled the dapps into a [single repository](https://github.com/stellar/scaffold-soroban), which contains the following dapps: ### [1. Payment Dapp](https://github.com/stellar/soroban-react-payment) - This dapp mirrors the Soroban payment flow in Freighter by using the wallet’s Soroban token balances to invoke the `xfer` method on the token’s contract. See the [demo](https://github.com/stellar/soroban-react-payment/releases/tag/v1.0.0) - + ### [2. Mint Token Dapp](https://github.com/stellar/soroban-react-mint-token) This dapp allows a token admin to mint tokens by using the admin account to invoke the `mint` method on the token’s contract. See the [demo](https://github.com/stellar/soroban-react-mint-token/releases/tag/v1.0.0) - + + ### [3. Atomic Swap Dapp](https://github.com/stellar/soroban-react-atomic-swap) This dapp demonstrates a simplified swap between two tokens by using the wallet’s Soroban token balances to invoke the `swap` method on the atomic swap contract. See the [demo](https://github.com/stellar/soroban-react-atomic-swap/releases/tag/v1.0.0) - -### How To Explore the Dapps on Scaffold-Soroban + + +## How To Explore the Dapps on Scaffold-Soroban To begin using these examples, navigate to [Scaffold-Soroban](https://scaffold-soroban.stellar.org/) and choose the name of the dapp you're interested in from the "select demo" dropdown: @@ -58,7 +69,7 @@ With the introduction of these dapps, let's delve deeper into some of their [sta Functionality behind the dapps is extensive and diverse, leveraging the `@stellar/stellar-sdk` library to integrate with the Soroban RPC and facilitating direct communication with Soroban using a JSON RPC interface on the Stellar network. They are equipped to communicate across different network setups, as they incorporate the `RPC_URLS` and `getServer` functionalities, providing adaptability that is crucial for various development and deployment scenarios. Users can retrieve user-friendly token information without engaging with complex blockchain operations, by utilizing functions like `getTokenSymbol`, `getTokenName`, and `getTokenDecimals`. -A significant feature is the `simulateTx` function, which allows users to preview the outcome of a transaction before actually executing it. `simulateTx` allows users to submit a trial contract invocation by first running a simulation of the contract invocation as defined on the incoming transaction. The results are then applied to a new copy of the transaction, which is returned with the ledger footprint and authorization set, making it ready for signing and sending. The returned transaction will also have an updated fee, the sum of the fee set on the incoming transaction with the contract resource fees estimated from the simulation. It is advisable to check the fee on the returned transaction and validate or take appropriate measures for interaction with the user to confirm it is acceptable. +A significant feature is the `simulateTx` function, which allows users to preview the outcome of a transaction before actually executing it. `simulateTx` allows users to submit a trial contract invocation by first running a simulation of the contract invocation as defined on the incoming transaction. The results are then applied to a new copy of the transaction, which is returned with the ledger footprint and authorization set, making it ready for signing and sending. The returned transaction will also have an updated fee, the sum of the fee set on the incoming transaction with the contract resource fees estimated from the simulation. It is advisable to check the fee on the returned transaction and validate or take appropriate measures for interaction with the user to confirm it is acceptable. Other utilities such as `accountToScVal` and `numberToI128` are also provided to simplify transaction creation by converting user-friendly inputs into the formats expected by the Soroban RPC on the Stellar network. Furthermore, the dapps are built with premade helper functions such as the `makePayment` function which facilitates streamlined "transfer" operations and also includes memos for supplementary transaction-related information. diff --git a/docs/index.mdx b/docs/README.mdx similarity index 99% rename from docs/index.mdx rename to docs/README.mdx index d2dd1114..990f0e6e 100644 --- a/docs/index.mdx +++ b/docs/README.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 0 +sidebar_position: 10 title: Welcome --- diff --git a/docs/advanced-tutorials/_category_.json b/docs/advanced-tutorials/_category_.json deleted file mode 100644 index 44b2f6a5..00000000 --- a/docs/advanced-tutorials/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "position": 45, - "label": "Advanced Tutorials", - "link": { - "type": "generated-index" - } - } \ No newline at end of file diff --git a/docs/command-line-reference/_category_.json b/docs/command-line-reference/_category_.json deleted file mode 100644 index f133e26a..00000000 --- a/docs/command-line-reference/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "position": 0, - "label": "Command-line Reference", - "link": { - "type": "generated-index" - } -} diff --git a/docs/developer-tools.mdx b/docs/developer-tools.mdx index f76485a1..8801bf30 100644 --- a/docs/developer-tools.mdx +++ b/docs/developer-tools.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 60 +sidebar_position: 75 title: Developer Tools --- @@ -11,7 +11,7 @@ All tools currently listed are built and maintained by dedicated community membe ### [Soroban Dev](https://sorobandev.com/) -A web developer’s guide to Soroban. Contains guides for learning Soroban and Rust, developer tools, example applications, and more. +A web developer's guide to Soroban. Contains guides for learning Soroban and Rust, developer tools, example applications, and more. ### [Use Soroban](https://usesoroban.app/) diff --git a/docs/fundamentals-and-concepts/faq.mdx b/docs/faq.mdx similarity index 92% rename from docs/fundamentals-and-concepts/faq.mdx rename to docs/faq.mdx index 68ff9296..266597bd 100644 --- a/docs/fundamentals-and-concepts/faq.mdx +++ b/docs/faq.mdx @@ -1,6 +1,6 @@ --- -sidebar_position: 2 -title: Soroban on Stellar FAQs +sidebar_position: 80 +title: FAQs description: Frequently asked questions about Soroban on Stellar. --- @@ -15,10 +15,7 @@ description: Frequently asked questions about Soroban on Stellar. property="og:description" content="Frequently asked questions about Soroban on Stellar." /> - + ### What is Soroban to Stellar? Is it a new blockchain? @@ -35,7 +32,7 @@ Yes. Stellar accounts are shared with Soroban. Smart contacts have access to Ste ### Can Soroban contracts interact with Stellar assets? -Yes. Soroban contains a built-in Stellar Asset Contract that is able to interact with classic trustlines. Read more about this [here](../advanced-tutorials/stellar-asset-contract.mdx). +Yes. Soroban contains a built-in Stellar Asset Contract that is able to interact with classic trustlines. Read more about this [here](tokens/stellar-asset-contract.mdx). ### Do issuers of Stellar assets maintain their authorization over an asset that has been sent to a non-account identifier in Soroban? (AUTH_REQUIRED, AUTH_REVOCABLE, AUTH_CLAWBACK) diff --git a/docs/fundamentals-and-concepts/interacting-with-contracts.mdx b/docs/fundamentals-and-concepts/interacting-with-contracts.mdx deleted file mode 100644 index 459835b6..00000000 --- a/docs/fundamentals-and-concepts/interacting-with-contracts.mdx +++ /dev/null @@ -1,156 +0,0 @@ ---- -sidebar_position: 15 -title: Interacting with Contracts -description: Interact with smart contracts. ---- - - - Interact with smart contracts. - - - - - - -## Three types of interactions - -### Function call - -A function call is the simplest and least expensive kind of contract interaction. A function call does exactly what you would expect a contract call to do in any other software development context: the contract transfers control and data to another part of the _same_ contract. Because a function call always transfers control to the same contract, they do not change the values returned by `get_current_contract` and `get_invoking_contract`. A function call is the only way to access the private methods of a contract, although it can also be used to access the public methods of a contract. - -To perform a function call, simply make a Rust function call. - -### Contract invocation - -A contract invocation is a more powerful and more expensive kind of contract interaction. A contract invocation is similar to starting a new process because the code that runs will be in a separate address space, meaning that they do not share any data other than what was passed in the invocation. While a contract invocation typically transfers control to a _different_ contract, it is possible to transfer control to the currently running contract. Regardless of whether the contract that receives control is a different contract or the currently running contract, the value returned by `get_invoking_contract` will be the previous value of `get_current_contract`. A contract invocation can only access the public methods of a contract. - -If a contract contains a public function `f`, then invoking `f` can be done by making a Rust function call to `f::invoke`. - -Some contracts, such as the token contract, only export the contract invocation functions. In doing so, they are able to assign those functions friendly names. For example, [initialize](https://github.com/stellar/soroban-token-contract/blob/42380647bb817bf01c739c19286f18be881e0e41/src/contract.rs#L55-L57) - -```rust -#[contractimpl(export_if = "export")] -impl TokenTrait for Token { - fn initialize(e: Env, admin: Identifier, decimal: u32, name: Binary, symbol: Binary) { -``` - -is [exported](https://github.com/stellar/soroban-token-contract/blob/42380647bb817bf01c739c19286f18be881e0e41/src/lib.rs#L26) as - -```rust -pub use crate::contract::initialize::invoke as initialize; -``` - -This function is then easily [called by the liquidity pool contract](https://github.com/stellar/soroban-examples/blob/4060d3bd5ee7846020b68ee583665a4d4cf4b315/liquidity_pool/src/lib.rs#L164-L171). - -### Stellar Operation - -A Stellar operation is the ultimate entry point of every contract interaction. An operation transfers control and external data to a contract, allowing execution to begin. - -This kind of interaction is currently supported in experimental versions of stellar-core only. - -## Interacting with contracts in tests - -[Debugging contracts](debugging) explains that it is much more convenient to debug using native code than Wasm. Given that you are testing native code, it is tempting to interact with your contract directly using function calls. If you attempt this approach, you will find that it doesn't always work. Function call interactions do not set the environment into the correct state for contract execution, so functions involving contract data and determining the current or invoking contract will not work. - -When writing tests, it is important to always interact with contracts through contract invocation. In a production setting, contract invocation will execute Wasm bytecode loaded from the ledger. So how does this work if you are testing native code? You must register your contract with the environment, so it knows what functions are available and how to call them. While this sounds complex, the `contractimpl` procedural macro automatically generates almost all the code to do this. All you have to do is write a small [stub](https://github.com/stellar/soroban-token-contract/blob/42380647bb817bf01c739c19286f18be881e0e41/src/testutils.rs#L12-L15) to actually call the generated code, such as - -```rust -pub fn register_test_contract(e: &Env, contract_id: &[u8; 32]) { - let contract_id = FixedBinary::from_array(e, *contract_id); - e.register_contract(&contract_id, crate::contract::Token {}); -} -``` - -Some contracts, such as the token contract, also provide a [friendlier interface](https://github.com/stellar/soroban-token-contract/blob/42380647bb817bf01c739c19286f18be881e0e41/src/testutils.rs#L26-L191) to facilitate testing. There are many ways these interfaces might make testing easier, but one common one is to allow automatic message signing by passing a [ed25519_dalek::Keypair](https://docs.rs/ed25519-dalek/latest/ed25519_dalek/struct.Keypair.html). - -Note that everything described in this section is only available if the `testutils` feature is enabled. - -### Example - -This machinery can also be used to test multiple contracts together. For example, the single offer contract test case [creates a token](https://github.com/stellar/soroban-examples/blob/56fef787395b5aed7cd7b19772cca28e21b3feb5/single_offer/src/test.rs#L22). - -## Calling contracts - -Contracts are invoked through a pair of host functions `call` and `try_call`: - -- `try_call(contract, function, args)` calls `function` exported from `contract`, passing `args` and returning a `Status` on any error. -- `call(contract, function, args)` just calls `try_call` with its arguments and traps on `Status`, essentially propagating the error. - -In both cases `contract` is a `Binary` host object containing the contract ID, `function` is a `Symbol` holding the name of an exported function to call, and `args` is a `Vector` of values to pass as arguments. - -These host functions can be invoked in two separate ways: - -- From outside the host, such as when a user submits a transaction that calls a contract. -- From within the host, when one contract calls another. - -Both cases follow the same logic: - -- The contract's Wasm bytecode is retrieved from a `CONTRACT_DATA` ledger entry in the host's storage system. -- A Wasm VM is instantiated for the duration of the invocation. -- The function is looked up and invoked, with arguments passed from caller to callee. - -When a call occurs from outside the host, any arguments will typically be provided in serialized XDR form accompanying the transaction, and will be deserialized and converted to host objects automatically before invoking the contract. - -When a call occurs from inside the host, the caller and callee contracts _share the same host_ and the caller can pass references to host objects directly to the callee without any need to serialize or deserialize them. - -Since host objects are immutable, there is limited risk to passing a shared reference from one contract to another: the callee cannot modify the object in a way that would surprise the caller, only create new objects. - -## Transaction Simulation - -### Footprint - -As mentioned in the [persisting data](../fundamentals-and-concepts/persisting-data.mdx) section, a contract can only load or store `CONTRACT_DATA` entries that are declared in a _footprint_ associated with its invocation. - -A footprint is a set of ledger keys, each marked as either read-only or read-write. Read-only keys are available to the transaction for reading; read-write keys are available for reading, writing, or both. - -Any Soroban transaction submitted by a user has to be accompanied by this footprint. A single footprint encompasses _all_ the data read and written by _all_ contracts transitively invoked by the transaction: not just the initial contract that the transaction calls, but also all contracts it calls, and so on. - -Since it can be difficult for a user to know which ledger entries a given contract call will attempt to read or write (especially entries that are caused by other contracts deep within a transaction), the host provides an auxiliary `simulateTransaction` mechanism that executes a transaction against a temporary, possibly out-of-date _snapshot_ of the ledger. The `simulateTransaction` mechanism is _not_ constrained to only read or write the contents of a footprint; rather it _records_ a footprint describing the transaction's execution, discards the execution's effects, and then returns the recorded footprint to its caller. - -This simulation-provided footprint can then be used to accompany a "real" submission of the same transaction to the network for real execution. If the state of the ledger has changed too much between the time of the simulated and the real submission, the footprint may be too stale and no longer accurately identify the _keys_ the transaction needs to read and/or write, at which point the simulation must be retried to refresh the footprint. - -In any event (whether successful or failing), the real transaction will execute atomically, deterministically, and with serializable consistency semantics. An inaccurate footprint simply causes deterministic transaction failure, not a stale-read anomaly. All effects of such a failed transaction are discarded, as they would be in the presence of any other error. - -### Authorization - -See the [authorization overview](authorization.mdx) docs and authorization in -transactions [section][auth-data] for general information on Soroban -authorization. - -[auth-data]: ./invoking-contracts-with-transactions.mdx#authorization-data - -Soroban's `simulateTransaction` mechanism can also be used to compute the `SorobanAuthorizedInvocation` trees -that must be authorized by the `Address`es for all the -`require_auth` checks to pass. - -Soroban host provides a special 'recording' mode for auth. Whenever -`require_auth` is called, the host records its context (address, contract id, -function, arguments), attributes it to a `SorobanAuthorizedInvocation` tree, and marks -it as successful. Then, after the invocation has finished, `simulateTransaction` can return -all the recorded trees, as well as the generated random nonce values. - -Given this information from the simulation, the client only needs to provide these -trees and nonces to the respective `Address`es for signing and then build the -final transaction using the simulation output and the corresponding signatures. - -The recording auth mode is optional for `simulateTransaction`. For example, when dealing -with the custom account contracts, it may be necessary to simulate the custom -account's `__check_auth` code (that is simply omitted in the recording auth mode), -for example, to get its ledger footprint. The non-recording mode is referred to -as 'enforcing'. Enforcing mode is basically equivalent to running the -transaction on-chain (with possibly a slightly stale ledger state); hence, it -requires all the signatures to be valid. - -Note that the recording auth mode never emulates authorization failures. The -reason for that is that failing authorization is always an exceptional -situation (i.e., the `Address`es for which you don't anticipate successful -authorization shouldn't be used in the first place). It is similar to how, for -example, the `simulateTransaction` mechanism doesn't emulate failures caused by the incorrect -footprint. `simulateTransaction` with enforcing auth mode may still be used to verify the -signatures before executing the transaction on-chain. diff --git a/docs/fundamentals-and-concepts/migrating-from-evm/_category_.json b/docs/fundamentals-and-concepts/migrating-from-evm/_category_.json deleted file mode 100644 index ee88e50f..00000000 --- a/docs/fundamentals-and-concepts/migrating-from-evm/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "position": 16, - "label": "Migrating from EVM", - "link": { - "type": "generated-index" - } -} diff --git a/docs/getting-started/_category_.json b/docs/getting-started/_category_.json index 6871e3ab..a2e1fc2e 100644 --- a/docs/getting-started/_category_.json +++ b/docs/getting-started/_category_.json @@ -1,7 +1,4 @@ { - "position": 10, - "label": "Getting Started", - "link": { - "type": "generated-index" - } -} \ No newline at end of file + "position": 20, + "label": "Getting Started" +} diff --git a/docs/getting-started/create-an-app.mdx b/docs/getting-started/create-an-app.mdx index 075b833c..6a6b5158 100644 --- a/docs/getting-started/create-an-app.mdx +++ b/docs/getting-started/create-an-app.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 6 +sidebar_position: 50 title: 5. Create an App description: Make a frontend web app that interacts with your smart contracts. --- @@ -476,7 +476,7 @@ Here are some common issues and how to fix them. Sometimes the call to `hello` can start failing. You can obviously stub out the call and define `result` some other way to troubleshoot. -One of the common problems here is that the contract becomes [archived](../fundamentals-and-concepts/state-archival.mdx). To check if this is the problem, you can re-run `npm run reset`. +One of the common problems here is that the contract becomes [archived](../soroban-internals/state-archival.mdx). To check if this is the problem, you can re-run `npm run reset`. If you're still having problems, join our Discord (link above) or [open an issue in GitHub](https://github.com/stellar/soroban-docs/issues/new/choose). @@ -495,6 +495,6 @@ Looking at `git diff` will be a great way to remember all the interesting things At this point, you've seen a full end-to-end example of building on Soroban! What's next? You choose! You can: -- See more complex example contracts in the [Basic Tutorials](/docs/category/basic-tutorials) and [Advanced Tutorials](/docs/category/advanced-tutorials) sections. -- Learn more about the [fundamentals and concepts](/docs/category/fundamentals-and-concepts) of Soroban. +- See more complex example contracts in the [Tutorials](../tutorials) sections. +- Learn more about the [internal architecture and design](../category/soroban-internals) of Soroban. - Check out a more full-featured [example app](https://github.com/stellar/soroban-example-dapp), which uses React rather than vanilla JavaScript and Next.js rather than Astro. This app also has a more complex setup & initialization process, with the option of using a [locally-hosted RPC node](../reference/rpc.mdx). diff --git a/docs/getting-started/deploy-incrementor.mdx b/docs/getting-started/deploy-incrementor.mdx index 4d4da538..85b9597b 100644 --- a/docs/getting-started/deploy-incrementor.mdx +++ b/docs/getting-started/deploy-incrementor.mdx @@ -1,11 +1,10 @@ --- -sidebar_position: 5 +sidebar_position: 40 title: 4. Deploy Incrementor description: Deploy the Incrementor contract to Testnet. --- - 4. Deploy Incrementor to Testnet. - Deploy a smart contract to a live test network. - Create your first smart contract in Rust. - Write a smart contract that stores and retrieves data. C[contract WASM] +``` + +We need **both** to be live for our contract calls to work. + +Let's work through how these can be recovered. The recovery process is slightly different for a convenient reason: we don't need simulation to figure out the footprints. Instead, we can leverage [`Contract.getFootprint()`](https://stellar.github.io/js-soroban-client/Contract.html#getFootprint), which prepares a footprint with the ledger keys used by a given contract instance (including its backing WASM code). + +Unfortunately, we still need simulation to figure out the _fees_ for our restoration. This, however, can be easily covered by the SDK's [`Server.prepareTransaction()`](https://stellar.github.io/js-soroban-client/Server.html#prepareTransaction) helper, which will do simulation and assembly for us. + +:::info + +This guide makes use of the (aptly named) `yeetTx` function we created in [another guide](../transactions/submit-transaction-wait-js.mdx). + +::: + +```typescript +import { + BASE_FEE, + Contract, + Keypair, + Networks, + TransactionBuilder, + SorobanDataBuilder, + Operation, + SorobanRpc, +} from "@stellar/stellar-sdk"; + +async function restoreContract( + signer: Keypair, + c: Contract, +): Promise { + const instance = c.getFootprint(); + + const account = await server.getAccount(signer.publicKey()); + const wasmEntry = await server.getLedgerEntries( + getWasmLedgerKey(instance) + ); + + const restoreTx = new TransactionBuilder(account, { fee: BASE_FEE }) + .setNetworkPassphrase(Networks.TESTNET) + .setSorobanData( + // Set the restoration footprint (remember, it should be in the + // read-write part!) + new SorobanDataBuilder().setReadWrite([ + instance, + wasmEntry + ]).build(), + ) + .addOperation(Operation.restoreFootprint({})) + .build(); + + const preppedTx = await server.prepareTransaction(restoreTx); + preppedTx.sign(signer); + return yeetTx(preppedTx); +} + +function getWasmLedgerKey(entry: xdr.ContractDataEntry): { + return xdr.LedgerKey.contractCode( + new xdr.LedgerKeyContractCode({ + hash: entry.val().instance().wasmHash() + }) + ); +} +``` diff --git a/docs/guides/archival/restore-data-js.mdx b/docs/guides/archival/restore-data-js.mdx new file mode 100644 index 00000000..62d8d2e3 --- /dev/null +++ b/docs/guides/archival/restore-data-js.mdx @@ -0,0 +1,95 @@ +--- +title: Restore archived contract data using the JavaScript SDK +hide_table_of_contents: true +--- + +This is a pretty likely occurrence: my piece of persistent data is archived because I haven't interacted with my contract in a while. How do I make it accessible again? + +If you find that a piece of persistent data is archived, it can be restored using a Stellar transaction containing a `RestoreFootprintOp` operation. We'll make two assumptions for the sake of this guide: + +- The contract instance itself is still live (i.e., others have been extending its TTL while you've been away). +- You don't know how your archived data is represented on the ledger. + +The restoration process we'll use involves three discrete steps: + +1. Simulate our transaction as we normally would. +2. If the simulation indicated it, we perform restoration with a `RestoreFootprintOp` operation using the hints we got from the simulation. +3. We retry running our initial transaction. + +Here's a function called `submitOrRestoreAndRetry()` that will take care of all those steps for us: + +:::info + +This guide makes use of the (aptly named) `yeetTx` function we created in [another guide](../transactions/submit-transaction-wait-js.mdx). + +::: + +```typescript +import { + BASE_FEE, + Networks, + Keypair, + TransactionBuilder, + SorobanDataBuilder, + SorobanRpc, + xdr, +} from "@stellar/stellar-sdk"; // add'l imports to yeetTx +const { Api, assembleTransaction } = SorobanRpc; + +// assume that `server` is the Server() instance from the yeetTx + +async function submitOrRestoreAndRetry( + signer: Keypair, + tx: Transaction, +): Promise { + // We can't use `prepareTransaction` here because we want to do + // restoration if necessary, basically assembling the simulation ourselves. + const sim = await server.simulateTransaction(tx); + + // Other failures are out of scope of this tutorial. + if (!Api.isSimulationSuccess(sim)) { + throw sim; + } + + // If simulation didn't fail, we don't need to restore anything! Just send it. + if (!Api.isSimulationRestore(sim)) { + const prepTx = assembleTransaction(tx, sim); + prepTx.sign(signer); + return yeetTx(prepTx); + } + + // Build the restoration operation using the RPC server's hints. + const account = await server.getAccount(signer.publicKey()); + let fee = parseInt(BASE_FEE); + fee += parseInt(sim.restorePreamble.minResourceFee); + + const restoreTx = new TransactionBuilder(account, { fee: fee.toString() }) + .setNetworkPassphrase(Networks.TESTNET) + .setSorobanData(sim.restorePreamble.transactionData.build()) + .addOperation(Operation.restoreFootprint({})) + .build(); + + restoreTx.sign(signer); + + const resp = await yeetTx(restoreTx); + if (resp.status !== Api.GetTransactionStatus.SUCCESS) { + throw resp; + } + + // now that we've restored the necessary data, we can retry our tx using + // the initial data from the simulation (which, hopefully, is still + // up-to-date) + const retryTxBuilder = TransactionBuilder.cloneFrom(tx, { + fee: (parseInt(tx.fee) + parseInt(sim.minResourceFee)).toString(), + sorobanData: sim.transactionData.build(), + }); + // because we consumed a sequence number when restoring, we need to make sure + // we set the correct value on this copy + retryTxBuilder.source.incrementSequenceNumber(); + + const retryTx = retryTxBuilder.build(); + retryTx.sign(signer); + + return yeetTx(retryTx); +} +``` diff --git a/docs/guides/cli/README.mdx b/docs/guides/cli/README.mdx new file mode 100644 index 00000000..e87ce3df --- /dev/null +++ b/docs/guides/cli/README.mdx @@ -0,0 +1,8 @@ +--- +title: Soroban CLI +hide_table_of_contents: true +--- + +The [Soroban CLI] is a crucial tool for developers to use while creating and interacting with Soroban smart contracts. + +[Soroban CLI]: ../../reference/soroban-cli.mdx diff --git a/docs/guides/cli/deploy-contract.mdx b/docs/guides/cli/deploy-contract.mdx new file mode 100644 index 00000000..f26426f2 --- /dev/null +++ b/docs/guides/cli/deploy-contract.mdx @@ -0,0 +1,13 @@ +--- +title: Deploy a Contract from Installed Wasm Bytecode +hide_table_of_contents: true +--- + +To deploy an instance of a compiled smart contract that has already been isntalled onto the Stellar network, use the `soroban contract deploy` command: + +```bash +soroban contract deploy \ + --source S... \ + --network testnet \ + --wasm-hash +``` diff --git a/docs/guides/cli/extend-contract-instance.mdx b/docs/guides/cli/extend-contract-instance.mdx new file mode 100644 index 00000000..b70db748 --- /dev/null +++ b/docs/guides/cli/extend-contract-instance.mdx @@ -0,0 +1,23 @@ +--- +title: Extend a deployed contract instance's TTL +hide_table_of_contents: true +--- + +You can use the Soroban CLI to extend the TTL of a contract instance like so: + +```bash +soroban contract extend \ + --source S... \ + --network testnet \ + --id C... \ + --ledgers-to-extend 535679 \ + --durability persistent +``` + +This example uses 535,679 ledgers as the new archival TTL. This is the maximum allowable value for this argument on the CLI. This corresponds to roughly 30 days (averaging 5 second ledger close times). + +When you extend a contract instance, this includes: + +- the contract instance itself +- any `env.storage().instance()` entries in the contract +- the contract's Wasm code diff --git a/docs/guides/cli/extend-contract-storage.mdx b/docs/guides/cli/extend-contract-storage.mdx new file mode 100644 index 00000000..a7c7d04e --- /dev/null +++ b/docs/guides/cli/extend-contract-storage.mdx @@ -0,0 +1,36 @@ +--- +title: Extend a deployed contract's storage entry TTL +hide_table_of_contents: true +--- + +You can use the Soroban CLI to extend the TTL of a contract's persistent storage entry. For a storage entry that uses a simple `Symbol` as its storage key, you can run a command like so: + +```bash +soroban contract extend \ + --source S... \ + --network testnet \ + --id C... \ + --key COUNTER \ + --ledgers-to-extend 535679 \ + --durability persistent +``` + +This example uses 535,679 ledgers as the new archival TTL. This is the maximum allowable value for this argument on the CLI. This corresponds to roughly 30 days (averaging 5 second ledger close times). + +If your storage entry uses a more advanced storage key, such as `Balance(Address)` in a token contract, you'll need to provide the key in a base64-encoded XDR form: + +```bash +soroban contract extend \ + --source S... \ + --network testnet \ + --id C... \ + --key-xdr AAAABgAAAAHXkotywnA8z+r365/0701QSlWouXn8m0UOoshCtNHOYQAAAA4AAAAHQmFsYW5jZQAAAAAB \ + --ledgers-to-extend 535679 \ + --durability persistent +``` + +:::info + +Be sure to check out our [guide on creating XDR ledger keys](../rpc/generate-ledger-keys-python.mdx) for help generating them. + +::: diff --git a/docs/guides/cli/extend-contract-wasm.mdx b/docs/guides/cli/extend-contract-wasm.mdx new file mode 100644 index 00000000..21de9824 --- /dev/null +++ b/docs/guides/cli/extend-contract-wasm.mdx @@ -0,0 +1,34 @@ +--- +title: Extend a deployed contract's Wasm code TTL +hide_table_of_contents: true +--- + +You can use the Soroban CLI to extend the TTL of a contract's Wasm bytecode. This can be done in two forms: if you do or do not have the compiled contract locally. If you do have the compiled binary on your local machine: + +```bash +soroban contract extend \ + --source S... \ + --network testnet \ + --wasm ../relative/path/to/soroban_contract.wasm \ + --ledgers-to-extend 535679 \ + --durability persistent +``` + +This example uses 535,679 ledgers as the new archival TTL. This is the maximum allowable value for this argument on the CLI. This corresponds to roughly 30 days (averaging 5 second ledger close times). + +If you do not have the compiled binary on your local machine, you can still use the CLI to extend the bytecode TTL. You'll need to know the Wasm hash of the installed contract code: + +```bash +soroban contract extend \ + --source S... \ + --network testnet \ + --wasm-hash \ + --ledgers-to-extend 535679 \ + --durability persistent +``` + +:::info + +You can learn more about finding the correct Wasm hash for a contract instance [here (JavaScript)](../rpc/retrieve-contract-code-js.mdx) and [here (Python)](../rpc/retrieve-contract-code-python.mdx). + +::: diff --git a/docs/guides/cli/install-deploy.mdx b/docs/guides/cli/install-deploy.mdx new file mode 100644 index 00000000..ef172d9a --- /dev/null +++ b/docs/guides/cli/install-deploy.mdx @@ -0,0 +1,13 @@ +--- +title: Install and Deploy a Smart Contract +hide_table_of_contents: true +--- + +You can combine the `install` and `deploy` commands of the Soroban CLI to accomplish both tasks: + +```bash +soroban contract deploy \ + --source S... \ + --network testnet \ + --wasm ../relative/path/to/soroban_contract.wasm +``` diff --git a/docs/guides/cli/install-wasm.mdx b/docs/guides/cli/install-wasm.mdx new file mode 100644 index 00000000..0dd70935 --- /dev/null +++ b/docs/guides/cli/install-wasm.mdx @@ -0,0 +1,19 @@ +--- +title: Install Wasm Bytecode +hide_table_of_contents: true +--- + +To use the Soroban CLI to install a compiled smart contract on the ledger, use the `soroban contract install` command: + +```bash +soroban contract install \ + --source S... \ + --network testnet \ + --wasm ../relative/path/to/soroban_contract.wasm +``` + +:::note + +Note this command will return the hash ID of the Wasm bytecode, rather than an address for a contract instance. + +::: diff --git a/docs/guides/cli/restore-contract-instance.mdx b/docs/guides/cli/restore-contract-instance.mdx new file mode 100644 index 00000000..7b26594a --- /dev/null +++ b/docs/guides/cli/restore-contract-instance.mdx @@ -0,0 +1,14 @@ +--- +title: Restore an archived contract using the Soroban CLI +hide_table_of_contents: true +--- + +If your contract instance has been archived, it can easily be restored using the Soroban CLI. + +```bash +soroban contract restore \ + --source S... \ + --network testnet \ + --id C... \ + --durability persistent +``` diff --git a/docs/guides/cli/restore-contract-storage.mdx b/docs/guides/cli/restore-contract-storage.mdx new file mode 100644 index 00000000..8629c8cf --- /dev/null +++ b/docs/guides/cli/restore-contract-storage.mdx @@ -0,0 +1,32 @@ +--- +title: Restore archived contract data using the Soroban CLI +hide_table_of_contents: true +--- + +If a contract's persistent storage entry has been archived, you can restore it using the Soroban CLI. For a storage entry that uses a simple `Symbol` as its storage key, you can run a command like so: + +```bash +soroban contract restore \ + --source S... \ + --network testnet \ + --id C... \ + --key COUNTER \ + --durability persistent +``` + +If your storage entry uses a more advanced storage key, such as `Balance(Address)` in a token contract, you'll need to provide the key in a base64-encoded XDR form: + +```bash +soroban contract restore \ + --source S... \ + --network testnet \ + --id C... \ + --key-xdr AAAABgAAAAHXkotywnA8z+r365/0701QSlWouXn8m0UOoshCtNHOYQAAAA4AAAAHQmFsYW5jZQAAAAAB \ + --durability persistent +``` + +:::info + +Be sure to check out our [guide on creating XDR ledger keys](../rpc/generate-ledger-keys-python.mdx) for help generating them. + +::: diff --git a/docs/guides/cli/wrap-token.mdx b/docs/guides/cli/wrap-token.mdx new file mode 100644 index 00000000..d71fcee7 --- /dev/null +++ b/docs/guides/cli/wrap-token.mdx @@ -0,0 +1,25 @@ +--- +title: Wrap a token using the Stellar Asset Contract +hide_table_of_contents: true +--- + +The Soroban CLI can be used to wrap an existing Stellar asset into a [Stellar Asset Contract] token that can be used in Soroban smart contracts: + +```bash +soroban lab token wrap \ + --source S... \ + --network testnet \ + --asset ABC:G... +``` + +The same can be done for the native [Lumens] asset: + +```bash +soroban lab token wrap \ + --source S... \ + --network testnet \ + --asset native +``` + +[Stellar Asset Contract]: ../../tokens/stellar-asset-contract.mdx +[Lumens]: https://developers.stellar.org/docs/fundamentals-and-concepts/lumens diff --git a/docs/guides/conventions/README.mdx b/docs/guides/conventions/README.mdx new file mode 100644 index 00000000..5e798a0d --- /dev/null +++ b/docs/guides/conventions/README.mdx @@ -0,0 +1,6 @@ +--- +title: Conventions +hide_table_of_contents: true +--- + +These guides describe the "typical" way something might be accomplished in a Rust contract. These guides aren't meant to be quite as _prescriptive_ as some others; instead, they serve to highlight some of the norms we've seen when crop up in contract development. diff --git a/docs/guides/conventions/error-enum.mdx b/docs/guides/conventions/error-enum.mdx new file mode 100644 index 00000000..4608974c --- /dev/null +++ b/docs/guides/conventions/error-enum.mdx @@ -0,0 +1,40 @@ +--- +title: Organize contract errors with an error enum type +hide_table_of_contents: true +--- + +A convenient way to manage and meaningfully communicate contract errors is to collect them into an `enum` struct. These errors are a special type of enum integer type that are stored on ledger as Status values containing a `u32` code. First, create the `Error` struct in your smart contract. + +```rust +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum Error { + FirstError = 1, + AnotherError = 2, + YetAnotherError = 3, + GenericError = 4 +} +``` + +Then, panic with an error when the conditions are met. This example will panic with the specified error. + +```rust +#[contractimpl] +impl Contract { + pub fn causeerror(env: Env, error_code: u32) -> Result<(), Error> { + match error_code { + 1 => Err(Error::FirstError), + 2 => Err(Error::AnotherError), + 3 => Err(Error::YetAnotherError), + _ => Err(Error::GenericError), + } + } +} +``` + +When converted to XDR, the value becomes an `ScVal`, containing a `ScStatus`, containing the integer value of the error as contract error. + +```json +{ "status": { "contractError": 1 } } +``` diff --git a/docs/basic-tutorials/upgrading-contracts.mdx b/docs/guides/conventions/upgrading-contracts.mdx similarity index 92% rename from docs/basic-tutorials/upgrading-contracts.mdx rename to docs/guides/conventions/upgrading-contracts.mdx index 5c5f1943..c9c357a5 100644 --- a/docs/basic-tutorials/upgrading-contracts.mdx +++ b/docs/guides/conventions/upgrading-contracts.mdx @@ -1,20 +1,22 @@ --- -sidebar_position: 9 -title: Upgrading Contracts -description: Upgrade a WASM smart contract. +title: Upgrade the Wasm bytecode of a deployed contract +hide_table_of_contents: true --- - Upgrade a WASM smart contract. + Upgrade the Wasm bytecode of a deployed contract - + @@ -78,8 +80,8 @@ pub fn upgrade(e: Env, new_wasm_hash: BytesN<32>) { The `update_current_contract_wasm` host function will also emit a `SYSTEM` contract [event] that contains the old and new wasm reference, allowing downstream users to be notified when a contract they use is updated. The event structure will have `topics = ["executable_update", old_executable: ContractExecutable, old_executable: ContractExecutable]` and `data = []`. -[here]: https://docs.rs/soroban-sdk/20.0.0/soroban_sdk/struct.Env.html#method.update_current_contract_wasm -[event]: ../fundamentals-and-concepts/events.mdx#event-types +[here]: https://docs.rs/soroban-sdk/20.0.2/soroban_sdk/struct.Env.html#method.update_current_contract_wasm +[event]: ../../soroban-internals/events.mdx#event-types ## Tests @@ -284,4 +286,4 @@ Now that the contract was upgraded, you'll see a new version. 2 ``` -[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli +[`soroban-cli`]: ../../getting-started/setup.mdx#install-the-soroban-cli diff --git a/docs/basic-tutorials/wasm-metadata.mdx b/docs/guides/conventions/wasm-metadata.mdx similarity index 72% rename from docs/basic-tutorials/wasm-metadata.mdx rename to docs/guides/conventions/wasm-metadata.mdx index bd5b4282..e1ce1767 100644 --- a/docs/basic-tutorials/wasm-metadata.mdx +++ b/docs/guides/conventions/wasm-metadata.mdx @@ -1,24 +1,23 @@ --- -sidebar_position: 8 -title: Metadata -description: Write structured metadata. +title: Write metadata for your contract. +hide_table_of_contents: true --- Write structured metadata. - + -The [contractmeta!] macro provided in the Rust SDK allows users to write two +The [`contractmeta!`] macro provided in the Rust SDK allows users to write two strings - a `key` and a `val` - within a serialized `SCMetaEntry::SCMetaV0` XDR object to the custom section of Wasm contracts. The section name for this metadata is `contractmetav0`. Developers can utilize this macro to write @@ -28,7 +27,6 @@ The [liquidity pool example] provides a clear demonstration of how to use the `contractmeta!` macro: ```rust - // Metadata that is added on to the Wasm custom section contractmeta!( key = "Description", @@ -38,5 +36,5 @@ contractmeta!( pub trait LiquidityPoolTrait {... ``` -[contractmeta!]: https://docs.rs/soroban-sdk/20.0.0/soroban_sdk/macro.contractmeta.html +[`contractmeta!`]: https://docs.rs/soroban-sdk/20.0.2/soroban_sdk/macro.contractmeta.html [liquidity pool example]: https://github.com/stellar/soroban-examples/blob/v20.0.0/liquidity_pool/src/lib.rs#L152-L155 diff --git a/docs/guides/conventions/work-contractspec-js.mdx b/docs/guides/conventions/work-contractspec-js.mdx new file mode 100644 index 00000000..0a2059a4 --- /dev/null +++ b/docs/guides/conventions/work-contractspec-js.mdx @@ -0,0 +1,7 @@ +--- +title: Work with ContractSpecs in JavaScript +hide_table_of_contents: true +draft: true +--- + +You do something... diff --git a/docs/guides/conversions/README.mdx b/docs/guides/conversions/README.mdx new file mode 100644 index 00000000..011728ee --- /dev/null +++ b/docs/guides/conversions/README.mdx @@ -0,0 +1,6 @@ +--- +title: Type Conversions +hide_table_of_contents: true +--- + +A collection of guides for converting from one data type to another, in a variety of SDK languages. diff --git a/docs/guides/conversions/address-to-bytesn.mdx b/docs/guides/conversions/address-to-bytesn.mdx new file mode 100644 index 00000000..ca5952b8 --- /dev/null +++ b/docs/guides/conversions/address-to-bytesn.mdx @@ -0,0 +1,11 @@ +--- +title: Convert an Address to BytesN using the Rust SDK +hide_table_of_contents: true +draft: true +--- + +The `Address` is an opaque type that could represent an "account" on the Stellar network (i.e., a keypair), or a "contract." From Soroban's point of view, it doesn't really matter which it is. The "account" variety of these addresses are typically displayed as a `G...` public address, and the "contract" variatey is typically displayed as a `C...` address. Another way that can be used to display an address is an array of 32 bytes. The Rust SDK can handle conversion between the two easily: + +```rust + +``` diff --git a/docs/guides/conversions/address-to-id.mdx b/docs/guides/conversions/address-to-id.mdx new file mode 100644 index 00000000..38fe72ac --- /dev/null +++ b/docs/guides/conversions/address-to-id.mdx @@ -0,0 +1,7 @@ +--- +title: Convert a contract Address to a contract ID in Rust +hide_table_of_contents: true +draft: true +--- + +`C...` converts to a hex-encoded `deadb33f` ID. diff --git a/docs/guides/conversions/id-to-address.mdx b/docs/guides/conversions/id-to-address.mdx new file mode 100644 index 00000000..585fae44 --- /dev/null +++ b/docs/guides/conversions/id-to-address.mdx @@ -0,0 +1,7 @@ +--- +title: Convert a contract ID to a contract Address +hide_table_of_contents: true +draft: true +--- + +The hex-encoded `deadb33f` ID converts to a `C...` StrKey. diff --git a/docs/guides/events/README.mdx b/docs/guides/events/README.mdx new file mode 100644 index 00000000..4f32abfe --- /dev/null +++ b/docs/guides/events/README.mdx @@ -0,0 +1,6 @@ +--- +title: Events +hide_table_of_contents: true +--- + +Learn how to emit, ingest, and use events published from a Soroban smart contract. diff --git a/docs/guides/events/consume.mdx b/docs/guides/events/consume.mdx new file mode 100644 index 00000000..3e4cb8f4 --- /dev/null +++ b/docs/guides/events/consume.mdx @@ -0,0 +1,7 @@ +--- +title: Consume previously ingested events +hide_table_of_contents: true +draft: true +--- + +Placeholder text goes here. diff --git a/docs/guides/events/ingest.mdx b/docs/guides/events/ingest.mdx new file mode 100644 index 00000000..215d71cb --- /dev/null +++ b/docs/guides/events/ingest.mdx @@ -0,0 +1,104 @@ +--- +title: Ingest events published from a contract +--- + +Soroban RPC provides a `getEvents` method which allows you to query events from a smart contract. However, the data retention window for these events is roughly 24 hours. If you need access to a longer-lived record of these events you'll want to "ingest" the events as they are published, maintaining your own record or database as events are ingested. + +There are many strategies you can use to ingest and keep the events published by a smart contract. Among the simplest might be using a community-developed tool such as [Mercury](https://mercurydata.app) which will take all the infrastructure work off your plate for a low subscription fee. + +Another approach we'll explore here is using a cron job to query Soroban RPC periodically and store the relevant events in a locally stored SQLite database, using [Prisma](https://www.prisma.io) as a database abstraction layer. By using Prisma here, it should be relatively trivial to scale this approach up to any other database software of your choosing. + +## Setup the Database Client + +The finer details of choosing a Prisma configuration are beyond the scope of this document. You can get a lot more information in the [Prisma quickstart](https://www.prisma.io/docs/getting-started/quickstart). Here is our Prisma schema's model: + +```text +model SorobanEvent { + id String @id + type String + ledger Int + contract_id String + topic_1 String? + topic_2 String? + topic_3 String? + topic_4 String? + value String +} +``` + +We'll use this model to create and query for the events stored in our database. + +## Query Events from Soroban RPC + +First, we'll need to query the events from Soroban RPC. This simple JavaScript example will use the `@stellar/stellar-sdk` library to make an RPC request using the `getEvents` method, filtering for all `transfer` events that are emitted by the native XLM contract. + +:::note + +We are making some assumptions here. We'll assume that your contract sees enough activity, and that you are querying for events frequently enough that you aren't in danger of needing to figure out the oldest ledger Soroban RPC is aware of. The approach we're taking is to find the largest (most recent) ledger sequence number in the database and query for events starting there. Your use-case may require some logic to determine what the latest ledger is, and what the oldest ledger available is, etc. + +::: + +```javascript +import { SorobanRpc } from "@stellar/stellar-sdk"; +import { PrismaClient } from "@prisma/client"; + +const server = new SorobanRpc.Server("https://soroban-testnet.stellar.org"); +const prisma = new PrismaClient(); + +let latestEventIngested = await prisma.sorobanEvent.findFirst({ + orderBy: [ + { + ledger: "desc", + }, + ], +}); + +let events = await server.getEvents({ + startLedger: latestEventIngested.ledger, + filters: [ + { + type: "contract", + contractIds: ["CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC"], + topics: [["AAAADwAAAAh0cmFuc2Zlcg==", "*", "*", "*"]], + }, + ], +}); +``` + +## Store Events in the Database + +Now, we'll check if the `events` object contains any new events we should store, and we do exactly that. We're storing the event's topics and values as base64-encoded strings here, but you could decode the necessary topics and values into the appropriate data types for your use-case. + +```javascript +if (events.events?.length) { + events.events.forEach(async (event) => { + await prisma.sorobanEvent.create({ + data: { + id: event.id, + type: event.type, + ledger: event.ledger, + contract_id: event.contractId.toString(), + topic_1: event.topic[0].toXDR("base64") || null, + topic_2: event.topic[1].toXDR("base64") || null, + topic_3: event.topic[2].toXDR("base64") || null, + topic_4: event.topic[3].toXDR("base64") || null, + value: event.value.toXDR("base64"), + }, + }); + }); +} +``` + +## Run the Script with Cron + +A cron entry is an excellent way to automate this script to gather and ingest events every so often. You could configure this script to run as (in)frequently as you want or need. This example would run the script every 24 hours at 1:14 pm: + +```bash +14 13 * * * node /absolute/path/to/script.js +``` + +Here's another example that will run the script every 30 minutes: + +```bash +30 * * * * node /absolute/path/to/script.js +``` diff --git a/docs/guides/events/publish.mdx b/docs/guides/events/publish.mdx new file mode 100644 index 00000000..fe396d27 --- /dev/null +++ b/docs/guides/events/publish.mdx @@ -0,0 +1,50 @@ +--- +title: Publish events from a Rust contract +hide_table_of_contents: true +--- + +An event can contain up to 4 topics, alongside the data it is publishing. The `data` can be any value or type you want. However, the topics must not contain: + +- `Vec` +- `Map` +- `Bytes` or `BytesN` longer than 32 bytes +- `contracttype` + +```rust +// This function does nothing beside publishing events. Topics we are using are +// some `u32` integers for the sake of simplicity here. +pub fn events_function(env: Env) { + // A symbol will be our `data` we want published + my_data = Symbol::new(&env, "data_to_publish"); + + // an event with 0 topics + env.events().publish((), my_data.clone()); + + // an event with 1 topic (Notice the extra comma after the topic in the + // tuple? That comma is required in Rust to make a one-element tuple) + env.events().publish((1u32,), my_data.clone()); + + // an event with 2 topics + env.events().publish((1u32, 2u32), my_data.clone()); + + // an event with 3 topics + env.events().publish((1u32, 2u32, 3u32), my_data.clone()); + + // an event with 4 topics + env.events().publish((1u32, 2u32, 3u32, 4u32), my_data.clone()); +} +``` + +A more realistic example can be found in the way the [token interface] works. For example, the interface requires an event to be published every time the `transfer` function is invoked, with the following information: + +```rust +pub fn transfer(env: Env, from: Address, to: Address, amount: i128) { + // transfer logic omitted here + env.events().publish( + (symbol_short!("transfer"), from, to), + amount + ); +} +``` + +[token interface]: ../../tokens/token-interface.mdx diff --git a/docs/guides/fees/README.mdx b/docs/guides/fees/README.mdx new file mode 100644 index 00000000..41cf7a0f --- /dev/null +++ b/docs/guides/fees/README.mdx @@ -0,0 +1,6 @@ +--- +title: Fees & Metering +hide_table_of_contents: true +--- + +Fees and metering in Soroban smart contracts work differently than the fees for "regular" Stellar transactions. The Stellar network still provides cheap, accessible transaction and that now includes smart contract metering! diff --git a/docs/guides/fees/cost-analysis.mdx b/docs/guides/fees/cost-analysis.mdx new file mode 100644 index 00000000..b82e3659 --- /dev/null +++ b/docs/guides/fees/cost-analysis.mdx @@ -0,0 +1,7 @@ +--- +title: Analyze contract cost and efficiency +hide_table_of_contents: true +draft: true +--- + +See [issue #552](https://github.com/stellar/soroban-docs/issues/552) for more context diff --git a/docs/guides/rpc/README.mdx b/docs/guides/rpc/README.mdx new file mode 100644 index 00000000..65363869 --- /dev/null +++ b/docs/guides/rpc/README.mdx @@ -0,0 +1,6 @@ +--- +title: RPC +hide_table_of_contents: true +--- + +Using and interacting with Soroban RPC is an important part of the smart contract development lifecycle. diff --git a/docs/guides/rpc/generate-ledger-keys-python.mdx b/docs/guides/rpc/generate-ledger-keys-python.mdx new file mode 100644 index 00000000..23e0004f --- /dev/null +++ b/docs/guides/rpc/generate-ledger-keys-python.mdx @@ -0,0 +1,31 @@ +--- +title: Generate ledger key parameters with a symbol key using the Python SDK +hide_table_of_contents: true +--- + +In the [`increment` example contract] stores an integer value in a ledger entry that is identified by a key with the symbol `COUNTER`. The value of this ledger key can be derived using the following code snippets. + +```python +from stellar_sdk import xdr +from stellar_sdk.strkey import StrKey +from stellar_sdk.soroban import Symbol + +def get_ledger_key_symbol(contract_id: str, symbol_text: str) -> str: + ledger_key = xdr.LedgerKey( + type=xdr.LedgerEntryType.CONTRACT_DATA, + contract_data=xdr.LedgerKeyContractData( + contract_id=xdr.hash.Hash(StrKey.decode_contract(contract_id)), + key=Symbol(symbol_text).to_xdr_sc_val(), + ), + ) + return ledger_key.to_xdr() + +print( + get_ledger_key_symbol( + "CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE", + "COUNTER" + ) +) +``` + +[`increment` example contract]: ../../getting-started/storing-data.mdx diff --git a/docs/guides/rpc/retrieve-contract-code-js.mdx b/docs/guides/rpc/retrieve-contract-code-js.mdx new file mode 100644 index 00000000..19a7d911 --- /dev/null +++ b/docs/guides/rpc/retrieve-contract-code-js.mdx @@ -0,0 +1,120 @@ +--- +title: Retrieve a contract code ledger entry using the Python SDK +hide_table_of_contents: true +--- + +When you deploy a contract, first the code is "installed" (i.e., it is uploaded onto the blockchain). This creates a `LedgerEntry` containing the Wasm byte-code, which is uniquely identified by its hash (that is, the hash of the uploaded code itself). Then, when the contract is "deployed," we create a `LedgerEntry` with a reference to that code's hash. So fetching the contract code is a two-step process: + +1. First, we look up the contract itself, to see which code hash it is referencing. +2. Then, we can look up the raw Wasm byte-code using that hash. + +```js +import { Address, xdr } from "stellar-sdk"; + +function getLedgerKeyContractCode(contractId) { + const [_, instance] = new ContractId(contractId).getFootprint(); + return instance.toXDR("base64"); +} + +console.log( + getLedgerKeyContractCode( + "CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE", + ), +); +// OUTPUT: AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFA== +``` + +We then take our output from this function, and use it as the element in the `keys` array parameter in our call to the `getLedgerEntries` method. + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "method": "getLedgerEntries", + "params": { + "keys": ["AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFA=="] + } +} +``` + +And the response we get contains the `LedgerEntryData` that can be used to find the `hash` we must use to request the Wasm byte-code. This hash is the `LedgerKey` that's been associated with the deployed contract code. + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "entries": [ + { + "key": "AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFA==", + "xdr": "AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFAAAABIAAAAAZBYoEJT3IaPMMk3FoRmnEQHoDxewPZL+Uor+xWI4uII=", + "lastModifiedLedgerSeq": 261603 + } + ], + "latestLedger": 262322 + } +} +``` + +Now take the `xdr` field from the previous response's `result` object, and create a `LedgerKey` from the hash contained inside. + +```js +const { xdr } = require("soroban-client"); + +function getLedgerKeyWasmId(contractCodeLedgerEntryData) { + const entry = xdr.LedgerEntryData.fromXDR( + contractCodeLedgerEntryData, + "base64", + ); + + const instance = entry.contractData().val().instance(); + + let ledgerKey = xdr.LedgerKey.contractCode( + new xdr.LedgerKeyContractCode({ + hash: instance.wasmHash(), + }), + ); + + return ledgerKey.toXDR("base64"); +} + +console.log( + getLedgerKeyWasmId( + "AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFAAAABIAAAAAZBYoEJT3IaPMMk3FoRmnEQHoDxewPZL+Uor+xWI4uII=", + ), +); +// OUTPUT: AAAAB2QWKBCU9yGjzDJNxaEZpxEB6A8XsD2S/lKK/sViOLiC +``` + +Now, finally we have a `LedgerKey` that correspond to the Wasm byte-code that has been deployed under the `ContractId` we started out with so very long ago. This `LedgerKey` can be used in a final request to the Soroban-RPC endpoint. + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "method": "getLedgerEntries", + "params": { + "keys": ["AAAAB2QWKBCU9yGjzDJNxaEZpxEB6A8XsD2S/lKK/sViOLiC"] + } +} +``` + +And the response we get contains (even more) `LedgerEntryData` that we can decode and parse to get the actual, deployed, real-life contract byte-code. We'll leave that exercise up to you. You can check out what is contained using the ["View XDR" page of the Stellar Laboratory](https://laboratory.stellar.org/#xdr-viewer?type=LedgerEntryData&network=testnet). + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "entries": [ + { + "key": "AAAAB2QWKBCU9yGjzDJNxaEZpxEB6A8XsD2S/lKK/sViOLiC", + "xdr": "AAAABwAAAABkFigQlPcho8wyTcWhGacRAegPF7A9kv5Siv7FYji4ggAAAlQAYXNtAQAAAAEPA2ACfn4BfmABfgF+YAAAAgcBAXYBRwAAAwQDAQICBQMBABEGGQN/AUGAgMAAC38AQYWAwAALfwBBkIDAAAsHMQUGbWVtb3J5AgAFaGVsbG8AAQFfAAMKX19kYXRhX2VuZAMBC19faGVhcF9iYXNlAwIK4QID1gIDAn8CfgF/I4CAgIAAQSBrIgEkgICAgAACQAJAIACnQf8BcSICQQ5GDQAgAkHKAEcNAQtCACEDQXshAgNAAkACQAJAAkAgAkUNAEIBIQQgAkGFgMCAAGotAAAiBUHfAEYNAyAFrSEEIAVBUGpBCkkNAiAFQb9/akEaSQ0BAkAgBUGff2pBGk8NACAEQkV8IQQMBAsQgoCAgAAACyABIAA3AwggASADQgiGQg6ENwMAQQAhAgNAAkAgAkEQRw0AQQAhAgJAA0AgAkEQRg0BIAFBEGogAmogASACaikDADcDACACQQhqIQIMAAsLIAFBEGqtQiCGQgSEQoSAgIAgEICAgIAAIQQgAUEgaiSAgICAACAEDwsgAUEQaiACakICNwMAIAJBCGohAgwACwsgBEJLfCEEDAELIARCUnwhBAsgAkEBaiECIAQgA0IGhoQhAwwACwsAAAsEAAAACwIACwsOAQBBgIDAAAsFSGVsbG8AHhFjb250cmFjdGVudm1ldGF2MAAAAAAAAAAUAAAAJQBDDmNvbnRyYWN0c3BlY3YwAAAAAAAAAAAAAAAFaGVsbG8AAAAAAAABAAAAAAAAAAJ0bwAAAAAAEQAAAAEAAAPqAAAAEQ==", + "lastModifiedLedgerSeq": 75206, + "liveUntilLedgerSeq": 320384 + } + ], + "latestLedger": 262384 + } +} +``` diff --git a/docs/guides/rpc/retrieve-contract-code-python.mdx b/docs/guides/rpc/retrieve-contract-code-python.mdx new file mode 100644 index 00000000..9f8e172b --- /dev/null +++ b/docs/guides/rpc/retrieve-contract-code-python.mdx @@ -0,0 +1,125 @@ +--- +title: Retrieve a contract code ledger entry using the Python SDK +hide_table_of_contents: true +--- + +When you deploy a contract, first the code is "installed" (i.e., it is uploaded onto the blockchain). This creates a `LedgerEntry` containing the Wasm byte-code, which is uniquely identified by its hash (that is, the hash of the uploaded code itself). Then, when the contract is "deployed," we create a `LedgerEntry` with a reference to that code's hash. So fetching the contract code is a two-step process: + +1. First, we look up the contract itself, to see which code hash it is referencing. +2. Then, we can look up the raw Wasm byte-code using that hash. + +```python +from stellar_sdk import xdr +from stellar_sdk.strkey import StrKey + +def get_ledger_key_contract_code(contract_id: str) -> str: + ledger_key = xdr.LedgerKey( + type=xdr.LedgerEntryType.CONTRACT_DATA, + contract_data=xdr.LedgerKeyContractData( + contract_id=xdr.Hash(StrKey.decodeContract(contract_id)), + key=xdr.SCVal( + type=xdr.SCValType.SCV_LEDGER_KEY_CONTRACT_EXECUTABLE, + ), + ), + ) + return ledger_key.to_xdr() + +print( + get_ledger_key_contract_code( + "CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE" + ) +) +# OUTPUT: AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFA== +``` + +We then take our output from this function, and use it as the element in the `keys` array parameter in our call to the `getLedgerEntries` method. + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "method": "getLedgerEntries", + "params": { + "keys": ["AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFA=="] + } +} +``` + +And the response we get contains the `LedgerEntryData` that can be used to find the `hash` we must use to request the Wasm byte-code. This hash is the `LedgerKey` that's been associated with the deployed contract code. + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "entries": [ + { + "key": "AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFA==", + "xdr": "AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFAAAABIAAAAAZBYoEJT3IaPMMk3FoRmnEQHoDxewPZL+Uor+xWI4uII=", + "lastModifiedLedgerSeq": 261603 + } + ], + "latestLedger": 262322 + } +} +``` + +Now take the `xdr` field from the previous response's `result` object, and create a `LedgerKey` from the hash contained inside. + +```python +from stellar_sdk import xdr + +def get_ledger_key_wasm_id(contract_code_ledger_entry_data: str) -> str: + # First, we dig the wasm_id hash out of the xdr we received from RPC + contract_code_wasm_hash = xdr.LedgerEntryData.from_xdr( + contract_code_ledger_entry_data + ).contract_data.val.exec.wasm_id.hash + # Now, we can create the `LedgerKey` as we've done in previous examples + ledger_key = xdr.LedgerKey( + type=xdr.LedgerEntryType.CONTRACT_CODE, + contract_code=xdr.LedgerKeyContractCode( + hash=xdr.hash.Hash(contract_code_wasm_hash) + ), + ) + return ledger_key.to_xdr() + +print( + get_ledger_key_wasm_id( + "AAAABq+aJSfjs7VXHWOwJGujK30xpTI3Zt98YN/As+O6b98jAAAAFAAAABIAAAAAZBYoEJT3IaPMMk3FoRmnEQHoDxewPZL+Uor+xWI4uII=" + ) +) +# OUTPUT: AAAAB2QWKBCU9yGjzDJNxaEZpxEB6A8XsD2S/lKK/sViOLiC +``` + +Now, finally we have a `LedgerKey` that correspond to the Wasm byte-code that has been deployed under the `ContractId` we started out with so very long ago. This `LedgerKey` can be used in a final request to the Soroban-RPC endpoint. + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "method": "getLedgerEntries", + "params": { + "keys": ["AAAAB2QWKBCU9yGjzDJNxaEZpxEB6A8XsD2S/lKK/sViOLiC"] + } +} +``` + +And the response we get contains (even more) `LedgerEntryData` that we can decode and parse to get the actual, deployed, real-life contract byte-code. We'll leave that exercise up to you. You can check out what is contained using the ["View XDR" page of the Stellar Laboratory](https://laboratory.stellar.org/#xdr-viewer?type=LedgerEntryData&network=testnet). + +```json +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "entries": [ + { + "key": "AAAAB2QWKBCU9yGjzDJNxaEZpxEB6A8XsD2S/lKK/sViOLiC", + "xdr": "AAAABwAAAABkFigQlPcho8wyTcWhGacRAegPF7A9kv5Siv7FYji4ggAAAlQAYXNtAQAAAAEPA2ACfn4BfmABfgF+YAAAAgcBAXYBRwAAAwQDAQICBQMBABEGGQN/AUGAgMAAC38AQYWAwAALfwBBkIDAAAsHMQUGbWVtb3J5AgAFaGVsbG8AAQFfAAMKX19kYXRhX2VuZAMBC19faGVhcF9iYXNlAwIK4QID1gIDAn8CfgF/I4CAgIAAQSBrIgEkgICAgAACQAJAIACnQf8BcSICQQ5GDQAgAkHKAEcNAQtCACEDQXshAgNAAkACQAJAAkAgAkUNAEIBIQQgAkGFgMCAAGotAAAiBUHfAEYNAyAFrSEEIAVBUGpBCkkNAiAFQb9/akEaSQ0BAkAgBUGff2pBGk8NACAEQkV8IQQMBAsQgoCAgAAACyABIAA3AwggASADQgiGQg6ENwMAQQAhAgNAAkAgAkEQRw0AQQAhAgJAA0AgAkEQRg0BIAFBEGogAmogASACaikDADcDACACQQhqIQIMAAsLIAFBEGqtQiCGQgSEQoSAgIAgEICAgIAAIQQgAUEgaiSAgICAACAEDwsgAUEQaiACakICNwMAIAJBCGohAgwACwsgBEJLfCEEDAELIARCUnwhBAsgAkEBaiECIAQgA0IGhoQhAwwACwsAAAsEAAAACwIACwsOAQBBgIDAAAsFSGVsbG8AHhFjb250cmFjdGVudm1ldGF2MAAAAAAAAAAUAAAAJQBDDmNvbnRyYWN0c3BlY3YwAAAAAAAAAAAAAAAFaGVsbG8AAAAAAAABAAAAAAAAAAJ0bwAAAAAAEQAAAAEAAAPqAAAAEQ==", + "lastModifiedLedgerSeq": 75206, + "liveUntilLedgerSeq": 320384 + } + ], + "latestLedger": 262384 + } +} +``` diff --git a/docs/guides/rpc/self-deploy-rpc.mdx b/docs/guides/rpc/self-deploy-rpc.mdx new file mode 100644 index 00000000..f97c84c9 --- /dev/null +++ b/docs/guides/rpc/self-deploy-rpc.mdx @@ -0,0 +1,7 @@ +--- +title: Self-deploy and use your own RPC instance +hide_table_of_contents: true +draft: true +--- + +Placeholder text goes here. diff --git a/docs/guides/rpc/use-public-rpc.mdx b/docs/guides/rpc/use-public-rpc.mdx new file mode 100644 index 00000000..70069fb3 --- /dev/null +++ b/docs/guides/rpc/use-public-rpc.mdx @@ -0,0 +1,7 @@ +--- +title: Make use of a public RPC instance +hide_table_of_contents: true +draft: true +--- + +Placeholder text goes here. diff --git a/docs/guides/storage/README.mdx b/docs/guides/storage/README.mdx new file mode 100644 index 00000000..f6694423 --- /dev/null +++ b/docs/guides/storage/README.mdx @@ -0,0 +1,6 @@ +--- +title: Storage +hide_table_of_contents: true +--- + +Soroban storage is available to affordably accommodate a wide range of uses. diff --git a/docs/guides/storage/choose-type.mdx b/docs/guides/storage/choose-type.mdx new file mode 100644 index 00000000..dcb41ff1 --- /dev/null +++ b/docs/guides/storage/choose-type.mdx @@ -0,0 +1,7 @@ +--- +title: Choose the right storage type for your use-case +hide_table_of_contents: true +draft: true +--- + +Placeholder text goes here. diff --git a/docs/guides/storage/use-instance.mdx b/docs/guides/storage/use-instance.mdx new file mode 100644 index 00000000..0cb7384c --- /dev/null +++ b/docs/guides/storage/use-instance.mdx @@ -0,0 +1,31 @@ +--- +title: Use instance storage in a contract +hide_table_of_contents: true +--- + +Under the hood, instance storage is exactly like persistent storage. The only difference is that anything stored in instance storage has an archival TTL that is tied to the contract instance itself. So, if a contract is live and available, the instance storage is guaranteed to be so, too. + +Instance storage is really useful for global contract data that is shared among all users of the contract (token administrator, for example). From the [token example contract](../../tutorials/tokens.mdx), the helper functions to set and retrieve the admininistrator address are basically just wrappers surrounding the one Admin ledger entry. + +:::caution + +It should be noted that _every_ piece of data stored in `instance()` storage is retrieved from the ledger _every_ time the contract is invoked. Even if the invoked function does not interact with any ledger data at all. This can lead to more expensive (computationally and financially) function invocations if the stored data grows over time. Choose judiciously which bits of data actually belong in the instance storage, and which should be kept in persistent storage. + +::: + +```rust +pub fn has_administrator(e: &Env) -> bool { + let key = DataKey::Admin; + e.storage().instance().has(&key) +} + +pub fn read_administrator(e: &Env) -> Address { + let key = DataKey::Admin; + e.storage().instance().get(&key).unwrap() +} + +pub fn write_administrator(e: &Env, id: &Address) { + let key = DataKey::Admin; + e.storage().instance().set(&key, id); +} +``` diff --git a/docs/guides/storage/use-persistent.mdx b/docs/guides/storage/use-persistent.mdx new file mode 100644 index 00000000..34cd5bba --- /dev/null +++ b/docs/guides/storage/use-persistent.mdx @@ -0,0 +1,37 @@ +--- +title: Use persistent storage in a contract +hide_table_of_contents: true +--- + +Persistent storage can be very useful for ledger entrys that are not common across every user of the contract instance, but that are not suitable to be temporary (user balances, for example). In this guide, we'll assume we want to store a random number for a user, and store it in the contract's persistent storage as though it were their favorite number. + +```rust +#[contracttype] +pub enum DataKey { + Favorite(Address), +} + +#[contract] +pub struct FavoriteContract; + +#[contractimpl] +impl FavoriteContract { + // This function generates, stores, and returns a random number for the user + pub fn generate_fave(env: Env, user: Address) -> u64 { + let key = DataKey::Favorite(user); + let fave: u64 = env.prng().gen(); + env.storage().persistent().set(&key, &fave); + fave + } + + // This function retrieves and returns the random number for the user + pub fn get_fave(env: Env, user: Address) -> u64 { + let key = DataKey::Favorite(user); + if let Some(fave) = env.storage().persistent().get(&key) { + fave + } else { + 0 + } + } +} +``` diff --git a/docs/guides/storage/use-temporary.mdx b/docs/guides/storage/use-temporary.mdx new file mode 100644 index 00000000..665e4aef --- /dev/null +++ b/docs/guides/storage/use-temporary.mdx @@ -0,0 +1,23 @@ +--- +title: Use temporary storage in a contract +hide_table_of_contents: true +--- + +Temporary storage is useful for a contract to store data that can quickly become irrelevant or out-dated. For example, here's how a contract might be used to store a recent price of BTC against the US Dollar. + +```rust +// This function updates the BTC price +pub fn update_btc_price(env: Env, price: i128) { + env.storage().temporary().set(&!symbol_short("BTC"), &price); +} + +// This function reads and returns the current BTC price (zero if the storage +// entry is archived) +pub fn get_btc_price(env: Env) -> i128 { + if let Some(price) = env.storage().temporary().get(&!symbol_short("BTC")) { + price + } else { + 0 + } +} +``` diff --git a/docs/guides/testing/README.mdx b/docs/guides/testing/README.mdx new file mode 100644 index 00000000..8c15c12d --- /dev/null +++ b/docs/guides/testing/README.mdx @@ -0,0 +1,6 @@ +--- +title: Testing +hide_table_of_contents: true +--- + +Smart contract testing is vital to ensure safe, resilient, and accurate computation. diff --git a/docs/guides/testing/basic-contract-tests.mdx b/docs/guides/testing/basic-contract-tests.mdx new file mode 100644 index 00000000..c4cc4a98 --- /dev/null +++ b/docs/guides/testing/basic-contract-tests.mdx @@ -0,0 +1,26 @@ +--- +title: Implement basic tests for a contract +hide_table_of_contents: true +--- + +A contract's test functions can be used as a simple way to ensure a contract's functions behave as expected. The [increment example contract](../../getting-started/deploy-incrementor.mdx) has a function that increments a counter by one on every invocation. The corresponding test invokes that function several time, ensuring with `assert_eq!(...)` the count increases as expected. + +```rust +#![cfg(test)] + +use super::{IncrementContract, IncrementContractClient}; +use soroban_sdk::{Env}; + +#[test] +fn test() { + // Almost every test will begin this same way. A default Soroban environment + // is created and the contract (along with its client) is registered in it. + let env = Env::default(); + let contract_id = env.register_contract(None, IncrementContract); + let client = IncrementContractClient::new(&env, &contract_id); + + assert_eq!(client.increment(), 1); + assert_eq!(client.increment(), 2); + assert_eq!(client.increment(), 3); +} +``` diff --git a/docs/guides/testing/integration-testing-multiple-contracts.mdx b/docs/guides/testing/integration-testing-multiple-contracts.mdx new file mode 100644 index 00000000..7a525c9d --- /dev/null +++ b/docs/guides/testing/integration-testing-multiple-contracts.mdx @@ -0,0 +1,7 @@ +--- +title: Integration testing in multiple contracts +hide_table_of_contents: true +draft: true +--- + +See [issue #553](https://github.com/stellar/soroban-docs/issues/553) for more context. diff --git a/docs/guides/testing/mint-native-token.mdx b/docs/guides/testing/mint-native-token.mdx new file mode 100644 index 00000000..fd404a0b --- /dev/null +++ b/docs/guides/testing/mint-native-token.mdx @@ -0,0 +1,11 @@ +--- +title: Mint native XLM in a contract test +hide_table_of_contents: true +draft: true +--- + +It can often be necessary to test whether your contract's interactions surrounding tokens work as intended. Often, the token you test again can be created from arbitrary details. However, there are occassions where testing against a specific token can be advantageous. Here is a test function that makes use of the Stellar Asset Contract for the native XLM token. + +```rust +env.token.native_asset_contract(); // or some such... +``` diff --git a/docs/guides/testing/test-contract-auth.mdx b/docs/guides/testing/test-contract-auth.mdx new file mode 100644 index 00000000..a7bf7eb1 --- /dev/null +++ b/docs/guides/testing/test-contract-auth.mdx @@ -0,0 +1,42 @@ +--- +title: Test authorized contract invocations +hide_table_of_contents: true +--- + +A contract's test functions can be used as a way to ensure the authorization is indeed carried out the way a developer intends. A simple example can be found in the [auth example contract](../../tutorials/auth.mdx). (In the following code block, some code has been omitted for brevity.) + +```rust +#[test] +fn test() { + let env = Env::default(); + env.mock_all_auths(); + + assert_eq!(client.increment(&user_1, &5), 5); + // Verify that the user indeed had to authorize a call of `increment` with + // the expected arguments: + assert_eq!( + env.auths(), + std::vec![( + // Address for which authorization check is performed + user_1.clone(), + // Invocation tree that needs to be authorized + AuthorizedInvocation { + // Function that is authorized. Can be a contract function or + // a host function that requires authorization. + function: AuthorizedFunction::Contract(( + // Address of the called contract + contract_id.clone(), + // Name of the called function + symbol_short!("increment"), + // Arguments used to call `increment` (converted to the + // env-managed vector via `into_val`) + (user_1.clone(), 5_u32).into_val(&env), + )), + // The contract doesn't call any other contracts that require + // authorization, + sub_invocations: std::vec![] + } + )] + ) +} +``` diff --git a/docs/guides/testing/testnet-reset.mdx b/docs/guides/testing/testnet-reset.mdx new file mode 100644 index 00000000..6dbd3596 --- /dev/null +++ b/docs/guides/testing/testnet-reset.mdx @@ -0,0 +1,7 @@ +--- +title: Automate Testnet and Futurenet reset data +hide_table_of_contents: true +draft: true +--- + +Talk about how to automate contract creation/deployment/etc. diff --git a/docs/guides/transactions/README.mdx b/docs/guides/transactions/README.mdx new file mode 100644 index 00000000..50534178 --- /dev/null +++ b/docs/guides/transactions/README.mdx @@ -0,0 +1,8 @@ +--- +title: Transactions +hide_table_of_contents: true +--- + +The entry point for every smart contract interaction is ultimately a [transaction] on the Stellar network. + +[transaction]: https://developers.stellar.org/docs/fundamentals-and-concepts/stellar-data-structures/operations-and-transactions diff --git a/docs/guides/transactions/invoke-contract-tx-js.mdx b/docs/guides/transactions/invoke-contract-tx-js.mdx new file mode 100644 index 00000000..72197de8 --- /dev/null +++ b/docs/guides/transactions/invoke-contract-tx-js.mdx @@ -0,0 +1,113 @@ +--- +title: Invoke a contract function in a Stellar transaction using JavaScript +hide_table_of_contents: true +--- + +This is a simple example using the `@stellar/stellar-sdk` JavaScript library to create, simulate, and then assemble a Stellar transaction which invokes an `increment` function of the [auth example contract](../../tutorials/auth.mdx). + +```javascript +(async () => { + const { + Keypair, + Contract, + SorobanRpc, + TransactionBuilder, + Networks, + BASE_FEE, + } = require("@stellar/stellar-sdk"); + + // The source account will be used to sign and send the transaction. + // GCWY3M4VRW4NXJRI7IVAU3CC7XOPN6PRBG6I5M7TAOQNKZXLT3KAH362 + const sourceKeypair = Keypair.fromSecret( + "SCQN3XGRO65BHNSWLSHYIR4B65AHLDUQ7YLHGIWQ4677AZFRS77TCZRB", + ); + + // Configure SorobanClient to use the `soroban-rpc` instance of your + // choosing. + const server = new SorobanRpc.Server( + "https://soroban-testnet.stellar.org:443", + ); + + // Here we will use a deployed instance of the `increment` example contract. + const contractAddress = + "CCTAMZGXBVCQJJCX64EVYTM6BKW5BXDI5PRCXTAYT6DVEDXKGS347HWU"; + const contract = new Contract(contractAddress); + + // Transactions require a valid sequence number (which varies from one + // account to another). We fetch this sequence number from the RPC server. + const sourceAccount = await server.getAccount(sourceKeypair.publicKey()); + + // The transaction begins as pretty standard. The source account, minimum + // fee, and network passphrase are provided. + let builtTransaction = new TransactionBuilder(sourceAccount, { + fee: BASE_FEE, + networkPassphrase: Networks.FUTURENET, + }) + // The invocation of the `increment` function of our contract is added + // to the transaction. Note: `increment` doesn't require any parameters, + // but many contract functions do. You would need to provide those here. + .addOperation(contract.call("increment")) + // This transaction will be valid for the next 30 seconds + .setTimeout(30) + .build(); + + console.log(`builtTransaction=${builtTransaction.toXDR()}`); + + // We use the RPC server to "prepare" the transaction. This simulating the + // transaction, discovering the storage footprint, and updating the + // transaction to include that footprint. If you know the footprint ahead of + // time, you could manually use `addFootprint` and skip this step. + let preparedTransaction = await server.prepareTransaction(builtTransaction); + + // Sign the transaction with the source account's keypair. + preparedTransaction.sign(sourceKeypair); + + // Let's see the base64-encoded XDR of the transaction we just built. + console.log( + `Signed prepared transaction XDR: ${preparedTransaction + .toEnvelope() + .toXDR("base64")}`, + ); + + // Submit the transaction to the Soroban-RPC server. The RPC server will + // then submit the transaction into the network for us. Then we will have to + // wait, polling `getTransaction` until the transaction completes. + try { + let sendResponse = await server.sendTransaction(preparedTransaction); + console.log(`Sent transaction: ${JSON.stringify(sendResponse)}`); + + if (sendResponse.status === "PENDING") { + let getResponse = await server.getTransaction(sendResponse.hash); + // Poll `getTransaction` until the status is not "NOT_FOUND" + while (getResponse.status === "NOT_FOUND") { + console.log("Waiting for transaction confirmation..."); + // See if the transaction is complete + getResponse = await server.getTransaction(sendResponse.hash); + // Wait one second + await new Promise((resolve) => setTimeout(resolve, 1000)); + } + + console.log(`getTransaction response: ${JSON.stringify(getResponse)}`); + + if (getResponse.status === "SUCCESS") { + // Make sure the transaction's resultMetaXDR is not empty + if (!getResponse.resultMetaXdr) { + throw "Empty resultMetaXDR in getTransaction response"; + } + // Find the return value from the contract and return it + let transactionMeta = getResponse.resultMetaXdr; + let returnValue = transactionMeta.v3().sorobanMeta().returnValue(); + console.log(`Transaction result: ${returnValue.value()}`); + } else { + throw `Transaction failed: ${getResponse.resultXdr}`; + } + } else { + throw sendResponse.errorResultXdr; + } + } catch (err) { + // Catch and report any errors we've thrown + console.log("Sending transaction failed"); + console.log(JSON.stringify(err)); + } +})(); +``` diff --git a/docs/guides/transactions/submit-transaction-wait-js.mdx b/docs/guides/transactions/submit-transaction-wait-js.mdx new file mode 100644 index 00000000..4fc53201 --- /dev/null +++ b/docs/guides/transactions/submit-transaction-wait-js.mdx @@ -0,0 +1,60 @@ +--- +title: Submit a transaction to Soroban RPC using the JavaScript SDK +hide_table_of_contents: true +--- + +Here is a simple, rudimentary looping mechanism to submit a transaction to Soroban RPC and wait for a result. + +```typescript +import { + Transaction, + FeeBumpTransaction, + SorobanRpc, +} from "@stellar/stellar-sdk"; + +const RPC_SERVER = "https://soroban-testnet.stellar.org/"; +const server = new SorobanRpc.Server(RPC_SERVER); + +// Submits a tx and then polls for its status until a timeout is reached. +async function yeetTx( + tx: Transaction | FeeBumpTransaction, +): Promise { + return server.sendTransaction(tx).then(async (reply) => { + if (reply.status !== "PENDING") { + throw reply; + } + + let status; + let attempts = 0; + while (attempts++ < 5) { + const tmpStatus = await server.getTransaction(reply.hash); + switch (tmpStatus.status) { + case "FAILED": + throw tmpStatus; + case "NOT_FOUND": + await sleep(500); + continue; + case "SUCCESS": + status = tmpStatus; + break; + } + } + + if (attempts >= 5 || !status) { + throw new Error(`Failed to find transaction ${reply.hash} in time.`); + } + + return status; + }); +} + +function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} +``` + +:::caution + +Remember: You should always handle errors gracefully! This is a fail-hard and fail-fast approach that should only be used in these examples. + +::: diff --git a/docs/host-functions-reference/_category_.json b/docs/host-functions-reference/_category_.json deleted file mode 100644 index dcd21d4f..00000000 --- a/docs/host-functions-reference/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "position": 0, - "label": "Host Functions Reference", - "link": { - "type": "generated-index" - } -} diff --git a/docs/intro/_category_.json b/docs/intro/_category_.json deleted file mode 100644 index 88e3c9ae..00000000 --- a/docs/intro/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "position": 0, - "label": "Intro", - "link": { - "type": "generated-index" - } -} diff --git a/docs/migrate/_category_.json b/docs/migrate/_category_.json new file mode 100644 index 00000000..d9330bdd --- /dev/null +++ b/docs/migrate/_category_.json @@ -0,0 +1,4 @@ +{ + "position": 60, + "label": "Migrate from Another Chain" +} diff --git a/docs/migrate/cosmos.mdx b/docs/migrate/cosmos.mdx new file mode 100644 index 00000000..04e0ecbc --- /dev/null +++ b/docs/migrate/cosmos.mdx @@ -0,0 +1,8 @@ +--- +sidebar_position: 30 +title: Cosmos +description: Migrate your smart contract code from Cosmos to Soroban +draft: true +--- + +I dunno, like copy/paste it? diff --git a/docs/migrate/evm/_category_.json b/docs/migrate/evm/_category_.json new file mode 100644 index 00000000..9561ee12 --- /dev/null +++ b/docs/migrate/evm/_category_.json @@ -0,0 +1,4 @@ +{ + "position": 10, + "label": "EVM Networks" +} diff --git a/docs/fundamentals-and-concepts/migrating-from-evm/introduction-to-solidity-and-rust.mdx b/docs/migrate/evm/introduction-to-solidity-and-rust.mdx similarity index 100% rename from docs/fundamentals-and-concepts/migrating-from-evm/introduction-to-solidity-and-rust.mdx rename to docs/migrate/evm/introduction-to-solidity-and-rust.mdx diff --git a/docs/fundamentals-and-concepts/migrating-from-evm/smart-contract-deployment.mdx b/docs/migrate/evm/smart-contract-deployment.mdx similarity index 98% rename from docs/fundamentals-and-concepts/migrating-from-evm/smart-contract-deployment.mdx rename to docs/migrate/evm/smart-contract-deployment.mdx index 7e78be14..a09ce525 100644 --- a/docs/fundamentals-and-concepts/migrating-from-evm/smart-contract-deployment.mdx +++ b/docs/migrate/evm/smart-contract-deployment.mdx @@ -62,7 +62,7 @@ async function main() { ### Soroban Client -Soroban offers a comparable library, [`stellar-sdk`](../../reference/sdks/js), that enables seamless interaction smart contracts deployed on the Stellar Network. This library supplies a comprehensive networking layer API for Soroban RPC methods as well as the traditional Horizon API, simplifying the process of building and signing transactions. Additionally, `stellar-sdk` streamlines communication with RPC instances and supports submitting transactions or querying network state with ease. +Soroban offers a comparable library, [`stellar-sdk`](../../reference/sdks/interact-with-contracts.mdx#javascript-sdk), that enables seamless interaction smart contracts deployed on the Stellar Network. This library supplies a comprehensive networking layer API for Soroban RPC methods as well as the traditional Horizon API, simplifying the process of building and signing transactions. Additionally, `stellar-sdk` streamlines communication with RPC instances and supports submitting transactions or querying network state with ease. ### Scripts diff --git a/docs/fundamentals-and-concepts/migrating-from-evm/solidity-and-rust-advanced-concepts.mdx b/docs/migrate/evm/solidity-and-rust-advanced-concepts.mdx similarity index 98% rename from docs/fundamentals-and-concepts/migrating-from-evm/solidity-and-rust-advanced-concepts.mdx rename to docs/migrate/evm/solidity-and-rust-advanced-concepts.mdx index 0ff1e0b1..12eeac6a 100644 --- a/docs/fundamentals-and-concepts/migrating-from-evm/solidity-and-rust-advanced-concepts.mdx +++ b/docs/migrate/evm/solidity-and-rust-advanced-concepts.mdx @@ -170,7 +170,7 @@ impl AllocContract { In this example, the `alloc` crate is imported into the smart contract using the `extern crate alloc;` statement. The `alloc` crate is then used to create a temporary vector that holds values from 0 to `count`. The values in the vector are then summed and returned. -For more details on how to use the `alloc` crate, including a hands-on practical exercise, visit the [alloc section](../../basic-tutorials/alloc#how-it-works) of the documentation. +For more details on how to use the `alloc` crate, including a hands-on practical exercise, visit the [alloc section](../../tutorials/alloc#how-it-works) of the documentation. #### Inheriting Functionality from Other Crates @@ -409,13 +409,13 @@ It's worth mentioning that the Soroban Rust SDK comes with several built-in requ Interfaces are an essential part of building smart contracts with Soroban. -There are many types of smart contract interfaces, and each has a specific purpose. One example of an interface built with Soroban is the [Token Interface](../../reference/interfaces/token-interface). This interface ensures that tokens deployed on Soroban are interoperable with Soroban's built-in tokens (such as the Stellar Asset Contract). The Token Interface consists of three compatibility requirements: +There are many types of smart contract interfaces, and each has a specific purpose. One example of an interface built with Soroban is the [Token Interface](../../tokens/token-interface.mdx). This interface ensures that tokens deployed on Soroban are interoperable with Soroban's built-in tokens (such as the Stellar Asset Contract). The Token Interface consists of three compatibility requirements: - `function interface` - `authorization` - `events` -For more information on smart contract interfaces built with Soroban, including the Token Interface, visit the [interfaces section](../../category/interfaces) of the documentation. +For more information on smart contract interfaces built with Soroban, including the Token Interface, visit the [tokens section](../../category/tokens) of the documentation. ## Writing Safe and Efficient Rust Code for Smart Contracts @@ -542,7 +542,7 @@ In contrast to Solidity's global variables, Soroban relies on passing an [`Env`] The `Env` provides access to information about the currently executing contract, who invoked it, contract data, functions for signing, hashing, etc. -For instance, you would use `env.storage().persistent().get(key)` to access a `persistent` target value from the contract's [storage](https://docs.rs/soroban-sdk/latest/soroban_sdk/struct.Env.html). Read more about the different storage types [here](../persisting-data.mdx). +For instance, you would use `env.storage().persistent().get(key)` to access a `persistent` target value from the contract's [storage](https://docs.rs/soroban-sdk/latest/soroban_sdk/struct.Env.html). Read more about the different storage types [here](../../soroban-internals/persisting-data.mdx). - `env.storage()` is used to get a struct for accessing and updating contract data that has been stored. - Used as `env.storage().persistent().get()` or `env.persistent().storage().set()`. @@ -898,7 +898,7 @@ By utilizing these authorization methods provided by the `Address` object from t Soroban's approach to authorization in this example offers several advantages over Solidity's model of ERC20 by eliminating the need for separate approval management. Instead, authorization checks can be directly incorporated into any Soroban function. This simplifies the contract codebase and reduces the complexity associated with managing separate approval states. -Soroban authorization provides Contract-level Authorization, Account Abstraction Functionality, and more advanced Authorization checks. To learn more about these advantages, visit the [Authorization section](../../fundamentals-and-concepts/authorization) of the documentation. +Soroban authorization provides Contract-level Authorization, Account Abstraction Functionality, and more advanced Authorization checks. To learn more about these advantages, visit the [Authorization section](../../soroban-internals/authorization) of the documentation. ## Summary diff --git a/docs/fundamentals-and-concepts/migrating-from-evm/solidity-and-rust-basics.mdx b/docs/migrate/evm/solidity-and-rust-basics.mdx similarity index 95% rename from docs/fundamentals-and-concepts/migrating-from-evm/solidity-and-rust-basics.mdx rename to docs/migrate/evm/solidity-and-rust-basics.mdx index 233b439a..cdcd8f08 100644 --- a/docs/fundamentals-and-concepts/migrating-from-evm/solidity-and-rust-basics.mdx +++ b/docs/migrate/evm/solidity-and-rust-basics.mdx @@ -107,7 +107,7 @@ Some of the basic constructs in Solidity include: 4. `Events`: Used to log changes in the contract state. 5. `Inheritance`: Solidity supports single and multiple inheritance. -We will explore some of these constructs in more detail in the next article, [Advanced Solidity Concepts](solidity-and-rust-advanced-concepts#advanced-solidity-concepts). +We will explore some of these constructs in more detail in the next article, [Advanced Solidity Concepts](solidity-and-rust-advanced-concepts.mdx#advanced-solidity-concepts). ### Rust Syntax @@ -121,7 +121,7 @@ fn main() { ### Data Types -The [Soroban Rust SDK](https://docs.rs/soroban-sdk/latest/soroban_sdk/index.html) supports a variety of [Built-In Types](../../fundamentals-and-concepts/built-in-types) which consist of both Primitive and [Custom Types](../../fundamentals-and-concepts/custom-types), such as: +The [Soroban Rust SDK](https://docs.rs/soroban-sdk/latest/soroban_sdk/index.html) supports a variety of [Built-In Types](../../soroban-internals/types/built-in-types.mdx) which consist of both Primitive and [Custom Types](../../soroban-internals/types/custom-types.mdx), such as: #### Primitive Data Types @@ -322,7 +322,7 @@ Rust enforces [**strict ownership rules**](https://doc.rust-lang.org/book/ch04-0 Contract development in Rust involves certain restrictions due to either unavailable features in the deployment environment or high runtime costs. Thus, the code written for contracts can be seen as a distinct _dialect_ of Rust, focusing on deterministic behavior and minimized code size. -To learn more about Rust's Contract Dialect, check out the [Contract Rust Dialect Page](../../fundamentals-and-concepts/rust-dialect). +To learn more about Rust's Contract Dialect, check out the [Contract Rust Dialect Page](../../soroban-internals/rust-dialect.mdx). ## Writing and Interacting with Simple Smart Contracts @@ -455,7 +455,7 @@ impl IncrementContract { } ``` -This code is an implementation of a smart contract written in Rust using the [`Soroban Rust SDK`](../../reference/sdks/rust), a Rust-based smart contract development toolkit developed by the [Stellar Development Foundation (SDF)](https://stellar.org/foundation). The Soroban Rust SDK provides a powerful set of tools for writing smart contracts that run on the Soroban Virtual Machine. +This code is an implementation of a smart contract written in Rust using the [`Soroban Rust SDK`](../../reference/sdks/write-contracts.mdx#soroban-rust-sdk), a Rust-based smart contract development toolkit developed by the [Stellar Development Foundation (SDF)](https://stellar.org/foundation). The Soroban Rust SDK provides a powerful set of tools for writing smart contracts that run on the Soroban Virtual Machine. Here's a line-by-line explanation of what the code is doing: @@ -541,7 +541,7 @@ env.storage().instance().get(&COUNTER).unwrap_or(0) This is a repeat of the code we saw earlier, which retrieves the value associated with the key `COUNTER` from the contract storage. If there is no value set for the key `COUNTER`, a default value of 0 is used. Finally, the `unwrap()` method is called to extract the actual value from the `Ok` wrapper, which is then returned to the caller of the function. -Now that we have written our smart contract, it's time to explore how we can interact with it using the [Soroban-CLI](../../reference/soroban-cli), one of many robust [Developer Tools](http://localhost:3000/docs/developer-tools) available. This powerful command-line tool allows us to interact with the Soroban Virtual Machine from a local machine, providing us with an efficient and flexible way to manage our smart contract. +Now that we have written our smart contract, it's time to explore how we can interact with it using the [Soroban-CLI](../../reference/soroban-cli.mdx), one of many robust [Developer Tools](../../developer-tools.mdx) available. This powerful command-line tool allows us to interact with the Soroban Virtual Machine from a local machine, providing us with an efficient and flexible way to manage our smart contract. ### Interacting with the Rust Smart Counter @@ -551,7 +551,7 @@ To interact with the Rust counter, create a new Rust library using the cargo new cargo new --lib increment ``` -Once the project is created, replace the `src/lib.rs` file with the [code example above](#writing-and-interacting-with-a-simple-counter-in-rust). +Once the project is created, replace the `src/lib.rs` file with the [code example above](#writing-a-smart-counter-in-rust). ```rust // Remember to replace your lib.rs file with the code example above. @@ -595,7 +595,7 @@ inherits = "release" debug-assertions = true ``` -> _Note_: For a detailed explanation of the `Cargo.toml` configuration used in this tutorial, check out the [Hello World Example](../../getting-started/hello-world#import-soroban-sdk-and-features). +> _Note_: For a detailed explanation of the `Cargo.toml` configuration used in this tutorial, check out the [Hello World Example](../../getting-started/hello-world.mdx#import-soroban-sdk-and-features). Next, build the project using the `soroban contract build` command. diff --git a/docs/migrate/near.mdx b/docs/migrate/near.mdx new file mode 100644 index 00000000..b5db4667 --- /dev/null +++ b/docs/migrate/near.mdx @@ -0,0 +1,8 @@ +--- +sidebar_position: 40 +title: Near +description: Migrate your smart contract code from Near to Soroban +draft: true +--- + +I dunno, like copy/paste it? diff --git a/docs/migrate/solana.mdx b/docs/migrate/solana.mdx new file mode 100644 index 00000000..89792c53 --- /dev/null +++ b/docs/migrate/solana.mdx @@ -0,0 +1,8 @@ +--- +sidebar_position: 20 +title: Solana +description: Migrate your smart contract code from Solana to Soroban +draft: true +--- + +I dunno, like copy/paste it? diff --git a/docs/reference/_category_.json b/docs/reference/_category_.json index f6d95cfe..46edd86b 100644 --- a/docs/reference/_category_.json +++ b/docs/reference/_category_.json @@ -1,7 +1,4 @@ { - "position": 50, - "label": "Reference", - "link": { - "type": "generated-index" - } + "position": 70, + "label": "Reference" } diff --git a/docs/reference/data-providers.mdx b/docs/reference/data-providers.mdx index e10a1b2f..bbb10447 100644 --- a/docs/reference/data-providers.mdx +++ b/docs/reference/data-providers.mdx @@ -1,6 +1,6 @@ --- title: Data Providers -sidebar_position: 8 +sidebar_position: 60 --- In order for the Stellar network to remain as open and accessible as it has always been, Soroban-related data is available through a number of channels. diff --git a/docs/reference/freighter.mdx b/docs/reference/freighter.mdx index b9ffecf2..cf9e9a58 100644 --- a/docs/reference/freighter.mdx +++ b/docs/reference/freighter.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 9 +sidebar_position: 70 title: Freighter Wallet description: Freighter is a browser extension that can sign Soroban transactions. --- @@ -71,7 +71,7 @@ If you're building a JS dapp, easily sign Soroban transactions using the [Freigh ## Sign Authorization Entries -In order to take advantage of [contract authorization](../fundamentals-and-concepts/authorization), you can use Freighter's API to sign an authorization entry. A good example of how signing an authorization entry works can be found in the [`authorizeEntry` helper of +In order to take advantage of [contract authorization](../soroban-internals/authorization.mdx), you can use Freighter's API to sign an authorization entry. A good example of how signing an authorization entry works can be found in the [`authorizeEntry` helper of `stellar-sdk`](https://github.com/stellar/js-stellar-base/blob/e3d6fc3351e7d242b374c7c6057668366364a279/src/auth.js#L97). Like in the helper, you can construct a [`HashIdPreimageSorobanAuthorization`](https://github.com/stellar/js-stellar-base/blob/a9567e5843760bfb6a8b786592046aee4c9d38b2/types/next.d.ts#L6895) and use the xdr representation of that structure to call `await freighterApi.signAuthEntry(preimageXdr)`. This call will return a `Buffer` of the signed hash of the `HashIdPreimageSorobanAuthorization` passed in, which can then be used to submit to the network during a contract authorization workflow. diff --git a/docs/reference/interfaces/_category_.json b/docs/reference/interfaces/_category_.json deleted file mode 100644 index 430dd772..00000000 --- a/docs/reference/interfaces/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "position": 2, - "label": "Interfaces", - "link": { - "type": "generated-index" - } -} diff --git a/docs/reference/networks.mdx b/docs/reference/networks.mdx new file mode 100644 index 00000000..2a34d52b --- /dev/null +++ b/docs/reference/networks.mdx @@ -0,0 +1,29 @@ +--- +sidebar_position: 30 +title: Networks +description: The shared Soroban test networks. +--- + +Testnet and Futurenet have been made available as the first shared test networks to enable developers to learn, tinker, and build applications on Soroban while being able to interact with other participants. + +| Testnet | Testnet | Futurenet | +| :----------------- | ----------------------------------- | ---------------------------------------- | +| Network Passphrase | `Test SDF Network ; September 2015` | `Test SDF Future Network ; October 2022` | +| Horizon API | https://horizon-testnet.stellar.org | https://horizon-futurenet.stellar.org | +| Friendbot API | https://friendbot.stellar.org | https://friendbot-futurenet.stellar.org | +| Validator | `core-live-testnet.stellar.org` | `core-live-futurenet.stellar.org` | +| History Archive | https://history-testnet.stellar.org | https://history-futurenet.stellar.org | + +:::caution + +Testnet can be reset at any time. A reset erases all accounts, contract data, and contract deployments from the network. + +::: + +:::caution + +All components deployed to Testnet and releases supporting Testnet, such as the [Soroban RPC Server], are in active development and will be unstable at times. They should be treated as development releases with no production capabilities, API or backward compatibility guarantees. + +::: + +[Soroban RPC Server]: https://github.com/stellar/quickstart#soroban-rpc-server diff --git a/docs/reference/rpc-list.mdx b/docs/reference/rpc-list.mdx index 74414c3e..78e92261 100644 --- a/docs/reference/rpc-list.mdx +++ b/docs/reference/rpc-list.mdx @@ -1,6 +1,6 @@ --- +sidebar_position: 50 title: RPC Providers -sidebar_position: 7 --- ## Ecosystem Providers diff --git a/docs/reference/rpc.mdx b/docs/reference/rpc.mdx index 23b7a0ea..4cda480c 100644 --- a/docs/reference/rpc.mdx +++ b/docs/reference/rpc.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 6 +sidebar_position: 40 title: RPC Usage --- @@ -111,7 +111,7 @@ soroban contract invoke \ When you're done with your Standalone node, you can close it with ctrlc (not cmd). This will fully remove the container (that's what the `--rm` option to the `docker` command does), which means you will need to re-deploy your contract and re-fund your identity the next time you start it. If you work with local nodes often, you may want to create scripts to make these initialization steps easier. For example, see the [example dapp's `initialize.sh`](https://github.com/stellar/soroban-example-dapp/blob/abdac3afdb6c410cc426831ece93371c1a27347d/initialize.sh). -[Testnet]: testnet +[Testnet]: networks.mdx [Run on Sandbox]: ../getting-started/hello-world#run-on-sandbox ### Testnet @@ -215,7 +215,7 @@ helm install my-rpc stellar/soroban-rpc \ This example of Helm chart usage highlights some key aspects: -- Set the `global.image.sorobanRpc.tag` to a tag from the [soroban-rpc dockerhub repo](https://hub.docker.com/r/stellar/soroban-rpc) for the image version you want to run. Refer to [the releases page](./releases) to find the correct tag for the Soroban release you are running. +- Set the `global.image.sorobanRpc.tag` to a tag from the [soroban-rpc dockerhub repo](https://hub.docker.com/r/stellar/soroban-rpc) for the image version you want to run. Refer to [the releases page](../releases.mdx) to find the correct tag for the Soroban release you are running. - The RPC server stores a revolving window of recent data from network ledgers to disk. The size of that data varies depending on the network and its transaction volumes, but it has an estimated range between 10 to 100 MB. To ensure the RPC pod has consistent access to disk storage space and read/write throughput, this example demonstrates how to optionally enable the Helm chart deployment to use a `PersistentVolumeClaim` (PVC) of 100MB from `default` storage class on Kubernetes by enabling these persistence parameters: diff --git a/docs/reference/sdks/_category_.json b/docs/reference/sdks/_category_.json index 7e1e701e..224dc2ce 100644 --- a/docs/reference/sdks/_category_.json +++ b/docs/reference/sdks/_category_.json @@ -1,7 +1,7 @@ { - "position": 1, + "position": 20, "label": "SDKs", "link": { - "type": "generated-index" + "type": "generated-index" } } diff --git a/docs/reference/sdks/assemblyscript-sdk.mdx b/docs/reference/sdks/assemblyscript-sdk.mdx deleted file mode 100644 index 75d8c308..00000000 --- a/docs/reference/sdks/assemblyscript-sdk.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -sidebar_position: 5 -title: AssemblyScript SDK -description: as-soroban-sdk supports writing Soroban contracts in AssemblyScript. ---- - -The `as-soroban-sdk` is an open source SDK that supports writing programs for the Soroban smart contract platform by using the AssemblyScript programming language. - -The AssemblyScript Soroban SDK is maintained by dedicated community developer, Soneso. - -:::info - -Report issues and share feedback about the `AssemblyScript Soroban SDK` -[here](https://github.com/Soneso/as-soroban-sdk/issues/new). - -::: - -## SDK Documentation - -SDK documentation is available at: -https://github.com/Soneso/as-soroban-sdk - -## Examples - -Many examples are available at: -https://github.com/Soneso/as-soroban-examples - -## Subscribe to Releases - -Subscribe to releases on the GitHub repository: -https://github.com/Soneso/as-soroban-sdk - -## Add `as-soroban-sdk` as a Dependency - -`npm install as-soroban-sdk` diff --git a/docs/reference/sdks/build-your-own-sdk.mdx b/docs/reference/sdks/build-your-own-sdk.mdx index a2400dda..5ddf696a 100644 --- a/docs/reference/sdks/build-your-own-sdk.mdx +++ b/docs/reference/sdks/build-your-own-sdk.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 11 +sidebar_position: 30 title: Build Your Own SDK description: A guide to developing Soroban SDKs for languages other than Rust. --- diff --git a/docs/reference/sdks/elixir.mdx b/docs/reference/sdks/elixir.mdx deleted file mode 100644 index c8fa23dc..00000000 --- a/docs/reference/sdks/elixir.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -sidebar_position: 9 -title: Elixir SDK -description: Soroban.ex supports writing Soroban applications in Elixir. ---- - -**Soroban.ex** is an open source library for Elixir to interact with the Soroban-RPC server, and facilitate the deployment and invocation of Soroban smart contracts. - -The Elixir SDK (**Soroban.ex**) can be found on GitHub at https://github.com/kommitters/soroban.ex. - -This SDK is maintained by dedicated community developers, kommitters Open Source. - -## Documentation - -Documentation is available at https://github.com/kommitters/soroban.ex#documentation. diff --git a/docs/reference/sdks/flutter-sdk.mdx b/docs/reference/sdks/flutter-sdk.mdx deleted file mode 100644 index aa5fa273..00000000 --- a/docs/reference/sdks/flutter-sdk.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -sidebar_position: 7 -title: Flutter SDK -description: stellar-flutter-sdk supports writing Soroban applications in Flutter. ---- - -The `stellar-flutter-sdk` is an open source Stellar SDK for Flutter developers. It provides APIs to build transactions and connect to Horizon. - -It also provides functionality to deploy and invoke Soroban smart contracts and communicates with the Soroban RPC Server. - -The [Flutter Stellar SDK](https://github.com/Soneso/stellar_flutter_sdk) is maintained by dedicated community developer, Soneso. - -## SDK Documentation for Soroban - -The SDK documentation for Soroban features is available [here](https://github.com/Soneso/stellar_flutter_sdk/blob/master/soroban.md). diff --git a/docs/reference/sdks/interact-with-contracts.mdx b/docs/reference/sdks/interact-with-contracts.mdx new file mode 100644 index 00000000..27e4cc19 --- /dev/null +++ b/docs/reference/sdks/interact-with-contracts.mdx @@ -0,0 +1,75 @@ +--- +sidebar_position: 20 +title: Interact with Contracts +description: SDKs support writing Soroban applications in many languages. +--- + +## JavaScript SDK + +`stellar-sdk` is the JavaScript library for communicating with a Soroban RPC server, communicating with the Horizon API, and building transactions on the Stellar network. It is used for building Stellar apps either on Node.js or in the browser. + +It provides: + +- a networking layer API for Soroban RPC methods and the Horizon API. +- facilities for building and signing transactions, for communicating with an RPC instance, for communicating with a Horizon instance, and for submitting transactions or querying network state. + +The SDK is available at: https://github.com/stellar/js-stellar-sdk and on NPM [here](https://www.npmjs.com/package/@stellar/stellar-sdk). + +## Python SDK + +`py-stellar-base` is a Python library for communicating with a Stellar Horizon server. It is used for building Stellar apps on Python. It supports Python 3.7+ as well as PyPy 3.7+. + +This SDK is maintained by a dedicated community developer. + +It provides: + +- a networking layer API for Horizon endpoints. +- facilities for building and signing transactions, for communicating with a Stellar Horizon instance, and for submitting transactions or querying network history. + +The Python SDK is available at: https://github.com/StellarCN/py-stellar-base + +## iOS SDK + +The `stellar-ios-mac-sdk` is an open source Stellar SDK for iOS & Mac. It provides APIs to build transactions and connect to Horizon. + +It also provides functionality to deploy and invoke Soroban smart contracts and communicates with the Soroban RPC Server. + +The [iOS Stellar SDK](https://github.com/Soneso/stellar-ios-mac-sdk) is maintained by dedicated community developer, Soneso. + +The SDK documentation for Soroban features is available [here](https://github.com/Soneso/stellar-ios-mac-sdk/blob/master/soroban.md). + +## Flutter SDK + +The `stellar-flutter-sdk` is an open source Stellar SDK for Flutter developers. It provides APIs to build transactions and connect to Horizon. + +It also provides functionality to deploy and invoke Soroban smart contracts and communicates with the Soroban RPC Server. + +The [Flutter Stellar SDK](https://github.com/Soneso/stellar_flutter_sdk) is maintained by dedicated community developer, Soneso. + +The SDK documentation for Soroban features is available [here](https://github.com/Soneso/stellar_flutter_sdk/blob/master/soroban.md). + +## PHP SDK + +The `stellar-php-sdk` is an open source Stellar SDK for PHP developers. It provides APIs to build transactions and connect to Horizon. + +It also provides functionality to deploy and invoke Soroban smart contracts and communicates with the Soroban RPC Server. + +The [PHP Stellar SDK](https://github.com/Soneso/stellar-php-sdk) is maintained by dedicated community developer, Soneso. + +The SDK documentation for Soroban features is available [here](https://github.com/Soneso/stellar-php-sdk/blob/main/soroban.md). + +## Elixir SDK + +`Soroban.ex` is an open source library for Elixir to interact with the Soroban-RPC server, and facilitate the deployment and invocation of Soroban smart contracts. + +The Elixir SDK (`Soroban.ex`) can be found on GitHub at https://github.com/kommitters/soroban.ex. + +This SDK is maintained by dedicated community developers, kommitters Open Source. + +Documentation is available at https://github.com/kommitters/soroban.ex#documentation. + +## Java SDK + +`java-stellar-sdk` provides APIs to build transactions and connect to Horizon, it also provides functionality to deploy and invoke Soroban smart contracts and communicates with the Soroban RPC Server. + +SDK is available at: https://github.com/stellar/java-stellar-sdk diff --git a/docs/reference/sdks/ios-sdk.mdx b/docs/reference/sdks/ios-sdk.mdx deleted file mode 100644 index ecf741a9..00000000 --- a/docs/reference/sdks/ios-sdk.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -sidebar_position: 6 -title: iOS SDK -description: stellar-ios-mac-sdk supports writing Soroban applications for iOS and Mac. ---- - -The `stellar-ios-mac-sdk` is an open source Stellar SDK for iOS & Mac. It provides APIs to build transactions and connect to Horizon. - -It also provides functionality to deploy and invoke Soroban smart contracts and communicates with the Soroban RPC Server. - -The [iOS Stellar SDK](https://github.com/Soneso/stellar-ios-mac-sdk) is maintained by dedicated community developer, Soneso. - -## SDK Documentation for Soroban - -The SDK documentation for Soroban features is available [here](https://github.com/Soneso/stellar-ios-mac-sdk/blob/master/soroban.md). diff --git a/docs/reference/sdks/java.mdx b/docs/reference/sdks/java.mdx deleted file mode 100644 index 2c27ea50..00000000 --- a/docs/reference/sdks/java.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -sidebar_position: 10 -title: Java SDK -description: java-stellar-sdk supports writing Soroban applications in Java. ---- - -java-stellar-sdk provides APIs to build transactions and connect to Horizon, it also provides functionality to deploy and invoke Soroban smart contracts and communicates with the Soroban RPC Server. - -## Java SDK - -SDK is available at: https://github.com/stellar/java-stellar-sdk diff --git a/docs/reference/sdks/js.mdx b/docs/reference/sdks/js.mdx deleted file mode 100644 index a03ba391..00000000 --- a/docs/reference/sdks/js.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -sidebar_position: 3 -title: JavaScript SDK -description: stellar-sdk supports writing Soroban applications in JavaScript. ---- - -`stellar-sdk` is the JavaScript library for communicating with a Soroban RPC server, communicating with the Horizon API, and building transactions on the Stellar network. It is used for building Stellar apps either on Node.js or in the browser. - -It provides: - -- a networking layer API for Soroban RPC methods and the Horizon API. -- facilities for building and signing transactions, for communicating with an RPC instance, for communicating with a Horizon instance, and for submitting transactions or querying network state. - -## JavaScript SDK - -The SDK is available at: https://github.com/stellar/js-stellar-sdk and on NPM [here](https://www.npmjs.com/package/@stellar/stellar-sdk). diff --git a/docs/reference/sdks/php-sdk.mdx b/docs/reference/sdks/php-sdk.mdx deleted file mode 100644 index 66f1e2ff..00000000 --- a/docs/reference/sdks/php-sdk.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -sidebar_position: 8 -title: PHP SDK -description: stellar-php-sdk supports writing Soroban applications in PHP. ---- - -The `stellar-php-sdk` is an open source Stellar SDK for PHP developers. It provides APIs to build transactions and connect to Horizon. - -It also provides functionality to deploy and invoke Soroban smart contracts and communicates with the Soroban RPC Server. - -The [PHP Stellar SDK](https://github.com/Soneso/stellar-php-sdk) is maintained by dedicated community developer, Soneso. - -## SDK Documentation for Soroban - -The SDK documentation for Soroban features is available [here](https://github.com/Soneso/stellar-php-sdk/blob/main/soroban.md). diff --git a/docs/reference/sdks/python.mdx b/docs/reference/sdks/python.mdx deleted file mode 100644 index 72158ec3..00000000 --- a/docs/reference/sdks/python.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -sidebar_position: 4 -title: Python SDK -description: py-stellar-base supports writing Soroban applications in Python. ---- - -py-stellar-base is a Python library for communicating with a Stellar Horizon server. It is used for building Stellar apps on Python. It supports Python 3.7+ as well as PyPy 3.7+. - -This SDK is maintained by a dedicated community developer. - -It provides: - -- a networking layer API for Horizon endpoints. -- facilities for building and signing transactions, for communicating with a Stellar Horizon instance, and for submitting transactions or querying network history. - -## Python SDK - -The Python SDK is available at: https://github.com/StellarCN/py-stellar-base/tree/soroban diff --git a/docs/reference/sdks/rust.mdx b/docs/reference/sdks/rust.mdx deleted file mode 100644 index 4dbef863..00000000 --- a/docs/reference/sdks/rust.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -sidebar_position: 1 -title: Soroban Rust SDK -description: soroban-sdk supports writing Soroban contracts in Rust. ---- - -The `soroban-sdk` Rust crate contains the Soroban Rust SDK. - -:::info - -Report issues and share feedback about the `soroban-sdk` -[here](https://github.com/stellar/rs-soroban-sdk/issues/new/choose). - -::: - -## SDK Documentation - -SDK documentation is available at: -https://docs.rs/soroban-sdk - -## Subscribe to Releases - -Subscribe to releases on the GitHub repository: -https://github.com/stellar/rs-soroban-sdk - -## Add `soroban-sdk` as a Dependency - -Use [crates.io](https://crates.io/crates/soroban-sdk) to find the version of the -most recent SDK release. - -Add the following sections to the `Cargo.toml` to import the `soroban-sdk` and -replace `$VERSION` with the released version. - -```toml -[dependencies] -soroban-sdk = $VERSION - -[dev_dependencies] -soroban-sdk = { version = $VERSION, features = ["testutils"] } -``` diff --git a/docs/reference/sdks/write-contracts.mdx b/docs/reference/sdks/write-contracts.mdx new file mode 100644 index 00000000..5f902a3f --- /dev/null +++ b/docs/reference/sdks/write-contracts.mdx @@ -0,0 +1,76 @@ +--- +sidebar_position: 10 +title: Write Contracts +description: SDKs support writing Soroban contracts in Rust and AssemblyScript. +--- + +## Soroban Rust SDK + +The `soroban-sdk` Rust crate contains the Soroban Rust SDK. + +:::info + +Report issues and share feedback about the `soroban-sdk` +[here](https://github.com/stellar/rs-soroban-sdk/issues/new/choose). + +::: + +### SDK Documentation + +SDK documentation is available at: +https://docs.rs/soroban-sdk + +### Subscribe to Releases + +Subscribe to releases on the GitHub repository: +https://github.com/stellar/rs-soroban-sdk + +### Add `soroban-sdk` as a Dependency + +Use [crates.io](https://crates.io/crates/soroban-sdk) to find the version of the +most recent SDK release. + +Add the following sections to the `Cargo.toml` to import the `soroban-sdk` and +replace `$VERSION` with the released version. + +```toml +[dependencies] +soroban-sdk = $VERSION + +[dev_dependencies] +soroban-sdk = { version = $VERSION, features = ["testutils"] } +``` + +## AssemblyScript SDK + +The `as-soroban-sdk` is an open source SDK that supports writing programs for the Soroban smart contract platform by using the AssemblyScript programming language. + +The AssemblyScript Soroban SDK is maintained by dedicated community developer, Soneso. + +:::info + +Report issues and share feedback about the `AssemblyScript Soroban SDK` +[here](https://github.com/Soneso/as-soroban-sdk/issues/new). + +::: + +### SDK Documentation + +SDK documentation is available at: +https://github.com/Soneso/as-soroban-sdk + +### Examples + +Many examples are available at: +https://github.com/Soneso/as-soroban-examples + +### Subscribe to Releases + +Subscribe to releases on the GitHub repository: +https://github.com/Soneso/as-soroban-sdk + +### Add `as-soroban-sdk` as a Dependency + +```bash +npm install as-soroban-sdk +``` diff --git a/docs/reference/soroban-cli.mdx b/docs/reference/soroban-cli.mdx index 11e41ba5..eb57f2a7 100644 --- a/docs/reference/soroban-cli.mdx +++ b/docs/reference/soroban-cli.mdx @@ -1,12 +1,12 @@ --- -sidebar_position: 5 +sidebar_position: 80 title: Soroban CLI description: The tool for interacting with deployed contracts. --- Soroban CLI is the command line interface to Soroban. It allows you to build, deploy, and interact with smart contracts; configure identities; generate key pairs; manage networks; and more. -Install Soroban CLI as explained in [Setup](../getting-started/setup). +Install Soroban CLI as explained in [Setup](../getting-started/setup.mdx). Auto-generated comprehensive reference documentation is available at: https://github.com/stellar/soroban-tools/blob/v20.1.0/docs/soroban-cli-full-docs.md diff --git a/docs/reference/testnet.mdx b/docs/reference/testnet.mdx deleted file mode 100644 index 47dcd96e..00000000 --- a/docs/reference/testnet.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -sidebar_position: 3 -title: Testnet -description: The shared Soroban test network. ---- - -Testnet is available as the first shared test network to enable developers to learn, tinker and build applications on Soroban while being able to interact with other participants. - -| Testnet | | -| :----------------- | ----------------------------------- | -| Network Passphrase | `Test SDF Network ; September 2015` | -| Horizon API | https://horizon-testnet.stellar.org | -| Friendbot API | https://friendbot.stellar.org | -| Validator | `core-live-testnet.stellar.org` | -| History Archive | https://history-testnet.stellar.org | - -| Futurenet | | -| :----------------- | ---------------------------------------- | -| Network Passphrase | `Test SDF Future Network ; October 2022` | -| Horizon API | https://horizon-futurenet.stellar.org | -| Friendbot API | https://friendbot-futurenet.stellar.org | -| Validator | `core-live-futurenet.stellar.org` | -| History Archive | https://history-futurenet.stellar.org | - -:::caution - -Testnet can be reset at any time. A reset erases all accounts, contract data, and contract deployments from the network. - -::: - -:::caution - -All components deployed to Testnet and releases supporting Testnet, such as the [Soroban RPC Server], are in active development and will be unstable at times. They should be treated as development releases with no production capabilities, API or backward compatibility guarantees. - -::: - -[Soroban RPC Server]: https://github.com/stellar/quickstart#soroban-rpc-server diff --git a/docs/reference/releases.mdx b/docs/releases.mdx similarity index 99% rename from docs/reference/releases.mdx rename to docs/releases.mdx index 5baf973c..077563e9 100644 --- a/docs/reference/releases.mdx +++ b/docs/releases.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 90 title: Releases description: Soroban software releases and changelogs. --- @@ -12,7 +12,7 @@ Release candidates are software releases that are also released to the [Testnet] ::: -[Testnet]: testnet.mdx +[Testnet]: reference/networks.mdx ## Stable v20.0.0 (December 18, 2023) @@ -990,7 +990,7 @@ See https://github.com/stellar/soroban-tools/releases v0.7.0 for more details. This release comes with a revamp of authorization approach that is breaking for most of the contracts that did any sort of auth logic or used tokens. -[example](../basic-tutorials/auth.mdx) and [authorization overview](../fundamentals-and-concepts/authorization.mdx) +[example](tutorials/auth.mdx) and [authorization overview](soroban-internals/authorization.mdx) for more details. ### Changelog diff --git a/docs/basic-tutorials/_category_.json b/docs/soroban-internals/_category_.json similarity index 68% rename from docs/basic-tutorials/_category_.json rename to docs/soroban-internals/_category_.json index d48e388f..ea4caea7 100644 --- a/docs/basic-tutorials/_category_.json +++ b/docs/soroban-internals/_category_.json @@ -1,6 +1,6 @@ { "position": 40, - "label": "Basic Tutorials", + "label": "Soroban Internals", "link": { "type": "generated-index" } diff --git a/docs/fundamentals-and-concepts/authorization.mdx b/docs/soroban-internals/authorization.mdx similarity index 97% rename from docs/fundamentals-and-concepts/authorization.mdx rename to docs/soroban-internals/authorization.mdx index a5cf097d..8766e0e0 100644 --- a/docs/fundamentals-and-concepts/authorization.mdx +++ b/docs/soroban-internals/authorization.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 20 title: Authorization description: Smart contract authorization. --- @@ -14,7 +14,7 @@ description: Smart contract authorization. /> @@ -105,7 +105,7 @@ for this authorization are defined by the `Address` and are enforced by the Soroban host. Replay protection is also implemented in the host, i.e., there is normally no need for a contract to manage its own nonces. -[auth example]: ../basic-tutorials/auth.mdx +[auth example]: ../tutorials/auth.mdx #### Authorizing Sub-contract Calls @@ -119,7 +119,7 @@ Contracts don't need to do anything special to benefit from this feature. Just calling a sub-contract that calls `require_auth` will ensure that the sub-contract call has been properly authorized. -[timelock example]: ../advanced-tutorials/timelock.mdx +[timelock example]: ../tutorials/timelock.mdx #### When to `require_auth` @@ -149,7 +149,7 @@ even have different authorization contexts (customized via arguments in `require_auth_for_args`). [Atomic swap] is an example that deals with authorization of two `Address`es. -[Atomic swap]: ../advanced-tutorials/atomic-swap.mdx +[Atomic swap]: ../tutorials/atomic-swap.mdx Note though, that contracts that deal with multiple authorized `Address`es need a bit more complex support on the client side (to collect and attach the proper @@ -187,7 +187,7 @@ with the existing Stellar accounts, Soroban supports 4 different kinds of the account implementations. Below are the general descriptions of these implementations. See the transaction -[guide](./invoking-contracts-with-transactions.mdx) for the +[guide](contract-interactions/stellar-transaction.mdx) for the concrete information of how different accounts are represented. ##### Stellar Account @@ -251,7 +251,7 @@ called). For the exact interface and more details, see the [custom account example]. -[custom account example]: ../advanced-tutorials/custom-account.mdx +[custom account example]: ../tutorials/custom-account.mdx ### Advanced Concepts diff --git a/docs/soroban-internals/contract-interactions/README.mdx b/docs/soroban-internals/contract-interactions/README.mdx new file mode 100644 index 00000000..a0b22bf4 --- /dev/null +++ b/docs/soroban-internals/contract-interactions/README.mdx @@ -0,0 +1,44 @@ +--- +title: Calling Contracts +description: Interact with smart contracts. +sidebar_position: 120 +sidebar_label: Contract Interactions +--- + + + Interact with smart contracts. + + + + + + +Contracts are invoked through a pair of host functions `call` and `try_call`: + +- `try_call(contract, function, args)` calls `function` exported from `contract`, passing `args` and returning a `Status` on any error. +- `call(contract, function, args)` just calls `try_call` with its arguments and traps on `Status`, essentially propagating the error. + +In both cases `contract` is a `Binary` host object containing the contract ID, `function` is a `Symbol` holding the name of an exported function to call, and `args` is a `Vector` of values to pass as arguments. + +These host functions can be invoked in two separate ways: + +- From outside the host, such as when a user submits a transaction that calls a contract. +- From within the host, when one contract calls another. + +Both cases follow the same logic: + +- The contract's Wasm bytecode is retrieved from a `CONTRACT_DATA` ledger entry in the host's storage system. +- A Wasm VM is instantiated for the duration of the invocation. +- The function is looked up and invoked, with arguments passed from caller to callee. + +When a call occurs from outside the host, any arguments will typically be provided in serialized XDR form accompanying the transaction, and will be deserialized and converted to host objects automatically before invoking the contract. + +When a call occurs from inside the host, the caller and callee contracts _share the same host_ and the caller can pass references to host objects directly to the callee without any need to serialize or deserialize them. + +Since host objects are immutable, there is limited risk to passing a shared reference from one contract to another: the callee cannot modify the object in a way that would surprise the caller, only create new objects. diff --git a/docs/soroban-internals/contract-interactions/cross-contract.mdx b/docs/soroban-internals/contract-interactions/cross-contract.mdx new file mode 100644 index 00000000..2a13a8c7 --- /dev/null +++ b/docs/soroban-internals/contract-interactions/cross-contract.mdx @@ -0,0 +1,25 @@ +--- +sidebar_position: 10 +title: Cross-Contract +description: Interact with a Soroban contract from within another Soroban contract. +--- + +A cross-contract invocation is a powerful (yet expensive) kind of contract interaction. A contract invocation is similar to starting a new process because the code that runs will be in a separate address space, meaning that they do not share any data other than what was passed in the invocation. While a contract invocation typically transfers control to a _different_ contract, it is possible to transfer control to the currently running contract. Regardless of whether the contract that receives control is a different contract or the currently running contract, the value returned by `get_invoking_contract` will be the previous value of `get_current_contract`. A contract invocation can only access the public methods of a contract. + +If a contract contains a public function `f`, then invoking `f` can be done by making a Rust function call to `f::invoke`. + +Some contracts, such as the token contract, only export the contract invocation functions. In doing so, they are able to assign those functions friendly names. For example, [initialize](https://github.com/stellar/soroban-token-contract/blob/42380647bb817bf01c739c19286f18be881e0e41/src/contract.rs#L55-L57) + +```rust +#[contractimpl(export_if = "export")] +impl TokenTrait for Token { + fn initialize(e: Env, admin: Identifier, decimal: u32, name: Binary, symbol: Binary) { +``` + +is [exported](https://github.com/stellar/soroban-token-contract/blob/42380647bb817bf01c739c19286f18be881e0e41/src/lib.rs#L26) as + +```rust +pub use crate::contract::initialize::invoke as initialize; +``` + +This function is then easily [called by the liquidity pool contract](https://github.com/stellar/soroban-examples/blob/4060d3bd5ee7846020b68ee583665a4d4cf4b315/liquidity_pool/src/lib.rs#L164-L171). diff --git a/docs/fundamentals-and-concepts/invoking-contracts-with-transactions.mdx b/docs/soroban-internals/contract-interactions/stellar-transaction.mdx similarity index 96% rename from docs/fundamentals-and-concepts/invoking-contracts-with-transactions.mdx rename to docs/soroban-internals/contract-interactions/stellar-transaction.mdx index 42c43a8f..528de15e 100644 --- a/docs/fundamentals-and-concepts/invoking-contracts-with-transactions.mdx +++ b/docs/soroban-internals/contract-interactions/stellar-transaction.mdx @@ -1,6 +1,6 @@ --- -sidebar_position: 16 -title: Interacting with Soroban via Stellar +sidebar_position: 30 +title: Stellar Transaction description: Invoke and deploy smart contracts with the InvokeHostFunctionOp operation. toc_max_heading_level: 4 --- @@ -20,7 +20,7 @@ toc_max_heading_level: 4 /> @@ -29,7 +29,7 @@ import TabItem from "@theme/TabItem"; ## Example SDK Usage -Some (but not all yet) of the Stellar SDKs have functions built-in to handle most of the process of building a Stellar transaction to interact with a Soroban smart contract. Below, we demonstrate in JavaScript and Python how to build and submit a Stellar transaction that will invoke an instance of the [increment example](../getting-started/storing-data) smart contract. +Some (but not all yet) of the Stellar SDKs have functions built-in to handle most of the process of building a Stellar transaction to interact with a Soroban smart contract. Below, we demonstrate in JavaScript and Python how to build and submit a Stellar transaction that will invoke an instance of the [increment example](../../getting-started/storing-data) smart contract. @@ -266,9 +266,9 @@ The `InvokeHostFunctionOp` can be used to perform the following Soroban operatio - Invoke contract functions. - Upload Wasm of the new contracts. -- Deploy new contracts using the uploaded Wasm or built-in implementations (this currently includes only the [token contract](../advanced-tutorials/stellar-asset-contract.mdx)). +- Deploy new contracts using the uploaded Wasm or built-in implementations (this currently includes only the [token contract](../../tokens/stellar-asset-contract.mdx)). -[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli +[`soroban-cli`]: ../../getting-started/setup.mdx#install-the-soroban-cli There is only a single `InvokeHostFunctionOp` allowed per transaction. Contracts should be used to perform multiple actions atomically, for example, to deploy @@ -402,7 +402,7 @@ The `hostFunction` in `InvokeHostFunctionOp` will be executed by the Soroban hos ##### JavaScript Usage -Each of these variations of host function invocation has convenience methods in the [JavaScript SDK](../reference/sdks/js): +Each of these variations of host function invocation has convenience methods in the [JavaScript SDK](../../reference/sdks/interact-with-contracts.mdx#javascript-sdk): - [`Operation.invokeHostFunction`](https://stellar.github.io/js-stellar-sdk/Operation.html#.invokeHostFunction) is the lowest-level method that corresponds directly to the XDR. - [`Operation.invokeContractFunction`](https://stellar.github.io/js-stellar-sdk/Operation.html#.invokeContractFunction) is an abstraction to invoke the method of a particular contract, similar to [`Contract.call`](https://stellar.github.io/js-stellar-sdk/Contract.html#call). @@ -411,7 +411,7 @@ Each of these variations of host function invocation has convenience methods in #### Authorization Data -Soroban's [authorization framework](../fundamentals-and-concepts/authorization.mdx) +Soroban's [authorization framework](../authorization.mdx) provides a standardized way for passing authorization data to the contract invocations via `SorobanAuthorizationEntry` structures. @@ -508,7 +508,7 @@ recording auth mode in Soroban's `simulateTransaction` mechanism (see the [docs] details). [envelope-xdr]: https://github.com/stellar/stellar-xdr/blob/e372df9f677961aac04c5a4cc80a3667f310b29f/Stellar-transaction.x#L703 -[simulate-transaction-doc]: ../fundamentals-and-concepts/interacting-with-contracts.mdx#authorization +[simulate-transaction-doc]: transaction-simulation.mdx#authorization ##### Stellar Account Signatures @@ -527,7 +527,7 @@ pub struct AccountEd25519Signature { ``` [structures]: https://github.com/stellar/rs-soroban-env/blob/99d8c92cdc7e5cd0f5311df8f88d04658ecde7d2/soroban-env-host/src/native_contract/account_contract.rs#L51 -[custom accounts]: ../fundamentals-and-concepts/authorization.mdx#account-abstraction +[custom accounts]: ../authorization.mdx#account-abstraction ##### JavaScript Usage @@ -559,7 +559,7 @@ const signedEntries = simTx.auth.map(async (entry) => Every Soroban transaction has to have a `SorobanTransactionData` transaction [extension] populated. This is needed to compute the -[Soroban resource fee](../fundamentals-and-concepts/fees-and-metering.mdx). +[Soroban resource fee](../fees-and-metering.mdx). [extension]: https://github.com/stellar/stellar-xdr/blob/c2e702c70951ff59a1eff257f08cf38d47210e5f/Stellar-transaction.x#L874 @@ -591,7 +591,7 @@ struct SorobanTransactionData This data comprises two parts: Soroban resources and the `refundableFee`. The `refundableFee` is the portion of the transaction fee eligible for refund. It includes the fees for the contract events emitted by the transaction, the return -value of the host function invocation, and fees for the [ledger space rent](./state-archival.mdx). +value of the host function invocation, and fees for the [ledger space rent](../state-archival.mdx). The `SorobanResources` structure includes the ledger footprint and the resource values, which together determine the resource consumption limit and the @@ -599,7 +599,7 @@ resource fee. The footprint must contain the `LedgerKey`s that will be read and/or written. The simplest method to determine the values in `SorobanResources` and -`refundableFee` is to use the [`simulateTransaction` mechanism](../fundamentals-and-concepts/interacting-with-contracts.mdx#transaction-simulation). +`refundableFee` is to use the [`simulateTransaction` mechanism](transaction-simulation.mdx). #### JavaScript Usage diff --git a/docs/soroban-internals/contract-interactions/tests.mdx b/docs/soroban-internals/contract-interactions/tests.mdx new file mode 100644 index 00000000..88e23026 --- /dev/null +++ b/docs/soroban-internals/contract-interactions/tests.mdx @@ -0,0 +1,24 @@ +--- +sidebar_position: 20 +title: Tests +description: Interacting with contracts in tests +--- + +[Debugging contracts](../debugging.mdx) explains that it is much more convenient to debug using native code than Wasm. Given that you are testing native code, it is tempting to interact with your contract directly using function calls. If you attempt this approach, you will find that it doesn't always work. Function call interactions do not set the environment into the correct state for contract execution, so functions involving contract data and determining the current or invoking contract will not work. + +When writing tests, it is important to always interact with contracts through contract invocation. In a production setting, contract invocation will execute Wasm bytecode loaded from the ledger. So how does this work if you are testing native code? You must register your contract with the environment, so it knows what functions are available and how to call them. While this sounds complex, the `contractimpl` procedural macro automatically generates almost all the code to do this. All you have to do is write a small [stub](https://github.com/stellar/soroban-token-contract/blob/42380647bb817bf01c739c19286f18be881e0e41/src/testutils.rs#L12-L15) to actually call the generated code, such as + +```rust title="test.rs" +pub fn register_test_contract(e: &Env, contract_id: &[u8; 32]) { + let contract_id = FixedBinary::from_array(e, *contract_id); + e.register_contract(&contract_id, crate::contract::Token {}); +} +``` + +Some contracts, such as the token contract, also provide a [friendlier interface](https://github.com/stellar/soroban-token-contract/blob/42380647bb817bf01c739c19286f18be881e0e41/src/testutils.rs#L26-L191) to facilitate testing. There are many ways these interfaces might make testing easier, but one common one is to allow automatic message signing by passing a [ed25519_dalek::Keypair](https://docs.rs/ed25519-dalek/latest/ed25519_dalek/struct.Keypair.html). + +Note that everything described in this section is only available if the `testutils` feature is enabled. + +### Example + +This machinery can also be used to test multiple contracts together. For example, the single offer contract test case [creates a token](https://github.com/stellar/soroban-examples/blob/56fef787395b5aed7cd7b19772cca28e21b3feb5/single_offer/src/test.rs#L22). diff --git a/docs/soroban-internals/contract-interactions/transaction-simulation.mdx b/docs/soroban-internals/contract-interactions/transaction-simulation.mdx new file mode 100644 index 00000000..ae44ac4b --- /dev/null +++ b/docs/soroban-internals/contract-interactions/transaction-simulation.mdx @@ -0,0 +1,57 @@ +--- +sidebar_position: 40 +title: Transaction Simulation +description: Simulate a contract interaction contained in a Stellar transaction. +--- + +## Footprint + +As mentioned in the [persisting data](../persisting-data.mdx) section, a contract can only load or store `CONTRACT_DATA` entries that are declared in a _footprint_ associated with its invocation. + +A footprint is a set of ledger keys, each marked as either read-only or read-write. Read-only keys are available to the transaction for reading; read-write keys are available for reading, writing, or both. + +Any Soroban transaction submitted by a user has to be accompanied by this footprint. A single footprint encompasses _all_ the data read and written by _all_ contracts transitively invoked by the transaction: not just the initial contract that the transaction calls, but also all contracts it calls, and so on. + +Since it can be difficult for a user to know which ledger entries a given contract call will attempt to read or write (especially entries that are caused by other contracts deep within a transaction), the host provides an auxiliary `simulateTransaction` mechanism that executes a transaction against a temporary, possibly out-of-date _snapshot_ of the ledger. The `simulateTransaction` mechanism is _not_ constrained to only read or write the contents of a footprint; rather it _records_ a footprint describing the transaction's execution, discards the execution's effects, and then returns the recorded footprint to its caller. + +This simulation-provided footprint can then be used to accompany a "real" submission of the same transaction to the network for real execution. If the state of the ledger has changed too much between the time of the simulated and the real submission, the footprint may be too stale and no longer accurately identify the _keys_ the transaction needs to read and/or write, at which point the simulation must be retried to refresh the footprint. + +In any event (whether successful or failing), the real transaction will execute atomically, deterministically, and with serializable consistency semantics. An inaccurate footprint simply causes deterministic transaction failure, not a stale-read anomaly. All effects of such a failed transaction are discarded, as they would be in the presence of any other error. + +## Authorization + +See the [authorization overview](../authorization.mdx) docs and authorization in +transactions [section][auth-data] for general information on Soroban +authorization. + +[auth-data]: stellar-transaction.mdx#authorization-data + +Soroban's `simulateTransaction` mechanism can also be used to compute the `SorobanAuthorizedInvocation` trees +that must be authorized by the `Address`es for all the +`require_auth` checks to pass. + +Soroban host provides a special 'recording' mode for auth. Whenever +`require_auth` is called, the host records its context (address, contract id, +function, arguments), attributes it to a `SorobanAuthorizedInvocation` tree, and marks +it as successful. Then, after the invocation has finished, `simulateTransaction` can return +all the recorded trees, as well as the generated random nonce values. + +Given this information from the simulation, the client only needs to provide these +trees and nonces to the respective `Address`es for signing and then build the +final transaction using the simulation output and the corresponding signatures. + +The recording auth mode is optional for `simulateTransaction`. For example, when dealing +with the custom account contracts, it may be necessary to simulate the custom +account's `__check_auth` code (that is simply omitted in the recording auth mode), +for example, to get its ledger footprint. The non-recording mode is referred to +as 'enforcing'. Enforcing mode is basically equivalent to running the +transaction on-chain (with possibly a slightly stale ledger state); hence, it +requires all the signatures to be valid. + +Note that the recording auth mode never emulates authorization failures. The +reason for that is that failing authorization is always an exceptional +situation (i.e., the `Address`es for which you don't anticipate successful +authorization shouldn't be used in the first place). It is similar to how, for +example, the `simulateTransaction` mechanism doesn't emulate failures caused by the incorrect +footprint. `simulateTransaction` with enforcing auth mode may still be used to verify the +signatures before executing the transaction on-chain. diff --git a/docs/fundamentals-and-concepts/contract-lifecycle.mdx b/docs/soroban-internals/contract-lifecycle.mdx similarity index 95% rename from docs/fundamentals-and-concepts/contract-lifecycle.mdx rename to docs/soroban-internals/contract-lifecycle.mdx index cfb770c3..21ecbd6a 100644 --- a/docs/fundamentals-and-concepts/contract-lifecycle.mdx +++ b/docs/soroban-internals/contract-lifecycle.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 6 +sidebar_position: 40 title: Contract Lifecycle description: The process of developing, deploying, and maintaining smart contracts. --- @@ -19,7 +19,7 @@ description: The process of developing, deploying, and maintaining smart contrac /> @@ -63,4 +63,4 @@ TBD: expand this section. ## Upgrading contracts -See the [Upgrading Contracts](../basic-tutorials/upgrading-contracts.mdx) page for details on this. +See the [Upgrading Contracts](../guides/conventions/upgrading-contracts.mdx) page for details on this. diff --git a/docs/fundamentals-and-concepts/debugging.mdx b/docs/soroban-internals/debugging.mdx similarity index 97% rename from docs/fundamentals-and-concepts/debugging.mdx rename to docs/soroban-internals/debugging.mdx index 0e718075..f66b4676 100644 --- a/docs/fundamentals-and-concepts/debugging.mdx +++ b/docs/soroban-internals/debugging.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 9 +sidebar_position: 70 title: Debugging description: Debug smart contracts natively and as WASM. --- @@ -17,7 +17,7 @@ description: Debug smart contracts natively and as WASM. /> diff --git a/docs/fundamentals-and-concepts/environment-concepts.mdx b/docs/soroban-internals/environment-concepts.mdx similarity index 98% rename from docs/fundamentals-and-concepts/environment-concepts.mdx rename to docs/soroban-internals/environment-concepts.mdx index 903eef61..af640d99 100644 --- a/docs/fundamentals-and-concepts/environment-concepts.mdx +++ b/docs/soroban-internals/environment-concepts.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 10 +sidebar_position: 80 title: Environment Concepts description: The interface that defines objects, functions, and data available to smart contracts. --- @@ -20,7 +20,7 @@ description: The interface that defines objects, functions, and data available t /> diff --git a/docs/fundamentals-and-concepts/errors.mdx b/docs/soroban-internals/errors.mdx similarity index 89% rename from docs/fundamentals-and-concepts/errors.mdx rename to docs/soroban-internals/errors.mdx index 9d136603..63183455 100644 --- a/docs/fundamentals-and-concepts/errors.mdx +++ b/docs/soroban-internals/errors.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 11 +sidebar_position: 90 title: Errors description: Generating errors from smart contracts. --- @@ -14,7 +14,7 @@ description: Generating errors from smart contracts. /> @@ -27,7 +27,7 @@ types of contract functions. :::info The [errors example] demonstrates how to define your own error types. -[errors example]: ../basic-tutorials/errors.mdx +[errors example]: ../tutorials/errors.mdx ::: diff --git a/docs/fundamentals-and-concepts/events.mdx b/docs/soroban-internals/events.mdx similarity index 96% rename from docs/fundamentals-and-concepts/events.mdx rename to docs/soroban-internals/events.mdx index 02227bcb..cc2e1599 100644 --- a/docs/fundamentals-and-concepts/events.mdx +++ b/docs/soroban-internals/events.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 12 +sidebar_position: 100 title: Events description: Monitor off-chain smart contract changes. --- @@ -17,7 +17,7 @@ description: Monitor off-chain smart contract changes. /> @@ -30,7 +30,7 @@ the [TransactionMetaV3] XDR below that there is a list of `OperationEvents` called `events`. Each `OperationEvent` corresponds to an operation in a transaction, and itself contains a list of `ContractEvents`. Note that `events` will only be populated if the transaction succeeds. Take a look at [this -example](../basic-tutorials/events.mdx) to learn more about how to emit an event +example](../tutorials/events.mdx) to learn more about how to emit an event in your contract. [TransactionMetaV3]: #transactionmetav3 diff --git a/docs/fundamentals-and-concepts/fees-and-metering.mdx b/docs/soroban-internals/fees-and-metering.mdx similarity index 98% rename from docs/fundamentals-and-concepts/fees-and-metering.mdx rename to docs/soroban-internals/fees-and-metering.mdx index 8399ea90..0f8ecff7 100644 --- a/docs/fundamentals-and-concepts/fees-and-metering.mdx +++ b/docs/soroban-internals/fees-and-metering.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 13 +sidebar_position: 110 title: Fees and Metering description: Smart contract fees and metering on Soroban. --- @@ -17,7 +17,7 @@ description: Smart contract fees and metering on Soroban. /> @@ -58,7 +58,7 @@ Some parameters may contribute to multiple fee components. For example, the tran The implementation details for fee computation are provided by the following [library](https://github.com/stellar/rs-soroban-env/blob/main/soroban-env-host/src/fees.rs). This library is used by the protocol to compute the fees and thus can be considered canonical. The resource fee rates may be updated based on network validator consensus. -The best way to find the required fees for any Soroban transaction is to use the [`simulateTransaction` mechanism](./interacting-with-contracts.mdx#transaction-simulation). +The best way to find the required fees for any Soroban transaction is to use the [`simulateTransaction` mechanism](contract-interactions/transaction-simulation.mdx). The fee rates are currently defined for the Testnet as follows: diff --git a/docs/fundamentals-and-concepts/high-level-overview.mdx b/docs/soroban-internals/high-level-overview.mdx similarity index 97% rename from docs/fundamentals-and-concepts/high-level-overview.mdx rename to docs/soroban-internals/high-level-overview.mdx index 671e952c..77171c84 100644 --- a/docs/fundamentals-and-concepts/high-level-overview.mdx +++ b/docs/soroban-internals/high-level-overview.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 1 +sidebar_position: 10 title: High-Level Overview description: An overview of Rust, SDKs, and the Soroban host environment. --- @@ -17,7 +17,7 @@ description: An overview of Rust, SDKs, and the Soroban host environment. /> diff --git a/docs/fundamentals-and-concepts/persisting-data.mdx b/docs/soroban-internals/persisting-data.mdx similarity index 96% rename from docs/fundamentals-and-concepts/persisting-data.mdx rename to docs/soroban-internals/persisting-data.mdx index e31cdcfa..091e5a73 100644 --- a/docs/fundamentals-and-concepts/persisting-data.mdx +++ b/docs/soroban-internals/persisting-data.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 17 +sidebar_position: 150 title: Persisting Data description: Store and access smart contract data. --- @@ -14,7 +14,7 @@ description: Store and access smart contract data. /> @@ -77,7 +77,7 @@ In addition to the types of state, it is also helpful to consider the type of co ### Best Practices - Prefer `Temporary` over `Persistent` and `Instance` storage - - Anything that can have a timeout should be `Temporary` with TTL set to the timeout. See the [resource limits table](../fundamentals-and-concepts/fees-and-metering.mdx#resource-limits) for the current maximum TTL/timeout. + - Anything that can have a timeout should be `Temporary` with TTL set to the timeout. See the [resource limits table](../soroban-internals/fees-and-metering.mdx#resource-limits) for the current maximum TTL/timeout. - Ideally, `Temporary` entries should be associated with an absolute ledger boundary and thus never need a TTL extension - Example: Soroban Auth signatures have an absolute expiration ledger, so nonces can be stored in `Temporary` entries without security risks - Example: SAC allowance that lives only until a given ledger (so that some old allowance signature can not be used in the future if not exhausted) diff --git a/docs/fundamentals-and-concepts/rust-dialect.mdx b/docs/soroban-internals/rust-dialect.mdx similarity index 98% rename from docs/fundamentals-and-concepts/rust-dialect.mdx rename to docs/soroban-internals/rust-dialect.mdx index dedfe90f..d3ffab72 100644 --- a/docs/fundamentals-and-concepts/rust-dialect.mdx +++ b/docs/soroban-internals/rust-dialect.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 60 title: Contract Rust Dialect description: Differences between Soroban Rust and typical Rust programming. --- @@ -17,7 +17,7 @@ description: Differences between Soroban Rust and typical Rust programming. /> diff --git a/docs/fundamentals-and-concepts/state-archival.mdx b/docs/soroban-internals/state-archival.mdx similarity index 95% rename from docs/fundamentals-and-concepts/state-archival.mdx rename to docs/soroban-internals/state-archival.mdx index edc6e513..1ebfb06b 100644 --- a/docs/fundamentals-and-concepts/state-archival.mdx +++ b/docs/soroban-internals/state-archival.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 18 +sidebar_position: 160 title: State Archival description: Smart contract state archival. --- @@ -14,10 +14,10 @@ description: Smart contract state archival. content="Learn about how state archival works on the Soroban smart contract platform." /> - + rel="canonical" + href="https://soroban.stellar.org/docs/soroban-internals/state-archival" + /> + Contract data is made up of three different types: `Persistent`, `Temporary`, and `Instance`. In a contract, these are accessed with `env.storage().persistent()`, `env.storage().temporary()`, and `env.storage().instance()` respectively; see the [`storage()` docs](https://docs.rs/soroban-sdk/latest/soroban_sdk/storage/struct.Storage.html). @@ -99,7 +99,7 @@ is a network parameter and defaults to 16 ledgers for `Temporary` entries and 4, ### Maximum TTL On any given ledger, an entry's TTL can be extended up to the maximum TTL. This is a -network parameter (see the [resource limits table](../fundamentals-and-concepts/fees-and-metering.mdx#resource-limits#resource-limits#resource-limits) +network parameter (see the [resource limits table](../soroban-internals/fees-and-metering.mdx#resource-limits) for the current maximum TTL). Maximum TTL is not enforced based on when an entry was created, but based on the current ledger. For example, if an entry is created on January 1st, 2024, its TTL could initially be extended up to January 1st, 2025. @@ -153,7 +153,7 @@ liveUntilLedger that is large enough. `ExtendFootprintTTLOp` is a Soroban operation, and therefore must be the only operation in a transaction. The transaction also needs to populate `SorobanTransactionData` transaction extension explained -[here](../fundamentals-and-concepts/invoking-contracts-with-transactions.mdx#transaction-resources). To fill +[here](contract-interactions/stellar-transaction.mdx#transaction-resources). To fill out `SorobanResources`, use the transaction simulation mentioned in the provided link, or make sure `readBytes` includes the key and entry size of every entry in the `readOnly` set. @@ -190,7 +190,7 @@ parameter and is subject to be updated (likely increased) via network upgrades. `RestoreFootprintOp` is a Soroban operation, and therefore must be the only operation in a transaction. The transaction also needs to populate `SorobanTransactionData` transaction extension explained -[here](../fundamentals-and-concepts/invoking-contracts-with-transactions.mdx#transaction-resources). To fill +[here](contract-interactions/stellar-transaction.mdx#transaction-resources). To fill out `SorobanResources`, use the transaction simulation mentioned in the provided link, or make sure `writeBytes` includes the key and entry size of every entry in the `readWrite` set and make sure `extendedMetaDataSizeBytes` is at least double of @@ -206,7 +206,7 @@ We've done our best to build tooling around state archival in both the Soroban R Both restoring and extending the TTL of ledger entries follows a three-step process regardless of their nature (contract data, instances, etc.): -1. **Identify the ledger entries**. This usually means acquiring them from a Soroban RPC server as part of your initial transaction simulation (see the [transaction simulation docs](https://soroban.stellar.org/docs/fundamentals-and-concepts/interacting-with-contracts#transaction-simulation) and the [`simulateTransaction`](https://soroban.stellar.org/api/methods/simulateTransaction) RPC method). +1. **Identify the ledger entries**. This usually means acquiring them from a Soroban RPC server as part of your initial transaction simulation (see the [transaction simulation docs](contract-interactions/transaction-simulation.mdx) and the [`simulateTransaction`](/api/methods/simulateTransaction) RPC method). 2. **Prepare your operation**. This means describing the ledger entries within the corresponding operation (i.e. `ExtendFootprintTTLOp` or `RestoreFootprintOp`) and its ledger footprint (the `SorobanTransactionData` field), then simulating it to fill out fee and resource usage information (when restoring, you usually have simulation results already). diff --git a/docs/soroban-internals/transaction-lifecycle.mdx b/docs/soroban-internals/transaction-lifecycle.mdx new file mode 100644 index 00000000..31135af6 --- /dev/null +++ b/docs/soroban-internals/transaction-lifecycle.mdx @@ -0,0 +1,14 @@ +--- +sidebar_position: 50 +title: Transaction Lifecycle +description: here's how a transaction works, and stuff. +--- + +See [GH issue #532](https://github.com/stellar/soroban-docs/issues/532) for details. + +We're getting a lot of questions that relate to the transaction lifecycle and don't have a great resource to send people to. + +The regular Stellar resources are confusing because: + +1. they don't have any information on preflight and +2. soroban-rpc's tx submission is async diff --git a/docs/soroban-internals/types/_category_.json b/docs/soroban-internals/types/_category_.json new file mode 100644 index 00000000..259870b5 --- /dev/null +++ b/docs/soroban-internals/types/_category_.json @@ -0,0 +1,4 @@ +{ + "position": 30, + "label": "Types" +} diff --git a/docs/fundamentals-and-concepts/built-in-types.mdx b/docs/soroban-internals/types/built-in-types.mdx similarity index 91% rename from docs/fundamentals-and-concepts/built-in-types.mdx rename to docs/soroban-internals/types/built-in-types.mdx index 9859d6ef..05129c1f 100644 --- a/docs/fundamentals-and-concepts/built-in-types.mdx +++ b/docs/soroban-internals/types/built-in-types.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 10 title: Built-In Types description: Built-in types used as smart contract inputs and outputs. --- @@ -17,21 +17,21 @@ description: Built-in types used as smart contract inputs and outputs. /> Built-in types are available to all contracts for use as contract function inputs and outputs, and are defined by the [environment] and the [Rust SDK]. -[environment]: environment-concepts -[Rust SDK]: ../reference/sdks/rust +[environment]: ../environment-concepts.mdx +[Rust SDK]: ../../reference/sdks/write-contracts.mdx#soroban-rust-sdk :::tip Custom types like structs, enums, and unions are also supported. See [Custom Types]. -[Custom Types]: custom-types +[Custom Types]: custom-types.mdx ::: @@ -112,5 +112,5 @@ identify the payment recipient), as a data key (for example, to store the balance), as the authentication & authorization source (for example, to authorize a token transfer) etc. -See [authorization documentation](authorization.mdx) for more details on how to +See [authorization documentation](../authorization.mdx) for more details on how to use the `Address` type. diff --git a/docs/fundamentals-and-concepts/custom-types.mdx b/docs/soroban-internals/types/custom-types.mdx similarity index 95% rename from docs/fundamentals-and-concepts/custom-types.mdx rename to docs/soroban-internals/types/custom-types.mdx index e2856a30..1e6a291a 100644 --- a/docs/fundamentals-and-concepts/custom-types.mdx +++ b/docs/soroban-internals/types/custom-types.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 7 +sidebar_position: 20 title: Custom Types description: Struct, union, and enum types defined by contracts. --- @@ -17,7 +17,7 @@ description: Struct, union, and enum types defined by contracts. /> @@ -28,7 +28,7 @@ for storage. :::info The [custom types example] demonstrates how to define your own types. -[custom types example]: ../basic-tutorials/custom-types.mdx +[custom types example]: ../../tutorials/custom-types.mdx ::: @@ -36,7 +36,7 @@ The [custom types example] demonstrates how to define your own types. Error enum types are another type contracts can define that have some unique behaviors. See [Errors] for more information. -[Errors]: ./errors +[Errors]: ../errors.mdx ::: diff --git a/docs/fundamentals-and-concepts/fully-typed-contracts.mdx b/docs/soroban-internals/types/fully-typed-contracts.mdx similarity index 83% rename from docs/fundamentals-and-concepts/fully-typed-contracts.mdx rename to docs/soroban-internals/types/fully-typed-contracts.mdx index 4c55a45c..741ffe7b 100644 --- a/docs/fundamentals-and-concepts/fully-typed-contracts.mdx +++ b/docs/soroban-internals/types/fully-typed-contracts.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 14 +sidebar_position: 30 title: "Fully-Typed Contracts" desctiption: Smart contract WASM files contain a machine-readable description of the interface type. sidebar_label: Fully-Typed Contracts @@ -21,15 +21,15 @@ sidebar_label: Fully-Typed Contracts /> -When you compile a contract created with [soroban-sdk](../reference/sdks/rust.mdx), the Wasm file ends up with a [custom section](https://webassembly.github.io/spec/core/appendix/custom.html) containing a machine-readable description of your contract's interface types, sometimes called its [spec](https://github.com/stellar/rs-soroban-sdk/tree/main/soroban-spec) or its [API](https://github.com/stellar/soroban-docs/pull/381#issuecomment-1507283476). This is similar to [ABIs](https://www.quicknode.com/guides/ethereum-development/smart-contracts/what-is-an-abi/) in Ethereum, except that Soroban will store every single one of them on-chain from day one, and they include the comments from the contract's author. +When you compile a contract created with [soroban-sdk](../../reference/sdks/write-contracts.mdx#soroban-rust-sdk), the Wasm file ends up with a [custom section](https://webassembly.github.io/spec/core/appendix/custom.html) containing a machine-readable description of your contract's interface types, sometimes called its [spec](https://github.com/stellar/rs-soroban-sdk/tree/main/soroban-spec) or its [API](https://github.com/stellar/soroban-docs/pull/381#issuecomment-1507283476). This is similar to [ABIs](https://www.quicknode.com/guides/ethereum-development/smart-contracts/what-is-an-abi/) in Ethereum, except that Soroban will store every single one of them on-chain from day one, and they include the comments from the contract's author. Today, these interface types are formatted using [XDR](https://developers.stellar.org/docs/encyclopedia/xdr), but this [may change](https://github.com/stellar/rs-soroban-sdk/issues/683) down the road. -The important part is that tooling can fetch these interface types to make your life easier. [Soroban CLI](../reference/soroban-cli.mdx) is the first tool to do so. Specifically, one subcommand: +The important part is that tooling can fetch these interface types to make your life easier. [Soroban CLI](../../reference/soroban-cli.mdx) is the first tool to do so. Specifically, one subcommand: ## `soroban contract invoke` @@ -41,7 +41,7 @@ A unique CLI for each smart contract. Constructed on-the-fly, right from the on- With aliases in your shell, you can also easily make explicit CLIs out of your most-used contracts. For example, if you use the [Smart Deploy](https://communityfund.stellar.org/projects/smart-deploy-scf-13) contract: -```text +```bash $ alias smartdeploy="soroban contract invoke --id 6808e8e2cce73cfca472a8197080938b320d72e7b696e34eb52ebf17070f4ee --" $ smartdeploy --help Usage: 6808e8e2cce73cfca472a8197080938b320d72e7b696e34eb52ebf17070f4ee [COMMAND] @@ -65,11 +65,13 @@ Options: Like any other CLI, you can also get help for any of these subcommands using something like `smartdeploy deploy --help`. Soroban CLI again fetches the on-chain interface types, this time using it to generate a full list of all arguments to the function, and even generates examples. And just to be totally clear, you don't need to alias these commands. This would work, too: - soroban contract invoke --id 6808e8e2cce73cfca472a8197080938b320d72e7b696e34eb52ebf17070f4ee -- deploy --help +```bash +soroban contract invoke --id 6808e8e2cce73cfca472a8197080938b320d72e7b696e34eb52ebf17070f4ee -- deploy --help +``` Or, if you clone [soroban-examples](https://github.com/stellar/soroban-examples) and `make build` them all, you can get CLI help for any individual contract or a specific function within a contract: -```text +```bash $ soroban contract invoke --id 1 --wasm target/wasm32-unknown-unknown/release/soroban_hello_world_contract.wasm -- hello --help Usage: hello [OPTIONS] diff --git a/docs/fundamentals-and-concepts/_category_.json b/docs/tokens/_category_.json similarity index 62% rename from docs/fundamentals-and-concepts/_category_.json rename to docs/tokens/_category_.json index 8b075cc5..cde3c06a 100644 --- a/docs/fundamentals-and-concepts/_category_.json +++ b/docs/tokens/_category_.json @@ -1,6 +1,6 @@ { "position": 50, - "label": "Fundamentals and Concepts", + "label": "Tokens", "link": { "type": "generated-index" } diff --git a/docs/advanced-tutorials/stellar-asset-contract.mdx b/docs/tokens/stellar-asset-contract.mdx similarity index 90% rename from docs/advanced-tutorials/stellar-asset-contract.mdx rename to docs/tokens/stellar-asset-contract.mdx index 5541d1be..f5f475e0 100644 --- a/docs/advanced-tutorials/stellar-asset-contract.mdx +++ b/docs/tokens/stellar-asset-contract.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 20 title: Stellar Asset Contract description: Use Stellar assets on Soroban. --- @@ -14,14 +14,11 @@ description: Use Stellar assets on Soroban. /> -# Stellar Asset Contract - -The Stellar Asset Contract is an implementation of [CAP-46-6 Smart Contract -Standardized Asset]. +The Stellar Asset Contract is an implementation of [CAP-46-6 Smart Contract Standardized Asset]. [CAP-46-6 Smart Contract Standardized Asset]: https://stellar.org/protocol/cap-46-06 @@ -33,16 +30,16 @@ assets. For this reason, we introduced the Stellar Asset Contract, or SAC for short, which allows users to use their Stellar account and trustline balances in Soroban. -The SAC implements the [token interface](../reference/interfaces/token-interface), which is similar to the +The SAC implements the [token interface](token-interface.mdx), which is similar to the widely used ERC-20 token standard. This should make it easier for existing smart contract developers to get started on Stellar. ## Deployment -For every 'classic' asset exactly one respective Stellar Asset Contract can be +For every Stellar asset exactly one respective Stellar Asset Contract can be deployed. It can be deployed using the `InvokeHostFunctionOp` with `HOST_FUNCTION_TYPE_CREATE_CONTRACT` and `CONTRACT_ID_FROM_ASSET` specified -[here](../fundamentals-and-concepts/invoking-contracts-with-transactions). The resulting token will have a +[here](../soroban-internals/contract-interactions/stellar-transaction.mdx). The resulting token will have a deterministic identifier, which will be the sha256 hash of `HashIDPreimage::ENVELOPE_TYPE_CONTRACT_ID_FROM_ASSET` xdr specified [here][contract_id]. @@ -115,12 +112,12 @@ about `AUTH_REQUIRED_FLAG` [here](https://developers.stellar.org/docs/issuing-as ## Authorization semantics -See the [authorization overview](../fundamentals-and-concepts/authorization.mdx) and -[auth example](../basic-tutorials/auth.mdx) for general information about authorization in +See the [authorization overview](../soroban-internals/authorization.mdx) and +[auth example](../tutorials/auth.mdx) for general information about authorization in Soroban. The token contract contains three kinds of operations that follow the token -[interface](../reference/interfaces/token-interface#code): +[interface](token-interface.mdx#code): - getters, such as `balance`, which do not change the state of the contract - unprivileged mutators, such as `incr_allow` and `xfer`, which change the state @@ -171,9 +168,9 @@ impl MyContract { See the full examples that utilize the token contract in various ways for more details: -- [Timelock](timelock.mdx) and [single offer](single-offer-sale.mdx) move token +- [Timelock](../tutorials/timelock.mdx) and [single offer](../tutorials/single-offer-sale.mdx) move token via `xfer` to and from the contract -- [Atomic swap](atomic-swap.mdx) uses `incr_allow` to transfer token on behalf +- [Atomic swap](../tutorials/atomic-swap.mdx) uses `incr_allow` to transfer token on behalf of the user Notice, that these examples don't do anything to support SAC specifically. @@ -196,6 +193,6 @@ implementation. ## Contract Interface This interface can be found in the [SDK]. It extends the common -[token interface](tokens.mdx). +[token interface](token-interface.mdx). [SDK]: https://github.com/stellar/rs-soroban-sdk/blob/v20.0.0/soroban-sdk/src/token.rs diff --git a/docs/reference/interfaces/token-interface.mdx b/docs/tokens/token-interface.mdx similarity index 97% rename from docs/reference/interfaces/token-interface.mdx rename to docs/tokens/token-interface.mdx index 244719ee..92666861 100644 --- a/docs/reference/interfaces/token-interface.mdx +++ b/docs/tokens/token-interface.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 1 +sidebar_position: 10 title: Token Interface description: The common interface implemented by tokens that are compatible with Soroban's built-in tokens. --- @@ -34,8 +34,9 @@ consistent with the interface described here: ### Code -The interface below uses the Rust [soroban-sdk](../sdks/rust.mdx) to declare a -trait that complies with the +The interface below uses the Rust +[soroban-sdk](../reference/sdks/write-contracts.mdx#soroban-rust-sdk) to declare +a trait that complies with the [SEP-41](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0041.md) token interface. @@ -192,7 +193,7 @@ Its important to note the that the token interface not only incorporates the aut To provide more context, when you use the token interface, there is a function called `authorized` that returns "true" if an address has token authorization. -More details on Authorization can be found [here](../../fundamentals-and-concepts/authorization). +More details on Authorization can be found [here](../soroban-internals/authorization.mdx). For the functions in the token interface, [trapping](https://doc.rust-lang.org/book/ch09-00-error-handling.html) should be used as the standard way to handle failure conditions since the interface is not designed to return error codes. This means that when a function encounters an error, it will halt execution and revert any state changes that occurred during the function call. diff --git a/docs/tutorials/README.mdx b/docs/tutorials/README.mdx new file mode 100644 index 00000000..ba319b52 --- /dev/null +++ b/docs/tutorials/README.mdx @@ -0,0 +1,12 @@ +--- +title: Tutorials +hide_table_of_contents: true +--- + +import DocCardList from "@theme/DocCardList"; + +The Soroban team has put together a large collection of [example contracts] to demonstrate use of the Soroban smart contracts platform. For many of these example contracts, we've written an accompanying "tutorial" that will walk you through the example contracts and describe a bit more about their design. You can think of these "tutorials" as example contracts that end with a deployable smart contract. You can use the provided filters to find a relevant tutorial for your experience level. + + + +[example contracts]: https://github.com/stellar/soroban-examples diff --git a/docs/TUTORIAL-TEMPLATE.mdx b/docs/tutorials/TEMPLATE.mdx similarity index 93% rename from docs/TUTORIAL-TEMPLATE.mdx rename to docs/tutorials/TEMPLATE.mdx index 15456926..b3907094 100644 --- a/docs/TUTORIAL-TEMPLATE.mdx +++ b/docs/tutorials/TEMPLATE.mdx @@ -1,12 +1,14 @@ --- -sidebar_position: 1000 -title: How-To Guides Template -description: A description of the how-to guide that is being written +title: Tutorial Template +description: A description of the tutorial that is being written. draft: true +sidebar_custom_props: + tutorial: + level: intermediate --- Quick note about what this [example demonstrates]. Maybe it's also based on some -other example. +[other example]. [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)][oigp] @@ -18,7 +20,7 @@ Place each link definition at the bottom of the section it (first) is used In [oigp]: https://gitpod.io/#https://github.com/stellar/soroban-examples/tree/v20.0.0 [example demonstrates]: https://github.com/stellar/soroban-examples/tree/v20.0.0/hello_world -[other example]: getting-started/ +[other example]: ../getting-started/ ## Run the Example @@ -47,7 +49,7 @@ running 1 test test test::test ... ok ``` -[Setup]: ./getting-started/setup.mdx +[Setup]: ../getting-started/setup.mdx ## Code @@ -168,6 +170,8 @@ soroban contract invoke \ --to Soroban ``` +[`soroban-cli`]: ../getting-started/setup.mdx#install-the-soroban-cli + ## Further Reading If you have some further links to share or background knowledge you can link to, diff --git a/docs/tutorials/_category_.json b/docs/tutorials/_category_.json new file mode 100644 index 00000000..332cedc9 --- /dev/null +++ b/docs/tutorials/_category_.json @@ -0,0 +1,9 @@ +{ + "position": 30, + "label": "Tutorials", + "link": { + "type": "doc", + "id": "tutorials/README" + }, + "collapsible": false +} diff --git a/docs/basic-tutorials/alloc.mdx b/docs/tutorials/alloc.mdx similarity index 88% rename from docs/basic-tutorials/alloc.mdx rename to docs/tutorials/alloc.mdx index 78b5b5ea..c98964d0 100644 --- a/docs/basic-tutorials/alloc.mdx +++ b/docs/tutorials/alloc.mdx @@ -1,23 +1,27 @@ --- -sidebar_position: 7 title: Allocator -description: Use the allocator feature in a smart contract. +description: Use the allocator feature to emulate heap memory in a smart contract. +sidebar_custom_props: + tutorial: + level: intermediate --- - Use the allocator feature in a smart contract. + + Use the allocator feature to emulate heap memory in a smart contract. + @@ -106,7 +110,7 @@ extern crate alloc; Imports the `alloc` crate, which is required in order to support allocation under `no_std`. See [Contract Rust dialect] for more info about `no_std`. -[contract rust dialect]: ../fundamentals-and-concepts/rust-dialect.mdx +[contract rust dialect]: ../soroban-internals/rust-dialect.mdx ```rust let mut v1 = alloc::vec![]; diff --git a/docs/advanced-tutorials/atomic-multi-swap.mdx b/docs/tutorials/atomic-multi-swap.mdx similarity index 70% rename from docs/advanced-tutorials/atomic-multi-swap.mdx rename to docs/tutorials/atomic-multi-swap.mdx index 0d7b017a..acfcb57f 100644 --- a/docs/advanced-tutorials/atomic-multi-swap.mdx +++ b/docs/tutorials/atomic-multi-swap.mdx @@ -1,20 +1,25 @@ --- -sidebar_position: 4 title: Batched Atomic Swaps -description: Swap tokens between two groups. +description: Swap a token pair among groups of authorized users. +sidebar_custom_props: + tutorial: + level: advanced --- - Swap tokens between two groups. + Swap a token pair among groups of authorized users. - + diff --git a/docs/advanced-tutorials/atomic-swap.mdx b/docs/tutorials/atomic-swap.mdx similarity index 95% rename from docs/advanced-tutorials/atomic-swap.mdx rename to docs/tutorials/atomic-swap.mdx index 5c58797d..f7021071 100644 --- a/docs/advanced-tutorials/atomic-swap.mdx +++ b/docs/tutorials/atomic-swap.mdx @@ -1,15 +1,17 @@ --- -sidebar_position: 3 title: Atomic Swap -description: Swap tokens atomically between two parties. +description: Swap tokens atomically between authorized users. +sidebar_custom_props: + tutorial: + level: advanced --- - Swap tokens atomically between two parties. + Swap tokens atomically between authorized users. @@ -25,7 +27,7 @@ The [atomic swap example] swaps two tokens between two authorized parties atomically while following the limits they set. This is example demonstrates advanced usage of Soroban auth framework and -assumes the reader is familiar with the [auth example](../basic-tutorials/auth.mdx) and with +assumes the reader is familiar with the [auth example](../tutorials/auth.mdx) and with Soroban token usage. [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)][oigp] diff --git a/docs/basic-tutorials/auth.mdx b/docs/tutorials/auth.mdx similarity index 95% rename from docs/basic-tutorials/auth.mdx rename to docs/tutorials/auth.mdx index 26a7c10b..80448194 100644 --- a/docs/basic-tutorials/auth.mdx +++ b/docs/tutorials/auth.mdx @@ -1,7 +1,9 @@ --- -sidebar_position: 4 title: Auth description: Implement authentication and authorization. +sidebar_custom_props: + tutorial: + level: beginner --- @@ -17,7 +19,7 @@ description: Implement authentication and authorization. /> @@ -418,20 +420,20 @@ soroban contract invoke \ Contract auth: [{"address_with_nonce":null,"root_invocation":{"contract_id":"0000000000000000000000000000000000000000000000000000000000000001","function_name":"increment","args":[{"object":{"address":{"account":{"public_key_type_ed25519":"c7bab0288753d58d3e21cc3fa68cd2546b5f78ae6635a6f1b3fe07e03ee846e9"}}}},{"u32":123}],"sub_invocations":[]},"signature_args":[]}] ``` -[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli +[`soroban-cli`]: ../getting-started/setup.mdx#install-the-soroban-cli ## Further reading -[Authorization documentation](../fundamentals-and-concepts/authorization.mdx) provides more details +[Authorization documentation](../soroban-internals/authorization.mdx) provides more details on how Soroban auth framework works. -[Timelock](../advanced-tutorials/timelock.mdx) and [Single Offer](../advanced-tutorials/single-offer-sale.mdx) examples +[Timelock](../tutorials/timelock.mdx) and [Single Offer](../tutorials/single-offer-sale.mdx) examples demonstrate authorizing token operations on behalf of the user, which can be extended to any nested contract invocations. -[Atomic Swap](../advanced-tutorials/atomic-swap.mdx) example demonstrates multi-party authorization +[Atomic Swap](../tutorials/atomic-swap.mdx) example demonstrates multi-party authorization where multiple users sign their parts of the contract invocation. -[Custom Account](../advanced-tutorials/custom-account.mdx) example for demonstrates an account +[Custom Account](../tutorials/custom-account.mdx) example for demonstrates an account contract that defines a custom authentication scheme and user-defined authorization policies. diff --git a/docs/basic-tutorials/cross-contract-call.mdx b/docs/tutorials/cross-contract-call.mdx similarity index 97% rename from docs/basic-tutorials/cross-contract-call.mdx rename to docs/tutorials/cross-contract-call.mdx index f7d3ba1f..61fefd50 100644 --- a/docs/basic-tutorials/cross-contract-call.mdx +++ b/docs/tutorials/cross-contract-call.mdx @@ -1,7 +1,9 @@ --- -sidebar_position: 5 title: Cross Contract Calls description: Call a smart contract from another smart contract. +sidebar_custom_props: + tutorial: + level: beginner --- @@ -17,7 +19,7 @@ description: Call a smart contract from another smart contract. /> @@ -309,4 +311,4 @@ The following output should occur using the code above. Contract B's `add_with` function invoked Contract A's `add` function to do the addition. -[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli +[`soroban-cli`]: ../getting-started/setup.mdx#install-the-soroban-cli diff --git a/docs/advanced-tutorials/custom-account.mdx b/docs/tutorials/custom-account.mdx similarity index 96% rename from docs/advanced-tutorials/custom-account.mdx rename to docs/tutorials/custom-account.mdx index 3f9d5618..66d66c1c 100644 --- a/docs/advanced-tutorials/custom-account.mdx +++ b/docs/tutorials/custom-account.mdx @@ -1,17 +1,20 @@ --- -sidebar_position: 8 title: Custom Account -description: Implement a contract that supports multisig and custom auth policies. +description: Implement an account contract supporting multisig and custom authorization policies. +sidebar_custom_props: + tutorial: + level: advanced --- - Implement a contract that supports multisig and custom auth policies. + Implement an account contract supporting multisig and custom authorization + policies. diff --git a/docs/basic-tutorials/custom-types.mdx b/docs/tutorials/custom-types.mdx similarity index 93% rename from docs/basic-tutorials/custom-types.mdx rename to docs/tutorials/custom-types.mdx index e0bd4321..c0adbc39 100644 --- a/docs/basic-tutorials/custom-types.mdx +++ b/docs/tutorials/custom-types.mdx @@ -1,20 +1,25 @@ --- -sidebar_position: 4 title: Custom Types -description: Define your data structures. +description: Define your own data structures in a smart contract. +sidebar_custom_props: + tutorial: + level: beginner --- - Define your data structures. + Define your own data structures in a smart contract. - + @@ -24,7 +29,7 @@ The [custom types example] demonstrates how to define your own data structures t [oigp]: https://gitpod.io/#https://github.com/stellar/soroban-examples/tree/v20.0.0 [custom types example]: https://github.com/stellar/soroban-examples/tree/v20.0.0/custom_types -[storing data example]: getting-started/storing-data.mdx +[storing data example]: ../getting-started/storing-data.mdx ## Run the Example @@ -274,4 +279,4 @@ soroban contract read --id 1 --key STATE STATE,"{""count"":25,""last_incr"":15}" ``` -[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli +[`soroban-cli`]: ../getting-started/setup.mdx#install-the-soroban-cli diff --git a/docs/basic-tutorials/deployer.mdx b/docs/tutorials/deployer.mdx similarity index 97% rename from docs/basic-tutorials/deployer.mdx rename to docs/tutorials/deployer.mdx index be975985..103c0466 100644 --- a/docs/basic-tutorials/deployer.mdx +++ b/docs/tutorials/deployer.mdx @@ -1,15 +1,19 @@ --- -sidebar_position: 6 title: Deployer -description: Deploy a smart contract using another smart contract. +description: Deploy and initialize a smart contract using another smart contract. +sidebar_custom_props: + tutorial: + level: beginner --- - Deploy a smart contract using another smart contract. + + Deploy and initialize a smart contract using another smart contract. + @@ -146,7 +150,7 @@ from their own address (`deployer == env.current_contract_address()``). :::info -For introduction to Soroban authorization see the [auth tutorial](https://soroban.stellar.org/docs/basic-tutorials/auth) +For introduction to Soroban authorization see the [auth tutorial](https://soroban.stellar.org/docs/tutorials/auth) ::: @@ -558,4 +562,4 @@ The following output should occur using the code above. 5 ``` -[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli +[`soroban-cli`]: ../getting-started/setup.mdx#install-the-soroban-cli diff --git a/docs/basic-tutorials/errors.mdx b/docs/tutorials/errors.mdx similarity index 97% rename from docs/basic-tutorials/errors.mdx rename to docs/tutorials/errors.mdx index 1066d186..56be8ef6 100644 --- a/docs/basic-tutorials/errors.mdx +++ b/docs/tutorials/errors.mdx @@ -1,7 +1,9 @@ --- -sidebar_position: 2 title: Errors description: Define and generate errors in a smart contract. +sidebar_custom_props: + tutorial: + level: beginner --- @@ -17,7 +19,7 @@ description: Define and generate errors in a smart contract. /> @@ -29,7 +31,7 @@ is an extension of the [storing data example]. [oigp]: https://gitpod.io/#https://github.com/stellar/soroban-examples/tree/v20.0.0 [errors example]: https://github.com/stellar/soroban-examples/tree/v20.0.0/errors -[storing data example]: getting-started/storing-data.mdx +[storing data example]: ../getting-started/storing-data.mdx ## Run the Example @@ -361,4 +363,4 @@ Use the `soroban` to inspect what the counter is. soroban contract read --id 1 --key COUNTER ``` -[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli +[`soroban-cli`]: ../getting-started/setup.mdx#install-the-soroban-cli diff --git a/docs/basic-tutorials/events.mdx b/docs/tutorials/events.mdx similarity index 92% rename from docs/basic-tutorials/events.mdx rename to docs/tutorials/events.mdx index 10bf500f..28bae963 100644 --- a/docs/basic-tutorials/events.mdx +++ b/docs/tutorials/events.mdx @@ -1,20 +1,22 @@ --- -sidebar_position: 1 title: Events -description: Publish events from a contract. +description: Publish events from a smart contract. +sidebar_custom_props: + tutorial: + level: beginner --- - Publish events from a contract. + Publish events from a smart contract. - + @@ -25,7 +27,7 @@ example is an extension of the [storing data example]. [oigp]: https://gitpod.io/#https://github.com/stellar/soroban-examples/tree/v20.0.0 [events example]: https://github.com/stellar/soroban-examples/tree/v20.0.0/events -[storing data example]: getting-started/storing-data.mdx +[storing data example]: ../getting-started/storing-data.mdx ## Run the Example @@ -282,4 +284,4 @@ format. ::: -[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli +[`soroban-cli`]: ../getting-started/setup.mdx#install-the-soroban-cli diff --git a/docs/advanced-tutorials/fuzzing.mdx b/docs/tutorials/fuzzing.mdx similarity index 98% rename from docs/advanced-tutorials/fuzzing.mdx rename to docs/tutorials/fuzzing.mdx index bc343303..81483df9 100644 --- a/docs/advanced-tutorials/fuzzing.mdx +++ b/docs/tutorials/fuzzing.mdx @@ -1,20 +1,27 @@ --- -sidebar_position: 9 title: Fuzz Testing -description: Fuzz test contracts with cargo-fuzz. +description: Increase confidence in a contract's correctness with fuzz testing. +sidebar_custom_props: + tutorial: + level: advanced --- - Fuzz test contracts with cargo-fuzz. + + Increase confidence in a contract's correctness with fuzz testing. + - + @@ -728,7 +735,6 @@ macro creates prototype values that the fuzz program can convert to contract values with the standard soroban conversion traits, [`FromVal`] or [`IntoVal`]. [`SorobanArbitrary`]: https://docs.rs/soroban-sdk/latest/soroban_sdk/arbitrary/trait.SorobanArbitrary.html -[`Env`]: https://docs.rs/soroban-sdk/latest/soroban_sdk/struct.Env.html [`FromVal`]: https://docs.rs/soroban-sdk/latest/soroban_sdk/trait.FromVal.html [`IntoVal`]: https://docs.rs/soroban-sdk/latest/soroban_sdk/trait.IntoVal.html @@ -770,8 +776,6 @@ general, to make a Soroban contract fuzzable, the contract crate must define a "soroban-sdk/testutils" feature, and the fuzz test, which is its own crate, must turn that feature on. -[`contracttype`]: https://docs.rs/soroban-sdk/latest/soroban_sdk/macro.contracttype.html - ## A More Complex Fuzz Test The [`fuzz_target_2.rs`] example, demonstrates the use of `SorobanArbitrary`, @@ -820,8 +824,6 @@ trait: let depositor_address = Address::from_val(&env, &input.addresses[cmd.depositor_index]); ``` -[`FromVal`]: https://docs.rs/soroban-sdk/latest/soroban_sdk/trait.FromVal.html - --- The contract we are fuzzing is a _timelock_ contract, where calculation of time @@ -930,9 +932,6 @@ In addition to fuzz testing, Soroban supports property testing in the style of quickcheck, by using the [`proptest`] and [`proptest-arbitrary-interop`] crates in conjunction with the `SorobanArbitrary` trait. -[`proptest`]: https://docs.rs/proptest -[`proptest-arbitrary-interop`]: https://docs.rs/proptest-arbitrary-interop - Property tests are similar to fuzz tests in that they generate randomized input. Property tests though do not instrument their test cases or mutate their input based on feedback from previous tests. Thus they are a weaker form of test. diff --git a/docs/advanced-tutorials/liquidity-pool.mdx b/docs/tutorials/liquidity-pool.mdx similarity index 98% rename from docs/advanced-tutorials/liquidity-pool.mdx rename to docs/tutorials/liquidity-pool.mdx index 4d3f3929..25fd46d6 100644 --- a/docs/advanced-tutorials/liquidity-pool.mdx +++ b/docs/tutorials/liquidity-pool.mdx @@ -1,7 +1,9 @@ --- -sidebar_position: 7 title: Liquidity Pool description: Write a constant-product liquidity pool contract. +sidebar_custom_props: + tutorial: + level: intermediate --- @@ -17,7 +19,7 @@ description: Write a constant-product liquidity pool contract. /> @@ -496,8 +498,8 @@ When this contract is first deployed, it could create a liquidity pool for _any_ pair of tokens available on Soroban. It must first be initialized with the following information: -- **`token_wasm_hash`:** The contract will end up [creating its own `POOL` - token] as well as [interacting with contracts for `token_a` and `token_b`]. +- **`token_wasm_hash`:** The contract will end up [creating its own `POOL` token] + as well as [interacting with contracts for `token_a` and `token_b`]. The way this example works is by using the [`token` example contract] for both of these jobs. When our liquidity pool contract is initialized it wants us to pass the wasm hash of the **already [installed]** token contract. It will then @@ -530,10 +532,10 @@ fn initialize(e: Env, token_wasm_hash: BytesN<32>, taken_a: Address, token_b: Ad } ``` -[creating its own `POOL` token]: #creating-a-custom-token-for-lp-shares +[creating its own `POOL` token]: #creating-a-custom-pool-token-for-lp-shares [interacting with contracts for `token_a` and `token_b`]: #token-transfers-tofrom-the-lp-contract -[`token` example contract]: ./tokens -[installed]: ../getting-started/deploy-to-testnet#two-step-deployment +[`token` example contract]: ./tokens.mdx +[installed]: ../getting-started/deploy-to-testnet.mdx#two-step-deployment [lexicographical order]: https://developers.stellar.org/docs/encyclopedia/liquidity-on-stellar-sdex-liquidity-pools#liquidity-pool-participation ### A "Constant Product" Liquidity Pool @@ -588,16 +590,16 @@ Soroban tokens: - **`token_a`** and **`token_b`**: Will be the two "reserve tokens" that users will deposit into the pool. These could be "wrapped" tokens from pre-existing Stellar assets, or they could be Soroban-native tokens. This contract doesn't - really care, as long as the functions it needs from the common [Token - Interface] are available in the token contract. + really care, as long as the functions it needs from the common [Token Interface] + are available in the token contract. -[Token Interface]: ../reference/interfaces/token-interface +[Token Interface]: ../tokens/token-interface.mdx #### Creating a Custom `POOL` Token for LP Shares We are utilizing the compiled `token` example contract as our asset contract for -the `POOL` token. This means it follows all the conventions of the [Token -Interface], and can be treated just like any other token. They could be +the `POOL` token. This means it follows all the conventions of the [Token Interface], +and can be treated just like any other token. They could be transferred, burned, minted, etc. It also means the LP developer _could_ take advantage of the administrative features such as clawbacks, authorization, and more. @@ -1012,4 +1014,4 @@ soroban contract invoke \ --min_b 196 \ ``` -[`soroban-cli`]: ../reference/soroban-cli +[`soroban-cli`]: ../reference/soroban-cli.mdx diff --git a/docs/basic-tutorials/logging.mdx b/docs/tutorials/logging.mdx similarity index 94% rename from docs/basic-tutorials/logging.mdx rename to docs/tutorials/logging.mdx index 0d1f2ef1..d2592d2c 100644 --- a/docs/basic-tutorials/logging.mdx +++ b/docs/tutorials/logging.mdx @@ -1,20 +1,22 @@ --- -sidebar_position: 3 title: Logging -description: Use logs to debug smart contracts. +description: Debug a smart contract with logs. +sidebar_custom_props: + tutorial: + level: beginner --- - Use logs to debug smart contracts. + Debug a smart contract with logs. - + @@ -39,8 +41,7 @@ details. :::caution -Logs are not accessible by dapps and other applications. See the [events -example] for how to produce structured events. +Logs are not accessible by dapps and other applications. See the [events example] for how to produce structured events. ::: @@ -292,4 +293,4 @@ soroban_cli::log::event::contract_log: log="Hello Symbol(me)" ``` [`log!`]: https://docs.rs/soroban-sdk/latest/soroban_sdk/macro.log.html -[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli +[`soroban-cli`]: ../getting-started/setup.mdx#install-the-soroban-cli diff --git a/docs/advanced-tutorials/single-offer-sale.mdx b/docs/tutorials/single-offer-sale.mdx similarity index 71% rename from docs/advanced-tutorials/single-offer-sale.mdx rename to docs/tutorials/single-offer-sale.mdx index c74658e4..6e9a970e 100644 --- a/docs/advanced-tutorials/single-offer-sale.mdx +++ b/docs/tutorials/single-offer-sale.mdx @@ -1,17 +1,19 @@ --- -sidebar_position: 6 title: Single Offer Sale -description: Allow a seller to sell one token for another token to multiple buyers. +description: Make a standing offer to sell a token in exchange for another token. +sidebar_custom_props: + tutorial: + level: intermediate --- - Allow a seller to sell one token for another token to multiple buyers. + Make a standing offer to sell a token in exchange for another token. diff --git a/docs/advanced-tutorials/timelock.mdx b/docs/tutorials/timelock.mdx similarity index 77% rename from docs/advanced-tutorials/timelock.mdx rename to docs/tutorials/timelock.mdx index 788ab597..ea873136 100644 --- a/docs/advanced-tutorials/timelock.mdx +++ b/docs/tutorials/timelock.mdx @@ -1,11 +1,15 @@ --- -sidebar_position: 5 title: Timelock -description: Write a timelock implementing a claimable balance. +description: Lockup some token to be claimed by another user under set conditions. +sidebar_custom_props: + tutorial: + level: intermediate --- - Write a timelock implementing a claimable balance. + + Lockup some token to be claimed by another user under set conditions + diff --git a/docs/advanced-tutorials/tokens.mdx b/docs/tutorials/tokens.mdx similarity index 98% rename from docs/advanced-tutorials/tokens.mdx rename to docs/tutorials/tokens.mdx index 17f7f29d..5930eae1 100644 --- a/docs/advanced-tutorials/tokens.mdx +++ b/docs/tutorials/tokens.mdx @@ -1,20 +1,25 @@ --- -sidebar_position: 1 title: Tokens -description: Construct a smart contract token. +description: Write a CAP-46-6 compliant token contract. +sidebar_custom_props: + tutorial: + level: beginner --- - Construct a smart contract token. + Write a CAP-46-6 compliant token contract - + @@ -28,7 +33,7 @@ the [Token Interface]. [oigp]: https://gitpod.io/#https://github.com/stellar/soroban-examples/tree/v20.0.0 [token example]: https://github.com/stellar/soroban-examples/tree/v20.0.0/token -[Token Interface]: ../reference/interfaces/token-interface.mdx +[Token Interface]: ../tokens/token-interface.mdx ## Run the Example @@ -548,7 +553,7 @@ This example contract, however, demonstrates how a smart contract token might be constructed that doesn't take advantage of the Stellar Asset Contract, but does still satisfy the commonly used Token Interface to maximize interoperability. -[Stellar Asset Contract]: stellar-asset-contract.mdx +[Stellar Asset Contract]: ../tokens/stellar-asset-contract.mdx [later]: #compatibility-with-stellar-assets ### Separation of Functionality @@ -673,7 +678,7 @@ authorization, etc. ::: -[Soroban-CLI]: ../reference/soroban-cli +[Soroban-CLI]: ../reference/soroban-cli.mdx ## Tests @@ -1098,4 +1103,4 @@ soroban contract invoke \ --id GBZV3NONYSUDVTEHATQO4BCJVFXJO3XQU5K32X3XREVZKSMMOZFO4ZXR ``` -[`soroban-cli`]: ../reference/soroban-cli +[`soroban-cli`]: ../reference/soroban-cli.mdx diff --git a/docs/under-the-hood/_category_.json b/docs/under-the-hood/_category_.json deleted file mode 100644 index 320a4f38..00000000 --- a/docs/under-the-hood/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "position": 60, - "label": "Under the Hood", - "link": { - "type": "generated-index" - } -} diff --git a/docusaurus.config.js b/docusaurus.config.js index 6cd14388..cf0f25c9 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -22,6 +22,18 @@ const config = { }, plugins: [ "docusaurus-plugin-sass", + // [ + // '@docusaurus/plugin-content-docs', + // { + // id: 'guides', + // path: 'guides', + // routeBasePath: 'guides', + // sidebarPath: require.resolve('./sidebarsGuides.js'), + // sidebarItemsGenerator: require('./src/sidebar-generator'), + // editUrl: "https://github.com/stellar/soroban-docs/tree/main/", + // showLastUpdateTime: true, + // }, + // ], [ '@docusaurus/plugin-content-docs', { @@ -36,16 +48,16 @@ const config = { ], [ '@docusaurus/plugin-content-docs', - { - id: 'dapps', - path: 'dapps', - routeBasePath: 'dapps', - sidebarPath: require.resolve('./sidebarsDapps.js'), - editUrl: "https://github.com/stellar/soroban-docs/tree/main/", - showLastUpdateTime: true, - showLastUpdateAuthor: true, - }, - ], + { + id: 'dapps', + path: 'dapps', + routeBasePath: 'dapps', + sidebarPath: require.resolve('./sidebarsDapps.js'), + editUrl: "https://github.com/stellar/soroban-docs/tree/main/", + showLastUpdateTime: true, + showLastUpdateAuthor: true, + }, + ], require('./src/dev-server-plugin'), require('./src/analytics-module') ], @@ -61,6 +73,7 @@ const config = { breadcrumbs: true, sidebarPath: require.resolve("./sidebars.js"), editUrl: "https://github.com/stellar/soroban-docs/tree/main/", + sidebarItemsGenerator: require('./src/sidebar-generator'), }, theme: { customCss: [require.resolve("./src/css/custom.scss")], @@ -78,7 +91,8 @@ const config = { image: 'img/meta.png', docs: { sidebar: { - autoCollapseCategories: false + autoCollapseCategories: false, + // hideable: true, } }, navbar: { @@ -110,6 +124,11 @@ const config = { label: 'Dapps', position: 'left' }, + // { + // to: '/guides', + // label: 'Guides', + // position: 'left' + // }, { href: 'https://github.com/stellar/soroban-docs', label: 'GitHub', diff --git a/nginx/includes/redirects.conf b/nginx/includes/redirects.conf index 4a49926e..e2ba6f48 100644 --- a/nginx/includes/redirects.conf +++ b/nginx/includes/redirects.conf @@ -1,22 +1,54 @@ rewrite "^/api/methods/getLedgerEntry$" "/api/methods/getLedgerEntries" permanent; -rewrite "^/docs/category/examples$" "/docs/category/basic-tutorials" permanent; +rewrite "^/docs/category/examples$" "/docs/tutorials" permanent; rewrite "^/docs/getting-started/run-rpc$" "/docs/reference/rpc" permanent; -rewrite "^/docs/category/tutorials$" "/docs/category/basic-tutorials" permanent; +rewrite "^/docs/category/tutorials$" "/docs/tutorials" permanent; rewrite "^/docs/tutorials/deploy-to-futurenet$" "/docs/getting-started/deploy-to-testnet" permanent; -rewrite "^/fundamentals-and-concepts/faq$" "/docs/fundamentals-and-concepts/faq" permanent; -rewrite "^/docs/examples/events$" "/docs/basic-tutorials/events" permanent; -rewrite "^/docs/learn/rust-dialect$" "/docs/fundamentals-and-concepts/rust-dialect" permanent; +rewrite "^/fundamentals-and-concepts/faq$" "/docs/faq" permanent; +rewrite "^/docs/examples/events$" "/docs/tutorials/events" permanent; +rewrite "^/docs/learn/rust-dialect$" "/docs/soroban-internals/rust-dialect" permanent; rewrite "^/docs/reference/command-line$" "/docs/reference/soroban-cli" permanent; -rewrite "^/docs/advanced-tutorials/liquidity-pool-b6f$" "/docs/advanced-tutorials/liquidity-pool" permanent; +rewrite "^/docs/advanced-tutorials/liquidity-pool-b6f$" "/docs/tutorials/liquidity-pool" permanent; rewrite "^/reference/soroban-cli$" "/docs/reference/soroban-cli" permanent; -rewrite "^/docs(/category)?/learn$" "/docs/category/fundamentals-and-concepts" permanent; -rewrite "^/docs/built-in-contracts/token$" "/docs/advanced-tutorials/stellar-asset-contract" permanent; +rewrite "^/docs(/category)?/learn$" "/docs/category/soroban-internals" permanent; +rewrite "^/docs/category/fundamentals-and-concepts$" "/docs/category/soroban-internals" permanent; +rewrite "^/docs/built-in-contracts/token$" "/docs/tokens/stellar-asset-contract" permanent; rewrite "^/docs/getting-started/deploy-to-a-local-network$" "/docs/getting-started/deploy-to-testnet" permanent; rewrite "^/docs/getting-started/deploy-to-futurenet$" "/docs/getting-started/deploy-to-testnet" permanent; rewrite "^/api/incomplete-methods$" "/api/methods" permanent; -rewrite "^/docs/tutorials/testing$" "/docs/fundamentals-and-concepts/debugging" permanent; -rewrite "^/docs/category/how-to-guides$" "/docs/category/basic-tutorials" permanent; -rewrite "^/docs/SDKs/rust$" "/docs/reference/sdks/rust" permanent; +rewrite "^/docs/tutorials/testing$" "/docs/soroban-internals/debugging" permanent; +rewrite "^/docs/category/how-to-guides$" "/docs/guides" permanent; +rewrite "^/docs/SDKs/rust$" "/docs/reference/sdks/write-contracts" permanent; rewrite "^/docs/getting-started/connect-freighter-wallet$" "/docs/reference/freighter" permanent; -rewrite "^/docs/common-interfaces/token$" "/docs/reference/interfaces/token-interface" permanent; -rewrite "^/docs/how-to-guides/tokens$" "/docs/advanced-tutorials/tokens" permanent; +rewrite "^/docs/common-interfaces/token$" "/docs/tokens/token-interface" permanent; +rewrite "^/docs/how-to-guides/tokens$" "/docs/tutorials/tokens" permanent; +# BEGIN re-structure redirects +rewrite "^/docs/interfaces/token-interface" "/docs/tokens/token-interface" permanent; +rewrite "^/docs/tutorials/stellar-asset-contract" "/docs/tokens/stellar-asset-contract" permanent; +rewrite "^/docs/category/migrating-from-evm$" "/docs/migrate/evm/introduction-to-solidity-and-rust" permanent; +rewrite "^/docs/fundamentals-and-concepts/migrating-from-evm(/.*)$" "/docs/migrate/evm$1" permanent; +rewrite "^/docs/reference/releases$" "/docs/releases" permanent; +rewrite "^/docs/fundamentals-and-concepts/faq$" "/docs/faq" permanent; +rewrite "^/docs/reference/testnet$" "/docs/reference/networks" permanent; +rewrite "^/docs/reference/sdks/(rust|assemblyscript-sdk)$" "/docs/reference/sdks/write-contracts" permanent; +rewrite "^/docs/reference/sdks/(js|python|ios-sdk|flutter-sdk|php-sdk|elixir|java)$" "/docs/reference/sdks/interact-with-contracts" permanent; +rewrite "^/docs/fundamentals-and-concepts/(built-in-types|custom-types|fully-typed-contracts)$" "/docs/soroban-internals/types/$1" permanent; +rewrite "^/docs/fundamentals-and-concepts/invoking-contracts-with-transactions$" "/docs/soroban-internals/contract-interactions/stellar-transactions" permanent; +rewrite "^/docs/fundamentals-and-concepts/interacting-with-contracts$" "/docs/soroban-internals/contract-interactions" permanent; +rewrite "^/docs/(basic|advanced)-tutorials/(.*)$" "/docs/tutorials/$2" permanent; +rewrite "^/docs/fundamentals-and-concepts/(.*)$" "/docs/soroban-internals/$1" permanent; +# Nothing has been done here yet, but I'm noting what changes will need to be addressed +# [x] "fundamentals-and-concepts" is now "soroban-internals" +# [x] all of the "basic-tutorials" are now in "tutorials" +# [x] all of the "advanced-tutorials" are now in "tutorials" +# [x] The new way of listing tutorials now replaces "/docs/category/tutorials" with "/docs/tutorials" +# [x] "reference/interfaces/token-interface" has moved to "tokens/token-interface" (this'll be a big one!) +# [x] "tutorials/stellar-asset-contract" has moved to "tokens/stellar-asset-contract" +# [x] "soroban-internals/migrate-from-evm" has moved to "migrate/evm" +# [x] "releases" has moved up one level ("/docs/{reference,resources}/releases" -> "/docs/releases") +# [x] "faq" has moved up one level ("/docs/{reference,resources}/faq" -> "/docs/faq") +# [x] "resources/testnet" has been moved to "resources/networks" +# [x] various SDK pages have been collapsed into "resources/sdks/{write-contracts,interact-with-contracts}" +# [x] "soroban-internals/{built-in-types,custom-types,fully-typed-contracts}" have been moved into an umbrella "soroban-internals/types" directory +# [x] "soroban-internals/invoking-contracts-with-transactions.mdx" has moved to "soroban-internals/contract-interactions/stellar-transactions.mdx" +# [x] other misc shuffling of content and pages into "soroban-internals/contract-interactions/" +# [x] "soroban-internals/interacting-with-contracts.mdx" moved to "soroban-internals/contract-interactions/index.mdx" diff --git a/package.json b/package.json index e3338f2b..92aa427f 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "serve": "docusaurus serve", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", - "format:mdx": "prettier --prose-wrap preserve --write \"docs/**/*.{md,mdx}\"", - "check:mdx": "prettier --prose-wrap preserve --check \"docs/**/*.{md,mdx}\"", + "format:mdx": "prettier --prose-wrap preserve --write \"{api,dapps,docs,guides}/**/*.{md,mdx}\"", + "check:mdx": "prettier --prose-wrap preserve --check \"{api,dapps,docs,guides}/**/*.{md,mdx}\"", "lint:fix": "eslint \"src/**/*.{js,jsx,ts,tsx}\" --fix", "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"", "prepare": "husky install", diff --git a/sidebars.js b/sidebars.js index 801bdbf8..23446022 100644 --- a/sidebars.js +++ b/sidebars.js @@ -4,5 +4,5 @@ module.exports = { type: 'autogenerated', dirName: '.', }, - ], + ] }; diff --git a/sidebarsApi.js b/sidebarsApi.js index 65579504..2dea37c7 100644 --- a/sidebarsApi.js +++ b/sidebarsApi.js @@ -6,10 +6,8 @@ module.exports = { collapsible: true, collapsed: false, link: { - type: 'generated-index', - title: 'Introduction', - description: 'A public discussion about the design of soroban-rpc.', - slug: '/', + type: 'doc', + id: 'README', }, items: [ 'goals', diff --git a/sidebarsDapps.js b/sidebarsDapps.js index 774dd63d..6b498cf7 100644 --- a/sidebarsDapps.js +++ b/sidebarsDapps.js @@ -1,15 +1,15 @@ module.exports = { mySidebar: [ + { + type: 'doc', + id: 'README', + label: 'Welcome', + }, { type: 'link', label: 'Dashboard', href: '/dashboard', }, - { - type: 'doc', - id: 'index', - label: 'Index', - }, { type: 'doc', id: 'scaffold-soroban', diff --git a/sidebarsGuides.js b/sidebarsGuides.js new file mode 100644 index 00000000..d1fc82ca --- /dev/null +++ b/sidebarsGuides.js @@ -0,0 +1,18 @@ +module.exports = { + guidesSidebar: [ + { + type: 'category', + label: 'Guides', + link: { + type: 'doc', + id: 'README', + }, + items: [ + { + type: 'autogenerated', + dirName: '.' + } + ] + }, + ], +}; diff --git a/src/components/atoms/SortableRow/index.js b/src/components/atoms/SortableRow/index.js new file mode 100644 index 00000000..a8a7c425 --- /dev/null +++ b/src/components/atoms/SortableRow/index.js @@ -0,0 +1,13 @@ +import React from "react" + +const SortableRow = (props) => { + return ( + + {props.title} + click here + {props.difficulty} + + ) +} + +export default SortableRow diff --git a/src/components/molecules/SortableTable/index.js b/src/components/molecules/SortableTable/index.js new file mode 100644 index 00000000..ef169bcb --- /dev/null +++ b/src/components/molecules/SortableTable/index.js @@ -0,0 +1,33 @@ +import React, { useState } from "react" +import styles from "./style.module.css"; + +const arrowDown = ; +const arrowUp = ; + +const SortableTable = (props) => { + const [isAscending, setIsAscending] = useState(false); + const [sortColumn, setSortColumn] = useState(null) + + const sortTable = (val) => { + const sortDirection = col === val ? !isAscending : false + setIsAscending(sortDirection) + setSortColumn(val) + } + + return ( + + + + + + + + + + {props.children} + +
TitleLinkTags
+ ) +} + +export default SortableTable diff --git a/src/components/molecules/SortableTable/style.module.css b/src/components/molecules/SortableTable/style.module.css new file mode 100644 index 00000000..3a41004c --- /dev/null +++ b/src/components/molecules/SortableTable/style.module.css @@ -0,0 +1,4 @@ +.sortable { + width: 100%; + display: table; +} diff --git a/src/css/custom.scss b/src/css/custom.scss index 2a7fb3e9..c63fec03 100644 --- a/src/css/custom.scss +++ b/src/css/custom.scss @@ -171,3 +171,9 @@ select[data-testid="example-pairing-select"] { font-size: var(--ifm-font-size-base); border-radius: 5px; } + +/* Hidden sidebar items */ + +.sidebar-category-items-hidden ul { + display: none !important; +} diff --git a/src/sidebar-generator.js b/src/sidebar-generator.js new file mode 100644 index 00000000..338353d5 --- /dev/null +++ b/src/sidebar-generator.js @@ -0,0 +1,35 @@ +const fs = require('fs') +const path = require('path') + +module.exports = async ({ defaultSidebarItemsGenerator, ...args }) => { + + if (args.version.contentPath.endsWith('docs')) { + /** + * Adds a custom class name to the "Tutorials" and "How-To Guides" index + * pages, which we then use in the `/src/css/custom.scss` file to hide + * the `
    ` element that is contained within the item. The result is a + * single "Tutorials/Guides" page that contains the list of all the docs + * underneath it, while those items are not displayed in the sidebar. + */ + args.docs.map((doc) => { + if (doc.id === 'guides/README' || doc.id === 'tutorials/README') { + doc.frontMatter.sidebar_class_name = "sidebar-category-items-hidden" + } + }) + } else if (args.version.contentPath.endsWith('guides')) { + /** + * Adds the `hide_table_of_contents` directive to each of the "Guides" + * docs so that the page width isn't shrunk down. + * + * @todo For whatever reason, this doesn't appear to work like the + * sidebar class name does (above). For now, make sure to manually add + * `hide_table_of_contents: true` to the front matter of each guide doc. + */ + args.docs.map((doc) => { + doc.frontMatter.hide_table_of_contents = true + }) + } + + const sidebarItems = await defaultSidebarItemsGenerator({ ...args }) + return sidebarItems +} diff --git a/src/theme/DocCardList/index.js b/src/theme/DocCardList/index.js new file mode 100644 index 00000000..88558cb4 --- /dev/null +++ b/src/theme/DocCardList/index.js @@ -0,0 +1,104 @@ +import React, {useState} from 'react'; +import clsx from 'clsx'; +import { + useCurrentSidebarCategory, + filterDocCardListItems, +} from '@docusaurus/theme-common'; +import { + useDocById, +} from '@docusaurus/theme-common/internal'; +import DocCard from '@theme/DocCard'; +import styles from './style.module.css' +import { title } from 'process'; + +function DocCardListForCurrentSidebarCategory({className}) { + const category = useCurrentSidebarCategory(); + return category.label === 'Tutorials' + ? + : category.label === 'How-To Guides' + ? + : ; +} + +function GuidesDocCardList(props) { + const {items, className} = props; + return ( +
    + {items.map((item, index) => { + if (item.type === 'category') { + return ( +
    +

    {item.label}

    + {item.items.map((item, index) => +

    {item.label}

    + )} +
    + ) + } + })} +
    + ) +} + +function TutorialsDocCardList(props) { + const [tutorialLevel, setTutorialLevel] = useState('All'); + const [tutorialQuery, setTutorialQuery] = useState(''); + + const {items, className} = props; + const filteredItems = filterDocCardListItems(items); + + const filterDocCardsByTutorialLevel = (level) => { + return filteredItems.filter(item => level.toLowerCase() === 'all' ? true : item.customProps?.tutorial?.level === level.toLowerCase()) + } + let filteredDocCards = filterDocCardsByTutorialLevel(tutorialLevel) + + const filterDocCardsByTutorialQuery = (query) => { + return filteredDocCards.filter(item => query !== '' ? item.label.toLowerCase().includes(query.toLowerCase()) || item.description.toLowerCase().includes(query.toLowerCase()) : true) + } + filteredDocCards = filterDocCardsByTutorialQuery(tutorialQuery) + + return ( + <> +
    +
    + +
    +
    + setTutorialQuery(e.target.value)} /> +
    +
    +
    + {filteredDocCards.map((item, index) => { + const doc = useDocById(item.docId ?? undefined); + item.description = item.description ?? doc?.description + return ( +

    {item.label} - {item.description}

    + ) + })} +
    + + ) +} + +export default function DocCardList(props) { + const {items, className} = props; + if (!items) { + return ; + } + const filteredItems = filterDocCardListItems(items); + return ( +
    + {filteredItems.map((item, index) => +
    + +
    + )} +
    + ); +} diff --git a/src/theme/DocCardList/style.module.css b/src/theme/DocCardList/style.module.css new file mode 100644 index 00000000..62868c44 --- /dev/null +++ b/src/theme/DocCardList/style.module.css @@ -0,0 +1,15 @@ +.docCardFilterSelect { + padding: 0.75rem; + width: 100%; + margin-bottom: 1rem; + font-size: var(--ifm-font-size-base); + border-radius: 5px; +} + +.docCardFilterSearch { + padding: 0.74rem; + width: 100%; + margin-bottom: 1rem; + font-size: var(--ifm-font-size-base); + border-radius: 5px; +} diff --git a/src/theme/DocItem/Footer/index.js b/src/theme/DocItem/Footer/index.js index 80f671ff..d3c7981d 100644 --- a/src/theme/DocItem/Footer/index.js +++ b/src/theme/DocItem/Footer/index.js @@ -5,6 +5,7 @@ import {useDoc} from '@docusaurus/theme-common/internal'; import LastUpdated from '@theme/LastUpdated'; import EditThisPage from '@theme/EditThisPage'; import TagsListInline from '@theme/TagsListInline'; +import DocCardList from '@theme/DocCardList'; import ReaderFeedback from '@site/src/components/ReaderFeedback'; import styles from './styles.module.css'; @@ -51,11 +52,18 @@ export default function DocItemFooter() { const canDisplayTagsRow = tags.length > 0; const canDisplayEditMetaRow = !!(editUrl || lastUpdatedAt || lastUpdatedBy); const canDisplayFooter = canDisplayTagsRow || canDisplayEditMetaRow; + const canDisplayDocCardsOnGuide = metadata.permalink.startsWith('/docs/guides') if (!canDisplayFooter) { return null; } return ( <> + {canDisplayDocCardsOnGuide && +
    + {metadata.permalink !== '/docs/guides/' &&

    Guides in this category:

    } + +
    + }