wallet

package
v1.8.5 Latest Latest
Warning

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

Go to latest
Published: Apr 20, 2024 License: MIT Imports: 28 Imported by: 2

README

Wallet

TODO

  • Update layout of this README to match Renter README. (ie subsystems, key files, links, etc)
Wallet Encryption Subsystem

This section gives an overview of how encryption is handled within the ScPrime wallet and refers to the source code within encrypt.go. The encryption within the wallet is done using the Twofish cipher in Galois Counter Mode and hashing is done using the Blake2B algorithm.

The following pieces of information are currently being encrypted by the wallet:

Masterkey

The masterkey is a key that is either derived from a custom password provided by the user or the wallet seed if no custom password is provided. Either way, the custom password or seed are hashed before being used as the masterkey to encrypt/decrypt the wallet to produce exactly 32 bytes of entropy for the Twofish cipher. The masterkey itself is also never used directly to encrypt any data. Instead it is used with the wallet's UID to derive a key to encrypt the seed.

To allow the user to recover the wallet after forgetting a custom password, the masterkey is encrypted and stored within the wallet's BoltDB bucket. In this case the encryption key used is derived from the primary seed and the wallet's UID.

Seed Encryption

To protect the user's primary seed, the so-called seedFile is encrypted before being stored on disk within the wallet's BoltDB bucket. This file contains the primary seed, a random UID and the encrypted verification plaintext. The UID is used to derive a key to encrypt the verification plaintext from the masterkey and the verification plaintext can be used to verify that decrypting the seed was successful. This is done by decrypting the seedFile and then decrypting the verification plaintext and comparing it to the expected plaintext in the verificationPlaintextconstant. Without the verification plaintext this wouldn't be possible since both the UID and the seed are random entropy.

Locking / Unlocking the Wallet

"Locking" and "Unlocking" the wallet refers to the process of wiping sensitive data from memory and loading the encrypted data from disk into memory and decrypting it respectively. The following fields are wiped by the wallet's wipeSecrets method when the wallet is locked.

  • w.keys // secret keys derived from seeds
  • w.seeds // imported seeds
  • w.primarySeed // wallet's primary seed
Changing the password

There are 2 ways to change the wallet's password. Either by providing the current masterkey which allows the wallet to decrypt the data on disk and reencrypt it using a new key or by using the primary seed. The latter will use the seed to retrieve the masterkey from disk and then use it to reencrypt the wallet.

Documentation

Index

Constants

View Source
const (
	// SiagFileExtension is the file extension to be used for siag files
	SiagFileExtension = ".siakey"

	// SiagFileHeader is the header for all siag files. Do not change. Because siag was created
	// early in development, compatibility with siag requires manually handling
	// the headers and version instead of using the persist package.
	SiagFileHeader = "siag"

	// SiagFileVersion is the version number to be used for siag files
	SiagFileVersion = "1.0"
)
View Source
const (
	// RespendTimeout records the number of blocks that the wallet will wait
	// before spending an output that has been spent in the past. If the
	// transaction spending the output has not made it to the transaction pool
	// after the limit, the assumption is that it never will.
	RespendTimeout = 100
)

Variables

View Source
var (

	// ErrInconsistentKeys is the error when keyfiles provided are for different addresses
	ErrInconsistentKeys = errors.New("keyfiles provided that are for different addresses")
	// ErrInsufficientKeys is the error when there's not enough keys provided to spend the siafunds
	ErrInsufficientKeys = errors.New("not enough keys provided to spend the siafunds")
	// ErrNoKeyfile is the error when no keyfile has been presented
	ErrNoKeyfile = errors.New("no keyfile has been presented")
	// ErrUnknownHeader is the error when file contains wrong header
	ErrUnknownHeader = errors.New("file contains the wrong header")
	// ErrUnknownVersion is the error when the file has an unknown version number
	ErrUnknownVersion = errors.New("file has an unknown version number")
)

Functions

func ComputeValuedTransactions added in v1.4.0

func ComputeValuedTransactions(pts []modules.ProcessedTransaction, blockHeight types.BlockHeight) ([]modules.ValuedTransaction, error)

ComputeValuedTransactions creates ValuedTransaction from a set of ProcessedTransactions.

func IsSpfTransportTx added in v1.8.5

