diff --git a/dapps/dapp-challenges/challenge-3-oracle.mdx b/dapps/dapp-challenges/challenge-3-oracle.mdx new file mode 100644 index 000000000..fa008b9b3 --- /dev/null +++ b/dapps/dapp-challenges/challenge-3-oracle.mdx @@ -0,0 +1,557 @@ +--- +sidebar_position: 0 +title: Oracle Dapp Challenge +description: Get prices with the Oracle Dapp! Beat the Challenge! +--- + +import oracle_connect from "../../static/img/oracle_connect.png"; +import oracle_home from "../../static/img/oracle_home.png"; +import oracle_mintBal from "../../static/img/oracle_mintBal.png"; +import oracle_approve from "../../static/img/oracle_approve.png"; +import oracle_mint from "../../static/img/oracle_mint.png"; +import oracle_calculate from "../../static/img/oracle_calculate.png"; +import oracle_balance_contract from "../../static/img/oracle_balance_contract.png"; +import oracle_balance_user from "../../static/img/oracle_balance_user.png"; +import oracle_deployed from "../../static/img/oracle_deployed.png"; +import { ParentChallengeForm } from "../../src/components/atoms/challenge-form"; +import { ParentChallengeContractForm } from "../../src/components/atoms/challenge-contract-form"; +import CompleteStepButton from "../../src/components/atoms/complete-step-button"; +import StartChallengeButton from "../../src/components/atoms/start-challenge-button"; +import "./styles.css"; +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + Oracle Pool Dapp Challenge. + + + + + + + + +This challenge will guide you through the process of building and shipping an oracle dapp on the Stellar network using Soroban. Oracle dapps (decentralized applications) provide the means for users to access real-world data and information from external sources and bring it on-chain. + +In this challenge, you will learn how to deploy smart contracts to Futurenet, and how to 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. However, it's crucial to clarify that despite its functionality, the dapp is not promoted nor intended for deployment in a production-level setting on Mainnet. The challenge is designed for educational purposes only, helping you understand how a dapp can be built and interacted with, with further customization and development, it has the potential to evolve into a full-fledged, ready-to-use oracle solution. + +## Checkpoint 0: πŸ“¦ Install πŸ“š + +Start by installing the required dependencies. + +Required: + +- `soroban-cli` 20.0.0-rc.4.1: [Install Soroban CLI](../../docs/getting-started/setup#install-the-soroban-cli) +- `Node` >=v18: [Download Node](https://nodejs.org/en/download/) +- `Freighter Wallet`: [Freighter Wallet](https://freighter.app/) + +First, clone the Soroban Dapps Challenge repo and check out the `oracle` branch, which contains the code for the oracle smart contract that powers this dapp: + +```sh +git clone https://github.com/stellar/soroban-dapps-challenge.git +cd soroban-dapps-challenge +git checkout oracle +``` + +:::tip +If you haven't already installed the soroban-cli , you can do so by running the following command: + +```sh +cargo install --locked --version 20.0.0-rc.4.1 soroban-cli +``` + +::: + +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. + +## Checkpoint 1: πŸ“ Setup the `initialize.sh` Script + +The `initialize.sh` script is a shell script that will help you initialize the contracts and install dependencies. It is located in the top level directory. + +The `initialize.sh` script performs following actions: + +- Creates a new wallet to serve as the token admin +- Funds token admin wallet with test tokens +- Builds and deploys contracts using this wallet +- Creates typescript bindings +- Installs dependencies + +For this section, you'll need to configure parameters to initialize `donation` and `oracle` contracts. + +You'll start with `donation` contract: + +- First, Open `initialize.sh`: + +- Find the following part at the end of the file: + +```sh +echo "Initialize the DONATION contract" +``` + +- For the `--recipient` parameter, specify the wallet address that will be used to withdraw money from the donation contract. This may be your address. + +```sh +initialize\ +--recipient \ +``` + +Now for the `oracle` contract: + +- Find the following part of `initialize.sh`: + +```sh +echo "Initialize the ORACLE contract" +``` + +- As you can see, there are several parameters that need to be specified here. + +```sh + initialize \ + --caller \ + --pair_name BTC_USDT \ + --epoch_interval \ + --relayer +``` + +Here is a description of each parameter: + +- `` - the address that will become the owner of the contract. This may be your address. Only the contract owner will be able to change the `epoch_interval` and `relayer` +- `` - frequency (in seconds) of price updates +- `` - address of the wallet that will update the price (in the backend, in the CRON task). It is suggested to create a dedicated wallet for this ([be sure to fund with test Lumens](https://laboratory.stellar.org/#account-creator?network=futurenet)) + +## Checkpoint 2: 🎬 Deploy Smart Contracts + +Now that the initialization script is set up it's time to deploy the smart contracts to a Sandbox environment. 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. Deploying smart contracts to a Sandbox environment simulates that process without actually affecting Mainnet. When you deploy the smart contracts, you'll instead deploy to Futurenet, a test network with more cutting-edge features that have not yet been implemented in the Mainnet. + +To build and deploy the contracts in a Sandbox environment, as well as to compile the TypeScript bindings, run the following command in your terminal: + +```sh +npm run setup +``` + +> Note: This command may require write privileges in some cases. If you encounter a "Permission denied" error when running this command, run the following command to grant write privileges to the `initialize.sh` script: +> +> ```sh +> chmod +x initialize.sh +> ``` + +If the command runs successfully, your terminal will return a series of messages notifying you about the successful initialization of the contracts and the post-installation sequence. + +```sh +Deploy the BTC TOKEN contract +Contract deployed successfully with ID: CD5ZAJAPX5AAOB55G7SQEM63EQK5JRUZN2LUCDP66BRWV5HNGPDGJVDD +Deploy the DONATION contract +Contract deployed successfully with ID: CC7U75NM4FQQSPLCSX2FTUCAQ6VI6VBA5LDYSU3FRKXN3X2W3AL2SAJ3 +Deploy the ORACLE contract +Contract deployed successfully with ID: CBK3VIRHK5QGHLKFTWHJI2ABMW2SATMIDPNQSCICCDRJU6DIFEWHLDD2 +Initialize the BTC TOKEN contract + +Done +Initialize the DONATION contract + +Done +Initialize the ORACLE contract + +Done + +> soroban-oracle-project@0.0.0 build-contracts +... +``` + +:::tip + +Please, save your deployed contract ID, you will need it to complete the challenge. + +::: + + + +## Checkpoint 3: ⏯️ Create a CRON task + +A CRON task is a scheduled operation performed at specified intervals, functioning as a customizable backend service. Here, you will run a CRON task to update the BTC price within the Oracle contract. Data can be fetched from an API and set to the contract using the `set_price` function, in this case, the tutorial will use the [CryptoPrice API](https://api-ninjas.com/api/cryptoprice). This is a free API that provides real-time cryptocurrency prices, and it is used in this tutorial for demonstration purposes only. You are free to use any price feed API of your choice. + +The function that updates the price is already implemented in the `cron-script.ts` file. To retrieve the data from the price feed, you will need to specify the following parameters: + +- Secret key of wallet (relayer) that will fetch BTC price from API and set it to smart contract; +- Contract address of deployed Oracle Contract; +- `API_KEY` from https://api-ninjas.com/api/cryptoprice (for free). + +Here is an example of a filled `cron-script.ts` file: + +```ts +const API_NINJA_KEY = "xSuoJa0icEhaQzk3IdomNWFmXK0qNG8lNZofYwJ4"; + +const sourceSecretKey = + "SBDLGM7RKXU6WYM2DRDIBULWAG7I6QDO3AONLERKWZPDDPQMMQ26F7TM"; +const sourceKeypair = SorobanClient.Keypair.fromSecret(sourceSecretKey); +const sourcePublicKey = sourceKeypair.publicKey(); + +const contractId = "CBDRRNXD2UETJJL376B2VT3RS22YPF4NPWRDCMSBZAIQGWJIUM3U7552"; +``` + +To run the CRON task, navigate to the `cron` directory and run: + +```sh +npm install +node cron-script.ts +``` + +Once the CRON task is running, it will fetch the BTC price from the API and set it to the contract every 15 minutes. + +Here is an example of the output: + +```sh +Running a task every 15 minutes +Current Time: 2023-11-08T00:30:00.036Z +lastEpochNr 0 +deltaTimestamp 1699403400 +Need to update the value +fetched priceData 3531576000 +[updatePairPrice] View Transaction: https://futurenet.steexp.com/tx/5c68dd1eb6df7a926fa8fda3a3cd187d2855b74ceaa41469f69b33f81930c33a +[updatePairPrice] response.status: SUCCESS +value set! +``` + +You can specify the frequency of the CRON task by changing the `cron.schedule` parameter in the `cron-script.ts` file. + +For example, to run the task every 5 minutes, change the parameter to: + +```ts +cron.schedule("*/5 * * * *", async () => { + ... +}); +``` + +It's important to note that since the price feed is dependent on the CRON task, the price will not update until the CRON task has run at least once. Furthermore, the CRON task will need to keep running in order to keep the price feed updated. You can host the task on your localhost or on a server such as [Vercel](https://vercel.com/docs/cron-jobs). For this example, the CRON task is hosted on a local host. + +## Checkpoint 4: 🀝 Connect the Frontend to the Backend + +Now that you have the smart contracts deployed, and the cron job running, it's time to check out the frontend of your dapp. + +From the top level directory run the following command to start the development server: + +```sh +npm run dev +``` + +Now, open your browser and visit [http://localhost:5173](http://localhost:5173). 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 the browser. 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). + +Now that you have the frontend running, it's time to connect it with your smart contracts. + +You will need to add some Futurenet network lumens to your wallet to interact with the dapp. Visit https://laboratory.stellar.org/#account-creator?network=futurenet, and follow the instructions to create and or fund an account on Futurenet. + +> Note: These are test lumens for use with Futurenet and cannot be used on Mainnet + +## Checkpoint 5: 🧿 Oracle Insights + +Gaze into the crystal ball of APIs and retrive the price feed from the all connected internet. Data at your fingertips, at one time an abyss but pioneers have paved the way for many to cross. Here you will reach into the realm of off-chain data and pull out the price of BTC. In this section, you will mint tokens and deposit Bitcoin (BTC) into the donation contract. The conversion to USD will utilize the oracle price feed to ensure your donation is aligned with the current BTC to USD conversion rate. + + + + + + + + + +#### Connect a Wallet + +Open the dapp frontend and click the "connect" and choose the wallet you want to use. For this example, you will use Freighter. + + + connect + + + + + +#### Mint USDC and BTC + +Open the `Mint BTC Tokens` tab, enter the desired token amount, and click the "Mint" button. + + + + + + +#### Approve Transaction + +You should see a popup from Freighter asking you to sign the transactions. Click on "Approve" and wait for the transaction to be confirmed. + + + + + + +#### Check Updated Balance + +You should see an updated balance in the account balance component. + + + + + + + + + + + + + + +#### Deposit into the Donation Contract + +Open the frontend, enter the amount of BTC in USD that you would like to donate, then click the "Calculate" button. You should see the amount of BTC that you need to deposit in order to donate the specified amount in USD. For example, if you enter 35923.82 USD, you should see 1 BTC. + +connect + + + + +#### Approve Transaction + +Click on "Approve" and wait for the transaction to be confirmed. + + + + + +#### Check Updated Balance + +Once the transaction is confirmed, you should see the contract and your wallet balances update in the `Donate` and `Mint BTC Tokens` tabs, respectively. + +connect +connect + + + + + + + + + +> Note: These are test tokens for use with Futurenet and cannot be used on Mainnet. + + + Funding completed + + +## Checkpoint 6: 🚒 Ship it! 🚁 + +In this step, you will deploy your dapp to a hosting platform so that it can be accessed by anyone with an internet connection. Note that it's on futurenet, the network used for testing, not mainnet for production use. You can use any hosting platform you like, but for demonstration purposes, this section will use [Vercel](https://vercel.com/). Vercel is a cloud platform for static sites and serverless functions that offers a free tier for developers. It also has a built-in integration with GitHub, which makes it easy to deploy your dapp directly from your GitHub repository. + +If you don't already have a [Vercel account], you will need to create one and link it to your GitHub account. + +[Vercel account]: https://vercel.com/login + +First install the Vercel cli: + +```bash +npm i --global vercel +``` + +Then, remove any existing `.vercel` directory in your project to ensure that you are starting with a clean slate: + +```bash +rm -rf .vercel +``` + +Next, you will need to create a new project on vercel. To do this, run the following command: + +```bash +vercel project add +``` + +For example: + +```bash +vercel project add oracle +``` + +Next you will pull in the project settings locally by running the following command: + +```bash +vercel pull +``` + +Follow the answers to the prompts below to ensure that your local project is correctly linked to the target Vercel project: + +```bash +? Set up β€œ~/Documents/GitHub/test/soroban-dapps-challenge”? [Y/n] y +? Which scope should contain your project? +? Link to existing project? [y/N] y +? What’s the name of your existing project? +``` + +After following the prompts, you should see something similar to the following output: + +```bash +... +πŸ”— Linked to julian-dev28/oracle (created .vercel) +> Downloading `development` Environment Variables for Project oracle +βœ… Created .vercel/.env.development.local file [92ms] + +> Downloading project settings +βœ… Downloaded project settings to ~/Documents/GitHub/test/soroban-dapps-challenge/.vercel/project.json [1ms] +``` + +Next, you will need to edit the `settings` section in `.vercel/project.json` to ensure that the `installCommand` is set to `npm i`: + +```diff + "settings": { + "createdAt": 1699390700432, + "framework": null, + "devCommand": null, +- "installCommand": null, ++ "installCommand": "npm i", + "buildCommand": null, + "outputDirectory": null, + "rootDirectory": null, + "directoryListing": false, + "nodeVersion": "18.x" + } +``` + +Next, run the following command to build your dapp: + +```bash +vercel build --prod +``` + +What does the `vercel build` command do? It builds your dapp for production, which means that it optimizes your code for performance and creates an optimized production build of your dapp in the `.vercel/output` directory. This is the directory that you will deploy to Vercel. + +The output of the `vercel build` command should look something like this: + +```bash +$ vite build +.. +dist/assets/index-91e5a562.js 490.69 kB β”‚ gzip: 139.50 kB +dist/assets/ModelViewer-fde23dd9.browser.esm-c08cdb2e.js 826.05 kB β”‚ gzip: 231.17 kB +dist/assets/index-46cc9288.js 3,107.82 kB β”‚ gzip: 888.20 kB +... +βœ“ built in 11.72s +✨ Done in 12.14s. +βœ… Build Completed in .vercel/output [19s] +``` + +Next, you will deploy your dapp to Vercel by running the following command: + +```bash +vercel deploy --prebuilt --prod +``` + +Using the `--prebuilt` flag tells Vercel to deploy the build outputs in `.vercel/output` that you created in the previous step. + +Once the deployment is complete, you should see something similar to the following output: + +```bash +πŸ” Inspect: https://vercel.com/julian-dev28/oracle2/Fk7RKb3H4RX1d1kBtHukgppRcv2m [9s] +βœ… Production: https://oracle2-3lrfgjzq9-julian-dev28.vercel.app [9s] +``` + +:::tip + +Please, save your production url, you will need it to complete the challenge. + +::: + +You can now visit the preview link to see your deployed dapp! πŸŽ‰ + +connect + +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 7: πŸ’ͺ Pass the Challenge! + +Now it's time to submit your work! + +Submit your `Production` URL from the previous step into the challenge form to pass the checkpoint! + + + +
+ +:::info + +Join [our Community in Discord](https://discord.gg/stellardev) in case you have any issues or questions. + +::: + +## Checkpoint 8: βœ… Check your work! + +In order to successfully complete this challenge, your work needs to be checked. Please, follow this steps: + +1. Fork [the challenge repository](https://github.com/stellar/soroban-dapps-challenge/fork). +2. Fill `oracle/challenge/output.txt` file with your wallet address. Filled file should look like: + +```sh +Public Key: GBSXUXZSA2VEXN5VGOWE5ODAJLC575JCMWRJ4FFRDWSTRCJ123456789 +``` + +3. Create a Pull Request to the `stellar/soroban-dapps-challenge/oracle` branch. When the PR will be created, CI actions will check the `oracle/challenge/output.txt` file data and update your progress. +4. Wait for the CI/CD pipeline results. +5. Fix errors if present: + +- find the error reason in the Oracle challenge CI results (you can find a link right in the pull request); +- return to your forked repository; +- fix errors and commit changes. The existing PR will be checked again. + +6. If the pipeline was successful, then congratulations! You completed the challenge!πŸ‘ + +Invite a friend to try out your dapp and ask them to provide feedback! + +## βš”οΈ Side Quests + +πŸͺ¬ Add a new feature to your dapp (e.g. add a new price feed, add a new token, etc.) + +🌐 Extend your dapp's functionality by allowing users to query and interact with historic oracle data directly through the user interface. + +πŸ’‘ Develop a function to respond to a significant BTC price change. + +## πŸ“š User Workflows Checklist + +During this exercise you should be able to: + +- Clone the example repo (Oracle Dapp) +- Set the correct parameters in the `initialize.sh` script +- Deploy your contract to Futurenet +- Deploy the example web ui somewhere (e.g. netlify, vercel, surge, etc.) + +Then via the web UI, you should be able to: + +- Connect your wallet +- See the BTC to USD conversion rate +- See your current balance +- See the contract balance +- Mint an asset +- Deposit an asset +- See your deposit(s) appear on the page as the transactions are confirmed + +## πŸ›‘οΈπŸ—‘οΈ Take On More Challenges + +View your progress and take on more challenges by visiting your [User Dashboard!](/dashboard) diff --git a/src/components/atoms/challenge-card/index.tsx b/src/components/atoms/challenge-card/index.tsx index 06746ac29..fa8cb0836 100644 --- a/src/components/atoms/challenge-card/index.tsx +++ b/src/components/atoms/challenge-card/index.tsx @@ -37,6 +37,12 @@ const challengeConfig: { [key: string]: ChallengeConfig } = { icon: iconBulb, route: "/dapps/dapp-challenges/challenge-2-liquidity-pool", }, + 3: { + icon: iconBulb, + route: "/dapps/dapp-challenges/challenge-3-oracle", + lastCheckpointRoute: + "/dapps/dapp-challenges/challenge-3-oracle#checkpoint-8--check-your-work", + }, }; const months = [ "Jan",