wallet

package
v0.48.3 Latest Latest
Warning

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

Go to latest
Published: Feb 29, 2020 License: MPL-2.0 Imports: 28 Imported by: 0

README

Wallet

Wallet service starts a loop that watches for new transfers (eth and erc20). To correctly start the service two values need to be changed in the config:

  1. Set Enable to true in WalletConfig
{
  "WalletConfig": {
    "Enabled": true,
  }
}
  1. And expose wallet API with APIModules
{
  APIModules: "eth,net,web3,peer,wallet",
}

API

wallet_getTransfersByAddress

Returns avaiable transfers in a given range.

Parameters
  • address: HEX - ethereum address encoded in hex
  • toBlock: BIGINT - end of the range. if nil query will return last transfers.
  • limit: BIGINT - limit of returned transfers.
Examples
{"jsonrpc":"2.0","id":7,"method":"wallet_getTransfersByAddress","params":["0xb81a6845649fa8c042dfaceb3f7a684873406993","0x0","0x5"]}
Returns

Objects in the same format.

wallet_getTokensBalances

Returns tokens balances mapping for every account. See section below for the response example.

Parameters
  • accounts HEX - list of ethereum addresses encoded in hex
  • tokens HEX - list of ethereum addresses encoded in hex
{"jsonrpc":"2.0","id":11,"method":"wallet_getTokensBalances","params":[["0x066ed5c2ed45d70ad72f40de0b4dd97bd67d84de", "0x0ed535be4c0aa276942a1a782669790547ad8768"], ["0x5e4bbdc178684478a615354d83c748a4393b20f0", "0x5e4bbdc178684478a615354d83c748a4393b20f0"]]}
Returns

First level keys accounts, second level keys are tokens.

{
  "0x066ed5c2ed45d70ad72f40de0b4dd97bd67d84de": {
    "0x1dfb2099f936b3e98bfc9b7059a8fb04edcce5b3": 12,
    "0x5e4bbdc178684478a615354d83c748a4393b20f0": 12
  },
  "0x0ed535be4c0aa276942a1a782669790547ad8768": {
    "0x1dfb2099f936b3e98bfc9b7059a8fb04edcce5b3": 14,
    "0x5e4bbdc178684478a615354d83c748a4393b20f0": 14
  }
}

Signals

Two signals can be emitted:

  1. newblock signal

Emitted when transfers from new block were added to the database. In this case block number if the number of this new block. Client expected to request transfers starting from received block.

{
  "type": "wallet",
  "event": {
    "type": "newblock",
    "blockNumber": 0,
    "accounts": [
      "0x42c8f505b4006d417dd4e0ba0e880692986adbd8",
      "0x3129mdasmeo132128391fml1130410k312312mll"
    ]
  }
}
  1. reorg signal.

Emitted when part of blocks were removed. Starting from a given block number all transfers were removed. Client expected to request new transfers from received block and replace transfers that were received previously.

{
  "type": "wallet",
  "event": {
    "type": "reorg",
    "blockNumber": 0,
    "accounts": [
      "0x42c8f505b4006d417dd4e0ba0e880692986adbd8"
    ]
  }
}
  1. history signal

Emmited when historical transfers were downloaded. Block number will refer the first block where historical transfers were found.

{
  "type": "wallet",
  "event": {
    "type": "history",
    "blockNumber": 0,
    "accounts": [
      "0x42c8f505b4006d417dd4e0ba0e880692986adbd8"
    ]
  }
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrServiceNotInitialized returned when wallet is not initialized/started,.
	ErrServiceNotInitialized = errors.New("wallet service is not initialized")
)

Functions

func GetTokensBalances

func GetTokensBalances(parent context.Context, client *ethclient.Client, accounts, tokens []common.Address) (map[common.Address]map[common.Address]*big.Int, error)

GetTokensBalances takes list of accounts and tokens and returns mapping of token balances for each account.

func IsTokenTransfer added in v0.39.6

func IsTokenTransfer(logs []*types.Log) bool

func WatchAccountsChanges

func WatchAccountsChanges(ctx context.Context, feed *event.Feed, initial []common.Address, reactor *Reactor) error

WatchAccountsChanges subsribes to a feed and watches for changes in accounts list. If there are new or removed accounts reactor will be restarted.

Types

type API

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

API is class with methods available over RPC.

func NewAPI

func NewAPI(s *Service) *API

