wallet

package
v0.4.0-rc.1 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2021 License: MIT Imports: 9 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	InitWalletReply_Status_name = map[int32]string{
		0: "PROCESSING",
		1: "DONE",
	}
	InitWalletReply_Status_value = map[string]int32{
		"PROCESSING": 0,
		"DONE":       1,
	}
)

Enum value maps for InitWalletReply_Status.

View Source
var File_wallet_proto protoreflect.FileDescriptor

Functions

func RegisterWalletServer

func RegisterWalletServer(s grpc.ServiceRegistrar, srv WalletServer)

Types

type BalanceInfo

type BalanceInfo struct {

	// The balance of the wallet
	TotalBalance uint64 `protobuf:"varint,1,opt,name=total_balance,json=totalBalance,proto3" json:"total_balance,omitempty"`
	// The confirmed balance of a wallet(with >= 1 confirmations)
	ConfirmedBalance uint64 `protobuf:"varint,2,opt,name=confirmed_balance,json=confirmedBalance,proto3" json:"confirmed_balance,omitempty"`
	// The unconfirmed balance of a wallet(with 0 confirmations)
	UnconfirmedBalance uint64 `protobuf:"varint,3,opt,name=unconfirmed_balance,json=unconfirmedBalance,proto3" json:"unconfirmed_balance,omitempty"`
	// contains filtered or unexported fields
}

func (*BalanceInfo) Descriptor deprecated

func (*BalanceInfo) Descriptor() ([]byte, []int)

Deprecated: Use BalanceInfo.ProtoReflect.Descriptor instead.

func (*BalanceInfo) GetConfirmedBalance

func (x *BalanceInfo) GetConfirmedBalance() uint64

func (*BalanceInfo) GetTotalBalance

func (x *BalanceInfo) GetTotalBalance() uint64

func (*BalanceInfo) GetUnconfirmedBalance

func (x *BalanceInfo) GetUnconfirmedBalance() uint64

func (*BalanceInfo) ProtoMessage

func (*BalanceInfo) ProtoMessage()

func (*BalanceInfo) ProtoReflect

func (x *BalanceInfo) ProtoReflect() protoreflect.Message

func (*BalanceInfo) Reset

func (x *BalanceInfo) Reset()

func (*BalanceInfo) String

func (x *BalanceInfo) String() string

type ChangePasswordReply

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

func (*ChangePasswordReply) Descriptor deprecated

func (*ChangePasswordReply) Descriptor() ([]byte, []int)

Deprecated: Use ChangePasswordReply.ProtoReflect.Descriptor instead.

func (*ChangePasswordReply) ProtoMessage

func (*ChangePasswordReply) ProtoMessage()

func (*ChangePasswordReply) ProtoReflect

func (x *ChangePasswordReply) ProtoReflect() protoreflect.Message

func (*ChangePasswordReply) Reset

func (x *ChangePasswordReply) Reset()

func (*ChangePasswordReply) String

func (x *ChangePasswordReply) String() string

type ChangePasswordRequest

type ChangePasswordRequest struct {

	//
	//current_password should be the current valid passphrase used to unlock the
	//daemon.
	CurrentPassword []byte `protobuf:"bytes,1,opt,name=current_password,json=currentPassword,proto3" json:"current_password,omitempty"`
	//
	//new_password should be the new passphrase that will be needed to unlock the
	//daemon.
	NewPassword []byte `protobuf:"bytes,2,opt,name=new_password,json=newPassword,proto3" json:"new_password,omitempty"`
	// contains filtered or unexported fields
}

func (*ChangePasswordRequest) Descriptor deprecated

func (*ChangePasswordRequest) Descriptor() ([]byte, []int)

Deprecated: Use ChangePasswordRequest.ProtoReflect.Descriptor instead.

func (*ChangePasswordRequest) GetCurrentPassword

func (x *ChangePasswordRequest) GetCurrentPassword() []byte

func (*ChangePasswordRequest) GetNewPassword

func (x *ChangePasswordRequest) GetNewPassword() []byte

func (*ChangePasswordRequest) ProtoMessage

func (*ChangePasswordRequest) ProtoMessage()

