accounts

package module
v0.0.0-...-3ebd7e5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 22, 2024 License: Apache-2.0 Imports: 41 Imported by: 11

README

x/accounts

The x/accounts module enhances the Cosmos SDK by providing tools and infrastructure for creating advanced smart accounts.

Basics

An account can be thought of as a simplified cosmos-sdk module that supports multiple deployments. This means:

  1. A single account implementation can be deployed to multiple addresses, similar to how CosmWasm allows multiple contract instances from one WASM upload.

  2. Each account address is mapped to its corresponding account code.

  3. Accounts maintain their own state partition, similar to modules.

  4. Accounts can define both message and query handlers.

This design allows for flexible and reusable account structures within the ecosystem.

Example account creation
Basic

Defining an account begins with creating a struct that encapsulates the account's state. If the account has no state, the struct is empty type Account struct{}.

By default, accounts utilize collections to manage their state.

State Isolation

It's crucial to understand that an account's state is isolated. This means:

  1. States are not shared between accounts of different types.
  2. States are not shared even between accounts of the same type.

For example, consider two accounts of type Counter:

  • One located at address "cosmos123"
  • Another at address "cosmos456"

These accounts do not share the same collections.Item instance. Instead, each maintains its own separate state.

type Account struct {
 // We will define that the account contains in its state a counter, it's an item.
 // It could also be a map or whatever!
 Counter collections.Item[uint64]
}
Init

Creating an account begins with defining its init message. This message is processed when an account is created, similar to:

  • The instantiate method in a CosmWasm contract
  • The constructor in an EVM contract

For an account to be a valid x/accounts implementer, it must define both:

  1. An Init method
  2. An init message

We start by defining the MsgInit and its corresponding MsgInitResponse as protobuf messages:

message MsgInit {
   uint64 counter = 1;
}

message MsgInitResponse {}

Next, we implement the Init method, which sets the initial counter. We also implement a method of the Account interface. This method:

Signals to the x/accounts runtime what the Init entrypoint is Performs some generic operations to maintain type safety in the system

Here's the Go implementation:

package counter

import (
    "context"
    "cosmossdk.io/x/accounts/accountstd"
)

type Account struct {
    Counter collections.Item[uint64]
}

func (a Account) Init(ctx context.Context, msg *MsgInit) (*MsgInitResponse, error) {
    err := a.Counter.Set(ctx, msg.Counter)
    if err != nil {
        return nil, err
    }
    
    return &MsgInitResponse{}, nil
}

func (a Account) RegisterInitHandler(builder *accountstd.InitBuilder) {
    accountstd.RegisterInitHandler(builder, a.Init)
}
Execute Handlers

Execute handlers are methods that an account can execute, defined as messages. These executions can be triggered:

  • During block execution (not queries) through transactions
  • During begin or end block

To define an execute handler, we start by creating its proto message:

message MsgIncreaseCounter {
   uint64 amount = 1;
}

message MsgIncreaseCounterResponse {
   uint64 new_value = 1;
}

Next, we implement the handling code for this message and register it using the RegisterExecuteHandlers method:

package counter

import (
    "context"
    "cosmossdk.io/x/accounts/accountstd"
)

type Account struct {
    Counter collections.Item[uint64]
}

func (a Account) Init(ctx context.Context, msg *MsgInit) (*MsgInitResponse, error) {
    err := a.Counter.Set(ctx, msg.Counter)
    if err != nil {
        return nil, err
    }
    return &MsgInitResponse{}, nil
}

// Handler for MsgIncreaseCounter
func (a Account) IncreaseCounter(ctx context.Context, msg *MsgIncreaseCounter) (*MsgIncreaseCounterResponse, error) {
    counter, err := a.Counter.Get(ctx)
    if err != nil {
        return nil, err
    }
    
    newValue := counter + msg.Amount
    err = a.Counter.Set(ctx, newValue)
    if err != nil {
        return nil, err
    }
    
    return &MsgIncreaseCounterResponse{NewValue: newValue}, nil
}

// Registration of the handler in the runtime
func (a Account) RegisterExecuteHandlers(builder *accountstd.ExecuteBuilder) {
    accountstd.RegisterExecuteHandler(builder, a.IncreaseCounter)
}