func (*API) AddCustomToken added in v0.38.1

func (api *API) AddCustomToken(ctx context.Context, token Token) error

func (*API) DeleteCustomToken added in v0.38.1

func (api *API) DeleteCustomToken(ctx context.Context, address common.Address) error

func (*API) GetCustomTokens added in v0.38.1

func (api *API) GetCustomTokens(ctx context.Context) ([]*Token, error)

func (*API) GetTokensBalances

func (api *API) GetTokensBalances(ctx context.Context, accounts, tokens []common.Address) (map[common.Address]map[common.Address]*big.Int, error)

GetTokensBalances return mapping of token balances for every account.

func (*API) GetTransfersByAddress

func (api *API) GetTransfersByAddress(ctx context.Context, address common.Address, toBlock, limit *hexutil.Big) ([]TransferView, error)

GetTransfersByAddress returns transfers for a single address

type AtomicGroup

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

AtomicGroup terminates as soon as first goroutine terminates..

func NewAtomicGroup

func NewAtomicGroup(parent context.Context) *AtomicGroup

func (*AtomicGroup) Add

func (d *AtomicGroup) Add(cmd Command)

Go spawns function in a goroutine and stores results or errors.

func (*AtomicGroup) Error

func (d *AtomicGroup) Error() error

Error stores an error that was reported by any of the downloader. Should be called after Wait.

func (*AtomicGroup) Stop

func (d *AtomicGroup) Stop()

func (*AtomicGroup) Wait

func (d *AtomicGroup) Wait()

Wait for all downloaders to finish.

func (*AtomicGroup) WaitAsync

func (d *AtomicGroup) WaitAsync() <-chan struct{}

type BalanceCache added in v0.40.0

type BalanceCache interface {
	BalanceAt(ctx context.Context, client BalanceReader, account common.Address, blockNumber *big.Int) (*big.Int, error)
}

type BalanceReader

type BalanceReader interface {
	BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error)
	NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error)
}

BalanceReader interface for reading balance at a specifeid address.

type BatchDownloader

type BatchDownloader interface {
	GetHeadersInRange(ctx context.Context, from, to *big.Int) ([]*DBHeader, error)
}

BatchDownloader interface for loading transfers in batches in speificed range of blocks.

type Command

type Command func(context.Context) error

type ConcurrentDownloader

type ConcurrentDownloader struct {
	*AtomicGroup
	*Result
}

func NewConcurrentDownloader

func NewConcurrentDownloader(ctx context.Context) *ConcurrentDownloader

NewConcurrentDownloader creates ConcurrentDownloader instance.

type DBHeader

type DBHeader struct {
	Number        *big.Int
	Hash          common.Hash
	Timestamp     uint64
	Erc20Transfer *Transfer
	Network       uint64
	Address       common.Address
	// Head is true if the block was a head at the time it was pulled from chain.
	Head bool
	// Loaded is true if trasfers from this block has been already fetched
	Loaded bool
}

DBHeader fields from header that are stored in database.

type Database

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

Database sql wrapper for operations with wallet objects.

func NewDB

func NewDB(db *sql.DB, network uint64) *Database

func (*Database) AddCustomToken added in v0.38.1

func (db *Database) AddCustomToken(token Token) error

func (Database) Close

func (db Database) Close() error

Close closes database.

func (*Database) DeleteCustomToken added in v0.38.1

func (db *Database) DeleteCustomToken(address common.Address) error

func (*Database) GetBlocks added in v0.40.0

func (db *Database) GetBlocks() (rst []*DBHeader, err error)

func (*Database) GetBlocksByAddress added in v0.40.0

func (db *Database) GetBlocksByAddress(address common.Address, limit int) (rst []*big.Int, err error)

GetBlocksByAddress loads blocks for a given address.

func (*Database) GetCustomTokens added in v0.38.1

func (db *Database) GetCustomTokens() ([]*Token, error)

func (*Database) GetFirstKnownBlock added in v0.40.0

func (db *Database) GetFirstKnownBlock(address common.Address) (rst *big.Int, err error)

func (*Database) GetHeaderByNumber

func (db *Database) GetHeaderByNumber(number *big.Int) (header *DBHeader, err error)

GetHeaderByNumber selects header using block number.

func (*Database) GetLastBlockByAddress added in v0.40.0

func (db *Database) GetLastBlockByAddress(address common.Address, limit int) (rst *big.Int, err error)

