From 21de3957e0123230e250fff6f7473d7afb8ea653 Mon Sep 17 00:00:00 2001 From: "Fifo (Fabricius Zatti)" <62725221+fazzatti@users.noreply.github.com> Date: Wed, 13 Dec 2023 19:29:26 -0300 Subject: [PATCH] Docs: Update Gitbook (#35) * GITBOOK-16: No subject * GITBOOK-17: No subject * GITBOOK-19: No subject --- .../certificates_of_deposit.optimized.wasm | Bin 0 -> 12556 bytes docs/SUMMARY.md | 2 + .../asset/stellar-asset-contract-handler.md | 3 + .../certificate-of-deposit-client.md | 106 ++++ docs/reference/contracts/contract-engine.md | 51 +- .../channel-accounts-transaction-submitter.md | 97 ++++ .../core/soroban-transaction-processor.md | 65 ++- docs/reference/horizon-handler.md | 1 + docs/reference/rpc/default-rpc-handler.md | 1 + .../rpc/validation-cloud-rpc-handler.md | 5 + docs/reference/soroban-handler.md | 1 + docs/tutorials/bulk-payments.md | 4 +- .../e2e-certificate-of-deposit-demo.md | 470 ++++++++++++++++++ 13 files changed, 786 insertions(+), 20 deletions(-) create mode 100644 docs/.gitbook/assets/certificates_of_deposit.optimized.wasm create mode 100644 docs/reference/asset/stellar-asset-contract-handler.md create mode 100644 docs/tutorials/e2e-certificate-of-deposit-demo.md diff --git a/docs/.gitbook/assets/certificates_of_deposit.optimized.wasm b/docs/.gitbook/assets/certificates_of_deposit.optimized.wasm new file mode 100644 index 0000000000000000000000000000000000000000..9efe0b7cad79b95a09f6ac9998660d20bda24b9f GIT binary patch literal 12556 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 JH|_N8|3BD-XO92? literal 0 HcmV?d00001 diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 1987492..e74d034 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -7,6 +7,7 @@ * [Issuing your first asset](tutorials/issuing-your-first-asset.md) * [Bulk Payments](tutorials/bulk-payments.md) +* [E2E Certificate of Deposit demo](tutorials/e2e-certificate-of-deposit-demo.md) ## 📄 Reference @@ -18,6 +19,7 @@ * [Friendbot](reference/account/helpers/friendbot.md) * [Asset](reference/asset/README.md) * [Classic Asset Handler](reference/asset/classic-asset-handler.md) + * [Stellar Asset Contract Handler](reference/asset/stellar-asset-contract-handler.md) * [Constants](reference/constants.md) * [Contracts](reference/contracts/README.md) * [Contract Engine](reference/contracts/contract-engine.md) diff --git a/docs/reference/asset/stellar-asset-contract-handler.md b/docs/reference/asset/stellar-asset-contract-handler.md new file mode 100644 index 0000000..560367d --- /dev/null +++ b/docs/reference/asset/stellar-asset-contract-handler.md @@ -0,0 +1,3 @@ +# Stellar Asset Contract Handler + +Coming Soon diff --git a/docs/reference/contracts/certificate-of-deposit-client.md b/docs/reference/contracts/certificate-of-deposit-client.md index b51c4a1..2a54403 100644 --- a/docs/reference/contracts/certificate-of-deposit-client.md +++ b/docs/reference/contracts/certificate-of-deposit-client.md @@ -1,2 +1,108 @@ # Certificate of Deposit Client +The `CertificateOfDepositClient` class extends `ContractEngine` to interact with a specific smart contract implementation for a Certificate of Deposit on the Stellar network. It implements methods for managing deposits, withdrawals, and fetching contract-related data. + +{% hint style="info" %} +Refer to the [e2e-certificate-of-deposit-demo.md](../../tutorials/e2e-certificate-of-deposit-demo.md "mention") for a detailed use case and code example including this client. A fully integrated version of this contract implementation with UI can also be seen at the [Custodial Asset Sandbox](https://stellar.cheesecakelabs.com/). +{% endhint %} + +## **Constructor** + +* **Parameters**: + * `contractId`: Contract ID of the deployed contract. + * `network`: Network configuration. + * `rpcHandler`: RPC handler for interactions. +* **Purpose**: Initializes the client with the necessary configurations to interact with the Certificate of Deposit contract. + +## **Methods** + +### deposit + +* **Purpose**: Deposits assets into the contract. +* **Parameters**: + * `address`: Account address making the deposit. + * `amount`: Deposit amount. + * `signers`: Authorizing signers. + * `header`: Transaction header. + * `feeBump`: Optional fee bump. + +### withdraw + +* **Purpose**: Withdraws assets from the contract. +* **Parameters**: + * `address`: Account address withdrawing assets. + * `acceptPrematureWithdraw`: Flag for premature withdrawal acceptance. + * `signers`: Authorizing signers. + * `header`: Transaction header. + * `feeBump`: Optional fee bump. + +### getEstimatedYield + +* **Purpose**: Fetches estimated yield. +* **Parameters**: + * `address`: Account address. + * `header`: Transaction header. + +### getPosition + +* **Purpose**: Retrieves current position. +* **Parameters**: + * `address`: Account address. + * `header`: Transaction header. + +### getEstimatedPrematureWithdraw + +* **Purpose**: Estimates premature withdrawal amount. +* **Parameters**: + * `address`: Account address. + * `header`: Transaction header. + +### getTimeLeft + +* **Purpose**: Determines time left for penalty-free withdrawal. +* **Parameters**: + * `address`: Account address. + * `header`: Transaction header. + +### initialize + +* **Purpose**: Initializes contract state. +* **Parameters**: + * `admin`, `asset`, `term`, `compoundStep`, `yieldRate`, `minDeposit`, `penaltyRate`, `allowancePeriod`: Contract parameters. + * `signers`: Authorizing signers. + * `header`: Transaction header. + * `feeBump`: Optional fee bump. + +{% hint style="info" %} +The initialization parameters affect the CD rules as the following: + + + +* **Admin**\ + Defines which account can manage the CD contract and also receives and provides the funds from/to the users. +* **Asset** \ + The contract id of the Stellar Asset Contract for the wrapped Classic Asset this CD interacts with. +* **Term** (seconds)\ + For how long this CD will accrue interest to a open deposit position. +* **Compound Step** (seconds)\ + How often will the interest be paid/compound. If set to '0', a different yield rate calculation is used and the interest rate will be applied linearly until the end of the term. +* **Yield Rate** (1 unit = 0.01%)\ + How much interest will be paid out. For compounding interest, this means at every compound interval, while the linear rate will reach this rate at the end of the term. +* **Minimum Deposit**\ + Minimum amount accepted for a deposit. +* **Penalty Rate** (1 unit = 0.01%)\ + If a user accepts the early withdraw, before the term is finished, this penalty rate will be applied to the earned interest. \ + \ + E.g. _A 200 units position (100 deposit + 100 earned yield) withdrawing early with a penalty rate of 50% will receive 150 units(100 deposit + 50 earned yield)_ + +$$ +Withdrawn Amount=Deposit+(Yield−Penalty Rate×Yield) +$$ + +* **Allowance Period** (Expiration ledger number)\ + Until which ledger will the allowance for the contract to access the admin funds be valid. +{% endhint %} + + + +This class provides a structured and convenient way to interact with the Certificate of Deposit contract on the Stellar network, encapsulating complex contract interactions into simpler method calls. diff --git a/docs/reference/contracts/contract-engine.md b/docs/reference/contracts/contract-engine.md index d40988b..84dd659 100644 --- a/docs/reference/contracts/contract-engine.md +++ b/docs/reference/contracts/contract-engine.md @@ -6,11 +6,21 @@ The `ContractEngine` class serves as a base for building clients that interact w * **Parameters**: * `network`: The network configuration for the Stellar blockchain. - * `rpcHandler`: The RPC handler for interacting with the Stellar network. When not provided, will connect directly to the RPC url set in the network configuration. - * `spec`: A `ContractSpec` object detailing the contract's specifications. - * `contractId`: A string representing the unique identifier of the deployed contract. - -## Methods + * `rpcHandler`: Optional. Interacts with the Stellar network; defaults to RPC URL in network config. + * `spec`: ContractSpec detailing contract specifications. + * `contractId`: Optional. Unique identifier of the deployed contract. + * `wasm`: Optional. Buffer of the loaded wasm file with compiled contract code. + * `wasmHash`: Optional. Hash of the deployed wasm code. + +{% hint style="info" %} +You can initialize a contract engine or child client contract in different ways. Since the contract id, wasm and wasm hash are all optional, choose whichever initialization is best for your use case.\ +\ +When executing the methods, a validation will take place to throw an error in case a requirement is not met.\ +\ +E.g. Attempting to deploy a contract instance without having a wasmHash. It would've been necessary to either initiate the instance with this argument or, to have performed a `uploadWasm` so that the wasm hash would've been updated in the instance. +{% endhint %} + +## Core Methods ### readFromContract @@ -31,6 +41,37 @@ The `ContractEngine` class serves as a base for building clients that interact w * `feeBump`: Optional `FeeBumpHeader` for fee bumping. * **Returns**: The output of the contract invocation after the transaction is processed. + + +## **Meta Management Methods** + +These methods in the ContractEngine facilitate the necessary steps for contract preparation and deployment, ensuring efficient and accurate interaction with the Soroban network. + +#### **uploadWasm** + +* **Purpose**: To upload the contract wasm to the network and update the wasm hash in the contract engine. +* **Parameters**: + * `wasm`: The wasm file buffer. + * `header`: The header for the transaction. + * `signers`: The signers for the transaction. + * `feeBump`: Optional fee bump header. +* **Returns**: No direct return. Updates wasm hash in the engine. +* **Usage**: Used for uploading wasm files to the Soroban server, necessary for contract deployment. + +#### **deploy** + +* **Purpose**: Deploys a new contract instance to the network and updates the contract ID in the engine. +* **Parameters**: + * `wasmHash`: The wasm hash of the contract to be deployed. + * `header`: The header for the transaction. + * `signers`: The signers for the transaction. + * `feeBump`: Optional fee bump header. +* **Returns**: No direct return. Updates contract ID in the engine. +* **Usage**: Critical for deploying contracts to the Soroban network, enabling interactions with the contract instance. + +\ + + ## Example Usage The `CertificateOfDepositClient` class (See [certificate-of-deposit-client.md](certificate-of-deposit-client.md "mention")) is an example of how to extend the `ContractEngine` class to interact with a specific smart contract. This client showcases the implementation of methods that utilize both `readFromContract` and `invokeContract` functionalities provided by `ContractEngine`. diff --git a/docs/reference/core/channel-accounts-transaction-submitter.md b/docs/reference/core/channel-accounts-transaction-submitter.md index 329aec7..2311079 100644 --- a/docs/reference/core/channel-accounts-transaction-submitter.md +++ b/docs/reference/core/channel-accounts-transaction-submitter.md @@ -1,2 +1,99 @@ # Channel Accounts Transaction Submitter +### ChannelAccountsTransactionSubmitter Class Overview + +The `ChannelAccountsTransactionSubmitter` class, implementing the `TransactionSubmitter` interface, is specifically designed for submitting transactions using a pool of channel accounts. This class is vital in scenarios where high transaction throughput is required on the Stellar network. It manages multiple channel accounts to parallelize transaction submissions, optimizing network interactions and reducing potential sequence errors. \ +\ +For more in-depth information refer to Stellar's official documentation on [Channel Accounts](https://developers.stellar.org/docs/encyclopedia/channel-accounts). + + + +{% hint style="info" %} +See the [bulk-payments.md](../../tutorials/bulk-payments.md "mention") tutorial on how this class can be utilized to perform several payments in parallel +{% endhint %} + +### Core Functionalities + +* #### Constructor + + * **Parameters**: + * `network`: Configuration for the Stellar network. + * `feeBump` (optional): Details for fee bumping transactions.\ + + + #### registerChannels + + * **Purpose**: Adds channel accounts to the pool for transaction processing. + * **Parameters**: `channels` (Array of `DefaultAccountHandler`).\ + + + #### createEnvelope + + * **Purpose**: Creates a transaction envelope using a channel account. + * **Parameters**: `txInvocation` (TransactionInvocation). + * **Returns**: Object containing `TransactionBuilder` and updated transaction invocation.\ + + + #### submit + + * **Purpose**: Submits a transaction to the Stellar network. + * **Parameters**: `envelope` (Transaction or FeeBumpTransaction). + * **Returns**: Response from the Horizon server.\ + + + #### postProcessTransaction + + * **Purpose**: Handles the response after transaction submission. + * **Parameters**: `response` (HorizonNamespace.SubmitTransactionResponse). + * **Returns**: Processed transaction data or error on failure.\ + + + #### noChannelPipeline + + * **Purpose**: Provides a fallback mechanism when no free channel is available. + * **Returns**: Allocated `DefaultAccountHandler` after a waiting period.\ + + + #### getChannels + + * **Purpose**: Retrieves the list of registered channel accounts. + * **Returns**: Array of `DefaultAccountHandler`.\ + + + The `ChannelAccountsTransactionSubmitter` plays a critical role in the transaction processing pipeline, especially when handling high volumes of transactions. It ensures efficient transaction submission by utilizing channel accounts, and it manages the allocation and release of these accounts to optimize network throughput. + +### How to use + +1. **Create TransactionSubmitter Instance**: Instantiate the `ChannelAccountsTransactionSubmitter` with the Stellar network configuration and optional fee bump settings. + + {% code overflow="wrap" %} + ```typescript + const transactionSubmitter = new + StellarPlus.Core.Classic.ChannelAccountsTransactionSubmitter(network, + defaultFeeBump); + ``` + {% endcode %} +2. **Register Channel Accounts**: Initialize and register channel accounts for transaction processing. This step is crucial for handling high-frequency transactions. + + {% code overflow="wrap" %} + ```typescript + await transactionSubmitter.registerChannels( + await StellarPlus.Utils.ChannelAccountsHandler.openChannels({ + /* ... */ }) + ); + ``` + {% endcode %} +3. **Use the Submitter:** Provide the submitter to a Soroban class that extends the [soroban-transaction-processor.md](soroban-transaction-processor.md "mention") and accepts a Submitter instance. All transactions processed by this instance will make use of the channel accounts. + + {% code overflow="wrap" %} + ```typescript + const cakeToken = new StellarPlus.Asset.ClassicAssetHandler( + "CAKE", + issuerAccount.getPublicKey(), + network, + issuerAccount, + transactionSubmitter + ); + + ``` + {% endcode %} diff --git a/docs/reference/core/soroban-transaction-processor.md b/docs/reference/core/soroban-transaction-processor.md index 4317a10..027972a 100644 --- a/docs/reference/core/soroban-transaction-processor.md +++ b/docs/reference/core/soroban-transaction-processor.md @@ -1,46 +1,50 @@ # Soroban Transaction Processor -The `SorobanTransactionProcessor` extends the `TransactionProcessor` class to incorporate the Soroban pipeline, focusing on building and processing transactions specifically for smart contracts on the Stellar network. This class handles the complexities of interacting with the Soroban environment, offering a streamlined approach to transaction handling. +The `SorobanTransactionProcessor` extends the `TransactionProcessor` class, specifically catering to Soroban transactions in the Stellar network. This class manages the intricacies of Soroban transaction handling, encompassing construction, simulation, preparation, and submission. -### Constructor +## Core Functionalities + +### **constructor** * **Parameters**: * `network`: The Stellar network configuration. * `rpcHandler` (optional): The RPC handler for Soroban transactions. If not provided, the default handler is used. -### Core Functionalities -#### buildTransaction -* **Purpose**: Constructs a Soroban transaction based on smart contract invocation parameters. +### buildTransaction + +(protected) + +* **Purpose**: Construct a Soroban transaction based on smart contract invocation parameters. * **Parameters**: * `args`(SorobanSimulateArgs): Includes the method, arguments, and header for the transaction. * `spec`: Contract specification. * `contractId`: The identifier of the contract. * **Returns**: A prepared `SorobanTransaction`. -#### simulateTransaction +### simulateTransaction * **Purpose**: Simulates the execution of a transaction in the Soroban environment. * **Parameters**: * `tx`: The `SorobanTransaction` to be simulated. * **Returns**: Simulation response, indicating the predicted outcome. -#### prepareTransaction +### prepareTransaction * **Purpose**: Prepares a Soroban transaction for submission. This step generally performs a `simulateTransaction`, followed by verifying the result, and, assembling the transaction for submission. * **Parameters**: * `tx`: The `SorobanTransaction` to be prepared. * **Returns**: A prepared `SorobanTransaction`. -#### submitSorobanTransaction +### submitSorobanTransaction * **Purpose**: Submits either a standard or fee-bumped Soroban transaction to the network. * **Parameters**: * `tx`: A `SorobanTransaction` or `SorobanFeeBumpTransaction`. * **Returns**: Submission response from the Soroban RPC server. -#### processSorobanTransaction +### processSorobanTransaction * **Purpose**: Processes a Soroban transaction, including signing, optional fee bumping, and submission. It bundles up the final steps once a transaction has been returned from `prepareTransaction` and handles the submission and post-processing of the transaction. * **Parameters**: @@ -49,14 +53,14 @@ The `SorobanTransactionProcessor` extends the `TransactionProcessor` class to in * `feeBump` (optional): Details for fee bumping. * **Returns**: The response after processing the transaction. -#### postProcessSorobanSubmission +### postProcessSorobanSubmission * **Purpose**: Handles the response to a Soroban transaction submission, including waiting for completion. * **Parameters**: * `response`: The initial response from the Soroban RPC server. * **Returns**: The final transaction status after processing. -#### waitForSorobanTransaction +### waitForSorobanTransaction * **Purpose**: Implements a wait mechanism for a transaction's status using exponential backoff. * **Parameters**: @@ -64,7 +68,7 @@ The `SorobanTransactionProcessor` extends the `TransactionProcessor` class to in * `secondsToWait`: Maximum wait time in seconds. * **Returns**: The final status of the transaction. -#### wrapSorobanFeeBump +### wrapSorobanFeeBump * **Purpose**: Wraps a Soroban transaction with a fee bump. * **Parameters**: @@ -72,6 +76,41 @@ The `SorobanTransactionProcessor` extends the `TransactionProcessor` class to in * `feeBump`: The fee bump header details. * **Returns**: A `FeeBumpTransaction`. -### Conclusion +### uploadContractWasm + +* **Purpose**: Uploads a wasm file to the network and returns the wasm hash. +* **Parameters**: + * `args`: `SorobanUploadArgs` containing: + * `wasm`: Buffer of wasm file. + * `header`: EnvelopeHeader. + * `signers`: AccountHandler\[]. + * `feeBump`: FeeBumpHeader, optional. +* **Returns**: `Promise` - The wasm hash of the uploaded file. + +### deployContract + +* **Purpose**: Deploys a new instance of a contract to the Soroban server. +* **Parameters**: + * `args`: `SorobanDeployArgs` containing: + * `wasmHash`: Wasm hash(string) of the contract to be deployed. + * `header`: EnvelopeHeader. + * `signers`: AccountHandler\[]. + * `feeBump`: FeeBumpHeader, optional. +* **Returns**: `Promise` - The contract ID of the deployed instance. + +### **wrapClassicAsset** + +* **Purpose**: Wraps a classic asset on the Stellar network and returns the address of the wrapped asset contract. +* **Parameters**: + * `args`: `WrapClassicAssetArgs` containing: + * `asset`: The classic asset to wrap. + * `header`: `EnvelopeHeader`. + * `signers`: Array of `AccountHandler[]`. + * `feeBump`: Optional `FeeBumpHeader`. +* **Returns**: `Promise` - The address of the wrapped asset contract. + +These methods extend the `SorobanTransactionProcessor` capabilities, allowing for direct interaction with wasm files and contract deployment on the Soroban platform. + +## Conclusion The `SorobanTransactionProcessor` class facilitates the handling of smart contract transactions in the Soroban environment, simplifying the complexities of transaction construction, simulation, and submission. This class is vital for developers working with Soroban smart contracts on the Stellar network, providing an efficient and structured approach to transaction processing. diff --git a/docs/reference/horizon-handler.md b/docs/reference/horizon-handler.md index c0016a8..8a737ea 100644 --- a/docs/reference/horizon-handler.md +++ b/docs/reference/horizon-handler.md @@ -1,2 +1,3 @@ # Horizon Handler +Coming Soon diff --git a/docs/reference/rpc/default-rpc-handler.md b/docs/reference/rpc/default-rpc-handler.md index 1aaf93a..d6a0c35 100644 --- a/docs/reference/rpc/default-rpc-handler.md +++ b/docs/reference/rpc/default-rpc-handler.md @@ -1,2 +1,3 @@ # Default RPC Handler +The `DefaultRpcHandler` class in Stellar's Soroban environment is designed for direct interactions with the Soroban RPC server. It's the default handler used for RPC functions when no custom handler is provided. This class handles key operations like retrieving transaction information, simulating and preparing transactions, and submitting them to the network. Its default usage ensures a standard, efficient way to communicate with the Soroban server, crucial for transaction management in Stellar's Soroban smart contracts framework. diff --git a/docs/reference/rpc/validation-cloud-rpc-handler.md b/docs/reference/rpc/validation-cloud-rpc-handler.md index 205f58e..cf2dbd3 100644 --- a/docs/reference/rpc/validation-cloud-rpc-handler.md +++ b/docs/reference/rpc/validation-cloud-rpc-handler.md @@ -1,2 +1,7 @@ # Validation Cloud RPC Handler +The `ValidationCloudRpcHandler` serves as an alternative for interacting with Stellar's Soroban smart contracts through a third-party RPC service provided by [Validation Cloud](https://www.validationcloud.io/). + +By default, when no handler is provided, the core engines will use the [default-rpc-handler.md](default-rpc-handler.md "mention") and connect to the network's RPC url. With this class, developers can switch to using Validation Cloud's infrastructure. This is particularly advantageous for those seeking a ready-to-use integration with dedicated infrastructure and advanced features. + +To use this service, developers simply need to create an account with Validation Cloud, opt for their free tier, and generate an API key for their Soroban API, streamlining the process of managing and executing smart contracts on Stellar. diff --git a/docs/reference/soroban-handler.md b/docs/reference/soroban-handler.md index 0aaa103..19c5d55 100644 --- a/docs/reference/soroban-handler.md +++ b/docs/reference/soroban-handler.md @@ -1,2 +1,3 @@ # Soroban Handler +Coming Soon diff --git a/docs/tutorials/bulk-payments.md b/docs/tutorials/bulk-payments.md index c0de180..7859acb 100644 --- a/docs/tutorials/bulk-payments.md +++ b/docs/tutorials/bulk-payments.md @@ -57,7 +57,7 @@ const transactionSubmitter = ); await transactionSubmitter.registerChannels( - await StellarPlus.Core.Classic.ChannelAccountsHandler.initializeNewChannels( + await StellarPlus.Utils.ChannelAccountsHandler.openChannels( { numberOfChannels: 15, sponsor: opex, @@ -248,7 +248,7 @@ const run = async () => { console.log("Initializing Channel Accounts"); await transactionSubmitter.registerChannels( - await StellarPlus.Core.Classic.ChannelAccountsHandler.initializeNewChannels( + await StellarPlus.Utils.ChannelAccountsHandler.openChannels( { numberOfChannels: 15, sponsor: opex, diff --git a/docs/tutorials/e2e-certificate-of-deposit-demo.md b/docs/tutorials/e2e-certificate-of-deposit-demo.md new file mode 100644 index 0000000..97e6bc4 --- /dev/null +++ b/docs/tutorials/e2e-certificate-of-deposit-demo.md @@ -0,0 +1,470 @@ +# E2E Certificate of Deposit demo + +In this tutorial, we'll demonstrate an end-to-end approach to deploy and interact with a certificate of deposit contract. This demo covers several steps such as configuring the necessary accounts, deploying and initializing the contract, up to interact as an end-user investing in the CD. + +## Prerequisites + +* **Basic Understanding of Stellar Concepts**: Familiarize yourself with Stellar network fundamentals, including assets, accounts, trustlines, and transactions. For more in-depth information, refer to [Stellar's official documentation](https://developers.stellar.org/docs). +* **Basic understanding of Stellar's Soroban:** Familiarize yourself with Soroban and how smart contracts integrate with the Stellar network. For more in-depth information refer to [Soroban's official documentation](https://soroban.stellar.org/docs). +* **Node.js Environment**: Set up a Node.js environment to run your JavaScript code. +* **StellarPlus Library**: Ensure that the StellarPlus library is installed in your project. For the installation steps, refer to [quick-start.md](../quick-start.md "mention"). + +## Objectives + +Our target with this demo is to exemplify a direct workflow to how the Stellar Plus library might assist in different parts of developing a Stellar solution. Here we'll focus on few key objectives: + +**Core** + +1. Upload a wasm file of the compiled Certificate of Deposit smart contract; +2. Deploy a new instance of this contract and initialize it with custom parameters; +3. Creating and wrapping a Stellar classic asset into a 'Stellar Asset Contract''; +4. Simulate a user account performing a deposit and opening a position; +5. Watching the interest rate being applied to the user position; +6. Withdrawing before the end term and facing the penalty; + +**Secondary** + +7. Create and fund the asset issuer account; +8. Create, set up and fund account to manage the contract; +9. Create, set up and fund account to simulate the User; +10. Create an Opex (operational expenditure) account to cover all of the transaction fees in the demo; + +**Bonus** + +11. Use a third-party RPC ([Validation Cloud](https://www.validationcloud.io/)) + +## Step-by-Step Guide + +### Initial Setup + +#### Step 1: Creating the Opex account + +In this first step, we'll start by defining which network we'll be operating in this demo, which for now is the `testnet`. Then we'll start a new account handler to manage the Opex account and initialize it with friendbot.\ +\ +Once the account is fully created and funded, we'll then creat a `TransactionInvocation` object for transactions made by the Opex account. This object will also be used to define the Fee Bump strategy for the subsequent transactions processed. + +{% code lineNumbers="true" %} +```typescript +const network = StellarPlus.Constants.testnet + +const opex = new StellarPlus.Account.DefaultAccountHandler({ + network, +}) +await opex.friendbot?.initialize() + +const opexTxInvocation = { + header: { + source: opex.getPublicKey(), + fee: '10000000', //1 XLM as maximum fee + timeout: 30, + }, + signers: [opex], +} +``` +{% endcode %} + +#### Step 2: Creating and Wrapping an Asset + +Here we also initialize a new account handler to manage the asset issuer account, then we initialize a new asset using the SACHandler(Stellar Asset Contract) which allows use to perform both Classic and Soroban actions for this asset.\ +\ +At the end, we wrap this Stellar classic asset into a default asset contract so it can interact directly with smart contracts. + +{% code lineNumbers="true" %} +```typescript +const issuer = new StellarPlus.Account.DefaultAccountHandler({ network }) +await issuer.friendbot?.initialize() + +const cakeToken = new StellarPlus.Asset.SACHandler({ + code: 'CAKE', + issuerPublicKey: issuer.getPublicKey(), + network, + issuerAccount: issuer, +}) + +await cakeToken.wrapAndDeploy(opexTxInvocation) +``` +{% endcode %} + +#### Step 3: Create a vault to manage the CD contract and the funds + +Similarly to the other accounts, we initiate a new account called `codVault`, which will act as the CD admin and also manage the funds from the deposits and withdrawals.\ +\ +After the account initialization, we use the asset handler to add a trustline and mint some token units directly to the vault. This asset management function is available because the issuer account handler was provided during the asset initialization. + +```typescript +const codVault = new StellarPlus.Account.DefaultAccountHandler({ network }) +await codVault.friendbot?.initialize() + +const codTxInvocation = { + header: { + source: codVault.getPublicKey(), + fee: '1000000', //0.1 XLM as maximum fee + timeout: 30, + }, + signers: [codVault], + feeBump: opexTxInvocation, +} + +await cakeToken.classicHandler.addTrustlineAndMint(codVault.getPublicKey(), 10000000, codTxInvocation) +``` + +A key element in this step is the definition of a 'Transaction Invocation' object for the vault account, which uses the vault account as the source and also introduces the vault as a signer. The Opex transaction invocation object is introduced here as a feeBump in this case, ensuring that all codVault invocations are covered by the Opex account.\ +\ +Another important highlight is that while the `codTxInvocation` object will ensure the vault is signing to authorize the trustline creation, the asset itself will be responsible for including the issuer account and signature to authorize the minting. + + + +### Creating a Certificate of Deposit dApp + +#### Step 4: Uploading and deploy an instance of the contract code + +Here, we start by loading the compiled wasm file from a local folder. You can use the following file in your demo. + +{% file src="../.gitbook/assets/certificates_of_deposit.optimized.wasm" %} +Compiled WASM for the Certificate of Deposit contract +{% endfile %} + +Once the file is loaded into a buffer, we initialize the CD client with the wasm buffer and upload it to the Stellar network. This will provide us with a unique wasm hash that identifies this code and can be used to deploy instances of this implementation on chain. This attribute is automatically stored in the client object for future usage. + +{% code lineNumbers="true" %} +```typescript +const wasmFilePath = './src/wasm-files/certificates_of_deposit.optimized.wasm' +const wasmBuffer = await loadWasmFile(wasmFilePath) + +const codClient = new StellarPlus.Contracts.CertificateOfDeposit({ + network, + wasm: wasmBuffer, +}) + +await codClient.uploadWasm(codTxInvocation) + +await codClient.deploy(codTxInvocation) +``` +{% endcode %} + +Right after, a deploy is triggered then, instaciating a new contract and getting a unique contract id to interact with this new certificate of deposit dApp. + +{% hint style="info" %} +In this step, we make use of a complimentary function to load the wasm file and return a buffer. The function is the following one: + +{% code lineNumbers="true" fullWidth="false" %} +```typescript +async function loadWasmFile(wasmFilePath: string): Promise { + try { + const buffer = await readFile(wasmFilePath) + return buffer + } catch (error) { + throw error + } +} +``` +{% endcode %} +{% endhint %} + +#### Step 5: Initialize the CD Contract + +Now that we have a fresh new instance of the contract, we need to initialize its state with the parameters to how this contract will operate. For this we first use a sorobanHandler to load the latest ledger sequence and set a future expiration ledger for the allowance that enables the contract to move the codVault's funds. + +Then, we set the main parameters expected by the contract initialization. These parameters define the following characteristics for this instance of the CD:\ + + +* **Admin**: codVault\ + Defines which account can manage the CD contract and also receives and provides the funds from/to the users. +* **Asset**: cakeToken's contract id\ + The contract id of the Stellar Asset Contract for the wrapped Classic Asset this CD interacts with. +* **Term**: 600 seconds\ + For how long this CD will accrue interest to a open deposit position. +* **Compound Step:** 4 seconds\ + How often will the interest be paid/compound. If set to '0', a different yield rate calculation is used and the interest rate will be applied linearly until the end of the term. +* **Yield Rate**: 15 (0.15%)\ + How much interest will be paid out. For compounding interest, this means at every compound interval, while the linear rate will reach this rate at the end of the term. +* **Minimum Deposit**: 100 units\ + Minimum amount accepted for a deposit. +* **Penalty Rate**: 5000 (50%)\ + If a user accepts the early withdraw, before the term is finished, this penalty rate will be applied to the earned interest. E.g. _A 200 units position (100 deposit + 100 earned yield) withdrawing early with a penalty rate of 50% will receive 150 units(100 deposit + 50 earned yield)_ + +$$ +Withdrawn Amount=Deposit+(Yield−Penalty Rate×Yield) +$$ + +* **Allowance Period**: Latest ledger + 200.000\ + Until which ledger will the allowance for the contract to access the codVault's funds be valid. + +{% code overflow="wrap" lineNumbers="true" %} +```typescript +const sorobanHandler = new StellarPlus.SorobanHandler(network) +const expirationLedger = (await sorobanHandler.server.getLatestLedger()).sequence + 200000 + +const codParams = { + admin: codVault.getPublicKey(), + asset: cakeToken.getContractId(), + term: BigInt(600) as bigint, + compoundStep: BigInt(4) as bigint, + yieldRate: BigInt(15) as bigint, + minDeposit: BigInt(100 * 10 ** 7) as bigint, + penaltyRate: BigInt(5000) as bigint, + allowancePeriod: expirationLedger, +} + +await codClient.initialize({ ...codParams, ...codTxInvocation }) +``` +{% endcode %} + +### User interacts with the contract + +#### Step 6: Setup a user account + +Just as we did before, we initialize user account and set up the necessary trustline and 'Transaction Invocation' object.\ + + +{% code overflow="wrap" lineNumbers="true" %} +```typescript +const userAccount = new StellarPlus.Account.DefaultAccountHandler({ network }) +await userAccount.friendbot?.initialize() + +const userTxInvocation = { + header: { + source: userAccount.getPublicKey(), + fee: '1000000', //0.1 XLM as maximum fee + timeout: 30, + }, + signers: [userAccount], + feeBump: opexTxInvocation, +} + +console.log('Depositing 10000 CAKE tokens to user account...') +await cakeToken.classicHandler.addTrustlineAndMint(userAccount.getPublicKey(), 10000000, userTxInvocation) +``` +{% endcode %} + +#### Step 7: Deposit and check open position + +The user then performs a deposit of 1000 CAKEs and right after, checks their open position in the CD. + +{% code overflow="wrap" lineNumbers="true" %} +```typescript +await codClient.deposit({ + address: userAccount.getPublicKey(), + amount: BigInt(1000 * 10 ** 7) as bigint, + ...userTxInvocation, +}) + +console.log( + 'User position in the certificate of deposit: ', + (await codClient.getPosition({ address: userAccount.getPublicKey(), ...userTxInvocation })) / + 10 ** (await cakeToken.decimals()) +) +``` +{% endcode %} + +#### Step 8: Wait a few seconds and withdraws + +After enough time is passed, we check the estimated yield that has accrued in the CD and perform an early withdrawal by accepting the penalty. + +{% code overflow="wrap" lineNumbers="true" %} +```typescript +setTimeout(async () => { + console.log( + 'User has earned and estimated yield of:', + (await codClient.getEstimatedYield({ address: userAccount.getPublicKey(), ...userTxInvocation })) / + 10 ** (await cakeToken.decimals()) + ) + + console.log('User withdraws from Certificate of Deposit vault (with early withdrawal penalty)...') + await codClient.withdraw({ + address: userAccount.getPublicKey(), + acceptPrematureWithdraw: true, + ...userTxInvocation, + }) +``` +{% endcode %} + +### Bonus + +#### Step 9: Use Validation Cloud's RPC + +For this step just as a fun bonus, instead of using SDF's testnet RPC, we'll instead switch to the ready-to-use integration with [Validation Cloud](https://www.validationcloud.io/). For this, you just need to create an account under their free tier and generate an API key for their Soroban API. + +With your own key, we'll just go back to Step 4 and make some slight changes. We'll initialize a custom Validation Cloud RPC handler providing our API key. Then we just need to provide this handler and optional argument when initializing our CD client.\ +\ +Since the CD client extends the [contract-engine.md](../reference/contracts/contract-engine.md "mention"), it'll automatically ensure this handler is used to perform all direct interactions with the RPC such as simulating and submitting transactions. + +{% code overflow="wrap" lineNumbers="true" %} +```typescript +const wasmFilePath = './src/wasm-files/certificates_of_deposit.optimized.wasm' +const wasmBuffer = await loadWasmFile(wasmFilePath) + +const vcRpcHandler = new StellarPlus.RPC.ValidationCloudRpcHandler( + network, + '' +) + +const codClient = new StellarPlus.Contracts.CertificateOfDeposit({ + network, + wasm: wasmBuffer, + rpcHandler: vcRpcHandler, +}) +``` +{% endcode %} + +### Complete Example + +Below is the complete code snippet, incorporating all the steps previously outlined and adding a few logging lines to visualize each step as it is executed. This example is structured within a single asynchronous function to accommodate the multiple asynchronous operations involved. By doing so, we can effectively use `await` for each step, ensuring that each operation is executed in a sequential and organized manner. + + + +{% code overflow="wrap" lineNumbers="true" %} +```typescript +import { readFile } from 'fs/promises' +import { StellarPlus } from './' + +async function loadWasmFile(wasmFilePath: string): Promise { + try { + const buffer = await readFile(wasmFilePath) + return buffer + } catch (error) { + throw error + } +} + +const run = async (): Promise => { + const network = StellarPlus.Constants.testnet + + console.log('Initializing opex account...') + const opex = new StellarPlus.Account.DefaultAccountHandler({ + network, + }) + await opex.friendbot?.initialize() + + const opexTxInvocation = { + header: { + source: opex.getPublicKey(), + fee: '10000000', //1 XLM as maximum fee + timeout: 30, + }, + signers: [opex], + } + + const issuer = new StellarPlus.Account.DefaultAccountHandler({ network }) + console.log('Initializing issuer account... ', issuer.getPublicKey()) + await issuer.friendbot?.initialize() + + const cakeToken = new StellarPlus.Asset.SACHandler({ + code: 'CAKE', + issuerPublicKey: issuer.getPublicKey(), + network, + issuerAccount: issuer, + }) + console.log('Wrapping Asset in SAC...') + const wrappedAssetContractId = await cakeToken.wrapAndDeploy(opexTxInvocation) + console.log('Wrapped Asset Contract ID: ', wrappedAssetContractId) + + console.log('Initializing Certificate of Deposit vault account...') + const codVault = new StellarPlus.Account.DefaultAccountHandler({ network }) + await codVault.friendbot?.initialize() + + const codTxInvocation = { + header: { + source: codVault.getPublicKey(), + fee: '1000000', //0.1 XLM as maximum fee + timeout: 30, + }, + signers: [codVault], + feeBump: opexTxInvocation, + } + + console.log('Adding trustline and tokens to Certificate of Deposit vault...') + await cakeToken.classicHandler.addTrustlineAndMint(codVault.getPublicKey(), 10000000, codTxInvocation) + + console.log('Vault Balance:', await cakeToken.classicHandler.balance(codVault.getPublicKey())) + + console.log('Loading Wasm file...') + const wasmFilePath = './src/wasm-files/certificates_of_deposit.optimized.wasm' + const wasmBuffer = await loadWasmFile(wasmFilePath) + + const vcRpcHandler = new StellarPlus.RPC.ValidationCloudRpcHandler( + network, + '' + ) + + const codClient = new StellarPlus.Contracts.CertificateOfDeposit({ + network, + wasm: wasmBuffer, + rpcHandler: vcRpcHandler, + }) + + console.log('Uploading wasm to network...') + await codClient.uploadWasm(codTxInvocation) + + console.log('Deploying new instance of contract...') + await codClient.deploy(codTxInvocation) + + const sorobanHandler = new StellarPlus.SorobanHandler(network) + const expirationLedger = (await sorobanHandler.server.getLatestLedger()).sequence + 200000 + + const codParams = { + admin: codVault.getPublicKey(), + asset: cakeToken.getContractId(), + term: BigInt(600) as bigint, + compoundStep: BigInt(4) as bigint, + yieldRate: BigInt(15) as bigint, + minDeposit: BigInt(100 * 10 ** 7) as bigint, + penaltyRate: BigInt(5000) as bigint, + allowancePeriod: expirationLedger, + } + + console.log("initializing contract's state...") + await codClient.initialize({ ...codParams, ...codTxInvocation }) + + console.log('Crreating user account...') + const userAccount = new StellarPlus.Account.DefaultAccountHandler({ network }) + await userAccount.friendbot?.initialize() + + const userTxInvocation = { + header: { + source: userAccount.getPublicKey(), + fee: '1000000', //0.1 XLM as maximum fee + timeout: 30, + }, + signers: [userAccount], + feeBump: opexTxInvocation, + } + + console.log('Depositing 10000 CAKE tokens to user account...') + await cakeToken.classicHandler.addTrustlineAndMint(userAccount.getPublicKey(), 10000000, userTxInvocation) + + console.log('User Balance(CAKE):', await cakeToken.classicHandler.balance(userAccount.getPublicKey())) + + console.log('User Deposits 1000 CAKE tokens to Certificate of Deposit vault...') + await codClient.deposit({ + address: userAccount.getPublicKey(), + amount: BigInt(1000 * 10 ** 7) as bigint, + ...userTxInvocation, + }) + + console.log('User position in the certificate of deposit: ', + (await codClient.getPosition({ address: userAccount.getPublicKey(), ...userTxInvocation })) / + 10 ** (await cakeToken.decimals()) + ) + + console.log('Waiting 5 seconds...') + setTimeout(async () => { + console.log( + 'User has earned and estimated yield of:', + (await codClient.getEstimatedYield({ address: userAccount.getPublicKey(), ...userTxInvocation })) / + 10 ** (await cakeToken.decimals()) + ) + console.log('User withdraws from Certificate of Deposit vault (with early withdrawal penalty)...') + await codClient.withdraw({ + address: userAccount.getPublicKey(), + acceptPrematureWithdraw: true, + ...userTxInvocation, + }) + + console.log('User Balance(CAKE):', await cakeToken.classicHandler.balance(userAccount.getPublicKey())) + }, 10000) +} +run() +``` +{% endcode %} +