func (a Account) RegisterInitHandler(builder *accountstd.InitBuilder) {
    accountstd.RegisterInitHandler(builder, a.Init)
}

This implementation defines an IncreaseCounter method that handles the MsgIncreaseCounter message, updating the counter value and returning the new value in the response.

Query Handlers

Query Handlers are read-only methods implemented by an account to expose information about itself. This information can be accessed by:

  • External clients (e.g., CLI, wallets)
  • Other modules and accounts within the system

Query handlers can be invoked:

  1. By external clients
  2. During block execution

To define a query handler, we follow a similar process to execute handlers:

  1. Define the request and response proto messages:
message QueryCounter {}

message QueryCounterResponse {
   uint64 value = 1;
}
  1. Implement and register the query handler:
package counter

import (
    "context"
    "cosmossdk.io/x/accounts/accountstd"
)

func (a Account) QueryCounter(ctx context.Context, _ *QueryCounterRequest) (*QueryCounterResponse, error) {
    counter, err := a.Counter.Get(ctx)
    if err != nil {
        return nil, err
    }
    return &QueryCounterResponse{
        Value: counter,
    }, nil
}

func (a Account) RegisterQueryHandlers(builder *accountstd.QueryBuilder) {
    accountstd.RegisterQueryHandler(builder, a.QueryCounter)
}

This implementation defines a QueryCounter method that retrieves the current counter value and returns it in the response. The RegisterQueryHandlers method registers this query handler with the system.

The Account Constructor

After creating our basic counter account, we implement the account constructor function:

package counter

import (
   "cosmossdk.io/collections"
   "cosmossdk.io/x/accounts/accountstd"
)

func NewAccount(deps accountstd.Dependencies) (Account, error) {
   return Account{
      Counter: collections.NewItem(deps.SchemaBuilder, CounterPrefix, "counter", collections.Uint64Value),
   }, nil
}

type Account struct {
   Counter collections.Item[uint64]
}

// Rest of the Account implementation...

The accountstd.Dependencies type provides an environment with essential components:

  1. AddressCodec: For encoding and decoding addresses
  2. SchemaBuilder: For schema construction (handled by the accounts module)
  3. HeaderService: For accessing block header information
  4. Other useful services and utilities

These dependencies allow the account to interact with the blockchain system.

App Wiring

Note: This assumes you've already wired the x/accounts module in your application. If not, refer to the Simapp example.

After creating our basic account, we wire it to the x/accounts module.

Depinject Method

Define the depinject constructor:

package counterdepinject

func ProvideAccount() accountstd.DepinjectAccount {
    return accountstd.DIAccount("counter", counter.NewAccount)
}

Add this to the application:

package app

func NewApp() *App {
    // ...
    appConfig = depinject.Configs(
        AppConfig(),
        depinject.Supply(
            appOpts,
            logger,
        ),
        depinject.Provide(
            counterdepinject.ProvideAccount,
        ),
    )
    // ...
}
Manual Method

Add the account to the x/accounts Keeper:

accountsKeeper, err := accounts.NewKeeper(
    appCodec,
    runtime.NewEnvironment(/* ... */),
    signingCtx.AddressCodec(),
    appCodec.InterfaceRegistry(),
    
    accountstd.AddAccount("counter", counter.NewAccount), // Add account here
    // Add more accounts if needed
)

Choose the method that best fits your application structure.

The accountstd Package

The accountstd package provides utility functions for use within account init, execution, or query handlers. Key functions include:

  1. Whoami(): Retrieves the address of the current account.
  2. Sender(): Gets the address of the transaction sender (not available in queries).
  3. Funds(): Retrieves funds provided by the sender during Init or Execution.
  4. ExecModule(): Allows the account to execute a module message. Note: Impersonation is prevented. An account can't send messages on behalf of others.
  5. QueryModule(): Enables querying a module.

These functions, along with others, facilitate account operations and interactions within the system. For a comprehensive list of available utilities, refer to the Go documentation.

Interfaces via Messages and Queries

