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 filex/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 filex/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.
-
Implementing the
RegisterPatient
Function in the Keeper: In the filex/registration/keeper/keeper.go
, theRegisterPatient
function was added:
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 theapp/app.go
file, theregistration
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