func (*ChangePasswordRequest) ProtoReflect

func (x *ChangePasswordRequest) ProtoReflect() protoreflect.Message

func (*ChangePasswordRequest) Reset

func (x *ChangePasswordRequest) Reset()

func (*ChangePasswordRequest) String

func (x *ChangePasswordRequest) String() string

type GenSeedReply

type GenSeedReply struct {
	SeedMnemonic []string `protobuf:"bytes,1,rep,name=seed_mnemonic,json=seedMnemonic,proto3" json:"seed_mnemonic,omitempty"`
	// contains filtered or unexported fields
}

func (*GenSeedReply) Descriptor deprecated

func (*GenSeedReply) Descriptor() ([]byte, []int)

Deprecated: Use GenSeedReply.ProtoReflect.Descriptor instead.

func (*GenSeedReply) GetSeedMnemonic

func (x *GenSeedReply) GetSeedMnemonic() []string

func (*GenSeedReply) ProtoMessage

func (*GenSeedReply) ProtoMessage()

func (*GenSeedReply) ProtoReflect

func (x *GenSeedReply) ProtoReflect() protoreflect.Message

func (*GenSeedReply) Reset

func (x *GenSeedReply) Reset()

func (*GenSeedReply) String

func (x *GenSeedReply) String() string

type GenSeedRequest

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

func (*GenSeedRequest) Descriptor deprecated

func (*GenSeedRequest) Descriptor() ([]byte, []int)

Deprecated: Use GenSeedRequest.ProtoReflect.Descriptor instead.

func (*GenSeedRequest) ProtoMessage

func (*GenSeedRequest) ProtoMessage()

func (*GenSeedRequest) ProtoReflect

func (x *GenSeedRequest) ProtoReflect() protoreflect.Message

func (*GenSeedRequest) Reset

func (x *GenSeedRequest) Reset()

func (*GenSeedRequest) String

func (x *GenSeedRequest) String() string

type InitWalletReply