Accounts can handle various messages and queries, allowing for flexible interface definitions:

  1. Multiple account types can handle the same message or query.
  2. Different accounts (even with the same type but different addresses) can process identical messages or queries.

This flexibility enables defining interfaces as common sets of messages and/or queries that accounts can handle.

Example: Transaction Authentication

  • We define a MsgAuthenticate message.
  • Any account capable of handling MsgAuthenticate is considered to implement the Authentication interface.
  • This approach allows for standardized interaction patterns across different account types.

(Note: More details on the Authentication interface will be provided later.)

Full Examples

Some examples can be found in the defaults package.

The Authentication Interface

x/accounts introduces the Authentication interface, allowing for flexible transaction (TX) authentication beyond traditional public key cryptography.

Chain developers can implement tailored authentication methods for their accounts. Any account that implements the Authentication interface can be authenticated within a transaction.

To implement the Authentication interface in x/accounts, an account must expose an execution handler capable of processing a specific message type.

The key message type for authentication is MsgAuthenticate, which is defined in the module's protocol buffer files:

https://github.com/cosmos/cosmos-sdk/blob/main/x/accounts/proto/cosmos/accounts/interfaces/account_abstraction/v1/interface.proto#L9-L24
Authentication Mechanism
AnteHandler in the SDK

The Cosmos SDK utilizes an AnteHandler to verify transaction (TX) integrity. Its primary function is to ensure that the messages within a transaction are correctly signed by the purported sender.

Authentication Flow for x/accounts Module

When the AnteHandler identifies that a message sender (and transaction signer) belongs to the x/accounts module, it delegates the authentication process to that module.

Authentication Interface Requirement

For successful authentication, the account must implement the Authentication interface. If an account fails to implement this interface, it's considered non-externally owned, resulting in transaction rejection.

Sequence Diagram
graph TD
    A[Tx Is Received] --> B[Execute Signature Verification Ante Handler]
    B --> D{Is signer an x/accounts account?}
    D -->|No| E[Continue with signature verification ante handler]
    D -->|Yes| F{Does account handle MsgAuthenticate?}
    F -->|No| G[Fail TX: Non-externally owned account]
    F -->|Yes| H[Invoke signer account MsgAuthenticate]
    E --> I[End]
    G --> I
    H --> I
Implementing the Authentication Interface

To implement the Authentication interface, an account must handle the execution of MsgAuthenticate. Here's an example of how to do this:

package base

import (
   "context"
   "errors"
   aa_interface_v1 "github.com/cosmos/cosmos-sdk/x/accounts/interfaces/account_abstraction/v1"
   "github.com/cosmos/cosmos-sdk/x/accounts/std"
)

// Account represents a base account structure
type Account struct {
   // Account fields...
}

// Authenticate implements the authentication flow for an abstracted base account.
func (a Account) Authenticate(ctx context.Context, msg *aa_interface_v1.MsgAuthenticate) (*aa_interface_v1.MsgAuthenticateResponse, error) {
   if !accountstd.SenderIsAccountsModule(ctx) {
      return nil, errors.New("unauthorized: only accounts module is allowed to call this")
   }
   // Implement your authentication logic here
   // ...
   return &aa_interface_v1.MsgAuthenticateResponse{}, nil
}

// RegisterExecuteHandlers registers the execution handlers for the account.
func (a Account) RegisterExecuteHandlers(builder *accountstd.ExecuteBuilder) {
   accountstd.RegisterExecuteHandler(builder, a.SwapPubKey) // Other handlers
   accountstd.RegisterExecuteHandler(builder, a.Authenticate) // Implements the Authentication interface
}
Key Implementation Points
  1. Sender Verification: Always verify that the sender is the x/accounts module. This prevents unauthorized accounts from triggering authentication.
  2. Authentication Safety: Ensure your authentication mechanism is secure:
    • Prevent replay attacks by making it impossible to reuse the same action with the same signature.
Implementation example

Please find an example here.

Supporting Custom Accounts in the x/auth gRPC Server

Overview

The x/auth module provides a mechanism for custom account types to be exposed via its Account and AccountInfo gRPC queries. This feature is particularly useful for ensuring compatibility with existing wallets that have not yet integrated with x/accounts but still need to parse account information post-migration.

