User Registration and Wallet Creation for Patients on the Experience Blockchain

User Registration and Wallet Creation for Patients on the Experience Blockchain post thumbnail image

The Experience blockchain is designed to provide a secure and decentralized platform for managing transactions and therapeutic services. A key feature of this platform is the user registration process and the simultaneous creation of a digital wallet. This post describes in detail how patient registration and wallet creation work on the Experience blockchain using Cosmos SDK.

What is the Experience Blockchain?

Experience is a customized blockchain developed using the Cosmos SDK, designed to manage transactions and therapeutic services. It features specific modules for user registration, $EXP token management, and therapy sessions. One of the fundamental aspects of Experience is the ability to automatically create a wallet for each patient who registers on the platform, ensuring secure and decentralized access to services.

Patient Registration and Wallet Creation Process

The registration process on the Experience platform is designed to be intuitive and secure. Each time a patient registers on the platform, a digital wallet associated with their account is automatically created. Here’s how the process works:

1. Creating the Patient Registration Module

The registration module (registration) is responsible for managing patient registration and creating their wallets. This module was developed using the Cosmos SDK and includes all the functions necessary to register new users on the blockchain.

  • Scaffolding the Registration Module: To start, a registration module was created using Starport:
  starport scaffold module registration

This command creates the basic structure for the registration module within the Experience blockchain project.

2. Defining the Registration Message

Within the registration module, a message (Msg) was defined to handle the action of registering a new patient. This message contains the data needed to create a new user account and its wallet.

  • Defining the MsgRegisterPatient Message: The file x/registration/types/msgs.go includes the following code to define the registration message:
  package types

  import (
      sdk "github.com/cosmos/cosmos-sdk/types"
  )

  const (
      TypeMsgRegisterPatient = "register_patient"
  )

  // MsgRegisterPatient defines a message for registering a new patient
  type MsgRegisterPatient struct {
      Creator sdk.AccAddress `json:"creator" yaml:"creator"`
      Name    string         `json:"name" yaml:"name"`
      Email   string         `json:"email" yaml:"email"`
  }

  // NewMsgRegisterPatient creates a new instance of MsgRegisterPatient
  func NewMsgRegisterPatient(creator sdk.AccAddress, name string, email string) *MsgRegisterPatient {
      return &MsgRegisterPatient{
          Creator: creator,
          Name:    name,
          Email:   email,
      }
  }

  // Implementations of Msg functions required by Cosmos SDK
  func (msg *MsgRegisterPatient) Route() string { return RouterKey }
  func (msg *MsgRegisterPatient) Type() string  { return TypeMsgRegisterPatient }
  func (msg *MsgRegisterPatient) GetSigners() []sdk.AccAddress {
      return []sdk.AccAddress{msg.Creator}
  }
  func (msg *MsgRegisterPatient) GetSignBytes() []byte {
      bz := ModuleCdc.MustMarshalJSON(msg)
      return sdk.MustSortJSON(bz)
  }
  func (msg *MsgRegisterPatient) ValidateBasic() error {
      if msg.Creator.Empty() {
          return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "creator can't be empty")
      }
      if len(msg.Name) == 0 {
          return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "name can't be empty")
      }
      if len(msg.Email) == 0 {
          return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "email can't be empty")
      }
      return nil
  }

This message (MsgRegisterPatient) includes fields such as the patient’s name, email, and creator address (creator).

3. Implementing the Registration Handler

The handler is the function that processes the registration message, creating a new user account and an associated wallet.

  • Creating the handleMsgRegisterPatient Handler: In the file x/registration/handler.go, the following code was added for the handler:
  package registration

  import (
      "github.com/cosmos/cosmos-sdk/types"
      "github.com/cosmos/cosmos-sdk/types/sdkerrors"

      "github.com/your_username/experience/x/registration/types"
  )

  // NewHandler creates a new handler for the patient registration module
  func NewHandler(k Keeper) types.Handler {
      return func(ctx types.Context, msg types.Msg) (*types.Result, error) {
          switch msg := msg.(type) {
          case *types.MsgRegisterPatient:
              return handleMsgRegisterPatient(ctx, k, msg)
          default:
              return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unrecognized registration message type")
          }
      }
  }

  // handleMsgRegisterPatient handles the patient registration message
  func handleMsgRegisterPatient(ctx types.Context, k Keeper, msg *types.MsgRegisterPatient) (*types.Result, error) {
      // Create the new patient and associated wallet
      if err := k.RegisterPatient(ctx, msg.Creator, msg.Name, msg.Email); err != nil {
          return nil, err
      }

      return &types.Result{Events: ctx.EventManager().Events()}, nil
  }
4. Logic of the Keeper for Registration and Wallet Creation