func IsSpfTransportTx(tx *types.Transaction) bool

IsSpfTransportTx returns true if given tx is a valid SPF transport to Solana.

func SignTransaction added in v1.3.5

func SignTransaction(txn *types.Transaction, seed modules.Seed, toSign []crypto.Hash, height types.BlockHeight) error

SignTransaction signs txn using secret keys derived from seed. The transaction should be complete with the exception of the Signature fields of each TransactionSignature referenced by toSign, which must not be empty.

SignTransaction must derive all of the keys from scratch, so it is appreciably slower than calling the Wallet.SignTransaction method. Only the first 1 million keys are derived.

func SpfBurntAmount added in v1.8.5

func SpfBurntAmount(tx *types.Transaction) types.Currency

SpfBurntAmount returns amount of SPF burnt in this transaction.

Types

type TransporterClient added in v1.8.5

type TransporterClient interface {
	PreminedList(ctx context.Context, req *transporter.PreminedListRequest) (*transporter.PreminedListResponse, error)
	CheckSolanaAddress(ctx context.Context, req *transporter.CheckSolanaAddressRequest) (*transporter.CheckSolanaAddressResponse, error)
	CheckAllowance(ctx context.Context, req *transporter.CheckAllowanceRequest) (*transporter.CheckAllowanceResponse, error)
	SubmitScpTx(ctx context.Context, req *transporter.SubmitScpTxRequest) (*transporter.SubmitScpTxResponse, error)
	TransportStatus(ctx context.Context, req *transporter.TransportStatusRequest) (*transporter.TransportStatusResponse, error)
}

TransporterClient defines transporter dependency.

type Wallet

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

Wallet is an object that tracks balances, creates keys and addresses, manages building and sending transactions.

func New

func New(cs modules.ConsensusSet, tpool modules.TransactionPool, persistDir string) (*Wallet, error)

New creates a new wallet, loading any known addresses from the input file name and then using the file to save in the future. Keys and addresses are not loaded into the wallet during the call to 'new', but rather during the call to 'Unlock'.

func NewCustomWallet added in v1.3.3

func NewCustomWallet(cs modules.ConsensusSet, tpool modules.TransactionPool, persistDir string, deps modules.Dependencies, opts ...WalletOption) (*Wallet, error)

NewCustomWallet creates a new wallet using custom dependencies.

func (*Wallet) AcceptSwapOffer added in v1.8.4

func (w *Wallet) AcceptSwapOffer(swapOffer modules.SwapOffer, receiveAddress types.UnlockHash) (modules.SwapOffer, error)

AcceptSwapOffer accepts an offered swap transaction by filling in missing amounts and addresses and signing the transaction fields

func (*Wallet) AddUnlockConditions added in v1.3.5

func (w *Wallet) AddUnlockConditions(uc types.UnlockConditions) error

AddUnlockConditions adds a set of UnlockConditions to the wallet database.

func (*Wallet) AddWatchAddresses added in v1.3.5

func (w *Wallet) AddWatchAddresses(addrs []types.UnlockHash, unused bool) error

AddWatchAddresses instructs the wallet to begin tracking a set of addresses, in addition to the addresses it was previously tracking. If none of the addresses have appeared in the blockchain, the unused flag may be set to true. Otherwise, the wallet must rescan the blockchain to search for transactions containing the addresses.

func (*Wallet) AddressTransactions added in v1.0.0

func (w *Wallet) AddressTransactions(uh types.UnlockHash) (pts []modules.ProcessedTransaction, err error)

AddressTransactions returns all of the wallet transactions associated with a single unlock hash.

func (*Wallet) AddressUnconfirmedTransactions added in v1.0.0

func (w *Wallet) AddressUnconfirmedTransactions(uh types.UnlockHash) (pts []modules.ProcessedTransaction, err error)

AddressUnconfirmedTransactions returns all of the unconfirmed wallet transactions related to a specific address.

func (*Wallet) Alerts added in v1.5.0

func (w *Wallet) Alerts() (crit, err, warn []modules.Alert)

Alerts implements the Alerter interface for the wallet.

func (*Wallet) AllAddresses added in v1.0.0

func (w *Wallet) AllAddresses() ([]types.UnlockHash, error)