type InitWalletReply struct {
	Account uint64                 `protobuf:"varint,1,opt,name=account,proto3" json:"account,omitempty"`
	Index   uint64                 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"`
	Status  InitWalletReply_Status `protobuf:"varint,3,opt,name=status,proto3,enum=InitWalletReply_Status" json:"status,omitempty"`
	Data    string                 `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
	// contains filtered or unexported fields
}

func (*InitWalletReply) Descriptor deprecated

func (*InitWalletReply) Descriptor() ([]byte, []int)

Deprecated: Use InitWalletReply.ProtoReflect.Descriptor instead.

func (*InitWalletReply) GetAccount

func (x *InitWalletReply) GetAccount() uint64

func (*InitWalletReply) GetData

func (x *InitWalletReply) GetData() string

func (*InitWalletReply) GetIndex

func (x *InitWalletReply) GetIndex() uint64

func (*InitWalletReply) GetStatus

func (x *InitWalletReply) GetStatus() InitWalletReply_Status

func (*InitWalletReply) ProtoMessage

func (*InitWalletReply) ProtoMessage()

func (*InitWalletReply) ProtoReflect

func (x *InitWalletReply) ProtoReflect() protoreflect.Message

func (*InitWalletReply) Reset

func (x *InitWalletReply) Reset()

func (*InitWalletReply) String

func (x *InitWalletReply) String() string

type InitWalletReply_Status

type InitWalletReply_Status int32
const (
	InitWalletReply_PROCESSING InitWalletReply_Status = 0
	InitWalletReply_DONE       InitWalletReply_Status = 1
)

func (InitWalletReply_Status) Descriptor

func (InitWalletReply_Status) Enum

func (InitWalletReply_Status) EnumDescriptor deprecated

func (InitWalletReply_Status) EnumDescriptor() ([]byte, []int)

Deprecated: Use InitWalletReply_Status.Descriptor instead.

func (InitWalletReply_Status) Number

func (InitWalletReply_Status) String

func (x InitWalletReply_Status) String() string

func (InitWalletReply_Status) Type

type InitWalletRequest

type InitWalletRequest struct {

	//
	//wallet_password is the passphrase that should be used to encrypt the
	//wallet. This MUST be at least 8 chars in length. After creation, this
	//password is required to unlock the daemon.
	WalletPassword []byte `protobuf:"bytes,1,opt,name=wallet_password,json=walletPassword,proto3" json:"wallet_password,omitempty"`
	//
	//seed_mnemonic is a 24-word mnemonic that encodes a prior seed obtained by the
	//user. This MUST be a generated by the GenSeed method
	SeedMnemonic []string `protobuf:"bytes,2,rep,name=seed_mnemonic,json=seedMnemonic,proto3" json:"seed_mnemonic,omitempty"`
	//
	//the flag to let the daemon restore existing funds for the wallet.
	Restore bool `protobuf:"varint,3,opt,name=restore,proto3" json:"restore,omitempty"`
	// contains filtered or unexported fields
}

func (*InitWalletRequest) Descriptor deprecated

func (*InitWalletRequest) Descriptor() ([]byte, []int)

Deprecated: Use InitWalletRequest.ProtoReflect.Descriptor instead.

func (*InitWalletRequest) GetRestore

func (x *InitWalletRequest) GetRestore() bool

func (*InitWalletRequest) GetSeedMnemonic

func (x *InitWalletRequest) GetSeedMnemonic() []string

func (*InitWalletRequest) GetWalletPassword

func (x *InitWalletRequest) GetWalletPassword() []byte

func (*InitWalletRequest) ProtoMessage

func (*InitWalletRequest) ProtoMessage()

func (*InitWalletRequest) ProtoReflect

func (x *InitWalletRequest) ProtoReflect() protoreflect.Message

func (*InitWalletRequest) Reset

func (x *InitWalletRequest) Reset()

func (*InitWalletRequest) String

func (x *InitWalletRequest) String() string

type SendToManyReply

type SendToManyReply struct {

	//
	//The serialized transaction sent out on the network.
	RawTx []byte `protobuf:"bytes,1,opt,name=raw_tx,json=rawTx,proto3" json:"raw_tx,omitempty"`
	// contains filtered or unexported fields
}

func (*SendToManyReply) Descriptor deprecated

func (*SendToManyReply) Descriptor() ([]byte, []int)

Deprecated: Use SendToManyReply.ProtoReflect.Descriptor instead.

func (*SendToManyReply) GetRawTx

func (x *SendToManyReply) GetRawTx() []byte

func (*SendToManyReply) ProtoMessage

func (*SendToManyReply) ProtoMessage()

func (*SendToManyReply) ProtoReflect

func (x *SendToManyReply) ProtoReflect() protoreflect.Message

func (*SendToManyReply) Reset

func (x *SendToManyReply) Reset()

func (*SendToManyReply) String

func (x *SendToManyReply) String() string

type SendToManyRequest

type SendToManyRequest struct {

	//
	//A slice of the outputs that should be created in the transaction produced.
	Outputs []*TxOut `protobuf:"bytes,1,rep,name=outputs,proto3" json:"outputs,omitempty"`
	//
	//The number of millisatoshis per byte that should be used when crafting
	//this transaction.
	MillisatPerByte int64 `protobuf:"varint,2,opt,name=millisat_per_byte,json=millisatPerByte,proto3" json:"millisat_per_byte,omitempty"`
	// Optional: if true the transaction will be pushed to the network
	Push bool `protobuf:"varint,3,opt,name=push,proto3" json:"push,omitempty"`
	// contains filtered or unexported fields
}

func (*SendToManyRequest) Descriptor deprecated

func (*SendToManyRequest) Descriptor() ([]byte, []int)

Deprecated: Use SendToManyRequest.ProtoReflect.Descriptor instead.

func (*SendToManyRequest) GetMillisatPerByte

func (x *SendToManyRequest) GetMillisatPerByte() int64

func (*SendToManyRequest) GetOutputs

func (x *SendToManyRequest) GetOutputs() []*TxOut

func (*SendToManyRequest) GetPush

func (x *SendToManyRequest) GetPush() bool

func (*SendToManyRequest) ProtoMessage

func (*SendToManyRequest) ProtoMessage()

func (*SendToManyRequest) ProtoReflect

func (x *SendToManyRequest) ProtoReflect() protoreflect.Message

func (*SendToManyRequest) Reset

func (x *SendToManyRequest) Reset()

func (*SendToManyRequest) String

func (x *SendToManyRequest) String() string

type TxOut

type TxOut struct {

	// The asset being spent
	Asset string `protobuf:"bytes,1,opt,name=asset,proto3" json:"asset,omitempty"`
	// The value of the output being spent.
	Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"`
	// The confidential address of the output being spent.
	Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
	// contains filtered or unexported fields
}

