Documentation ¶
Overview ¶
Package api exposes all the wallet capabilities to manage connections, wallets, keys, and transactions.
It is built with th JSON-RPC v2 standard. More info: See https://www.jsonrpc.org/specification for more information.
Terminology ¶
Client:
The client is the actor behind the API that has the responsibility to review and validate the requests. It can be a human or a bot.
Client front-end:
The client front-end is the interface through which the client interact with the API. It can be a command-line interface, a graphical user-interface, or a script.
Third-party application:
The application that connects to the API (through HTTP or directly to JSON-RPC) to access wallets information, send transaction, etc.
Third-party application workflow ¶
All applications consuming this API should start with the following workflow:
connect_wallet: it allows the third-party application to initiate the connection with the API.
get_permissions: the application requires permissions from the client to consume the API. As a result, it should check if it has enough.
request_permissions: if the application doesn't have enough permissions to work, it has to request some.
Index ¶
- Constants
- Variables
- func RestrictedAPI(log *zap.Logger, walletStore WalletStore, pipeline Pipeline, ...) (*jsonrpc.API, error)
- func TraceIDFromContext(ctx context.Context) string
- type ConnectWallet
- type ConnectWalletParams
- type ConnectWalletResult
- type ConnectedWallet
- type DisconnectWallet
- type DisconnectWalletParams
- type ErrorType
- type GetPermissions
- type GetPermissionsParams
- type GetPermissionsResult
- type ListKeys
- type ListKeysParams
- type ListKeysResult
- type Node
- type NodeSelector
- type ParsedSendTransactionParams
- type Pipeline
- type RequestPermissions
- type RequestPermissionsParams
- type RequestPermissionsResult
- type SelectedWallet
- type SendTransaction
- type SendTransactionParams
- type SendTransactionResult
- type Sessions
- type WalletStore
Constants ¶
const ( // ErrorCodeNodeRequestFailed refers to the inability of the program to // talk to the network nodes. ErrorCodeNodeRequestFailed jsonrpc.ErrorCode = 1000 // ErrorCodeRequestNotPermitted refers a request made by a third-party application // that is not permitted to do. ErrorCodeRequestNotPermitted jsonrpc.ErrorCode = 2000 // ErrorCodeConnectionHasBeenClosed refers to an interruption of the service triggered // by the client. ErrorCodeConnectionHasBeenClosed jsonrpc.ErrorCode = 3000 // ErrorCodeRequestHasBeenRejected refers to an explicit rejection of a request by the // client. ErrorCodeRequestHasBeenRejected jsonrpc.ErrorCode = 3001 )
Variables ¶
var ( ErrClientRejectedTheRequest = errors.New("the client rejected the request") ErrConnectionClosed = errors.New("the client closed the connection") ErrConnectionTokenIsRequired = errors.New("the connection token is required") ErrCouldNotConnectToWallet = errors.New("couldn't connect to the wallet") ErrCouldNotGetLastBlockInformation = errors.New("couldn't get information about the last block on the network") ErrCouldNotRequestPermissions = errors.New("couldn't request permissions") ErrCouldNotSendTransaction = errors.New("couldn't send transaction") ErrEncodedTransactionIsNotValidBase64String = errors.New("the encoded transaction is not a valid base-64 string") ErrEncodedTransactionIsRequired = errors.New("the encoded transaction is required") ErrHostnameIsRequired = errors.New("the hostname is required") ErrNoHealthyNodeAvailable = errors.New("no healthy node available") ErrParamsDoNotMatch = errors.New("the params do not match expected ones") ErrParamsRequired = errors.New("the params are required") ErrPublicKeyIsNotAllowedToBeUsed = errors.New("the public key is not allowed to be used") ErrPublicKeyIsRequired = errors.New("the public key is required") ErrReadAccessOnPublicKeysRequired = errors.New(`a "read" access on public keys is required`) ErrRequestInterrupted = errors.New("the request has been interrupted") ErrRequestedPermissionsAreRequired = errors.New("the requested permissions are required") ErrSendingModeCannotBeTypeUnspecified = errors.New(`the sending mode can't be "TYPE_UNSPECIFIED"`) ErrSendingModeIsRequired = errors.New("the sending mode is required") ErrTransactionFailed = errors.New("the transaction failed") ErrWalletDoesNotExist = errors.New("the wallet does not exist") )
var ErrNoWalletConnected = errors.New("no wallet connected")
Functions ¶
func RestrictedAPI ¶
func RestrictedAPI(log *zap.Logger, walletStore WalletStore, pipeline Pipeline, nodeSelector NodeSelector) (*jsonrpc.API, error)
RestrictedAPI builds a JSON-RPC API of the wallet with a subset of the requests that are intended to be exposed to external services, such as bots, apps, scripts. The reason is that we don't want external clients to be able to call administration capabilities that should only be exposed to the user.
func TraceIDFromContext ¶
Types ¶
type ConnectWallet ¶
type ConnectWallet struct {
// contains filtered or unexported fields
}
func NewConnectWallet ¶
func NewConnectWallet( walletStore WalletStore, pipeline Pipeline, sessions *Sessions, ) *ConnectWallet
func (*ConnectWallet) Handle ¶
func (h *ConnectWallet) Handle(ctx context.Context, rawParams jsonrpc.Params) (jsonrpc.Result, *jsonrpc.ErrorDetails)
Handle initiates the wallet connection between the API and a third-party application.
It triggers a selection of the wallet the client wants to use for this connection. The wallet is then loaded in memory. All changes done to that wallet will start in-memory, and then, be saved in the wallet file. Any changes done to the wallet outside the JSON-RPC session (via the command-line for example) will be overridden. For the effects to be taken into account, the wallet has to be disconnected first, and then re-connected.
All sessions have to be initialized by using this handler. Otherwise, a call to any other handlers will be rejected.
type ConnectWalletParams ¶
type ConnectWalletParams struct {
Hostname string `json:"hostname"`
}
type ConnectWalletResult ¶
type ConnectWalletResult struct {
Token string `json:"token"`
}
type ConnectedWallet ¶
type ConnectedWallet struct { // Hostname is the hostname for which the connection is set. Hostname string // Wallet is the wallet selected by the client for this connection. Wallet wallet.Wallet // RestrictedKeys holds the keys that have been selected by the client // during the permissions request. RestrictedKeys map[string]wallet.KeyPair }
ConnectedWallet contains the resources and the information of the current connection, required by the wallet handlers to work, and based on the permissions the client has set.
func NewConnectedWallet ¶
func NewConnectedWallet(hostname string, w wallet.Wallet) (*ConnectedWallet, error)
func (*ConnectedWallet) Permissions ¶
func (s *ConnectedWallet) Permissions() wallet.Permissions
func (*ConnectedWallet) ReloadWithWallet ¶
func (s *ConnectedWallet) ReloadWithWallet(updatedWallet wallet.Wallet) error
func (*ConnectedWallet) UpdatePermissions ¶
func (s *ConnectedWallet) UpdatePermissions(perms wallet.Permissions) error
type DisconnectWallet ¶
type DisconnectWallet struct {
// contains filtered or unexported fields
}
func NewDisconnectWallet ¶
func NewDisconnectWallet(sessions *Sessions) *DisconnectWallet
func (*DisconnectWallet) Handle ¶
func (h *DisconnectWallet) Handle(_ context.Context, rawParams jsonrpc.Params) (jsonrpc.Result, *jsonrpc.ErrorDetails)
Handle disconnect a wallet for a third-party application.
It doesn't fail. If there's no connected wallet for the given token, nothing happens.
The wallet resources are unloaded.
type DisconnectWalletParams ¶
type DisconnectWalletParams struct {
Token string `json:"hostname"`
}
type ErrorType ¶
type ErrorType string
ErrorType defines the type of error that is sent to the client, for fine grain error management and reporting.
var ( // InternalError defines an unexpected technical error upon which the client // can't act. // The client front-end should report it to the client and automatically // abort the processing of the ongoing request. // It can be raised if a file is not accessible or corrupt, for example. InternalError ErrorType = "Internal Error" // ServerError defines a programmatic error threw by the server, such as // a request cancellation. // It's a type of error that should be expected and handled. ServerError ErrorType = "Server Error" // NetworkError defines an error that comes from the network and its nodes. NetworkError ErrorType = "Network Error" // ClientError defines an error that originated from the client and that // requires its intervention to correct it. // It can be raised if a passphrase is invalid, for example. ClientError ErrorType = "Client Error" )
type GetPermissions ¶
type GetPermissions struct {
// contains filtered or unexported fields
}
func NewGetPermissions ¶
func NewGetPermissions(sessions *Sessions) *GetPermissions
func (*GetPermissions) Handle ¶
func (h *GetPermissions) Handle(_ context.Context, rawParams jsonrpc.Params) (jsonrpc.Result, *jsonrpc.ErrorDetails)
Handle returns the permissions set on the given hostname.
If a third-party application doesn't have enough permissions, it has to request them using `request_permissions` handler.
Using this handler does not require permissions.
type GetPermissionsParams ¶
type GetPermissionsParams struct {
Token string `json:"token"`
}
type GetPermissionsResult ¶
type GetPermissionsResult struct {
Permissions wallet.PermissionsSummary `json:"permissions"`
}
type ListKeys ¶
type ListKeys struct {
// contains filtered or unexported fields
}
func NewListKeys ¶
type ListKeysParams ¶
type ListKeysParams struct {
Token string `json:"token"`
}
type ListKeysResult ¶
type ListKeysResult struct {
Keys []string `json:"keys"`
}
type Node ¶
type Node interface { Host() string Stop() error SendTransaction(context.Context, *commandspb.Transaction, apipb.SubmitTransactionRequest_Type) (string, error) CheckTransaction(context.Context, *commandspb.Transaction) (*apipb.CheckTransactionResponse, error) HealthCheck(context.Context) error LastBlock(context.Context) (*apipb.LastBlockHeightResponse, error) }
Node is the component used to get network information and send transactions.
type NodeSelector ¶
NodeSelector implementing the strategy for node selection.
type ParsedSendTransactionParams ¶
type ParsedSendTransactionParams struct { Token string PublicKey string SendingMode apipb.SubmitTransactionRequest_Type RawTransaction string }
type Pipeline ¶
type Pipeline interface { // NotifyError is used to report errors to the client. NotifyError(ctx context.Context, traceID string, t ErrorType, err error) // RequestWalletConnectionReview is used to trigger a client review of // the wallet connection requested by the specified hostname. // It returns true if the client approved the wallet connection, false // otherwise. RequestWalletConnectionReview(ctx context.Context, traceID, hostname string) (bool, error) // NotifySuccessfulRequest is used to notify the client the request is // successful. NotifySuccessfulRequest(ctx context.Context, traceID string) // RequestWalletSelection is used to trigger selection of the wallet the // client wants to use for the specified hostname. RequestWalletSelection(ctx context.Context, traceID, hostname string, availableWallets []string) (SelectedWallet, error) // RequestPassphrase is used to request the client to enter the passphrase of // the wallet. It's primarily used for request that requires saving changes // on it. RequestPassphrase(ctx context.Context, traceID, wallet string) (string, error) // RequestPermissionsReview is used to trigger a client review of the permissions // requested by the specified hostname. // It returns true if the client approved the requested permissions, false // otherwise. RequestPermissionsReview(ctx context.Context, traceID, hostname, wallet string, perms map[string]string) (bool, error) // RequestTransactionReview is used to trigger a client review of the // transaction a third-party application wants to send. // It returns true if the client approved the sending of the transaction, // false otherwise. RequestTransactionReview(ctx context.Context, traceID, hostname, wallet, pubKey, transaction string, receivedAt time.Time) (bool, error) // NotifyTransactionStatus is used to report the transaction status once // sent. NotifyTransactionStatus(ctx context.Context, traceID, txHash, tx string, err error, sentAt time.Time) }
Pipeline is the component connecting the client front-end and the JSON-RPC API. Convention:
- Notify* functions do not expect a response.
- Request* functions are expecting a client intervention.
type RequestPermissions ¶
type RequestPermissions struct {
// contains filtered or unexported fields
}
func NewRequestPermissions ¶
func NewRequestPermissions( walletStore WalletStore, pipeline Pipeline, sessions *Sessions, ) *RequestPermissions
func (*RequestPermissions) Handle ¶
func (h *RequestPermissions) Handle(ctx context.Context, rawParams jsonrpc.Params) (jsonrpc.Result, *jsonrpc.ErrorDetails)
Handle allows a third-party application to request permissions to access certain capabilities of the wallet.
To update the permissions, the third-party application has to specify all the permissions it required, even those that are already active. This way the client get a full understanding of all the requested access, and is much more capable to evaluate abusive requests and applications. Any permission that is omitted is considered to be revoked.
The client will be asked to review the permissions the third-party application is requesting. It has the possibility to approve or reject the request.
Everytime the permissions are updated, the connected wallet resources are updated.
Using this handler does not require permissions.
type RequestPermissionsParams ¶
type RequestPermissionsParams struct { Token string `json:"token"` RequestedPermissions wallet.PermissionsSummary `json:"requestedPermissions"` }
type RequestPermissionsResult ¶
type RequestPermissionsResult struct {
Permissions wallet.PermissionsSummary `json:"permissions"`
}
type SelectedWallet ¶
SelectedWallet holds the result of the wallet selection from the client.
type SendTransaction ¶
type SendTransaction struct {
// contains filtered or unexported fields
}
func NewSendTransaction ¶
func NewSendTransaction(pipeline Pipeline, nodeSelector NodeSelector, sessions *Sessions) *SendTransaction
type SendTransactionParams ¶
type SendTransactionResult ¶
type Sessions ¶
type Sessions struct {
// contains filtered or unexported fields
}
func NewSessions ¶
func NewSessions() *Sessions
func (*Sessions) ConnectWallet ¶
ConnectWallet initiates a wallet connection and load associated resources in it. If a connection already exists, it's disconnected and a new token is generated.
func (*Sessions) DisconnectWallet ¶
DisconnectWallet unloads the connected wallet resources and revokes the token. It doesn't fail. Non-existing token does nothing.
func (*Sessions) GetConnectedWallet ¶
func (s *Sessions) GetConnectedWallet(token string) (*ConnectedWallet, error)
GetConnectedWallet retrieves the resources and information of the connected wallet, associated to the specified token.
type WalletStore ¶
type WalletStore interface { WalletExists(ctx context.Context, name string) (bool, error) GetWallet(ctx context.Context, name, passphrase string) (wallet.Wallet, error) ListWallets(ctx context.Context) ([]string, error) SaveWallet(ctx context.Context, w wallet.Wallet, passphrase string) error }
WalletStore is the component used to retrieve and update wallets from the computer.