From b3b7229e25e42d10ec76add6a6d86af024ba5275 Mon Sep 17 00:00:00 2001 From: MedovTimur <62596970+MedovTimur@users.noreply.github.com> Date: Tue, 17 Sep 2024 12:44:14 +0300 Subject: [PATCH] New article about migration to sails (#159) Co-authored-by: AndrePanin --- docs/build/sails/migration.md | 154 ++++++++++++++++++++++++++++++++++ yarn.lock | 22 +---- 2 files changed, 157 insertions(+), 19 deletions(-) create mode 100644 docs/build/sails/migration.md diff --git a/docs/build/sails/migration.md b/docs/build/sails/migration.md new file mode 100644 index 0000000..2d61df4 --- /dev/null +++ b/docs/build/sails/migration.md @@ -0,0 +1,154 @@ +--- +sidebar_label: Migration +sidebar_position: 6 +--- + +# Migration of `gstd` programs + +[`Sails`](/docs/build/sails/sails.mdx) is a library for writing applications utilizing the Gear Protocol with simplicity and clarity. This powerful tool represents the next step in the evolution of the Gear Protocol. + +Initially, Gear applications typically employ the less convenient [`gstd`](/docs/build/gstd/gstd.md) library for managing low-level operations and essential functionality. The `Sails` library builds programs on top of `gstd`, handling most low-level interactions under the hood. As projects grow, adopting the `Sails` framework allows developers to shift towards a more modular and service-oriented architecture. Existing dApps written with `gstd` can be effortlessly migrated to `Sails`. + +This guide focuses on the key steps involved in transitioning existing gstd-based code to the `Sails` framework, outlining the necessary code transformations and architectural adjustments while leveraging the underlying `gstd` infrastructure. + +## Setting Up Your Sails Project + +To get started with the migration process, you can use a template to create a new project with Sails. + +- First, install the sails-cli tool using the following command: + + ```bash + cargo install sails-cli + ``` + +- After installation, you can generate a new project named "vara-app" by running: + + ```bash + cargo-sails new-program vara-app + ``` + +## Migrating Action Handling + +- In **gstd**-based projects, actions are typically defined using enums, which are processed within a `handle` function. This function decodes incoming messages and matches them to the corresponding action: + + ```rust + pub enum Action { + DoA, + DoB, + } + + impl Metadata for ProgramMetadata { + type Handle = In; + } + + #[no_mangle] + extern fn handle() { + let action: Action = msg::load().expect("Failed to decode `Action` message."); + match action { + Action::DoA => { /* Implementation for action A */ }, + Action::DoB => { /* Implementation for action B */ }, + } + } + ``` + +- In **`Sails`**, this approach is restructured to leverage the framework’s service-oriented architecture. Rather than processing all actions through a single entry point, each action is encapsulated in its own service method. Here’s how the same functionality would look in `Sails`: + + ```rust + #[service] + impl Service { + pub fn do_a(&mut self) { /* Implementation for action A */ } + pub fn do_b(&mut self) { /* Implementation for action B */ } + } + ``` + +This shift abstracts the message decoding and routing logic, with `Sails` automatically handling the dispatch of incoming messages to the appropriate service methods. The resulting code is more modular, with each action represented as a discrete method. + +## Migrating Reply Messages + +- In the case of low-level use of **`gstd`**, sending a reply message is done manually after the action has been processed. The reply should be sent using the `msg::reply` function: + + ```rust + #[no_mangle] + extern fn handle() { + let action: Action = msg::load().expect("Failed to decode `Action` message."); + match action { + Action::DoA => { + // Implementation for action A + msg::reply(reply, 0).expect("Failed to encode `reply`"); + }, + } + + } + ``` + +- When using **`Sails`**, replies are returned directly from the service function, and the framework manages the encoding and sending of the message: + + ```rust + #[service] + impl Service { + pub fn do_a(&mut self) -> TypeOfReply { + // Implementation for action A + reply + } + } + ``` + +This reduces manual work, as the framework abstracts the reply handling, resulting in more concise code. + +## Migrating State Queries + +- State queries are often implemented through enums, which handle different state requests and responses manually within a `state` function: + + ```rust + pub enum StateQuery { + State1, + State2, + } + + pub enum StateReply { + State1(...), + State2(...), + } + + impl Metadata for ProgramMetadata { + type State = InOut; + } + + #[no_mangle] + extern fn state() { + let query: StateQuery = msg::load().expect("Unable to load the state query"); + match query { + StateQuery::State1 => { + msg::reply(StateReply::State1(state), 0).expect("Unable to share the state"); + }, + StateQuery::State2 => { + msg::reply(StateReply::State2(state), 0).expect("Unable to share the state"); + }, + } + } + ``` + +- When migrating to **`Sails`**, state-related functions are methods that take `&self` as a parameter, since they don’t modify the state but only query it: + + ```rust + #[service] + impl Service { + pub fn state_1(&self) -> TypeOfReply { + // Implementation for State1 + state + } + + pub fn state_2(&self) -> TypeOfReply { + // Implementation for State2 + state + } + } + ``` + +## Conclusion + +Migrating a project from the `gstd` library to the `Sails` framework is a straightforward process that primarily involves adapting the code to a more modular and service-oriented structure. Since `Sails` operates on top of `gstd`, the core functionality remains the same, but the framework provides a more organized and maintainable approach to handling actions, replies, and state queries. + +By following the steps outlined in this guide, you can easily refactor your project to take advantage of the abstractions and efficiency offered by `Sails`. This migration not only simplifies code management but also enhances the long-term scalability. + +With just a few adjustments to your existing codebase, such as reorganizing action handling into service methods and streamlining state queries, your project can seamlessly transition to `Sails` without sacrificing any of the functionality provided by `gstd`. diff --git a/yarn.lock b/yarn.lock index ce94534..68c4220 100644 --- a/yarn.lock +++ b/yarn.lock @@ -390,7 +390,7 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.24.7", "@babel/parser@^7.25.0", "@babel/parser@^7.25.6": +"@babel/parser@^7.25.0", "@babel/parser@^7.25.6": version "7.25.6" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.6.tgz#85660c5ef388cbbf6e3d2a694ee97a38f18afe2f" integrity sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q== @@ -10165,16 +10165,7 @@ std-env@^3.0.1: resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0, string-width@^4.2.0: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -10223,14 +10214,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==