Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add wallet service #1241

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/pactus-project/pactus/util"
"github.com/pactus-project/pactus/util/logger"
"github.com/pactus-project/pactus/version"
"github.com/pactus-project/pactus/wallet"
"github.com/pactus-project/pactus/www/grpc"
"github.com/pactus-project/pactus/www/http"
"github.com/pactus-project/pactus/www/jsonrpc"
Expand Down Expand Up @@ -46,9 +47,11 @@ func NewNode(genDoc *genesis.Genesis, conf *config.Config,
// Initialize the logger
logger.InitGlobalLogger(conf.Logger)

chainType := genDoc.ChainType()

logger.Info("You are running a Pactus blockchain",
"version", version.NodeVersion,
"network", genDoc.ChainType())
"network", chainType)

messageCh := make(chan message.Message, 500)
eventCh := make(chan event.Event, 500)
Expand All @@ -74,6 +77,7 @@ func NewNode(genDoc *genesis.Genesis, conf *config.Config,
}

consMgr := consensus.NewManager(conf.Consensus, st, valKeys, rewardAddrs, messageCh)
walletMgr := wallet.NewWalletManager(chainType)

syn, err := sync.NewSynchronizer(conf.Sync, valKeys, st, consMgr, net, messageCh)
if err != nil {
Expand All @@ -84,7 +88,7 @@ func NewNode(genDoc *genesis.Genesis, conf *config.Config,
if conf.GRPC.BasicAuth != "" {
enableHTTPAuth = true
}
grpcServer := grpc.NewServer(conf.GRPC, st, syn, net, consMgr)
grpcServer := grpc.NewServer(conf.GRPC, st, syn, net, consMgr, walletMgr)
httpServer := http.NewServer(conf.HTTP, enableHTTPAuth)
jsonrpcServer := jsonrpc.NewServer(conf.JSONRPC)
nanomsgServer := nanomsg.NewServer(conf.Nanomsg, eventCh)
Expand Down
170 changes: 170 additions & 0 deletions wallet/manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package wallet

import (
"github.com/pactus-project/pactus/crypto"
"github.com/pactus-project/pactus/crypto/bls"
"github.com/pactus-project/pactus/genesis"
"github.com/pactus-project/pactus/types/tx"
"github.com/pactus-project/pactus/wallet/vault"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

type Manager struct {
wallets map[string]*Wallet
chainType genesis.ChainType
}

func NewWalletManager(chainType genesis.ChainType) *Manager {
return &Manager{
wallets: make(map[string]*Wallet),
chainType: chainType,

Check warning on line 21 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L19-L21

Added lines #L19 - L21 were not covered by tests
}
}

func (w *Manager) GetValidatorAddress(
publicKey string,
) (string, error) {
pubKey, err := bls.PublicKeyFromString(publicKey)
if err != nil {
return "", err

Check warning on line 30 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L27-L30

Added lines #L27 - L30 were not covered by tests
}

return pubKey.ValidatorAddress().String(), nil

Check warning on line 33 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L33

Added line #L33 was not covered by tests
}

func (w *Manager) CreateWallet(
mnemonic, language,
password, walletPath string,
) error {
wlt, err := Create(walletPath, mnemonic, language, w.chainType)
if err != nil {
return err

Check warning on line 42 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L39-L42

Added lines #L39 - L42 were not covered by tests
}

if err := wlt.UpdatePassword("", password); err != nil {
return err

Check warning on line 46 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L45-L46

Added lines #L45 - L46 were not covered by tests
}

if err := wlt.Save(); err != nil {
return err

Check warning on line 50 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L49-L50

Added lines #L49 - L50 were not covered by tests
}

return nil

Check warning on line 53 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L53

Added line #L53 was not covered by tests
}

func (w *Manager) LoadWallet(
walletName, walletPath string,
) error {
if _, ok := w.wallets[walletName]; ok {

Check warning on line 59 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L58-L59

Added lines #L58 - L59 were not covered by tests
// TODO: define special codes for errors
return status.Errorf(codes.AlreadyExists, "wallet already loaded")

Check warning on line 61 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L61

Added line #L61 was not covered by tests
}

wlt, err := Open(walletPath, true)
if err != nil {
return err

Check warning on line 66 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L64-L66

Added lines #L64 - L66 were not covered by tests
}

w.wallets[walletName] = wlt

Check warning on line 69 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L69

Added line #L69 was not covered by tests

return nil

Check warning on line 71 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L71

Added line #L71 was not covered by tests
}

func (w *Manager) UnloadWallet(
walletName string,
) error {
if _, ok := w.wallets[walletName]; !ok {
return status.Errorf(codes.NotFound, "wallet is not loaded")

Check warning on line 78 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L76-L78

Added lines #L76 - L78 were not covered by tests
}

delete(w.wallets, walletName)

Check warning on line 81 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L81

Added line #L81 was not covered by tests

return nil

Check warning on line 83 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L83

Added line #L83 was not covered by tests
}

func (w *Manager) TotalBalance(
walletName string,
) (int64, error) {
wlt, ok := w.wallets[walletName]
if !ok {
return 0, status.Errorf(codes.NotFound, "wallet is not loaded")

Check warning on line 91 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L88-L91

Added lines #L88 - L91 were not covered by tests
}

return wlt.TotalBalance().ToNanoPAC(), nil

Check warning on line 94 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L94

Added line #L94 was not covered by tests
}

func (w *Manager) SignRawTransaction(
walletName, password string, rawTx []byte,
) ([]byte, []byte, error) {
wlt, ok := w.wallets[walletName]
if !ok {
return nil, nil, status.Errorf(codes.NotFound, "wallet is not loaded")

Check warning on line 102 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L99-L102

Added lines #L99 - L102 were not covered by tests
}

trx, err := tx.FromBytes(rawTx)
if err != nil {
return nil, nil, err

Check warning on line 107 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L105-L107

Added lines #L105 - L107 were not covered by tests
}

if err := wlt.SignTransaction(password, trx); err != nil {
return nil, nil, err

Check warning on line 111 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L110-L111

Added lines #L110 - L111 were not covered by tests
}

data, err := trx.Bytes()
if err != nil {
return nil, nil, err

Check warning on line 116 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L114-L116

Added lines #L114 - L116 were not covered by tests
}

return trx.ID().Bytes(), data, nil

Check warning on line 119 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L119

Added line #L119 was not covered by tests
}

func (w *Manager) GetNewAddress(
walletName, label string,
addressType crypto.AddressType,
) (*vault.AddressInfo, error) {
wlt, ok := w.wallets[walletName]
if !ok {
return nil, status.Errorf(codes.NotFound, "wallet is not loaded")

Check warning on line 128 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L125-L128

Added lines #L125 - L128 were not covered by tests
}

var addressInfo *vault.AddressInfo
switch addressType {
case crypto.AddressTypeBLSAccount:
info, err := wlt.NewBLSAccountAddress(label)
if err != nil {
return nil, err

Check warning on line 136 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L131-L136

Added lines #L131 - L136 were not covered by tests
}
addressInfo = info

Check warning on line 138 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L138

Added line #L138 was not covered by tests

case crypto.AddressTypeValidator:
info, err := wlt.NewValidatorAddress(label)
if err != nil {
return nil, err

Check warning on line 143 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L140-L143

Added lines #L140 - L143 were not covered by tests
}
addressInfo = info

Check warning on line 145 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L145

Added line #L145 was not covered by tests

case crypto.AddressTypeTreasury:
return nil, status.Errorf(codes.InvalidArgument, "invalid address type")

Check warning on line 148 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L147-L148

Added lines #L147 - L148 were not covered by tests

default:
return nil, status.Errorf(codes.InvalidArgument, "invalid address type")

Check warning on line 151 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L150-L151

Added lines #L150 - L151 were not covered by tests
}

if err := wlt.Save(); err != nil {
return nil, err

Check warning on line 155 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L154-L155

Added lines #L154 - L155 were not covered by tests
}

return addressInfo, nil

Check warning on line 158 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L158

Added line #L158 was not covered by tests
}

func (w *Manager) AddressHistory(
walletName, address string,
) ([]HistoryInfo, error) {
wlt, ok := w.wallets[walletName]
if !ok {
return nil, status.Errorf(codes.NotFound, "wallet is not loaded")

Check warning on line 166 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L163-L166

Added lines #L163 - L166 were not covered by tests
}

return wlt.GetHistory(address), nil

Check warning on line 169 in wallet/manager.go

View check run for this annotation

Codecov / codecov/patch

wallet/manager.go#L169

Added line #L169 was not covered by tests
}
45 changes: 24 additions & 21 deletions www/grpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,42 @@ import (
"github.com/pactus-project/pactus/state"
"github.com/pactus-project/pactus/sync"
"github.com/pactus-project/pactus/util/logger"
"github.com/pactus-project/pactus/wallet"
pactus "github.com/pactus-project/pactus/www/grpc/gen/go"
"google.golang.org/grpc"
)

type Server struct {
ctx context.Context
cancel context.CancelFunc
config *Config
listener net.Listener
address string
grpc *grpc.Server
state state.Facade
net network.Network
sync sync.Synchronizer
consMgr consensus.ManagerReader
logger *logger.SubLogger
ctx context.Context
cancel context.CancelFunc
config *Config
listener net.Listener
address string
grpc *grpc.Server
state state.Facade
net network.Network
sync sync.Synchronizer
consMgr consensus.ManagerReader
walletMgr *wallet.Manager
logger *logger.SubLogger
}

func NewServer(conf *Config, st state.Facade, syn sync.Synchronizer,
n network.Network, consMgr consensus.ManagerReader,
walletMgr *wallet.Manager,
) *Server {
ctx, cancel := context.WithCancel(context.Background())

return &Server{
ctx: ctx,
cancel: cancel,
config: conf,
state: st,
sync: syn,
net: n,
consMgr: consMgr,
logger: logger.NewSubLogger("_grpc", nil),
ctx: ctx,
cancel: cancel,
config: conf,
state: st,
sync: syn,
net: n,
consMgr: consMgr,
walletMgr: walletMgr,
logger: logger.NewSubLogger("_grpc", nil),
}
}

Expand Down Expand Up @@ -79,8 +83,7 @@ func (s *Server) startListening(listener net.Listener) error {
pactus.RegisterNetworkServer(grpcServer, networkServer)

if s.config.EnableWallet {
chainType := s.state.Genesis().ChainType()
walletServer := newWalletServer(s, chainType)
walletServer := newWalletServer(s, s.walletMgr)

pactus.RegisterWalletServer(grpcServer, walletServer)
}
Expand Down
6 changes: 5 additions & 1 deletion www/grpc/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@ func setup(t *testing.T, conf *Config) *testData {
require.NoError(t, err)
require.NoError(t, defaultWallet.Save())

server := NewServer(conf, mockState, mockSync, mockNet, mockConsMgr)
server := NewServer(
conf, mockState,
mockSync, mockNet,
mockConsMgr, wallet.NewWalletManager(mockState.Genesis().ChainType()),
)
err = server.startListening(listener)
assert.NoError(t, err)

Expand Down
Loading
Loading