AllAddresses returns all addresses that the wallet is able to spend from, including unseeded addresses. Addresses are returned sorted in byte-order.

func (*Wallet) AllSeeds added in v1.0.0

func (w *Wallet) AllSeeds() ([]modules.Seed, error)

AllSeeds returns a list of all seeds known to and used by the wallet.

func (*Wallet) BuildUnsignedBatchTransaction added in v1.6.3

func (w *Wallet) BuildUnsignedBatchTransaction(coinOutputs []types.SiacoinOutput, fundOutputs []types.SiafundOutput, fundbOutputs []types.SiafundOutput, txParams ...modules.TxParameter) (modules.TransactionBuilder, error)

BuildUnsignedBatchTransaction builds and returns an unsigned transaction.

func (*Wallet) ChangeKey added in v1.2.2

func (w *Wallet) ChangeKey(masterKey crypto.CipherKey, newKey crypto.CipherKey) error

ChangeKey changes the wallet's encryption key from masterKey to newKey.

func (*Wallet) ChangeKeyWithSeed added in v1.5.0

func (w *Wallet) ChangeKeyWithSeed(seed modules.Seed, newKey crypto.CipherKey) error

ChangeKeyWithSeed is the same as ChangeKey but uses the primary seed instead of the current masterKey.

func (*Wallet) CheckSwapOffer added in v1.8.4

func (w *Wallet) CheckSwapOffer(swap modules.SwapOffer) (s modules.SwapSummary, err error)

CheckSwapOffer returns a summary of the swap.

func (*Wallet) Close added in v0.3.1

func (w *Wallet) Close() error

Close terminates all ongoing processes involving the wallet, enabling garbage collection.

func (*Wallet) ConfirmedBalance added in v1.0.0

func (w *Wallet) ConfirmedBalance() (balance modules.ConfirmedBalance, err error)

ConfirmedBalance returns the balance of the wallet according to all of the confirmed transactions.

func (*Wallet) CreateBackup added in v1.0.0

func (w *Wallet) CreateBackup(backupFilepath string) error

CreateBackup creates a backup file at the desired filepath.

func (*Wallet) CreateSwapOffer added in v1.8.4

func (w *Wallet) CreateSwapOffer(amountOffered types.Currency, typeOffered types.Specifier, amountAccepted types.Currency, typeAccepted types.Specifier, receiveAddress types.UnlockHash) (modules.SwapOffer, error)

CreateSwapOffer creates a transaction proposal for exchanging between SCP and SPF

func (*Wallet) DustThreshold added in v1.3.1

func (w *Wallet) DustThreshold() (types.Currency, error)

DustThreshold returns the quantity per byte below which a Currency is considered to be Dust.

func (*Wallet) Encrypt added in v1.0.0

func (w *Wallet) Encrypt(masterKey crypto.CipherKey) (modules.Seed, error)

Encrypt will create a primary seed for the wallet and encrypt it using masterKey. If masterKey is blank, then the hash of the primary seed will be used instead. The wallet will still be locked after Encrypt is called.

Encrypt can only be called once throughout the life of the wallet, and will return an error on subsequent calls (even after restarting the wallet). To reset the wallet, the wallet files must be moved to a different directory or deleted.

func (*Wallet) Encrypted added in v1.0.0

func (w *Wallet) Encrypted() (bool, error)

Encrypted returns whether or not the wallet has been encrypted.

func (*Wallet) FinalizeSwapOffer added in v1.8.4

func (w *Wallet) FinalizeSwapOffer(swapOffer modules.SwapOffer) ([]types.Transaction, error)

FinalizeSwapOffer finalizes the offer after it was accepted by counterparty

func (*Wallet) Height added in v1.3.2

func (w *Wallet) Height() (types.BlockHeight, error)

Height return the internal processed consensus height of the wallet

func (*Wallet) InitFromSeed added in v1.2.0

func (w *Wallet) InitFromSeed(masterKey crypto.CipherKey, seed modules.Seed) error

InitFromSeed functions like Init, but using a specified seed. Unlike Init, the blockchain will be scanned to determine the seed's progress. For this reason, InitFromSeed should not be called until the blockchain is fully synced.

func (*Wallet) IsMasterKey added in v1.5.0

func (w *Wallet) IsMasterKey(masterKey crypto.CipherKey) (bool, error)