The Keeper is responsible for the business logic within the module. The RegisterPatient function creates a new user account and an associated wallet.

  package keeper

  import (
      "github.com/cosmos/cosmos-sdk/types"
      "github.com/cosmos/cosmos-sdk/x/auth/types"

      "github.com/your_username/experience/x/registration/types"
  )

  // RegisterPatient registers a new patient and creates a wallet
  func (k Keeper) RegisterPatient(ctx types.Context, creator types.AccAddress, name string, email string) error {
      // Create a new patient account
      acc := k.accountKeeper.NewAccountWithAddress(ctx, creator)

      // Add the account to the account keeper
      k.accountKeeper.SetAccount(ctx, acc)

      // Generate events for logging
      ctx.EventManager().EmitEvents(types.Events{
          types.NewEvent(
              types.EventTypeMessage,
              types.NewAttribute(types.AttributeKeyModule, types.AttributeValueCategory),
              types.NewAttribute(types.AttributeKeySender, creator.String()),
          ),
      })

      return nil
  }

This function creates a new account for the patient using the accountKeeper and adds it to the blockchain context.

5. Integrating the Module into the app.go File

Finally, the app.go file was updated to include the registration module and handle registration transactions and wallet creation.

  • Modifying the app.go File: In the app/app.go file, the registration module was added and initialized:
  package app

  import (
      // Import standard and custom modules
      "github.com/cosmos/cosmos-sdk/baseapp"
      "github.com/cosmos/cosmos-sdk/codec"
      "github.com/cosmos/cosmos-sdk/types/module"
      "github.com/cosmos/cosmos-sdk/x/auth"
      authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
      authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
      bank "github.com/cosmos/cosmos-sdk/x/bank"
      bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
      banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
      registrationmodule "github.com/your_username/experience/x/registration"
      registrationkeeper "github.com/your_username/experience/x/registration/keeper"
      registrationtypes "github.com/your_username/experience/x/registration/types"

      // Necessary imports for logging and database
      "github.com/tendermint/tendermint/libs/log"
      dbm "github.com/tendermint/tm-db"
  )

  const AppName = "ExperienceApp"

  var DefaultNodeHome = os.ExpandEnv("$HOME/.experienceapp")

  type App struct {
      *baseapp.BaseApp
      cdc               *codec.LegacyAmino
      appCodec          codec.Codec
      interfaceRegistry types.InterfaceRegistry

      // Keeper of standard modules
      AccountKeeper authkeeper.AccountKeeper
      BankKeeper    bankkeeper.Keeper

      // Keeper of custom modules
      RegistrationKeeper registrationkeeper.Keeper

      // Modules
      mm *module.Manager
  }

  func NewApp(
      logger log.Logger,
      db dbm.DB,
      traceStore io.Writer,
      loadLatest bool,
      skipUpgradeHeights map[int64]bool,
      homePath string,
      invCheckPeriod uint,
      encodingConfig codec.EncodingConfig,
      appOpts sdk.AppOptions,
      baseAppOptions ...func(*baseapp.BaseApp),
  ) *App {
      appCodec := encodingConfig.Marshaler
      cdc := encodingConfig.Amino
      interfaceRegistry := encodingConfig.InterfaceRegistry

      bApp := baseapp.NewBaseApp(AppName, logger, db, encodingConfig.TxConfig.TxDecoder(), baseAppOptions...)
      bApp.SetCommitMultiStoreTracer(traceStore)
      bApp.SetVersion(version.Version)
      bApp.SetInterfaceRegistry(interfaceRegistry)

      keys := sdk.NewKVStoreKeys(
          authtypes.StoreKey, banktypes.StoreKey, registrationtypes.StoreKey,
      )



      app := &App{
          BaseApp:           bApp,
          cdc:               cdc,
          appCodec:          appCodec,
          interfaceRegistry: interfaceRegistry,
          AccountKeeper:     authkeeper.NewAccountKeeper(appCodec, keys[authtypes.StoreKey], authtypes.ProtoBaseAccount),
          BankKeeper:        bankkeeper.NewBaseKeeper(appCodec, keys[banktypes.StoreKey], app.AccountKeeper),
          RegistrationKeeper: registrationkeeper.NewKeeper(
              appCodec, keys[registrationtypes.StoreKey], app.AccountKeeper,
          ),
      }

      // Module Manager configuration
      app.mm = module.NewManager(
          auth.NewAppModule(appCodec, app.AccountKeeper, nil),
          bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
          registrationmodule.NewAppModule(appCodec, app.RegistrationKeeper),
      )

      // Router configuration for modules
      app.Router().AddRoute(banktypes.ModuleName, bank.NewHandler(app.BankKeeper)).
          AddRoute(registrationtypes.ModuleName, registrationmodule.NewHandler(app.RegistrationKeeper))

      return app
  }


Conclusion

Integrating a registration module on the Experience blockchain allows for the automatic creation of wallets for each patient who registers on the platform. This feature ensures that patients have immediate and secure access to the services and transactions available on the blockchain. Using Cosmos SDK, it is easy to customize modules and functionalities to meet the specific needs of any blockchain application.

Photo by pexels.com

Share
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Related Post