Implementation

To support this feature, your custom account type needs to implement the auth.QueryLegacyAccount handler. Here are some important points to consider:

  1. Selective Implementation: This implementation is not required for every account type. It's only necessary for accounts you want to expose through the x/auth gRPC Account and AccountInfo methods.
  2. Flexible Response: The info field in the QueryLegacyAccountResponse is optional. If your custom account cannot be represented as a BaseAccount, you can leave this field empty.
Example Implementation

A concrete example of implementation can be found in defaults/base/account.go. Here's a simplified version:

func (a Account) AuthRetroCompatibility(ctx context.Context, _ *authtypes.QueryLegacyAccount) (*authtypes.QueryLegacyAccountResponse, error) {
    seq := a.GetSequence()
    num := a.GetNumber()
    address := a.GetAddress()
    pubKey := a.GetPubKey()

    baseAccount := &authtypes.BaseAccount{
        AccountNumber: num,
        Sequence:      seq,
        Address:       address,
    }

    // Convert pubKey to Any type
    pubKeyAny, err := gogotypes.NewAnyWithValue(pubKey)
    if err != nil {
        return nil, err
    }
    baseAccount.PubKey = pubKeyAny

    // Convert the entire baseAccount to Any type
    accountAny, err := gogotypes.NewAnyWithValue(baseAccount)
    if err != nil {
        return nil, err
    }

    return &authtypes.QueryLegacyAccountResponse{
        Account: accountAny,
        Info:    baseAccount,
    }, nil
}
Usage Notes
  • Implement this handler only for account types you want to expose via x/auth gRPC methods.
  • The info field in the response can be nil if your account doesn't fit the BaseAccount structure.

Genesis

Creating accounts on genesis

In order to create accounts at genesis, the x/accounts module allows developers to provide a list of genesis MsgInit messages that will be executed in the x/accounts genesis flow.

The init messages are generated offline. You can also use the following CLI command to generate the json messages: simd tx accounts init [account type] [msg] --from me --genesis. This will generate a jsonified init message wrapped in an x/accounts MsgInit.

This follows the same initialization flow and rules that would happen if the chain is running. The only concrete difference is that this is happening at the genesis block.

For example, given the following genesis.json file:

{
  "app_state": {
    "accounts": {
      "init_account_msgs": [
        {
          "sender": "account_creator_address",
          "account_type": "lockup",
          "message": {
            "@type": "cosmos.accounts.defaults.lockup.MsgInitLockupAccount",
            "owner": "some_owner",
            "end_time": "..",
            "start_time": ".."
          },
          "funds": [
            {
              "denom": "stake",
              "amount": "1000"
            }
          ]
        }
      ]
    }
  }
}

The accounts module will run the lockup account initialization message.

Bundling

Transaction bundling enables a designated account (the bundler) to submit transactions on behalf of multiple users. This approach offers several advantages:

  1. Fee Abstraction: The bundler assumes responsibility for transaction fees, simplifying the process for end-users.
  2. Flexible Fee Arrangements: Users and bundlers can negotiate fee structures off-chain, allowing for customized payment models.
  3. Improved User Experience: By abstracting away fee complexities, bundling can make blockchain interactions more accessible to a wider audience.
  4. Potential for Optimization: Bundlers can potentially optimize gas usage and reduce overall transaction costs.
graph TD
   A1[User 1] -->|Send Tx| B[Bundler]
   A2[User 2] -->|Send Tx| B
   A3[User 3] -->|Send Tx| B
   B -->|Package Txs into MsgExecuteBundle| C[MsgExecuteBundle]
   C -->|Submit| D[x/accounts module]
   D -->|Execute Tx 1| E1[Execute independently]
   D -->|Execute Tx 2| E2[Execute independently]
   D -->|Execute Tx 3| E3[Execute independently]
Tx Extension

For a transaction to be processed by a bundler, it must include a TxExtension. This extension is defined in the interface.proto file.