IsMasterKey verifies that the masterKey is the key used to encrypt the wallet.

func (*Wallet) IsWatchedAddress added in v1.5.2

func (w *Wallet) IsWatchedAddress(address types.UnlockHash) bool

IsWatchedAddress checks if the supplied unlockhash is in the list of watched addresses. Returns true only if the address is already known

func (*Wallet) LastAddresses added in v1.4.0

func (w *Wallet) LastAddresses(n uint64) ([]types.UnlockHash, error)

LastAddresses returns the last n addresses starting at the last seedProgress for which an address was generated. If n is greater than the current progress, fewer than n keys will be returned. That means all addresses can be retrieved in reverse order by simply supplying math.MaxUint64 for n.

func (*Wallet) Load033xWallet added in v1.0.0

func (w *Wallet) Load033xWallet(masterKey crypto.CipherKey, filepath033x string) error

Load033xWallet loads a v0.3.3.x wallet as an unseeded key, such that the funds become spendable to the current wallet.

func (*Wallet) LoadSeed added in v1.0.0

func (w *Wallet) LoadSeed(masterKey crypto.CipherKey, seed modules.Seed) error

LoadSeed will track all of the addresses generated by the input seed, reclaiming any funds that were lost due to a deleted file or lost encryption key. An error will be returned if the seed has already been integrated with the wallet.

func (*Wallet) LoadSiagKeys added in v1.0.0

func (w *Wallet) LoadSiagKeys(masterKey crypto.CipherKey, keyfiles []string) error

LoadSiagKeys loads a set of siag-generated keys into the wallet.

func (*Wallet) Lock added in v1.0.0

func (w *Wallet) Lock() error

Lock will erase all keys from memory and prevent the wallet from spending coins until it is unlocked.

func (*Wallet) NextAddress added in v1.0.0

func (w *Wallet) NextAddress() (types.UnlockConditions, error)

NextAddress returns an unlock hash that is ready to receive siacoins or siafunds. The address is generated using the primary address seed.

func (*Wallet) NextAddresses added in v1.3.2

func (w *Wallet) NextAddresses(n uint64) ([]types.UnlockConditions, error)

NextAddresses returns n unlock hashes that are ready to receive siacoins or siafunds. The addresses are generated using the primary address seed.

Warning: If this function is used to generate large numbers of addresses, those addresses should be used. Otherwise the lookahead might not be able to keep up and multiple wallets with the same seed might desync.

func (*Wallet) PrimarySeed added in v1.0.0

func (w *Wallet) PrimarySeed() (modules.Seed, uint64, error)

PrimarySeed returns the decrypted primary seed of the wallet, as well as the number of addresses that the seed can be safely used to generate.

func (*Wallet) ProcessConsensusChange added in v1.0.0

func (w *Wallet) ProcessConsensusChange(cc modules.ConsensusChange)

ProcessConsensusChange parses a consensus change to update the set of confirmed outputs known to the wallet.

func (*Wallet) ReceiveUpdatedUnconfirmedTransactions added in v1.0.0

func (w *Wallet) ReceiveUpdatedUnconfirmedTransactions(diff *modules.TransactionPoolDiff)

ReceiveUpdatedUnconfirmedTransactions updates the wallet's unconfirmed transaction set.

func (*Wallet) RegisterTransaction

func (w *Wallet) RegisterTransaction(t types.Transaction, parents []types.Transaction) (modules.TransactionBuilder, error)

RegisterTransaction takes a transaction and its parents and returns a modules.TransactionBuilder which can be used to expand the transaction. The most typical call is 'RegisterTransaction(types.Transaction{}, nil)', which registers a new transaction without parents.

func (*Wallet) RemoveWatchAddresses added in v1.3.5

func (w *Wallet) RemoveWatchAddresses(addrs []types.UnlockHash, unused bool) error

RemoveWatchAddresses instructs the wallet to stop tracking a set of addresses and delete their associated transactions. If none of the addresses have appeared in the blockchain, the unused flag may be set to true. Otherwise, the wallet must rescan the blockchain to rebuild its transaction history.

func (*Wallet) Rescanning added in v1.2.2

func (w *Wallet) Rescanning() (bool, error)

Rescanning reports whether the wallet is currently rescanning the blockchain.

