api

package
v0.54.0 Latest Latest
Warning

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

Go to latest
Published: Aug 16, 2022 License: MIT Imports: 18 Imported by: 1

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:

  1. connect_wallet: it allows the third-party application to initiate the connection with the API.

  2. get_permissions: the application requires permissions from the client to consume the API. As a result, it should check if it has enough.

  3. request_permissions: if the application doesn't have enough permissions to work, it has to request some.

Index

Constants

View Source
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

View Source
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")
)
View Source
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

func TraceIDFromContext(ctx context.Context) string

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

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

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

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

func NewListKeys(sessions *Sessions) *ListKeys

func (*ListKeys) Handle

func (h *ListKeys) Handle(_ context.Context, rawParams jsonrpc.Params) (jsonrpc.Result, *jsonrpc.ErrorDetails)

Handle returns the public keys the third-party application has access to.

This requires a "read" access on "public_keys".

type ListKeysParams

type ListKeysParams struct {
	Token string `json:"token"`
}

type ListKeysResult

type ListKeysResult struct {
	Keys []string `json:"keys"`
}

type Node

Node is the component used to get network information and send transactions.

type NodeSelector

type NodeSelector interface {
	Node(ctx context.Context) (Node, error)
	Stop()
}

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

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

type SelectedWallet struct {
	Wallet     string `json:"wallet"`
	Passphrase string `json:"passphrase"`
}

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

func (*SendTransaction) Handle

type SendTransactionParams

type SendTransactionParams struct {
	Token              string `json:"token"`
	PublicKey          string `json:"publicKey"`
	SendingMode        string `json:"sendingMode"`
	EncodedTransaction string `json:"encodedTransaction"`
}

type SendTransactionResult

type SendTransactionResult struct {
	ReceivedAt time.Time `json:"receivedAt"`
	SentAt     time.Time `json:"sentAt"`
	TxHash     string    `json:"transactionHash"`
}

type Sessions

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

func NewSessions

func NewSessions() *Sessions

func (*Sessions) ConnectWallet

func (s *Sessions) ConnectWallet(hostname string, w wallet.Wallet) (string, error)

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

func (s *Sessions) DisconnectWallet(token string)

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.

Directories

Path Synopsis
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.
mocks
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

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