// TxExtension is the extension option that AA's add to txs when they're bundled.
message TxExtension {
   // authentication_gas_limit expresses the gas limit to be used for the authentication part of the
   // bundled tx.
   uint64 authentication_gas_limit = 1;
   // bundler_payment_messages expresses a list of messages that the account
   // executes to pay the bundler for submitting the bundled tx.
   // It can be empty if the bundler does not need any form of payment,
   // the handshake for submitting the UserOperation might have happened off-chain.
   // Bundlers and accounts are free to use any form of payment, in fact the payment can
   // either be empty or be expressed as:
   // - NFT payment
   // - IBC Token payment.
   // - Payment through delegations.
   repeated google.protobuf.Any bundler_payment_messages = 2;
   // bundler_payment_gas_limit defines the gas limit to be used for the bundler payment.
   // This ensures that, since the bundler executes a list of bundled tx and there needs to
   // be minimal trust between bundler and the tx sender, the sender cannot consume
   // the whole bundle gas.
   uint64 bundler_payment_gas_limit = 3;
   // execution_gas_limit defines the gas limit to be used for the execution of the UserOperation's
   // execution messages.
   uint64 execution_gas_limit = 4;
}

The purpose of the TxExtension is to provide crucial information for the bundler to process and execute the transaction efficiently and securely. It allows for fine-grained control over gas limits for different parts of the transaction execution and facilitates flexible payment arrangements between the user and the bundler. Field explanations:

  1. authentication_gas_limit (uint64):

Specifies the maximum amount of gas that can be used for authenticating the bundled transaction. Ensures that the authentication process doesn't consume excessive resources.

  1. bundler_payment_messages (repeated google.protobuf.Any):

Contains a list of messages defining how the account will pay the bundler for submitting the transaction. Offers flexibility in payment methods, including NFTs, IBC tokens, or delegations. Can be empty if payment arrangements are made off-chain or if the bundler doesn't require payment.

  1. bundler_payment_gas_limit (uint64):

Sets the maximum gas that can be used for processing the bundler payment. Prevents a malicious sender from consuming all the gas allocated for the entire bundle, enhancing security in the bundling process.

  1. execution_gas_limit (uint64):

Defines the maximum gas allowed for executing the actual transaction messages (UserOperation). Helps in accurately estimating and controlling the resources needed for the main transaction execution.

Compatibility of Your Chain with Bundling
Important Considerations

Bundling introduces a bypass mechanism for ante handler checks. This has significant implications for chains that rely on ante handlers for:

  • Message validation
  • Admission control logic

If your chain heavily depends on these ante handler functionalities, enabling bundling may compromise your chain's security or operational logic.

Disabling Bundling

For chains where bundling is incompatible with existing security measures or operational requirements, you can disable this feature. To do so:

  1. Locate your app.go file
  2. Add the following method call:

Non depinject:

// add keepers
func NewApp(...) {
    ...
    accountsKeeper, err := accounts.NewKeeper(...)
    if err != nil {
        panic(err)
    }
    accountsKeeper.DisableTxBundling() <-- // add this line
    app.AccountsKeeper = accountsKeeper
	...
}

Depinject:

	var appModules map[string]appmodule.AppModule
	if err := depinject.Inject(appConfig,
		&appBuilder,
		...
		&app.AuthKeeper,
		&app.AccountsKeeper,
		...
	); err != nil {
		panic(err)
	}
	
	app.AccountsKeeper.DisableBundling() // <- add this line

Documentation

Index

Constants

View Source
const (
	ModuleName = "accounts"
	StoreKey   = "_" + ModuleName // unfortunately accounts collides with auth store key

	ConsensusVersion = 1
)
View Source
const (
	// TODO(tip): evaluate if the following numbers should be parametrised over state, or over the node.
	SimulateAuthenticateGasLimit   = 1_000_000
	SimulateBundlerPaymentGasLimit = SimulateAuthenticateGasLimit
	ExecuteGasLimit                = SimulateAuthenticateGasLimit
)

Variables