func (*Wallet) Reset added in v1.2.0

func (w *Wallet) Reset() error

Reset will reset the wallet, clearing the database and returning it to the unencrypted state.

func (*Wallet) SendBatchTransaction added in v1.6.3

func (w *Wallet) SendBatchTransaction(coinOutputs []types.SiacoinOutput, fundOutputs []types.SiafundOutput, fundbOutputs []types.SiafundOutput, txParams ...modules.TxParameter) (txns []types.Transaction, err0 error)

SendBatchTransaction creates a transaction that includes the specified coin or fund outputs. The transaction is submitted to the transaction pool and is also returned.

NOTE: The ScPrime.info blockchain explorer does not currently correctly display transactions that contain both SPF and SCP outputs. Specifically, the explorer displays all SCP outputs as miner fees when an SPF output is specified. Since it is important that the general public has confidence in the blockchain explorer the SendBatchTransaction function is artificially limited to not allowing a user to define both coin and fund outputs. Ideally the blockchain explorer will someday be fixed to correctly display these types of transactions. After this happens the check to prevent both coin and fund outputs from being supplied can be removed.

func (*Wallet) SendSiacoins added in v1.0.0

func (w *Wallet) SendSiacoins(amount types.Currency, dest types.UnlockHash) ([]types.Transaction, error)

SendSiacoins creates a transaction sending 'amount' to 'dest'. The transaction is submitted to the transaction pool and is also returned. Fees are added to the amount sent.

func (*Wallet) SendSiacoinsFeeIncluded added in v1.5.0

func (w *Wallet) SendSiacoinsFeeIncluded(amount types.Currency, dest types.UnlockHash) ([]types.Transaction, error)

SendSiacoinsFeeIncluded creates a transaction sending 'amount' to 'dest'. The transaction is submitted to the transaction pool and is also returned. Fees are subtracted from the amount sent.

func (*Wallet) SendSiacoinsFromAddress added in v1.8.5

func (w *Wallet) SendSiacoinsFromAddress(coinOutputs []types.SiacoinOutput, sendFrom types.UnlockHash) (txns []types.Transaction, err error)

SendSiacoinsFromAddress sends Siacoins from requested UnlockHash.

func (*Wallet) SendSiacoinsMulti added in v1.3.0

func (w *Wallet) SendSiacoinsMulti(coinOutputs []types.SiacoinOutput) (txns []types.Transaction, err error)

SendSiacoinsMulti creates a transaction that includes the specified outputs. The transaction is submitted to the transaction pool and is also returned.

func (*Wallet) SendSiafundbs added in v1.7.0

func (w *Wallet) SendSiafundbs(amount types.Currency, dest types.UnlockHash) (txns []types.Transaction, err error)

SendSiafundbs creates a transaction sending 'amount' to 'dest'. The transaction is submitted to the transaction pool and is also returned.

func (*Wallet) SendSiafunds added in v1.0.0

func (w *Wallet) SendSiafunds(amount types.Currency, dest types.UnlockHash) (txns []types.Transaction, err error)

SendSiafunds creates a transaction sending 'amount' to 'dest'. The transaction is submitted to the transaction pool and is also returned.

func (*Wallet) SendSiafundsMulti added in v1.6.3

func (w *Wallet) SendSiafundsMulti(fundOutputs []types.SiafundOutput) (txns []types.Transaction, err error)

SendSiafundsMulti creates a transaction that includes the specified outputs. The transaction is submitted to the transaction pool and is also returned.

func (*Wallet) SetSettings added in v1.3.2

func (w *Wallet) SetSettings(s modules.WalletSettings) error

SetSettings will update the settings for the wallet.

func (*Wallet) Settings added in v1.3.2

func (w *Wallet) Settings() (modules.WalletSettings, error)

Settings returns the wallet's current settings

func (*Wallet) SiafundTransportAllowance added in v1.8.5

func (w *Wallet) SiafundTransportAllowance(t types.SpfType) (*types.SpfTransportAllowance, error)

SiafundTransportAllowance returns current allowance to transport SPFs.

func (*Wallet) SiafundTransportHistory added in v1.8.5

func (w *Wallet) SiafundTransportHistory() ([]types.SpfTransport, error)

SiafundTransportHistory returns all historical and in-progress SPF transport records.