func (*TxOut) Descriptor deprecated

func (*TxOut) Descriptor() ([]byte, []int)

Deprecated: Use TxOut.ProtoReflect.Descriptor instead.

func (*TxOut) GetAddress

func (x *TxOut) GetAddress() string

func (*TxOut) GetAsset

func (x *TxOut) GetAsset() string

func (*TxOut) GetValue

func (x *TxOut) GetValue() int64

func (*TxOut) ProtoMessage

func (*TxOut) ProtoMessage()

func (*TxOut) ProtoReflect

func (x *TxOut) ProtoReflect() protoreflect.Message

func (*TxOut) Reset

func (x *TxOut) Reset()

func (*TxOut) String

func (x *TxOut) String() string

type UnimplementedWalletServer

type UnimplementedWalletServer struct {
}

UnimplementedWalletServer must be embedded to have forward compatible implementations.

func (UnimplementedWalletServer) ChangePassword

func (UnimplementedWalletServer) GenSeed

func (UnimplementedWalletServer) InitWallet

func (UnimplementedWalletServer) SendToMany

func (UnimplementedWalletServer) UnlockWallet

func (UnimplementedWalletServer) WalletAddress

func (UnimplementedWalletServer) WalletBalance

type UnlockWalletReply

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

func (*UnlockWalletReply) Descriptor deprecated

func (*UnlockWalletReply) Descriptor() ([]byte, []int)

Deprecated: Use UnlockWalletReply.ProtoReflect.Descriptor instead.

func (*UnlockWalletReply) ProtoMessage

func (*UnlockWalletReply) ProtoMessage()

func (*UnlockWalletReply) ProtoReflect

func (x *UnlockWalletReply) ProtoReflect() protoreflect.Message

func (*UnlockWalletReply) Reset

func (x *UnlockWalletReply) Reset()

func (*UnlockWalletReply) String

func (x *UnlockWalletReply) String() string

type UnlockWalletRequest

type UnlockWalletRequest struct {

	//
	//wallet_password should be the current valid passphrase for the daemon. This
	//will be required to decrypt on-disk material that the daemon requires to
	//function properly.
	WalletPassword []byte `protobuf:"bytes,1,opt,name=wallet_password,json=walletPassword,proto3" json:"wallet_password,omitempty"`
	// contains filtered or unexported fields
}

func (*UnlockWalletRequest) Descriptor deprecated

func (*UnlockWalletRequest) Descriptor() ([]byte, []int)

Deprecated: Use UnlockWalletRequest.ProtoReflect.Descriptor instead.

func (*UnlockWalletRequest) GetWalletPassword

func (x *UnlockWalletRequest) GetWalletPassword() []byte

func (*UnlockWalletRequest) ProtoMessage

func (*UnlockWalletRequest) ProtoMessage()

func (*UnlockWalletRequest) ProtoReflect

func (x *UnlockWalletRequest) ProtoReflect() protoreflect.Message

func (*UnlockWalletRequest) Reset

func (x *UnlockWalletRequest) Reset()

func (*UnlockWalletRequest) String

func (x *UnlockWalletRequest) String() string

type UnsafeWalletServer

type UnsafeWalletServer interface {
	// contains filtered or unexported methods
}

UnsafeWalletServer may be embedded to opt out of forward compatibility for this service. Use of this interface is not recommended, as added methods to WalletServer will result in compilation errors.

type WalletAddressReply

type WalletAddressReply struct {

	// The confidential address encoded using a blech32 format.
	Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
	// The blinding private key for the given address encoded in hex format
	Blinding string `protobuf:"bytes,2,opt,name=blinding,proto3" json:"blinding,omitempty"`
	// contains filtered or unexported fields
}

func (*WalletAddressReply) Descriptor deprecated

func (*WalletAddressReply) Descriptor() ([]byte, []int)

Deprecated: Use WalletAddressReply.ProtoReflect.Descriptor instead.

func (*WalletAddressReply) GetAddress

func (x *WalletAddressReply) GetAddress() string

func (*WalletAddressReply) GetBlinding

func (x *WalletAddressReply) GetBlinding() string

func (*WalletAddressReply) ProtoMessage

func (*WalletAddressReply) ProtoMessage()

func (*WalletAddressReply) ProtoReflect

func (x *WalletAddressReply) ProtoReflect() protoreflect.Message

func (*WalletAddressReply) Reset

func (x *WalletAddressReply) Reset()

func (*WalletAddressReply) String

func (x *WalletAddressReply) String() string

type WalletAddressRequest

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

func (*WalletAddressRequest) Descriptor deprecated

func (*WalletAddressRequest) Descriptor() ([]byte, []int)

Deprecated: Use WalletAddressRequest.ProtoReflect.Descriptor instead.

func (*WalletAddressRequest) ProtoMessage

func (*WalletAddressRequest) ProtoMessage()

func (*WalletAddressRequest) ProtoReflect

func (x *WalletAddressRequest) ProtoReflect() protoreflect.Message

func (*WalletAddressRequest) Reset

func (x *WalletAddressRequest) Reset()

func (*WalletAddressRequest) String

func (x *WalletAddressRequest) String() string

type WalletBalanceReply

type WalletBalanceReply struct {

	// The balance info (total, confirmed, unconfirmed) of the wallet grouped by
	// asset
	Balance map[string]*BalanceInfo `` /* 155-byte string literal not displayed */
	// contains filtered or unexported fields
}

func (*WalletBalanceReply) Descriptor deprecated

func (*WalletBalanceReply) Descriptor() ([]byte, []int)

Deprecated: Use WalletBalanceReply.ProtoReflect.Descriptor instead.

func (*WalletBalanceReply) GetBalance

func (x *WalletBalanceReply) GetBalance() map[string]*BalanceInfo

func (*WalletBalanceReply) ProtoMessage

func (*WalletBalanceReply) ProtoMessage()

func (*WalletBalanceReply) ProtoReflect

func (x *WalletBalanceReply) ProtoReflect() protoreflect.Message

func (*WalletBalanceReply) Reset

func (x *WalletBalanceReply) Reset()

func (*WalletBalanceReply) String

func (x *WalletBalanceReply) String() string

type WalletBalanceRequest

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

func (*WalletBalanceRequest) Descriptor deprecated

func (*WalletBalanceRequest) Descriptor() ([]byte, []int)

Deprecated: Use WalletBalanceRequest.ProtoReflect.Descriptor instead.

func (*WalletBalanceRequest) ProtoMessage

func (*WalletBalanceRequest) ProtoMessage()

func (*WalletBalanceRequest) ProtoReflect

func (x *WalletBalanceRequest) ProtoReflect() protoreflect.Message

func (*WalletBalanceRequest) Reset

func (x *WalletBalanceRequest) Reset()

func (*WalletBalanceRequest) String

func (x *WalletBalanceRequest) String() string

type WalletClient

type WalletClient interface {
	//
	//GenSeed is the first method that should be used to instantiate a new tdexd
	//instance. This method allows a caller to generate a new HD Wallet.
	//Once the seed is obtained and verified by the user, the InitWallet
	//method should be used to commit the newly generated seed, and create the
	//wallet.
	GenSeed(ctx context.Context, in *GenSeedRequest, opts ...grpc.CallOption) (*GenSeedReply, error)
	//
	//InitWallet is used when tdexd is starting up for the first time to fully
	//initialize the daemon and its internal wallet. At the very least a mnemonic
	//and a wallet password must be provided. This will be used to encrypt sensitive
	//material on disk. Alternatively, this can be used along with the GenSeed RPC
	//to obtain a seed, then present it to the user. Once it has been verified by
	//the user, the seed can be fed into this RPC in order to commit the new wallet.
	InitWallet(ctx context.Context, in *InitWalletRequest, opts ...grpc.CallOption) (Wallet_InitWalletClient, error)
	//
	//UnlockWallet is used at startup of tdexd to provide a password to unlock
	//the wallet database.
	UnlockWallet(ctx context.Context, in *UnlockWalletRequest, opts ...grpc.CallOption) (*UnlockWalletReply, error)
	//
	//ChangePassword changes the password of the encrypted wallet. This will
	//automatically unlock the wallet database if successful.
	ChangePassword(ctx context.Context, in *ChangePasswordRequest, opts ...grpc.CallOption) (*ChangePasswordReply, error)
	//
	//WalletAddress returns a Liquid confidential p2wpkh address (BLECH32)
	WalletAddress(ctx context.Context, in *WalletAddressRequest, opts ...grpc.CallOption) (*WalletAddressReply, error)
	//
	//WalletBalance returns total unspent outputs (confirmed and unconfirmed), all
	//confirmed unspent outputs and all unconfirmed unspent outputs under control
	//of the wallet.
	WalletBalance(ctx context.Context, in *WalletBalanceRequest, opts ...grpc.CallOption) (*WalletBalanceReply, error)
	//SendToMany sends funds to many outputs
	SendToMany(ctx context.Context, in *SendToManyRequest, opts ...grpc.CallOption) (*SendToManyReply, error)
}

WalletClient is the client API for Wallet service.

For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.

func NewWalletClient

func NewWalletClient(cc grpc.ClientConnInterface) WalletClient

type WalletServer

type WalletServer interface {
	//
	//GenSeed is the first method that should be used to instantiate a new tdexd
	//instance. This method allows a caller to generate a new HD Wallet.
	//Once the seed is obtained and verified by the user, the InitWallet
	//method should be used to commit the newly generated seed, and create the
	//wallet.
	GenSeed(context.Context, *GenSeedRequest) (*GenSeedReply, error)
	//
	//InitWallet is used when tdexd is starting up for the first time to fully
	//initialize the daemon and its internal wallet. At the very least a mnemonic
	//and a wallet password must be provided. This will be used to encrypt sensitive
	//material on disk. Alternatively, this can be used along with the GenSeed RPC
	//to obtain a seed, then present it to the user. Once it has been verified by
	//the user, the seed can be fed into this RPC in order to commit the new wallet.
	InitWallet(*InitWalletRequest, Wallet_InitWalletServer) error
	//
	//UnlockWallet is used at startup of tdexd to provide a password to unlock
	//the wallet database.
	UnlockWallet(context.Context, *UnlockWalletRequest) (*UnlockWalletReply, error)
	//
	//ChangePassword changes the password of the encrypted wallet. This will
	//automatically unlock the wallet database if successful.
	ChangePassword(context.Context, *ChangePasswordRequest) (*ChangePasswordReply, error)
	//
	//WalletAddress returns a Liquid confidential p2wpkh address (BLECH32)
	WalletAddress(context.Context, *WalletAddressRequest) (*WalletAddressReply, error)
	//
	//WalletBalance returns total unspent outputs (confirmed and unconfirmed), all
	//confirmed unspent outputs and all unconfirmed unspent outputs under control
	//of the wallet.
	WalletBalance(context.Context, *WalletBalanceRequest) (*WalletBalanceReply, error)
	//SendToMany sends funds to many outputs
	SendToMany(context.Context, *SendToManyRequest) (*SendToManyReply, error)
	// contains filtered or unexported methods
}

WalletServer is the server API for Wallet service. All implementations must embed UnimplementedWalletServer for forward compatibility

type Wallet_InitWalletClient

type Wallet_InitWalletClient interface {
	Recv() (*InitWalletReply, error)
	grpc.ClientStream
}

type Wallet_InitWalletServer

type Wallet_InitWalletServer interface {
	Send(*InitWalletReply) error
	grpc.ServerStream
}

Jump to

Keyboard shortcuts

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