View Source
var (
	ErrAASemantics = errors.New(ModuleName, 0, "invalid account abstraction tx semantics")
	// ErrAuthentication is returned when the authentication fails.
	ErrAuthentication = errors.New(ModuleName, 1, "authentication failed")
	// ErrBundlerPayment is returned when the bundler payment fails.
	ErrBundlerPayment = errors.New(ModuleName, 2, "bundler payment failed")
	// ErrExecution is returned when the execution fails.
	ErrExecution = errors.New(ModuleName, 3, "execution failed")
)
View Source
var (
	// AccountTypeKeyPrefix is the prefix for the account type key.
	AccountTypeKeyPrefix = collections.NewPrefix(0)
	// AccountNumberKey is the key for the account number.
	AccountNumberKey = collections.NewPrefix(1)
	// AccountByNumber is the key for the accounts by number.
	AccountByNumber = collections.NewPrefix(2)
)
View Source
var ErrBundlingDisabled = errors.New("accounts: bundling is disabled")
View Source
var (

	// ErrUnauthorized is returned when a message sender is not allowed to perform the operation.
	ErrUnauthorized = errors.New("unauthorized")
)
View Source
var ModuleAccountAddress = address.Module(ModuleName)

ModuleAccountAddress defines the x/accounts module address.

Functions

func NewMsgServer

func NewMsgServer(k Keeper) v1.MsgServer

func NewQueryServer

func NewQueryServer(k Keeper) v1.QueryServer

NewQueryServer initializes a new instance of QueryServer. It precalculates and stores schemas for efficient schema retrieval.

Types

type AppModule

type AppModule struct {
	// contains filtered or unexported fields
}

func NewAppModule

func NewAppModule(cdc codec.Codec, k Keeper) AppModule

func (AppModule) ConsensusVersion

func (AppModule) ConsensusVersion() uint64

func (AppModule) DefaultGenesis

func (am AppModule) DefaultGenesis() json.RawMessage

func (AppModule) ExportGenesis

func (am AppModule) ExportGenesis(ctx context.Context) (json.RawMessage, error)

func (AppModule) GetQueryCmd

func (AppModule) GetQueryCmd() *cobra.Command

func (AppModule) GetTxCmd

func (AppModule) GetTxCmd() *cobra.Command

func (AppModule) InitGenesis

func (am AppModule) InitGenesis(ctx context.Context, message json.RawMessage) error

func (AppModule) IsAppModule

func (AppModule) IsAppModule()

func (AppModule) IsOnePerModuleType

func (am AppModule) IsOnePerModuleType()

IsOnePerModuleType implements the depinject.OnePerModuleType interface.

func (AppModule) Name

func (am AppModule) Name() string

Name returns the module's name. Deprecated: kept for legacy reasons.

func (AppModule) RegisterInterfaces

func (AppModule) RegisterInterfaces(registrar registry.InterfaceRegistrar)

func (AppModule) RegisterServices

func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error

func (AppModule) ValidateGenesis

func (am AppModule) ValidateGenesis(message json.RawMessage) error

type InterfaceRegistry

type InterfaceRegistry interface {
	RegisterInterface(name string, iface any, impls ...gogoproto.Message)
	RegisterImplementations(iface any, impls ...gogoproto.Message)
}

type Keeper

type Keeper struct {
	appmodule.Environment

	// Schema is the schema for the module.
	Schema collections.Schema
	// AccountNumber is the last global account number.
	AccountNumber collections.Sequence
	// AccountsByType maps account address to their implementation.
	AccountsByType collections.Map[[]byte, string]
	// AccountByNumber maps account number to their address.
	AccountByNumber collections.Map[[]byte, uint64]

	// AccountsState keeps track of the state of each account.
	// NOTE: this is only used for genesis import and export.
	// Account set and get their own state but this helps providing a nice mapping
	// between: (account number, account state key) => account state value.
	AccountsState collections.Map[collections.Pair[uint64, []byte], []byte]
	// contains filtered or unexported fields
}

func NewKeeper

func NewKeeper(
	cdc codec.Codec,
	env appmodule.Environment,
	addressCodec address.Codec,
	ir InterfaceRegistry,
	txDecoder *txdecode.Decoder,
	accounts ...accountstd.AccountCreatorFunc,
) (Keeper, error)

func (Keeper) AuthenticateAccount