func (*Wallet) SiafundTransportSend added in v1.8.5

func (w *Wallet) SiafundTransportSend(spfAmount types.SpfAmount, t types.SpfTransportType, preminedUnlockHash *types.UnlockHash, solanaAddr types.SolanaAddress) (dur time.Duration, cur *types.Currency, err0 error)

SiafundTransportSend initiates SPF transport. Results in burning SPFs!

func (*Wallet) SignTransaction

func (w *Wallet) SignTransaction(txn *types.Transaction, toSign []crypto.Hash) error

SignTransaction signs txn using secret keys known to the wallet. The transaction should be complete with the exception of the Signature fields of each TransactionSignature referenced by toSign. For convenience, if toSign is empty, SignTransaction signs everything that it can.

func (*Wallet) StartTransaction added in v1.0.0

func (w *Wallet) StartTransaction() (modules.TransactionBuilder, error)

StartTransaction is a convenience function that calls RegisterTransaction(types.Transaction{}, nil).

func (*Wallet) SweepSeed added in v1.2.0

func (w *Wallet) SweepSeed(seed modules.Seed) (coins, funds types.Currency, err error)

SweepSeed scans the blockchain for outputs generated from seed and creates a transaction that transfers them to the wallet. Note that this incurs a transaction fee. It returns the total value of the outputs, minus the fee. If only siafunds were found, the fee is deducted from the wallet.

func (*Wallet) Transaction added in v1.0.0

func (w *Wallet) Transaction(txid types.TransactionID) (pt modules.ProcessedTransaction, found bool, err error)

Transaction returns the transaction with the given id. 'False' is returned if the transaction does not exist.

func (*Wallet) Transactions added in v1.0.0

func (w *Wallet) Transactions(startHeight, endHeight types.BlockHeight) (pts []modules.ProcessedTransaction, err error)

Transactions returns all transactions relevant to the wallet that were confirmed in the range [startHeight, endHeight].

func (*Wallet) UnconfirmedBalance added in v1.0.0

func (w *Wallet) UnconfirmedBalance() (outgoingSiacoins types.Currency, incomingSiacoins types.Currency, err error)

UnconfirmedBalance returns the number of outgoing and incoming siacoins in the unconfirmed transaction set. Refund outputs are included in this reporting.

func (*Wallet) UnconfirmedTransactions added in v1.0.0

func (w *Wallet) UnconfirmedTransactions() ([]modules.ProcessedTransaction, error)

UnconfirmedTransactions returns the set of unconfirmed transactions that are relevant to the wallet.

func (*Wallet) Unlock added in v1.0.0

func (w *Wallet) Unlock(masterKey crypto.CipherKey) error

Unlock will decrypt the wallet seed and load all of the addresses into memory.

func (*Wallet) UnlockAsync added in v1.5.0

func (w *Wallet) UnlockAsync(masterKey crypto.CipherKey) <-chan error

UnlockAsync will decrypt the wallet seed and load all of the addresses into memory.

func (*Wallet) UnlockConditions added in v1.3.5

func (w *Wallet) UnlockConditions(addr types.UnlockHash) (uc types.UnlockConditions, err error)

UnlockConditions returns the UnlockConditions for the specified address, if they are known to the wallet.

func (*Wallet) Unlocked added in v1.0.0

func (w *Wallet) Unlocked() (bool, error)

Unlocked indicates whether the wallet is locked or unlocked.

func (*Wallet) UnspentOutputs added in v1.3.5

func (w *Wallet) UnspentOutputs() ([]modules.UnspentOutput, error)

UnspentOutputs returns the unspent outputs tracked by the wallet.

func (*Wallet) WatchAddresses added in v1.3.5

func (w *Wallet) WatchAddresses() ([]types.UnlockHash, error)

WatchAddresses returns the set of addresses that the wallet is currently watching.

type WalletConfig added in v1.8.5

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

WalletConfig holds wallet configuration used in Options pattern.

type WalletOption added in v1.8.5

type WalletOption func(*WalletConfig)

WalletOption changes something in WalletConfig.

func WithTransporterClient added in v1.8.5

func WithTransporterClient(transporterClient TransporterClient) WalletOption

WithTransporterClient returns an option setting transporterClient.

Directories

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

Jump to

Keyboard shortcuts

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