func (*Database) GetLastKnownBlockByAddress added in v0.40.0

func (db *Database) GetLastKnownBlockByAddress(address common.Address) (rst *big.Int, err error)

func (*Database) GetLastKnownBlockByAddresses added in v0.40.0

func (db *Database) GetLastKnownBlockByAddresses(addresses []common.Address) (map[common.Address]*big.Int, []common.Address, error)

func (*Database) GetLastSavedBlock added in v0.40.0

func (db *Database) GetLastSavedBlock() (rst *DBHeader, err error)

func (*Database) GetLastSavedBlockBefore added in v0.40.0

func (db *Database) GetLastSavedBlockBefore(block *big.Int) (rst *DBHeader, err error)

func (*Database) GetPreloadedTransactions added in v0.40.0

func (db *Database) GetPreloadedTransactions(address common.Address, blockHash common.Hash) (rst []Transfer, err error)

func (*Database) GetTransactionsLog added in v0.40.0

func (db *Database) GetTransactionsLog(address common.Address, transactionHash common.Hash) (*types.Log, error)

func (*Database) GetTransfers

func (db *Database) GetTransfers(start, end *big.Int) (rst []Transfer, err error)

GetTransfers load transfers transfer betweeen two blocks.

func (*Database) GetTransfersByAddress

func (db *Database) GetTransfersByAddress(address common.Address, toBlock *big.Int, limit int64) (rst []Transfer, err error)

GetTransfersByAddress loads transfers for a given address between two blocks.

func (*Database) GetTransfersInRange added in v0.40.0

func (db *Database) GetTransfersInRange(address common.Address, start, end *big.Int) (rst []Transfer, err error)

GetTransfersInRange loads transfers for a given address between two blocks.

func (Database) ProcessBlocks added in v0.40.0

func (db Database) ProcessBlocks(account common.Address, from *big.Int, to *big.Int, headers []*DBHeader) (err error)

func (Database) ProcessTranfers

func (db Database) ProcessTranfers(transfers []Transfer, removed []*DBHeader) (err error)

ProcessTranfers atomically adds/removes blocks and adds new tranfers.

func (*Database) RemoveBlockWithTransfer added in v0.40.0

func (db *Database) RemoveBlockWithTransfer(address common.Address, block *big.Int) error

func (Database) SaveBlocks added in v0.40.0

func (db Database) SaveBlocks(account common.Address, headers []*DBHeader) (err error)

func (*Database) SaveHeaders

func (db *Database) SaveHeaders(headers []*types.Header, address common.Address) (err error)

SaveHeaders stores a list of headers atomically.

func (Database) SaveTranfers added in v0.40.0

func (db Database) SaveTranfers(address common.Address, transfers []Transfer, blocks []*big.Int) (err error)

SaveTranfers

type ERC20TransfersDownloader

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

ERC20TransfersDownloader is a downloader for erc20 tokens transfers.

func NewERC20TransfersDownloader

func NewERC20TransfersDownloader(client *ethclient.Client, accounts []common.Address, signer types.Signer) *ERC20TransfersDownloader

NewERC20TransfersDownloader returns new instance.

func (*ERC20TransfersDownloader) GetHeadersInRange added in v0.40.0

func (d *ERC20TransfersDownloader) GetHeadersInRange(parent context.Context, from, to *big.Int) ([]*DBHeader, error)

GetHeadersInRange returns transfers between two blocks. time to get logs for 100000 blocks = 1.144686979s. with 249 events in the result set.

func (*ERC20TransfersDownloader) GetTransfers

func (d *ERC20TransfersDownloader) GetTransfers(ctx context.Context, header *DBHeader) ([]Transfer, error)

GetTransfers for erc20 uses eth_getLogs rpc with Transfer event signature and our address acount.

type ETHTransferDownloader

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

ETHTransferDownloader downloads regular eth transfers.

func (*ETHTransferDownloader) GetTransfers

func (d *ETHTransferDownloader) GetTransfers(ctx context.Context, header *DBHeader) (rst []Transfer, err error)

GetTransfers checks if the balance was changed between two blocks. If so it downloads transaction that transfer ethereum from that block.

func (*ETHTransferDownloader) GetTransfersByNumber

func (d *ETHTransferDownloader) GetTransfersByNumber(ctx context.Context, number *big.Int) ([]Transfer, error)

type Event

type Event struct {
	Type                      EventType              `json:"type"`
	BlockNumber               *big.Int               `json:"blockNumber"`
	Accounts                  []common.Address       `json:"accounts"`
	NewTransactionsPerAccount map[common.Address]int `json:"newTransactions"`
	ERC20                     bool                   `json:"erc20"`
}

Event is a type for wallet events.

type EventType

type EventType string

EventType type for event types.

const (
	// EventNewBlock emitted when new block was added to the same canonical chan.
	EventNewBlock EventType = "newblock"
	// EventReorg emitted when canonical chain was changed. In this case, BlockNumber will be an earliest added block.
	EventReorg EventType = "reorg"
	// EventNewHistory emitted if transfer from older block was added.
	EventNewHistory EventType = "history"
	// EventFetchingRecentHistory emitted when fetching of lastest tx history is started
	EventFetchingRecentHistory EventType = "recent-history-fetching"
	// EventRecentHistoryFetched emitted when fetching of lastest tx history is started
	EventRecentHistoryReady EventType = "recent-history-ready"
)

type FiniteCommand

type FiniteCommand struct {
	Interval time.Duration
	Runable  func(context.Context) error
}

FiniteCommand terminates when error is nil.

func (FiniteCommand) Run

func (c FiniteCommand) Run(ctx context.Context) error

type Group

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

func NewGroup

func NewGroup(parent context.Context) *Group

func (*Group) Add

func (g *Group) Add(cmd Command)

func (*Group) Stop

func (g *Group) Stop()

func (*Group) Wait

func (g *Group) Wait()

func (*Group) WaitAsync

func (g *Group) WaitAsync() <-chan struct{}

type HeaderReader

type HeaderReader interface {
	HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
	HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
}

HeaderReader interface for reading headers using block number or hash.

type InfiniteCommand

type InfiniteCommand struct {
	Interval time.Duration
	Runable  func(context.Context) error
}

InfiniteCommand runs until context is closed.

func (InfiniteCommand) Run

func (c InfiniteCommand) Run(ctx context.Context) error

type IterativeDownloader

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

IterativeDownloader downloads batches of transfers in a specified size.

func SetupIterativeDownloader

func SetupIterativeDownloader(
	db *Database, client HeaderReader, address common.Address,
	downloader BatchDownloader, size *big.Int, to *big.Int, from *big.Int) (*IterativeDownloader, error)

SetupIterativeDownloader configures IterativeDownloader with last known synced block.

func (*IterativeDownloader) Finished

func (d *IterativeDownloader) Finished() bool

Finished true when earliest block with given sync option is zero.

func (*IterativeDownloader) Header

func (d *IterativeDownloader) Header() *big.Int

Header return last synced header.

func (*IterativeDownloader) Next

func (d *IterativeDownloader) Next(parent context.Context) ([]*DBHeader, *big.Int, *big.Int, error)

Next moves closer to the end on every new iteration.

func (*IterativeDownloader) Revert

func (d *IterativeDownloader) Revert()

Revert reverts last step progress. Should be used if application failed to process transfers. For example failed to persist them.

type JSONBlob

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

JSONBlob type for marshaling/unmarshaling inner type to json.

func (*JSONBlob) Scan

func (blob *JSONBlob) Scan(value interface{}) error

Scan implements interface.

func (*JSONBlob) Value

func (blob *JSONBlob) Value() (driver.Value, error)

Value implements interface.

type Reactor

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

Reactor listens to new blocks and stores transfers into the database.

func NewReactor

func NewReactor(db *Database, feed *event.Feed, client *ethclient.Client, chain *big.Int) *Reactor

NewReactor creates instance of the Reactor.

func (*Reactor) Start

func (r *Reactor) Start(accounts []common.Address) error

Start runs reactor loop in background.

func (*Reactor) Stop

func (r *Reactor) Stop()

Stop stops reactor loop and waits till it exits.

type Result

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

func (*Result) Get

func (r *Result) Get() []Transfer

func (*Result) GetHeaders added in v0.40.0

func (r *Result) GetHeaders() []*DBHeader

func (*Result) GetRanges added in v0.40.0

func (r *Result) GetRanges() [][]*big.Int

func (*Result) Push

func (r *Result) Push(transfers ...Transfer)

func (*Result) PushHeader added in v0.40.0

func (r *Result) PushHeader(block *DBHeader)

func (*Result) PushRange added in v0.40.0

func (r *Result) PushRange(blockRange []*big.Int)

type SQLBigInt

type SQLBigInt big.Int

SQLBigInt type for storing uint256 in the databse. FIXME(dshulyak) SQL big int is max 64 bits. Maybe store as bytes in big endian and hope that lexographical sorting will work.

func (*SQLBigInt) Scan

func (i *SQLBigInt) Scan(value interface{}) error

Scan implements interface.

func (*SQLBigInt) Value

func (i *SQLBigInt) Value() (driver.Value, error)

Value implements interface.

type Service

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

Service is a wallet service.

func NewService

func NewService(db *Database, accountsFeed *event.Feed) *Service

NewService initializes service instance.

func (*Service) APIs

func (s *Service) APIs() []rpc.API

APIs returns list of available RPC APIs.

func (*Service) Protocols

func (s *Service) Protocols() []p2p.Protocol

Protocols returns list of p2p protocols.

func (*Service) Start

func (s *Service) Start(*p2p.Server) error

Start signals transmitter.

func (*Service) StartReactor

func (s *Service) StartReactor(client *ethclient.Client, accounts []common.Address, chain *big.Int) error

StartReactor separately because it requires known ethereum address, which will become available only after login.

func (*Service) Stop

func (s *Service) Stop() error

Stop reactor, signals transmitter and close db.

func (*Service) StopReactor

func (s *Service) StopReactor() error

StopReactor stops reactor and closes database.

type SignalsTransmitter

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

SignalsTransmitter transmits received events as wallet signals.

func (*SignalsTransmitter) Start

func (tmr *SignalsTransmitter) Start() error

Start runs loop in background.

func (*SignalsTransmitter) Stop

func (tmr *SignalsTransmitter) Stop()

Stop stops the loop and waits till it exits.

type SyncOption

type SyncOption uint

SyncOption is used to specify that application processed transfers for that block.

type Token added in v0.38.1

type Token struct {
	Address common.Address `json:"address"`
	Name    string         `json:"name"`
	Symbol  string         `json:"symbol"`
	Color   string         `json:"color"`

	// Decimals defines how divisible the token is. For example, 0 would be
	// indivisible, whereas 18 would allow very small amounts of the token
	// to be traded.
	Decimals uint `json:"decimals"`
}

type Transfer

type Transfer struct {
	Type        TransferType       `json:"type"`
	ID          common.Hash        `json:"-"`
	Address     common.Address     `json:"address"`
	BlockNumber *big.Int           `json:"blockNumber"`
	BlockHash   common.Hash        `json:"blockhash"`
	Timestamp   uint64             `json:"timestamp"`
	Transaction *types.Transaction `json:"transaction"`
	Loaded      bool
	// From is derived from tx signature in order to offload this computation from UI component.
	From    common.Address `json:"from"`
	Receipt *types.Receipt `json:"receipt"`
	// Log that was used to generate erc20 transfer. Nil for eth transfer.
	Log *types.Log `json:"log"`
}

Transfer stores information about transfer.

type TransferDownloader

type TransferDownloader interface {
	GetTransfersByNumber(context.Context, *big.Int) ([]Transfer, error)
}

TransferDownloader downloads transfers from single block using number.

type TransferType

type TransferType string

TransferType type of the asset that was transferred.

type TransferView

type TransferView struct {
	ID          common.Hash    `json:"id"`
	Type        TransferType   `json:"type"`
	Address     common.Address `json:"address"`
	BlockNumber *hexutil.Big   `json:"blockNumber"`
	BlockHash   common.Hash    `json:"blockhash"`
	Timestamp   hexutil.Uint64 `json:"timestamp"`
	GasPrice    *hexutil.Big   `json:"gasPrice"`
	GasLimit    hexutil.Uint64 `json:"gasLimit"`
	GasUsed     hexutil.Uint64 `json:"gasUsed"`
	Nonce       hexutil.Uint64 `json:"nonce"`
	TxStatus    hexutil.Uint64 `json:"txStatus"`
	Input       hexutil.Bytes  `json:"input"`
	TxHash      common.Hash    `json:"txHash"`
	Value       *hexutil.Big   `json:"value"`
	From        common.Address `json:"from"`
	To          common.Address `json:"to"`
	Contract    common.Address `json:"contract"`
}

TransferView stores only fields used by a client and ensures that all relevant fields are encoded in hex.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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