func (k Keeper) AuthenticateAccount(ctx context.Context, signer []byte, bundler string, rawTx *tx.TxRaw, protoTx *tx.Tx, signIndex uint32) error

AuthenticateAccount runs the authentication flow of an account.

func (*Keeper) DisableTxBundling

func (k *Keeper) DisableTxBundling()

func (Keeper) Execute

func (k Keeper) Execute(
	ctx context.Context,
	accountAddr []byte,
	sender []byte,
	execRequest transaction.Msg,
	funds sdk.Coins,
) (transaction.Msg, error)

Execute executes a state transition on the given account.

func (Keeper) ExecuteBundledTx

func (k Keeper) ExecuteBundledTx(ctx context.Context, bundler string, txBytes []byte) *v1.BundledTxResponse

ExecuteBundledTx will execute the single bundled tx.

func (Keeper) ExportState

func (k Keeper) ExportState(ctx context.Context) (*v1.GenesisState, error)

func (Keeper) ImportState

func (k Keeper) ImportState(ctx context.Context, genState *v1.GenesisState) error

func (Keeper) Init

func (k Keeper) Init(
	ctx context.Context,
	accountType string,
	creator []byte,
	initRequest transaction.Msg,
	funds sdk.Coins,
) (transaction.Msg, []byte, error)

Init creates a new account of the given type.

func (Keeper) InitAccountNumberSeqUnsafe

func (k Keeper) InitAccountNumberSeqUnsafe(ctx context.Context, accNum uint64) error

InitAccountNumberSeqUnsafe use to set accounts account number tracking. Only use for account number migration.

func (Keeper) IsAbstractedAccount

func (k Keeper) IsAbstractedAccount(ctx context.Context, addr []byte) (bool, error)

IsAbstractedAccount returns if the provided address is an abstracted account or not.

func (Keeper) IsAccountsModuleAccount

func (k Keeper) IsAccountsModuleAccount(
	ctx context.Context,
	accountAddr []byte,
) bool

IsAccountsModuleAccount check if an address belong to a smart account.

func (Keeper) MigrateLegacyAccount

func (k Keeper) MigrateLegacyAccount(
	ctx context.Context,
	addr []byte,
	accNum uint64,
	accType string,
	msg transaction.Msg,
) (transaction.Msg, error)

MigrateLegacyAccount is used to migrate a legacy account to x/accounts. Concretely speaking this works like Init, but with a custom account number provided, Where the creator is the account itself. This can be used by the x/auth module to gradually migrate base accounts to x/accounts. NOTE: this assumes the calling module checks for account overrides.

func (Keeper) NextAccountNumber

func (k Keeper) NextAccountNumber(
	ctx context.Context,
) (accNum uint64, err error)

func (Keeper) Query

func (k Keeper) Query(
	ctx context.Context,
	accountAddr []byte,
	queryRequest transaction.Msg,
) (transaction.Msg, error)

Query queries the given account.

func (Keeper) SendModuleMessage

func (k Keeper) SendModuleMessage(ctx context.Context, sender []byte, msg transaction.Msg) (transaction.Msg, error)

SendModuleMessage can be used to send a message towards a module. It should be used when the response type is not known by the caller.

type ModuleInputs

type ModuleInputs struct {
	depinject.In

	Cdc          codec.Codec
	Environment  appmodule.Environment
	AddressCodec address.Codec
	Registry     cdctypes.InterfaceRegistry

	Accounts []accountstd.DepinjectAccount // at least one account must be provided
}

type ModuleOutputs

type ModuleOutputs struct {
	depinject.Out

	AccountsKeeper Keeper
	Module         appmodule.AppModule
}

func ProvideModule

func ProvideModule(in ModuleInputs) ModuleOutputs

Directories

Path Synopsis
Package accountstd exports the types and functions that are used by developers to implement smart accounts.
Package accountstd exports the types and functions that are used by developers to implement smart accounts.
defaults
base Module
lockup Module
multisig Module
interfaces
internal
prefixstore
Package prefixstore provides a store that prefixes all keys with a given prefix.
Package prefixstore provides a store that prefixes all keys with a given prefix.
testing

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL