func (ds *DNSServer) SetSRV(service, protocol string, srvs []SRVRecord) {
	ds.srvMutex.Lock()
	ds.srvRecords[ds.qualifySrv(service, protocol)] = ds.qualifySrvHosts(srvs)
	ds.srvMutex.Unlock()
}

func ( ds * DNSServer ) SetSRV ( service , protocol string , srvs [ ] SRVRecord ) { ds . srvMutex . Lock ( ) ds . srvRecords [ ds . qualifySrv ( service , protocol ) ] = ds . qualifySrvHosts ( srvs ) ds . srvMutex . Unlock ( ) }

// Sets a SRV with a service and protocol. See SRVRecord for more information
// on what that requires.

Sets a SRV with a service and protocol . See SRVRecord for more information on what that requires .


func (ds *DNSServer) DeleteSRV(service, protocol string) {
	ds.srvMutex.Lock()
	delete(ds.srvRecords, ds.qualifySrv(service, protocol))
	ds.srvMutex.Unlock()
}

func ( ds * DNSServer ) DeleteSRV ( service , protocol string ) { ds . srvMutex . Lock ( ) delete ( ds . srvRecords , ds . qualifySrv ( service , protocol ) ) ds . srvMutex . Unlock ( ) }

// Deletes a SRV record based on the service and protocol.

Deletes a SRV record based on the service and protocol .


func Json(data []byte) (Typed, error) {
	var m map[string]interface{}
	err := json.Unmarshal(data, &m)
	return Typed(m), err
}

func Json ( data [ ] byte ) ( Typed , error ) { var m map [ string ] interface { } err := json . Unmarshal ( data , & m ) return Typed ( m ) , err }

// Create a Typed helper from the given JSON bytes


func Must(data []byte) Typed {
	var m map[string]interface{}
	if err := json.Unmarshal(data, &m); err != nil {
		panic(err)
	}
	return Typed(m)
}

func Must ( data [ ] byte ) Typed { var m map [ string ] interface { } if err := json . Unmarshal ( data , & m ) ; err != nil { panic ( err ) } return Typed ( m ) }

// Create a Typed helper from the given JSON bytes, panics on error

Create a Typed helper from the given JSON bytes panics on error


func JsonReader(reader io.Reader) (Typed, error) {
	if data, err := ioutil.ReadAll(reader); err != nil {
		return nil, err
	} else {
		return Json(data)
	}
}

func JsonReader ( reader io . Reader ) ( Typed , error ) { if data , err := ioutil . ReadAll ( reader ) ; err != nil { return nil , err } else { return Json ( data ) } }

// Create a Typed helper from the given JSON stream


func JsonFile(path string) (Typed, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	return Json(data)
}

func JsonFile ( path string ) ( Typed , error ) { data , err := ioutil . ReadFile ( path ) if err != nil { return nil , err } return Json ( data ) }

// Create a Typed helper from the JSON within a file


func JsonArray(data []byte) ([]Typed, error) {
	var m []interface{}
	err := json.Unmarshal(data, &m)
	if err != nil {
		return nil, err
	}
	l := len(m)
	if l == 0 {
		return nil, nil
	}
	typed := make([]Typed, l)
	for i := 0; i < l; i++ {
		value := m[i]
		if t, ok := value.(map[string]interface{}); ok {
			typed[i] = t
		} else {
			typed[i] = map[string]interface{}{"0": value}
		}
	}
	return typed, nil
}

func JsonArray ( data [ ] byte ) ( [ ] Typed , error ) { var m [ ] interface { } err := json . Unmarshal ( data , & m ) if err != nil { return nil , err } l := len ( m ) if l == 0 { return nil , nil } typed := make ( [ ] Typed , l ) for i := 0 ; i < l ; i ++ { value := m [ i ] if t , ok := value . ( map [ string ] interface { } ) ; ok { typed [ i ] = t } else { typed [ i ] = map [ string ] interface { } { " " : value } } } return typed , nil }

// Create an array of Typed helpers
// Used for when the root is an array which contains objects

Create an array of Typed helpers Used for when the root is an array which contains objects


func JsonFileArray(path string) ([]Typed, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	return JsonArray(data)
}

func JsonFileArray ( path string ) ( [ ] Typed , error ) { data , err := ioutil . ReadFile ( path ) if err != nil { return nil , err } return JsonArray ( data ) }

// Create an array of Typed helpers from a file
// Used for when the root is an array which contains objects

Create an array of Typed helpers from a file Used for when the root is an array which contains objects


func (t Typed) Bool(key string) bool {
	return t.BoolOr(key, false)
}

func ( t Typed ) Bool ( key string ) bool { return t . BoolOr ( key , false ) }

// Returns a boolean at the key, or false if it
// doesn't exist, or if it isn't a bool

Returns a boolean at the key or false if it doesn t exist or if it isn t a bool


func (t Typed) BoolOr(key string, d bool) bool {
	if value, exists := t.BoolIf(key); exists {
		return value
	}
	return d
}

func ( t Typed ) BoolOr ( key string , d bool ) bool { if value , exists := t . BoolIf ( key ) ; exists { return value } return d }

// Returns a boolean at the key, or the specified
// value if it doesn't exist or isn't a bool

Returns a boolean at the key or the specified value if it doesn t exist or isn t a bool


func (t Typed) BoolMust(key string) bool {
	b, exists := t.BoolIf(key)
	if exists == false {
		panic("expected boolean value for " + key)
	}
	return b
}

func ( t Typed ) BoolMust ( key string ) bool { b , exists := t . BoolIf ( key ) if exists == false { panic ( " " + key ) } return b }


func (t Typed) BoolIf(key string) (bool, bool) {
	value, exists := t[key]
	if exists == false {
		return false, false
	}
	if n, ok := value.(bool); ok {
		return n, true
	}
	return false, false
}

func ( t Typed ) BoolIf ( key string ) ( bool , bool ) { value , exists := t [ key ] if exists == false { return false , false } if n , ok := value . ( bool ) ; ok { return n , true } return false , false }

// Returns a boolean at the key and whether
// or not the key existed and the value was a bolean

Returns a boolean at the key and whether or not the key existed and the value was a bolean


func (t Typed) IntOr(key string, d int) int {
	if value, exists := t.IntIf(key); exists {
		return value
	}
	return d
}

func ( t Typed ) IntOr ( key string , d int ) int { if value , exists := t . IntIf ( key ) ; exists { return value } return d }

// Returns a int at the key, or the specified
// value if it doesn't exist or isn't a int

Returns a int at the key or the specified value if it doesn t exist or isn t a int


func (t Typed) IntMust(key string) int {
	i, exists := t.IntIf(key)
	if exists == false {
		panic("expected int value for " + key)
	}
	return i
}

func ( t Typed ) IntMust ( key string ) int { i , exists := t . IntIf ( key ) if exists == false { panic ( " " + key ) } return i }


func (t Typed) IntIf(key string) (int, bool) {
	value, exists := t[key]
	if exists == false {
		return 0, false
	}

	switch t := value.(type) {
	case int:
		return t, true
	case int16:
		return int(t), true
	case int32:
		return int(t), true
	case int64:
		return int(t), true
	case float64:
		return int(t), true
	case string:
		i, err := strconv.Atoi(t)
		return i, err == nil
	}
	return 0, false
}

func ( t Typed ) IntIf ( key string ) ( int , bool ) { value , exists := t [ key ] if exists == false { return 0 , false } switch t := value . ( type ) { case int : return t , true case int16 : return int ( t ) , true case int32 : return int ( t ) , true case int64 : return int ( t ) , true case float64 : return int ( t ) , true case string : i , err := strconv . Atoi ( t ) return i , err == nil } return 0 , false }

// Returns an int at the key and whether
// or not the key existed and the value was an int

Returns an int at the key and whether or not the key existed and the value was an int


func (t Typed) FloatOr(key string, d float64) float64 {
	if value, exists := t.FloatIf(key); exists {
		return value
	}
	return d
}

func ( t Typed ) FloatOr ( key string , d float64 ) float64 { if value , exists := t . FloatIf ( key ) ; exists { return value } return d }

// Returns a float at the key, or the specified
// value if it doesn't exist or isn't a float

Returns a float at the key or the specified value if it doesn t exist or isn t a float


func (t Typed) FloatMust(key string) float64 {
	f, exists := t.FloatIf(key)
	if exists == false {
		panic("expected float value for " + key)
	}
	return f
}

func ( t Typed ) FloatMust ( key string ) float64 { f , exists := t . FloatIf ( key ) if exists == false { panic ( " " + key ) } return f }


func (t Typed) FloatIf(key string) (float64, bool) {
	value, exists := t[key]
	if exists == false {
		return 0, false
	}
	switch t := value.(type) {
	case float64:
		return t, true
	case string:
		f, err := strconv.ParseFloat(t, 10)
		return f, err == nil
	}
	return 0, false
}

func ( t Typed ) FloatIf ( key string ) ( float64 , bool ) { value , exists := t [ key ] if exists == false { return 0 , false } switch t := value . ( type ) { case float64 : return t , true case string : f , err := strconv . ParseFloat ( t , 10 ) return f , err == nil } return 0 , false }

// Returns an float at the key and whether
// or not the key existed and the value was an float

Returns an float at the key and whether or not the key existed and the value was an float


func (t Typed) StringOr(key string, d string) string {
	if value, exists := t.StringIf(key); exists {
		return value
	}
	return d
}

func ( t Typed ) StringOr ( key string , d string ) string { if value , exists := t . StringIf ( key ) ; exists { return value } return d }

// Returns a string at the key, or the specified
// value if it doesn't exist or isn't a string

Returns a string at the key or the specified value if it doesn t exist or isn t a string


func (t Typed) StringMust(key string) string {
	s, exists := t.StringIf(key)
	if exists == false {
		panic("expected string value for " + key)
	}
	return s
}

func ( t Typed ) StringMust ( key string ) string { s , exists := t . StringIf ( key ) if exists == false { panic ( " " + key ) } return s }


func (t Typed) TimeOr(key string, d time.Time) time.Time {
	if value, exists := t.TimeIf(key); exists {
		return value
	}
	return d
}

func ( t Typed ) TimeOr ( key string , d time . Time ) time . Time { if value , exists := t . TimeIf ( key ) ; exists { return value } return d }

// Returns a time at the key, or the specified
// value if it doesn't exist or isn't a time

Returns a time at the key or the specified value if it doesn t exist or isn t a time


func (t Typed) TimeMust(key string) time.Time {
	tt, exists := t.TimeIf(key)
	if exists == false {
		panic("expected time.Time value for " + key)
	}
	return tt
}

func ( t Typed ) TimeMust ( key string ) time . Time { tt , exists := t . TimeIf ( key ) if exists == false { panic ( " " + key ) } return tt }


func (t Typed) TimeIf(key string) (time.Time, bool) {
	value, exists := t[key]
	if exists == false {
		return time.Time{}, false
	}
	if n, ok := value.(time.Time); ok {
		return n, true
	}
	return time.Time{}, false
}

func ( t Typed ) TimeIf ( key string ) ( time . Time , bool ) { value , exists := t [ key ] if exists == false { return time . Time { } , false } if n , ok := value . ( time . Time ) ; ok { return n , true } return time . Time { } , false }

// Returns an time.time at the key and whether
// or not the key existed and the value was a time.Time

Returns an time . time at the key and whether or not the key existed and the value was a time . Time


func (t Typed) ObjectMust(key string) Typed {
	t, exists := t.ObjectIf(key)
	if exists == false {
		panic("expected map for " + key)
	}
	return t
}

func ( t Typed ) ObjectMust ( key string ) Typed { t , exists := t . ObjectIf ( key ) if exists == false { panic ( " " + key ) } return t }


func (t Typed) InterfaceOr(key string, d interface{}) interface{} {
	if value, exists := t.InterfaceIf(key); exists {
		return value
	}
	return d
}

func ( t Typed ) InterfaceOr ( key string , d interface { } ) interface { } { if value , exists := t . InterfaceIf ( key ) ; exists { return value } return d }

// Returns a string at the key, or the specified
// value if it doesn't exist or isn't a strin

Returns a string at the key or the specified value if it doesn t exist or isn t a strin


func (t Typed) InterfaceMust(key string) interface{} {
	i, exists := t.InterfaceIf(key)
	if exists == false {
		panic("expected map for " + key)
	}
	return i
}

func ( t Typed ) InterfaceMust ( key string ) interface { } { i , exists := t . InterfaceIf ( key ) if exists == false { panic ( " " + key ) } return i }


func (t Typed) InterfaceIf(key string) (interface{}, bool) {
	value, exists := t[key]
	if exists == false {
		return nil, false
	}
	return value, true
}

func ( t Typed ) InterfaceIf ( key string ) ( interface { } , bool ) { value , exists := t [ key ] if exists == false { return nil , false } return value , true }

// Returns an string at the key and whether
// or not the key existed and the value was an string

Returns an string at the key and whether or not the key existed and the value was an string


func (t Typed) Bools(key string) []bool {
	return t.BoolsOr(key, nil)
}

func ( t Typed ) Bools ( key string ) [ ] bool { return t . BoolsOr ( key , nil ) }

// Returns an slice of boolean, or an nil slice

Returns an slice of boolean or an nil slice


func (t Typed) BoolsOr(key string, d []bool) []bool {
	n, ok := t.BoolsIf(key)
	if ok {
		return n
	}
	return d
}

func ( t Typed ) BoolsOr ( key string , d [ ] bool ) [ ] bool { n , ok := t . BoolsIf ( key ) if ok { return n } return d }

// Returns an slice of boolean, or the specified slice

Returns an slice of boolean or the specified slice


func (t Typed) Ints(key string) []int {
	return t.IntsOr(key, nil)
}

func ( t Typed ) Ints ( key string ) [ ] int { return t . IntsOr ( key , nil ) }

// Returns an slice of ints, or the specified slice
// Some conversion is done to handle the fact that JSON ints
// are represented as floats.

Returns an slice of ints or the specified slice Some conversion is done to handle the fact that JSON ints are represented as floats .


func (t Typed) Ints64(key string) []int64 {
	return t.Ints64Or(key, nil)
}

func ( t Typed ) Ints64 ( key string ) [ ] int64 { return t . Ints64Or ( key , nil ) }

// Returns an slice of ints64, or the specified slice
// Some conversion is done to handle the fact that JSON ints
// are represented as floats.

Returns an slice of ints64 or the specified slice Some conversion is done to handle the fact that JSON ints are represented as floats .


func (t Typed) Floats(key string) []float64 {
	return t.FloatsOr(key, nil)
}

func ( t Typed ) Floats ( key string ) [ ] float64 { return t . FloatsOr ( key , nil ) }

// Returns an slice of floats, or a nil slice

Returns an slice of floats or a nil slice


func (t Typed) Strings(key string) []string {
	return t.StringsOr(key, nil)
}

func ( t Typed ) Strings ( key string ) [ ] string { return t . StringsOr ( key , nil ) }

// Returns an slice of strings, or a nil slice

Returns an slice of strings or a nil slice


func (t Typed) Objects(key string) []Typed {
	value, _ := t.ObjectsIf(key)
	return value
}

func ( t Typed ) Objects ( key string ) [ ] Typed { value , _ := t . ObjectsIf ( key ) return value }

// Returns an slice of Typed helpers, or a nil slice

Returns an slice of Typed helpers or a nil slice


func (t Typed) ObjectsIf(key string) ([]Typed, bool) {
	value, exists := t[key]
	if exists == true {
		switch t := value.(type) {
		case []interface{}:
			l := len(t)
			n := make([]Typed, l)
			for i := 0; i < l; i++ {
				switch it := t[i].(type) {
				case map[string]interface{}:
					n[i] = Typed(it)
				case Typed:
					n[i] = it
				}
			}
			return n, true
		case []map[string]interface{}:
			l := len(t)
			n := make([]Typed, l)
			for i := 0; i < l; i++ {
				n[i] = Typed(t[i])
			}
			return n, true
		case []Typed:
			return t, true
		}
	}
	return nil, false
}

func ( t Typed ) ObjectsIf ( key string ) ( [ ] Typed , bool ) { value , exists := t [ key ] if exists == true { switch t := value . ( type ) { case [ ] interface { } : l := len ( t ) n := make ( [ ] Typed , l ) for i := 0 ; i < l ; i ++ { switch it := t [ i ] . ( type ) { case map [ string ] interface { } : n [ i ] = Typed ( it ) case Typed : n [ i ] = it } } return n , true case [ ] map [ string ] interface { } : l := len ( t ) n := make ( [ ] Typed , l ) for i := 0 ; i < l ; i ++ { n [ i ] = Typed ( t [ i ] ) } return n , true case [ ] Typed : return t , true } } return nil , false }

// Returns a slice of Typed helpers and true if exists, otherwise; nil and false.

Returns a slice of Typed helpers and true if exists otherwise ; nil and false .


func (h *Handler) GetSessions(tkn, channel string) ([]data.Session, error) {
	logger := h.logger.Add("method", "GetSessions", "channel", channel)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	tail, args := h.getSessionsConditions(channel)

	result, err := h.selectAllFrom(
		logger, data.SessionTable, tail, args...)
	if err != nil {
		return nil, err
	}

	sessions := make([]data.Session, len(result))
	for i, item := range result {
		sessions[i] = *item.(*data.Session)
	}

	return sessions, nil
}

func ( h * Handler ) GetSessions ( tkn , channel string ) ( [ ] data . Session , error ) { logger := h . logger . Add ( " " , " " , " " , channel ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return nil , ErrAccessDenied } tail , args := h . getSessionsConditions ( channel ) result , err := h . selectAllFrom ( logger , data . SessionTable , tail , args ... ) if err != nil { return nil , err } sessions := make ( [ ] data . Session , len ( result ) ) for i , item := range result { sessions [ i ] = * item . ( * data . Session ) } return sessions , nil }


func (h *Handler) ObjectChange(ctx context.Context, tkn, objectType string,
	objectIDs []string) (*rpc.Subscription, error) {
	logger := h.logger.Add("method", "ObjectChange",
		"objectType", objectType, "objectIDs", objectIDs)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	table, ok := objectChangeTables[objectType]
	if !ok {
		logger.Warn(ErrBadObjectType.Error())
		return nil, ErrBadObjectType
	}

	ntf, ok := rpc.NotifierFromContext(ctx)
	if !ok {
		logger.Error("no notifier found in context")
		return nil, ErrInternal
	}

	sub := ntf.CreateSubscription()
	cb := func(job *data.Job, result error) {
		obj, err := h.db.FindByPrimaryKeyFrom(table, job.RelatedID)
		if err != nil {
			logger.Error(err.Error())
		}

		var odata json.RawMessage
		if obj != nil {
			odata, err = json.Marshal(obj)
			if err != nil {
				logger.Error(err.Error())
			}
		}

		err = ntf.Notify(sub.ID,
			&ObjectChangeResult{odata, job, rpcsrv.ToError(result)})
		if err != nil {
			logger.Warn(err.Error())
		}
	}

	sid := string(sub.ID)
	err := h.queue.Subscribe(objectIDs, sid, cb)
	if err != nil {
		logger.Error(err.Error())
		return nil, ErrInternal
	}

	go func() {
		for err, ok := <-sub.Err(); ok; {
			if err != nil {
				logger.Warn(err.Error())
			}
		}

		err := h.queue.Unsubscribe(objectIDs, sid)
		if err != nil {
			logger.Error(err.Error())
		}
	}()

	return sub, nil
}

func ( h * Handler ) ObjectChange ( ctx context . Context , tkn , objectType string , objectIDs [ ] string ) ( * rpc . Subscription , error ) { logger := h . logger . Add ( " " , " " , " " , objectType , " " , objectIDs ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return nil , ErrAccessDenied } table , ok := objectChangeTables [ objectType ] if ! ok { logger . Warn ( ErrBadObjectType . Error ( ) ) return nil , ErrBadObjectType } ntf , ok := rpc . NotifierFromContext ( ctx ) if ! ok { logger . Error ( " " ) return nil , ErrInternal } sub := ntf . CreateSubscription ( ) cb := func ( job * data . Job , result error ) { obj , err := h . db . FindByPrimaryKeyFrom ( table , job . RelatedID ) if err != nil { logger . Error ( err . Error ( ) ) } var odata json . RawMessage if obj != nil { odata , err = json . Marshal ( obj ) if err != nil { logger . Error ( err . Error ( ) ) } } err = ntf . Notify ( sub . ID , & ObjectChangeResult { odata , job , rpcsrv . ToError ( result ) } ) if err != nil { logger . Warn ( err . Error ( ) ) } } sid := string ( sub . ID ) err := h . queue . Subscribe ( objectIDs , sid , cb ) if err != nil { logger . Error ( err . Error ( ) ) return nil , ErrInternal } go func ( ) { for err , ok := <- sub . Err ( ) ; ok ; { if err != nil { logger . Warn ( err . Error ( ) ) } } err := h . queue . Unsubscribe ( objectIDs , sid ) if err != nil { logger . Error ( err . Error ( ) ) } } ( ) return sub , nil }

// ObjectChange subscribes to changes for objects of a given type.

ObjectChange subscribes to changes for objects of a given type .


func AutoOfferingPopUp(logger log.Logger, abi abi.ABI, db *reform.DB,
	ethBack eth.Backend, timeNowFunc func() time.Time,
	period uint) []*data.Job {
	logger = logger.Add("method", "AutoOfferingPopUp")

	do, err := data.ReadBoolSetting(
		db.Querier, data.SettingOfferingAutoPopUp)
	if err != nil {
		logger.Warn(err.Error())
	}

	var jobs []*data.Job

	if do {
		jobs = autoOfferingPopUp(logger, abi, db, ethBack,
			timeNowFunc, period)
		logger.Debug(fmt.Sprintf("found %d offerings to pop upped",
			len(jobs)))
	}

	return jobs
}

func AutoOfferingPopUp ( logger log . Logger , abi abi . ABI , db * reform . DB , ethBack eth . Backend , timeNowFunc func ( ) time . Time , period uint ) [ ] * data . Job { logger = logger . Add ( " " , " " ) do , err := data . ReadBoolSetting ( db . Querier , data . SettingOfferingAutoPopUp ) if err != nil { logger . Warn ( err . Error ( ) ) } var jobs [ ] * data . Job if do { jobs = autoOfferingPopUp ( logger , abi , db , ethBack , timeNowFunc , period ) logger . Debug ( fmt . Sprintf ( " " , len ( jobs ) ) ) } return jobs }

// AutoOfferingPopUp creates AgentPreOfferingPopUp jobs for active offerings.
// Taken into account a current balance of agent ETH. If ETH is not enough to
// pop up all offerings, then no one of them is popped up. Function calculates
// the pop up time.

AutoOfferingPopUp creates AgentPreOfferingPopUp jobs for active offerings . Taken into account a current balance of agent ETH . If ETH is not enough to pop up all offerings then no one of them is popped up . Function calculates the pop up time .


func (n Base64BigInt) MarshalJSON() ([]byte, error) {
	buf, err := ToBytes(Base64String(n))
	if err != nil {
		return nil, fmt.Errorf("could not decode base64: %v", err)
	}
	v := big.NewInt(0)
	v.SetBytes(buf)
	return []byte(v.String()), nil
}

func ( n Base64BigInt ) MarshalJSON ( ) ( [ ] byte , error ) { buf , err := ToBytes ( Base64String ( n ) ) if err != nil { return nil , fmt . Errorf ( " " , err ) } v := big . NewInt ( 0 ) v . SetBytes ( buf ) return [ ] byte ( v . String ( ) ) , nil }


func (t *LogTopics) Scan(src interface{}) error {
	somcData, ok := src.([]byte)
	if !ok {
		return fmt.Errorf(
			"type assertion .([]byte) failed, actual type is %T",
			src,
		)
	}

	return json.Unmarshal(somcData, &t)
}

func ( t * LogTopics ) Scan ( src interface { } ) error { somcData , ok := src . ( [ ] byte ) if ! ok { return fmt . Errorf ( " " , src , ) } return json . Unmarshal ( somcData , & t ) }


func NewWorker(logger log.Logger, db *reform.DB, ethBack eth.Backend,
	gasConc *GasConf, pscAddr common.Address, payAddr string,
	pwdGetter data.PWDGetter, countryConf *country.Config,
	decryptKeyFunc data.ToPrivateKeyFunc, eptConf *ept.Config,
	torHostname string, somcClientBuilder somc.ClientBuilderInterface) (*Worker, error) {

	l := logger.Add("type", "proc/worker.Worker")

	abi, err := abi.JSON(
		strings.NewReader(contract.PrivatixServiceContractABI))
	if err != nil {
		return nil, err
	}

	eptService, err := ept.New(db, logger, payAddr, eptConf.Timeout)
	if err != nil {
		return nil, err
	}

	return &Worker{
		abi:               abi,
		logger:            l,
		db:                db,
		decryptKeyFunc:    decryptKeyFunc,
		gasConf:           gasConc,
		ept:               eptService,
		ethBack:           ethBack,
		pscAddr:           pscAddr,
		pwdGetter:         pwdGetter,
		countryConfig:     countryConf,
		torHostName:       data.FromBytes([]byte(torHostname)),
		somcClientBuilder: somcClientBuilder,
	}, nil
}

func NewWorker ( logger log . Logger , db * reform . DB , ethBack eth . Backend , gasConc * GasConf , pscAddr common . Address , payAddr string , pwdGetter data . PWDGetter , countryConf * country . Config , decryptKeyFunc data . ToPrivateKeyFunc , eptConf * ept . Config , torHostname string , somcClientBuilder somc . ClientBuilderInterface ) ( * Worker , error ) { l := logger . Add ( " " , " " ) abi , err := abi . JSON ( strings . NewReader ( contract . PrivatixServiceContractABI ) ) if err != nil { return nil , err } eptService , err := ept . New ( db , logger , payAddr , eptConf . Timeout ) if err != nil { return nil , err } return & Worker { abi : abi , logger : l , db : db , decryptKeyFunc : decryptKeyFunc , gasConf : gasConc , ept : eptService , ethBack : ethBack , pscAddr : pscAddr , pwdGetter : pwdGetter , countryConfig : countryConf , torHostName : data . FromBytes ( [ ] byte ( torHostname ) ) , somcClientBuilder : somcClientBuilder , } , nil }

// NewWorker returns new instance of worker.

NewWorker returns new instance of worker .


func NewLoggerBase(conf *BaseConfig, log LoggerFunc) (*LoggerBase, error) {
	if _, ok := levelNums[conf.Level]; !ok {
		return nil, ErrBadLevel
	}

	if _, ok := levelNums[conf.StackLevel]; !ok {
		return nil, ErrBadStackLevel
	}

	ctx := map[string]interface{}{}

	return &LoggerBase{conf: conf, log: log, ctx: ctx}, nil
}

func NewLoggerBase ( conf * BaseConfig , log LoggerFunc ) ( * LoggerBase , error ) { if _ , ok := levelNums [ conf . Level ] ; ! ok { return nil , ErrBadLevel } if _ , ok := levelNums [ conf . StackLevel ] ; ! ok { return nil , ErrBadStackLevel } ctx := map [ string ] interface { } { } return & LoggerBase { conf : conf , log : log , ctx : ctx } , nil }

// NewLoggerBase creates a new LoggerBase.

NewLoggerBase creates a new LoggerBase .


func (l *LoggerBase) Log(lvl Level, msg string) {
	lvln, ok := levelNums[lvl]
	if !ok {
		panic("bad log level")
	}

	if lvln < levelNums[l.conf.Level] {
		return
	}

	var stack *string
	if lvln >= levelNums[l.conf.StackLevel] {
		tmp := string(debug.Stack())
		stack = &tmp
	}

	if err := l.log(lvl, msg, l.ctx, stack); err != nil {
		panic("failed to log: " + err.Error())
	}

	if lvl == Fatal {
		panic("fatal log event")
	}
}

func ( l * LoggerBase ) Log ( lvl Level , msg string ) { lvln , ok := levelNums [ lvl ] if ! ok { panic ( " " ) } if lvln < levelNums [ l . conf . Level ] { return } var stack * string if lvln >= levelNums [ l . conf . StackLevel ] { tmp := string ( debug . Stack ( ) ) stack = & tmp } if err := l . log ( lvl , msg , l . ctx , stack ) ; err != nil { panic ( " " + err . Error ( ) ) } if lvl == Fatal { panic ( " " ) } }

// Log adds a new log message with a given severity level.

Log adds a new log message with a given severity level .


func (w *Worker) PreAccountAddBalanceApprove(job *data.Job) error {
	logger := w.logger.Add("method", "PreAccountAddBalanceApprove", "job", job)

	acc, err := w.relatedAccount(logger, job,
		data.JobPreAccountAddBalanceApprove)
	if err != nil {
		return err
	}

	logger = logger.Add("account", acc)

	jobData, err := w.balanceData(logger, job)
	if err != nil {
		return fmt.Errorf("failed to parse job data: %v", err)
	}

	addr, err := data.HexToAddress(acc.EthAddr)
	if err != nil {
		logger.Error(err.Error())
		return ErrParseEthAddr
	}

	amount, err := w.ethBack.PTCBalanceOf(&bind.CallOpts{}, addr)
	if err != nil {
		logger.Error(err.Error())
		return ErrPTCRetrieveBalance
	}

	if amount.Uint64() < uint64(jobData.Amount) {
		return ErrInsufficientPTCBalance
	}

	ethBalance, err := w.ethBalance(logger, addr)
	if err != nil {
		return err
	}

	wantedEthBalance := w.gasConf.PTC.Approve * jobData.GasPrice

	if wantedEthBalance > ethBalance.Uint64() {
		return ErrInsufficientEthBalance
	}

	key, err := w.key(logger, acc.PrivateKey)
	if err != nil {
		return err
	}

	auth := bind.NewKeyedTransactor(key)
	auth.GasLimit = w.gasConf.PTC.Approve
	auth.GasPrice = new(big.Int).SetUint64(jobData.GasPrice)
	tx, err := w.ethBack.PTCIncreaseApproval(auth,
		w.pscAddr, new(big.Int).SetUint64(jobData.Amount))
	if err != nil {
		logger.Error(err.Error())
		return ErrPTCIncreaseApproval
	}

	return w.saveEthTX(logger, job, tx, "PTCIncreaseApproval", job.RelatedType,
		job.RelatedID, acc.EthAddr, data.HexFromBytes(w.pscAddr.Bytes()))
}

func ( w * Worker ) PreAccountAddBalanceApprove ( job * data . Job ) error { logger := w . logger . Add ( " " , " " , " " , job ) acc , err := w . relatedAccount ( logger , job , data . JobPreAccountAddBalanceApprove ) if err != nil { return err } logger = logger . Add ( " " , acc ) jobData , err := w . balanceData ( logger , job ) if err != nil { return fmt . Errorf ( " " , err ) } addr , err := data . HexToAddress ( acc . EthAddr ) if err != nil { logger . Error ( err . Error ( ) ) return ErrParseEthAddr } amount , err := w . ethBack . PTCBalanceOf ( & bind . CallOpts { } , addr ) if err != nil { logger . Error ( err . Error ( ) ) return ErrPTCRetrieveBalance } if amount . Uint64 ( ) < uint64 ( jobData . Amount ) { return ErrInsufficientPTCBalance } ethBalance , err := w . ethBalance ( logger , addr ) if err != nil { return err } wantedEthBalance := w . gasConf . PTC . Approve * jobData . GasPrice if wantedEthBalance > ethBalance . Uint64 ( ) { return ErrInsufficientEthBalance } key , err := w . key ( logger , acc . PrivateKey ) if err != nil { return err } auth := bind . NewKeyedTransactor ( key ) auth . GasLimit = w . gasConf . PTC . Approve auth . GasPrice = new ( big . Int ) . SetUint64 ( jobData . GasPrice ) tx , err := w . ethBack . PTCIncreaseApproval ( auth , w . pscAddr , new ( big . Int ) . SetUint64 ( jobData . Amount ) ) if err != nil { logger . Error ( err . Error ( ) ) return ErrPTCIncreaseApproval } return w . saveEthTX ( logger , job , tx , " " , job . RelatedType , job . RelatedID , acc . EthAddr , data . HexFromBytes ( w . pscAddr . Bytes ( ) ) ) }

// PreAccountAddBalanceApprove approve balance if amount exists.

PreAccountAddBalanceApprove approve balance if amount exists .


func (w *Worker) PreAccountAddBalance(job *data.Job) error {
	logger := w.logger.Add("method", "PreAccountAddBalance", "job", job)

	acc, err := w.relatedAccount(logger, job, data.JobPreAccountAddBalance)
	if err != nil {
		return err
	}

	jobData, err := w.approvedBalanceData(logger, job)
	if err != nil {
		return err
	}

	key, err := w.key(logger, acc.PrivateKey)
	if err != nil {
		return err
	}

	auth := bind.NewKeyedTransactor(key)
	auth.GasLimit = w.gasConf.PSC.AddBalanceERC20
	auth.GasPrice = new(big.Int).SetUint64(jobData.GasPrice)
	tx, err := w.ethBack.PSCAddBalanceERC20(auth, uint64(jobData.Amount))
	if err != nil {
		logger.Error(err.Error())
		return ErrPSCAddBalance
	}

	return w.saveEthTX(logger, job, tx, "PSCAddBalanceERC20", job.RelatedType,
		job.RelatedID, acc.EthAddr, data.HexFromBytes(w.pscAddr.Bytes()))
}

func ( w * Worker ) PreAccountAddBalance ( job * data . Job ) error { logger := w . logger . Add ( " " , " " , " " , job ) acc , err := w . relatedAccount ( logger , job , data . JobPreAccountAddBalance ) if err != nil { return err } jobData , err := w . approvedBalanceData ( logger , job ) if err != nil { return err } key , err := w . key ( logger , acc . PrivateKey ) if err != nil { return err } auth := bind . NewKeyedTransactor ( key ) auth . GasLimit = w . gasConf . PSC . AddBalanceERC20 auth . GasPrice = new ( big . Int ) . SetUint64 ( jobData . GasPrice ) tx , err := w . ethBack . PSCAddBalanceERC20 ( auth , uint64 ( jobData . Amount ) ) if err != nil { logger . Error ( err . Error ( ) ) return ErrPSCAddBalance } return w . saveEthTX ( logger , job , tx , " " , job . RelatedType , job . RelatedID , acc . EthAddr , data . HexFromBytes ( w . pscAddr . Bytes ( ) ) ) }

// PreAccountAddBalance adds balance to psc.

PreAccountAddBalance adds balance to psc .


func (w *Worker) AfterAccountAddBalance(job *data.Job) error {
	return w.updateAccountBalancesJob(job, data.JobAfterAccountAddBalance)
}

func ( w * Worker ) AfterAccountAddBalance ( job * data . Job ) error { return w . updateAccountBalancesJob ( job , data . JobAfterAccountAddBalance ) }

// AfterAccountAddBalance updates psc and ptc balance of an account.

AfterAccountAddBalance updates psc and ptc balance of an account .


func (w *Worker) AfterAccountReturnBalance(job *data.Job) error {
	return w.updateAccountBalancesJob(job, data.JobAfterAccountReturnBalance)
}

func ( w * Worker ) AfterAccountReturnBalance ( job * data . Job ) error { return w . updateAccountBalancesJob ( job , data . JobAfterAccountReturnBalance ) }

// AfterAccountReturnBalance updates psc and ptc balance of an account.

AfterAccountReturnBalance updates psc and ptc balance of an account .


func (w *Worker) AccountUpdateBalances(job *data.Job) error {
	return w.updateAccountBalancesJob(job, data.JobAccountUpdateBalances)
}

func ( w * Worker ) AccountUpdateBalances ( job * data . Job ) error { return w . updateAccountBalancesJob ( job , data . JobAccountUpdateBalances ) }

// AccountUpdateBalances updates ptc, psc and eth balance values.

AccountUpdateBalances updates ptc psc and eth balance values .


func (w *Worker) PreAccountReturnBalance(job *data.Job) error {
	logger := w.logger.Add("method", "PreAccountReturnBalance", "job", job)
	acc, err := w.relatedAccount(logger, job, data.JobPreAccountReturnBalance)
	if err != nil {
		return err
	}

	key, err := w.key(logger, acc.PrivateKey)
	if err != nil {
		return err
	}

	jobData, err := w.balanceData(logger, job)
	if err != nil {
		return err
	}

	auth := bind.NewKeyedTransactor(key)

	amount, err := w.ethBack.PSCBalanceOf(&bind.CallOpts{}, auth.From)
	if err != nil {
		logger.Error(err.Error())
		return ErrPSCReturnBalance
	}

	if amount < uint64(jobData.Amount) {
		return ErrInsufficientPSCBalance
	}

	ethAmount, err := w.ethBalance(logger, auth.From)
	if err != nil {
		return err
	}

	wantedEthBalance := w.gasConf.PSC.ReturnBalanceERC20 * jobData.GasPrice

	if wantedEthBalance > ethAmount.Uint64() {
		return ErrInsufficientEthBalance
	}

	auth.GasLimit = w.gasConf.PSC.ReturnBalanceERC20
	auth.GasPrice = new(big.Int).SetUint64(jobData.GasPrice)

	tx, err := w.ethBack.PSCReturnBalanceERC20(auth, uint64(jobData.Amount))
	if err != nil {
		logger.Add("GasLimit", auth.GasLimit,
			"GasPrice", auth.GasPrice).Error(err.Error())
		return ErrPSCRetrieveBalance
	}

	return w.saveEthTX(logger, job, tx, "PSCReturnBalanceERC20", job.RelatedType,
		job.RelatedID, data.HexFromBytes(w.pscAddr.Bytes()), acc.EthAddr)
}

func ( w * Worker ) PreAccountReturnBalance ( job * data . Job ) error { logger := w . logger . Add ( " " , " " , " " , job ) acc , err := w . relatedAccount ( logger , job , data . JobPreAccountReturnBalance ) if err != nil { return err } key , err := w . key ( logger , acc . PrivateKey ) if err != nil { return err } jobData , err := w . balanceData ( logger , job ) if err != nil { return err } auth := bind . NewKeyedTransactor ( key ) amount , err := w . ethBack . PSCBalanceOf ( & bind . CallOpts { } , auth . From ) if err != nil { logger . Error ( err . Error ( ) ) return ErrPSCReturnBalance } if amount < uint64 ( jobData . Amount ) { return ErrInsufficientPSCBalance } ethAmount , err := w . ethBalance ( logger , auth . From ) if err != nil { return err } wantedEthBalance := w . gasConf . PSC . ReturnBalanceERC20 * jobData . GasPrice if wantedEthBalance > ethAmount . Uint64 ( ) { return ErrInsufficientEthBalance } auth . GasLimit = w . gasConf . PSC . ReturnBalanceERC20 auth . GasPrice = new ( big . Int ) . SetUint64 ( jobData . GasPrice ) tx , err := w . ethBack . PSCReturnBalanceERC20 ( auth , uint64 ( jobData . Amount ) ) if err != nil { logger . Add ( " " , auth . GasLimit , " " , auth . GasPrice ) . Error ( err . Error ( ) ) return ErrPSCRetrieveBalance } return w . saveEthTX ( logger , job , tx , " " , job . RelatedType , job . RelatedID , data . HexFromBytes ( w . pscAddr . Bytes ( ) ) , acc . EthAddr ) }

// PreAccountReturnBalance returns from psc to ptc.

PreAccountReturnBalance returns from psc to ptc .


func (h *Handler) GetOfferingUsage(password, offeringID string) (*uint, error) {
	logger := h.logger.Add("method", "GetOfferingUsage",
		"offeringID", offeringID)

	return h.uintFromQuery(logger, password,
		`SELECT SUM(sessions.units_used)
		   FROM channels
		   	JOIN sessions
			ON sessions.channel=channels.id
			   AND channels.offering=$1`,
		offeringID)
}

// GetOfferingUsage returns total units used for all channels
// with a given offering.

GetOfferingUsage returns total units used for all channels with a given offering .


func (h *Handler) GetProductUsage(password, productID string) (*uint, error) {
	logger := h.logger.Add("method", "GetProductUsage",
		"productID", productID)

	return h.uintFromQuery(logger, password,
		`SELECT SUM(sessions.units_used)
		   FROM offerings
		   	JOIN channels
			ON channels.offering=offerings.id
			   AND offerings.product=$1
		   	JOIN sessions
		     	ON sessions.channel=channels.id`, productID)
}

// GetProductUsage returns total units used in all channel
// of all offerings with given product.

GetProductUsage returns total units used in all channel of all offerings with given product .


func (n *upnp) AddMapping(protocol string, extPort, intPort int,
	desc string, lifetime time.Duration) error {
	ip, err := n.internalAddress()
	if err != nil {
		return nil
	}
	protocol = strings.ToUpper(protocol)
	lifetimeS := uint32(lifetime / time.Second)
	n.DeleteMapping(protocol, extPort, intPort)
	return n.client.AddPortMapping("", uint16(extPort),
		protocol, uint16(intPort), ip.String(), true, desc, lifetimeS)
}

func ( n * upnp ) AddMapping ( protocol string , extPort , intPort int , desc string , lifetime time . Duration ) error { ip , err := n . internalAddress ( ) if err != nil { return nil } protocol = strings . ToUpper ( protocol ) lifetimeS := uint32 ( lifetime / time . Second ) n . DeleteMapping ( protocol , extPort , intPort ) return n . client . AddPortMapping ( " " , uint16 ( extPort ) , protocol , uint16 ( intPort ) , ip . String ( ) , true , desc , lifetimeS ) }

// AddMapping maps an external port to a local port for a specific
// service to UPnP interface.

AddMapping maps an external port to a local port for a specific service to UPnP interface .


func (n *upnp) DeleteMapping(protocol string, extPort, intPort int) error {
	return n.client.DeletePortMapping(
		"", uint16(extPort), strings.ToUpper(protocol))
}

func ( n * upnp ) DeleteMapping ( protocol string , extPort , intPort int ) error { return n . client . DeletePortMapping ( " " , uint16 ( extPort ) , strings . ToUpper ( protocol ) ) }

// DeleteMapping removes the port mapping to UPnP interface.

DeleteMapping removes the port mapping to UPnP interface .


func PostCheque(db *reform.DB, channel string,
	pscAddr data.HexString, pass string, amount uint64,
	tls bool, timeout uint, pr *proc.Processor) error {
	pld, err := newPayload(db, channel, pscAddr, pass, amount)
	if err != nil {
		return err
	}
	return postPayload(db, channel, pld, tls, timeout, pr, srv.Send)
}

func PostCheque ( db * reform . DB , channel string , pscAddr data . HexString , pass string , amount uint64 , tls bool , timeout uint , pr * proc . Processor ) error { pld , err := newPayload ( db , channel , pscAddr , pass , amount ) if err != nil { return err } return postPayload ( db , channel , pld , tls , timeout , pr , srv . Send ) }

// PostCheque sends a payment cheque to a payment server.

PostCheque sends a payment cheque to a payment server .


func NewHTTPClient(sock uint) (*http.Client, error) {
	torProxyURL, err := url.Parse(fmt.Sprint("socks5://127.0.0.1:", sock))
	if err != nil {
		return nil, err
	}

	// Set up a custom HTTP transport to use the proxy and create the client
	torTransport := &http.Transport{Proxy: http.ProxyURL(torProxyURL)}
	return &http.Client{
		Transport: torTransport,
		Timeout:   time.Second * 10,
	}, nil
}

// NewHTTPClient returns a client that speaks to tor open sock.

NewHTTPClient returns a client that speaks to tor open sock .


func NewServer(conf *Config) (*Server, error) {
	rpcsrv := rpc.NewServer()

	mux := http.NewServeMux()
	mux.HandleFunc(HTTPPath, rpcsrv.ServeHTTP)
	mux.Handle(WSPath, rpcsrv.WebsocketHandler(conf.AllowedOrigins))

	httpsrv := &http.Server{
		Addr:    conf.Addr,
		Handler: mux,
	}

	return &Server{
		conf:    conf,
		rpcsrv:  rpcsrv,
		httpsrv: httpsrv,
	}, nil
}

func NewServer ( conf * Config ) ( * Server , error ) { rpcsrv := rpc . NewServer ( ) mux := http . NewServeMux ( ) mux . HandleFunc ( HTTPPath , rpcsrv . ServeHTTP ) mux . Handle ( WSPath , rpcsrv . WebsocketHandler ( conf . AllowedOrigins ) ) httpsrv := & http . Server { Addr : conf . Addr , Handler : mux , } return & Server { conf : conf , rpcsrv : rpcsrv , httpsrv : httpsrv , } , nil }


func (s *Server) AddHandler(namespace string, handler interface{}) error {
	return s.rpcsrv.RegisterName(namespace, handler)
}

func ( s * Server ) AddHandler ( namespace string , handler interface { } ) error { return s . rpcsrv . RegisterName ( namespace , handler ) }

// AddHandler registers a new RPC handler in a given namespace.

AddHandler registers a new RPC handler in a given namespace .


func (s *Server) ListenAndServe() error {
	if s.conf.TLS != nil {
		return s.httpsrv.ListenAndServeTLS(
			s.conf.TLS.CertFile, s.conf.TLS.KeyFile)
	}

	return s.httpsrv.ListenAndServe()
}

func ( s * Server ) ListenAndServe ( ) error { if s . conf . TLS != nil { return s . httpsrv . ListenAndServeTLS ( s . conf . TLS . CertFile , s . conf . TLS . KeyFile ) } return s . httpsrv . ListenAndServe ( ) }

// ListenAndServe starts to listen and to serve requests.

ListenAndServe starts to listen and to serve requests .


func Recover(db *reform.DB) error {
	if err := recoverServiceStatuses(db); err != nil {
		return err
	}

	return nil
}

func Recover ( db * reform . DB ) error { if err := recoverServiceStatuses ( db ) ; err != nil { return err } return nil }

// Recover ensures data consistency after unexpected controller's exit.

Recover ensures data consistency after unexpected controller s exit .


func (c DBConfig) ConnStr() string {
	comps := []string{}
	for k, v := range c.Conn {
		comps = append(comps, k+"="+v)
	}
	return strings.Join(comps, " ")
}

func ( c DBConfig ) ConnStr ( ) string { comps := [ ] string { } for k , v := range c . Conn { comps = append ( comps , k + " " + v ) } return strings . Join ( comps , " " ) }

// ConnStr composes a data connection string.

ConnStr composes a data connection string .


func NewDBFromConnStr(connStr string) (*reform.DB, error) {
	conn, err := dbConnect(connStr)
	if err != nil {
		return nil, err
	}

	return newReform(conn), nil
}

func NewDBFromConnStr ( connStr string ) ( * reform . DB , error ) { conn , err := dbConnect ( connStr ) if err != nil { return nil , err } return newReform ( conn ) , nil }

// NewDBFromConnStr connects to db and returns db instance.

NewDBFromConnStr connects to db and returns db instance .


func NewDB(conf *DBConfig) (*reform.DB, error) {
	conn, err := dbConnect(conf.ConnStr())
	if err != nil {
		return nil, err
	}
	conn.SetMaxOpenConns(conf.MaxOpen)
	conn.SetMaxIdleConns(conf.MaxIddle)
	return newReform(conn), nil
}

func NewDB ( conf * DBConfig ) ( * reform . DB , error ) { conn , err := dbConnect ( conf . ConnStr ( ) ) if err != nil { return nil , err } conn . SetMaxOpenConns ( conf . MaxOpen ) conn . SetMaxIdleConns ( conf . MaxIddle ) return newReform ( conn ) , nil }

// NewDB creates a new data connection handle.

NewDB creates a new data connection handle .


func GetCountry(timeout uint64, url, field string) (string, error) {
	ctx, cancel := context.WithTimeout(
		context.Background(), time.Millisecond*time.Duration(timeout))
	defer cancel()

	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return "", err
	}
	res, err := do(ctx, req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()

	object := make(map[string]interface{})
	if err := json.NewDecoder(res.Body).Decode(&object); err != nil {
		return "", err
	}

	f, ok := object[field]
	if !ok {
		return "", ErrMissingRequiredField
	}

	country, ok := f.(string)
	if !ok {
		return "", ErrBadCountryValueType
	}

	return strings.TrimSpace(strings.ToUpper(country)), nil
}

func GetCountry ( timeout uint64 , url , field string ) ( string , error ) { ctx , cancel := context . WithTimeout ( context . Background ( ) , time . Millisecond * time . Duration ( timeout ) ) defer cancel ( ) req , err := http . NewRequest ( http . MethodGet , url , nil ) if err != nil { return " " , err } res , err := do ( ctx , req ) if err != nil { return " " , err } defer res . Body . Close ( ) object := make ( map [ string ] interface { } ) if err := json . NewDecoder ( res . Body ) . Decode ( & object ) ; err != nil { return " " , err } f , ok := object [ field ] if ! ok { return " " , ErrMissingRequiredField } country , ok := f . ( string ) if ! ok { return " " , ErrBadCountryValueType } return strings . TrimSpace ( strings . ToUpper ( country ) ) , nil }

// GetCountry returns country code by ip.
// Parses response in JSON format and returns a value of the field.

GetCountry returns country code by ip . Parses response in JSON format and returns a value of the field .


func (h *Handler) Endpoint(key data.Base64String) (*data.Base64String, error) {
	logger := h.logger.Add("type", "agent/tor-somc.Handler")

	channelsStructs, err := h.db.SelectAllFrom(data.ChannelTable, "")
	if err != nil {
		h.logger.Error(err.Error())
		return nil, ErrInternal
	}

	for _, chanStruct := range channelsStructs {
		channel := chanStruct.(*data.Channel)
		channelKey, err := h.channelKey(logger, channel)
		if err != nil {
			h.logger.Error(err.Error())
			return nil, ErrInternal
		}
		if channelKey == key {
			endpoint, err := h.endpointByChannelID(logger, channel.ID)
			if err != nil {
				return nil, err
			}
			return &endpoint.RawMsg, nil
		}
	}

	return nil, ErrChannelNotFound
}

func ( h * Handler ) Endpoint ( key data . Base64String ) ( * data . Base64String , error ) { logger := h . logger . Add ( " " , " " ) channelsStructs , err := h . db . SelectAllFrom ( data . ChannelTable , " " ) if err != nil { h . logger . Error ( err . Error ( ) ) return nil , ErrInternal } for _ , chanStruct := range channelsStructs { channel := chanStruct . ( * data . Channel ) channelKey , err := h . channelKey ( logger , channel ) if err != nil { h . logger . Error ( err . Error ( ) ) return nil , ErrInternal } if channelKey == key { endpoint , err := h . endpointByChannelID ( logger , channel . ID ) if err != nil { return nil , err } return & endpoint . RawMsg , nil } } return nil , ErrChannelNotFound }

// Endpoint returns endpoint msg for a channel with given key.

Endpoint returns endpoint msg for a channel with given key .


func NewServer(conf *Config, logger log.Logger, db *reform.DB) *Server {
	s := &Server{
		Server: srv.NewServer(conf.Config),
		logger: logger.Add("type", "pay.Server"),
		db:     db,
	}

	s.HandleFunc(payPath,
		s.RequireHTTPMethods(s.logger, s.handlePay, http.MethodPost))

	return s
}

func NewServer ( conf * Config , logger log . Logger , db * reform . DB ) * Server { s := & Server { Server : srv . NewServer ( conf . Config ) , logger : logger . Add ( " " , " " ) , db : db , } s . HandleFunc ( payPath , s . RequireHTTPMethods ( s . logger , s . handlePay , http . MethodPost ) ) return s }


func NewMonitor(conf *Config, c Client, db *reform.DB, l log.Logger, psc,
	ptc common.Address, role string, q Queue) (*Monitor, error) {
	abiJSON := contract.PrivatixServiceContractABI
	pscABI, err := abi.JSON(strings.NewReader(abiJSON))
	if err != nil {
		l.Error(err.Error())
		return nil, ErrFailedToParseABI
	}
	abiJSON2 := contract.PrivatixTokenContractABI
	ptcABI, err := abi.JSON(strings.NewReader(abiJSON2))
	if err != nil {
		l.Error(err.Error())
		return nil, ErrFailedToParseABI
	}
	ethCallTimeout := time.Duration(conf.EthCallTimeout) * time.Millisecond
	queryPause := time.Duration(conf.QueryPause) * time.Millisecond
	m := &Monitor{
		db:             db,
		eth:            c,
		logger:         l.Add("type", "monitor.Monitor"),
		queue:          q,
		ethCallTimeout: ethCallTimeout,
		pscABI:         pscABI,
		ptcABI:         ptcABI,
		pscAddr:        psc,
		queryPause:     queryPause,
	}

	m.initLastProcessedBlock(role, conf.InitialBlocks)

	f := m.clientQueries
	m.jobsProducers = m.clientJobsProducers()
	if role == data.RoleAgent {
		f = m.agentQueries
		m.jobsProducers = m.agentJobsProducers()
	}
	m.getFilterLogQueries = func(from, to uint64) ([]ethereum.FilterQuery, error) {
		return f(from, to, psc, ptc)
	}

	return m, nil
}

func NewMonitor ( conf * Config , c Client , db * reform . DB , l log . Logger , psc , ptc common . Address , role string , q Queue ) ( * Monitor , error ) { abiJSON := contract . PrivatixServiceContractABI pscABI , err := abi . JSON ( strings . NewReader ( abiJSON ) ) if err != nil { l . Error ( err . Error ( ) ) return nil , ErrFailedToParseABI } abiJSON2 := contract . PrivatixTokenContractABI ptcABI , err := abi . JSON ( strings . NewReader ( abiJSON2 ) ) if err != nil { l . Error ( err . Error ( ) ) return nil , ErrFailedToParseABI } ethCallTimeout := time . Duration ( conf . EthCallTimeout ) * time . Millisecond queryPause := time . Duration ( conf . QueryPause ) * time . Millisecond m := & Monitor { db : db , eth : c , logger : l . Add ( " " , " " ) , queue : q , ethCallTimeout : ethCallTimeout , pscABI : pscABI , ptcABI : ptcABI , pscAddr : psc , queryPause : queryPause , } m . initLastProcessedBlock ( role , conf . InitialBlocks ) f := m . clientQueries m . jobsProducers = m . clientJobsProducers ( ) if role == data . RoleAgent { f = m . agentQueries m . jobsProducers = m . agentJobsProducers ( ) } m . getFilterLogQueries = func ( from , to uint64 ) ( [ ] ethereum . FilterQuery , error ) { return f ( from , to , psc , ptc ) } return m , nil }

// NewMonitor creates new blockchain monitor.

NewMonitor creates new blockchain monitor .


func (m *Monitor) initLastProcessedBlock(role string, initialBlocks uint64) {
	logger := m.logger.Add("method", "initLastProcessedBlock",
		"role", role, "initialBlocks", initialBlocks)

	block, err := m.getLastProcessedBlockNumber()
	if block > 0 || err != nil || role != data.RoleClient ||
		initialBlocks == 0 {
		return
	}

	ctx, cancel := context.WithTimeout(context.Background(),
		m.ethCallTimeout)
	defer cancel()

	lastBlock, err := m.eth.HeaderByNumber(ctx, nil)
	if err != nil {
		logger.Error(err.Error())
		return
	}

	lastEthBlockNum := lastBlock.Number.Uint64()
	logger = logger.Add("lastEthBlockNum", lastEthBlockNum)

	if initialBlocks > lastEthBlockNum {
		logger.Warn("initialBlocks value is very big")
		return
	}

	lastProcessedBlock := lastEthBlockNum - initialBlocks

	_, err = m.db.Exec(`UPDATE settings SET value=$1 WHERE key=$2`,
		lastProcessedBlock, data.SettingLastProcessedBlock)
	if err != nil {
		logger.Error(err.Error())
	}
	logger.Debug(fmt.Sprintf("last processed block: %d",
		lastProcessedBlock))
}

// initLastProcessedBlock calculates last processed block. If user role is
// client and value of "eth.event.lastProcessedBlock" setting is 0, then value
// of "eth.event.lastProcessedBlock" setting is equal the difference between
// the last Ethereum block and a InitialBlocks value. If InitialBlocks
// value is 0, then this parameter is ignored.

initLastProcessedBlock calculates last processed block . If user role is client and value of eth . event . lastProcessedBlock setting is 0 then value of eth . event . lastProcessedBlock setting is equal the difference between the last Ethereum block and a InitialBlocks value . If InitialBlocks value is 0 then this parameter is ignored .


func (m *Monitor) Start() {
	logger := m.logger.Add("method", "Start")
	ctx, cancel := context.WithCancel(context.Background())
	ticker := time.NewTicker(m.queryPause)
	m.stopMonitor = func() {
		ticker.Stop()
		cancel()
	}
	go func() {
		for {
			select {
			case <-ctx.Done():
				return
			case <-ticker.C:
				err := m.queryLogsAndCreateJobs(
					m.getFilterLogQueries, m.jobsProducers)
				if err != nil {
					logger.Warn(err.Error())
				}
			}
		}
	}()
}

func ( m * Monitor ) Start ( ) { logger := m . logger . Add ( " " , " " ) ctx , cancel := context . WithCancel ( context . Background ( ) ) ticker := time . NewTicker ( m . queryPause ) m . stopMonitor = func ( ) { ticker . Stop ( ) cancel ( ) } go func ( ) { for { select { case <- ctx . Done ( ) : return case <- ticker . C : err := m . queryLogsAndCreateJobs ( m . getFilterLogQueries , m . jobsProducers ) if err != nil { logger . Warn ( err . Error ( ) ) } } } } ( ) }

// Start starts scanning blockchain for events.

Start starts scanning blockchain for events .


func newClient(cfg *Config, logger log.Logger) (*client, error) {
	logger2 := logger.Add("method", "newClient", "config", cfg)

	u, err := url.Parse(cfg.GethURL)
	if err != nil {
		return nil, err
	}

	ctx, cancel := context.WithCancel(context.Background())

	c := &client{cancel: cancel, cfg: cfg, logger: logger}

	var rpcClient *rpc.Client

	switch u.Scheme {
	case httpProtocol, https:
		httpTransport := transport(cfg.HTTPClient)

		rpcClient, err = rpc.DialHTTPWithClient(cfg.GethURL,
			httpClient(cfg.HTTPClient, httpTransport))

		c.httpTransport = httpTransport
	case ws, wss:
		rpcClient, err = rpc.DialWebsocket(ctx, cfg.GethURL, "")
	case stdIO:
		rpcClient, err = rpc.DialStdIO(ctx)
	case ipc:
		rpcClient, err = rpc.DialIPC(ctx, cfg.GethURL)
	default:
		logger2.Add("scheme", u.Scheme).Error(err.Error())
		return nil, ErrURLScheme
	}
	if err != nil {
		logger2.Error(err.Error())
		return nil, ErrCreateClient
	}

	c.client = ethclient.NewClient(rpcClient)
	return c, nil
}

func newClient ( cfg * Config , logger log . Logger ) ( * client , error ) { logger2 := logger . Add ( " " , " " , " " , cfg ) u , err := url . Parse ( cfg . GethURL ) if err != nil { return nil , err } ctx , cancel := context . WithCancel ( context . Background ( ) ) c := & client { cancel : cancel , cfg : cfg , logger : logger } var rpcClient * rpc . Client switch u . Scheme { case httpProtocol , https : httpTransport := transport ( cfg . HTTPClient ) rpcClient , err = rpc . DialHTTPWithClient ( cfg . GethURL , httpClient ( cfg . HTTPClient , httpTransport ) ) c . httpTransport = httpTransport case ws , wss : rpcClient , err = rpc . DialWebsocket ( ctx , cfg . GethURL , " " ) case stdIO : rpcClient , err = rpc . DialStdIO ( ctx ) case ipc : rpcClient , err = rpc . DialIPC ( ctx , cfg . GethURL ) default : logger2 . Add ( " " , u . Scheme ) . Error ( err . Error ( ) ) return nil , ErrURLScheme } if err != nil { logger2 . Error ( err . Error ( ) ) return nil , ErrCreateClient } c . client = ethclient . NewClient ( rpcClient ) return c , nil }

// newClient creates client for connection to the Ethereum.

newClient creates client for connection to the Ethereum .


func Loop(ctx context.Context, logger log.Logger, db *reform.DB,
	queue job.Queue, duration time.Duration, f func() []*data.Job) {
	tik := time.NewTicker(duration)
	logger = logger.Add("method", "Loop")

	go loop(ctx, tik, db, queue, f, logger, nil)
}

func Loop ( ctx context . Context , logger log . Logger , db * reform . DB , queue job . Queue , duration time . Duration , f func ( ) [ ] * data . Job ) { tik := time . NewTicker ( duration ) logger = logger . Add ( " " , " " ) go loop ( ctx , tik , db , queue , f , logger , nil ) }

// Loop performs a function that creates new jobs with a certain frequency.
// If at the moment there is already a similar active job, then such job is
// ignored. The function works correctly only with jobs for which duplicates
// are allowed.

Loop performs a function that creates new jobs with a certain frequency . If at the moment there is already a similar active job then such job is ignored . The function works correctly only with jobs for which duplicates are allowed .


func (c *Client) Offering(hash data.HexString) (data.Base64String, error) {
	return c.requestWithPayload("api_offering", string(hash))
}

func ( c * Client ) Offering ( hash data . HexString ) ( data . Base64String , error ) { return c . requestWithPayload ( " " , string ( hash ) ) }

// Offering gets offering message through tor net.

Offering gets offering message through tor net .


func (c *Client) Endpoint(channelKey data.Base64String) (data.Base64String, error) {
	return c.requestWithPayload("api_endpoint", string(channelKey))
}

func ( c * Client ) Endpoint ( channelKey data . Base64String ) ( data . Base64String , error ) { return c . requestWithPayload ( " " , string ( channelKey ) ) }

// Endpoint gets endpoint message through tor net.

Endpoint gets endpoint message through tor net .


func (c *Client) Ping() error {
	_, err := c.client.Head(c.url())
	return err
}

func ( c * Client ) Ping ( ) error { _ , err := c . client . Head ( c . url ( ) ) return err }

// Ping returns an error if remote enpoint cannot be reached.

Ping returns an error if remote enpoint cannot be reached .


func (h *Handler) GetEthTransactions(tkn, relType, relID string,
	offset, limit uint) (*GetEthTransactionsResult, error) {
	logger := h.logger.Add("method", "GetEthTransactions", "relatedType",
		relType, "relatedID", relID, "limit", limit, "offset", offset)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	conds := make([]string, 0)
	args := make([]interface{}, 0)
	// If the relType is `accountAggregated`, then gets an Ethereum
	// address of the account and find all transactions where this address
	// is the sender.
	if relType == AccountAggregatedType {
		var acc data.Account
		if err := h.findByPrimaryKey(
			logger, ErrAccountNotFound, &acc, relID); err != nil {
			return nil, err
		}
		args = append(args, acc.EthAddr)
		conds = append(
			conds,
			"addr_from="+h.db.Placeholder(len(args)))
	} else if relType != "" {
		args = append(args, relType)
		conds = append(
			conds,
			"related_type="+h.db.Placeholder(len(args)))
	}
	if relID != "" && relType != AccountAggregatedType {
		args = append(args, relID)
		conds = append(
			conds,
			"related_id="+h.db.Placeholder(len(args)))
	}

	tail := ""
	if len(conds) > 0 {
		tail = "WHERE " + strings.Join(conds, " AND ")
	}

	count, err := h.numberOfObjects(
		logger, data.EthTxTable.Name(), tail, args)
	if err != nil {
		return nil, err
	}

	offsetLimit := h.offsetLimit(offset, limit)

	sorting := `ORDER BY issued DESC`

	tail = fmt.Sprintf("%s %s %s", tail, sorting, offsetLimit)

	txs, err := h.selectAllFrom(logger, data.EthTxTable, tail, args...)
	if err != nil {
		return nil, err
	}

	ret := make([]data.EthTx, len(txs))

	for i, v := range txs {
		ret[i] = *v.(*data.EthTx)
	}
	return &GetEthTransactionsResult{ret, count}, nil
}

// GetEthTransactions returns transactions by related object.

GetEthTransactions returns transactions by related object .


func AgentSeal(msg, clientPub []byte, agentKey *ecdsa.PrivateKey) ([]byte, error) {
	pubKey, err := ethcrypto.UnmarshalPubkey(clientPub)
	if err != nil {
		return nil, err
	}

	pub := ecies.ImportECDSAPublic(pubKey)
	msgEncrypted, err := ecies.Encrypt(rand.Reader, pub, msg, nil, nil)
	if err != nil {
		return nil, err
	}

	return PackWithSignature(msgEncrypted, agentKey)
}

func AgentSeal ( msg , clientPub [ ] byte , agentKey * ecdsa . PrivateKey ) ( [ ] byte , error ) { pubKey , err := ethcrypto . UnmarshalPubkey ( clientPub ) if err != nil { return nil , err } pub := ecies . ImportECDSAPublic ( pubKey ) msgEncrypted , err := ecies . Encrypt ( rand . Reader , pub , msg , nil , nil ) if err != nil { return nil , err } return PackWithSignature ( msgEncrypted , agentKey ) }

// AgentSeal encrypts message using client's public key and packs with
// agent signature.

AgentSeal encrypts message using client s public key and packs with agent signature .


func ClientOpen(c, agentPub []byte, clientPrv *ecdsa.PrivateKey) ([]byte, error) {
	sealed, sig := UnpackSignature(c)
	hash := ethcrypto.Keccak256(sealed)

	if !VerifySignature(agentPub, hash, sig) {
		return nil, ErrWrongSignature
	}

	prv := ecies.ImportECDSA(clientPrv)

	opened, err := prv.Decrypt(sealed, nil, nil)
	if err != nil {
		return nil, err
	}

	return opened, nil
}

func ClientOpen ( c , agentPub [ ] byte , clientPrv * ecdsa . PrivateKey ) ( [ ] byte , error ) { sealed , sig := UnpackSignature ( c ) hash := ethcrypto . Keccak256 ( sealed ) if ! VerifySignature ( agentPub , hash , sig ) { return nil , ErrWrongSignature } prv := ecies . ImportECDSA ( clientPrv ) opened , err := prv . Decrypt ( sealed , nil , nil ) if err != nil { return nil , err } return opened , nil }

// ClientOpen decrypts message using client's key and verifies using agent's key.

ClientOpen decrypts message using client s key and verifies using agent s key .


func PackWithSignature(msg []byte, key *ecdsa.PrivateKey) ([]byte, error) {
	sig, err := signature(key, msg)
	if err != nil {
		return nil, err
	}

	return packSignature(msg, sig), nil
}

func PackWithSignature ( msg [ ] byte , key * ecdsa . PrivateKey ) ( [ ] byte , error ) { sig , err := signature ( key , msg ) if err != nil { return nil , err } return packSignature ( msg , sig ) , nil }

// PackWithSignature packs message with signature.

PackWithSignature packs message with signature .


func UnpackSignature(c []byte) (msg []byte, sig []byte) {
	msg = c[:len(c)-sigLen]
	sig = c[len(c)-sigLen:]
	return
}

func UnpackSignature ( c [ ] byte ) ( msg [ ] byte , sig [ ] byte ) { msg = c [ : len ( c ) - sigLen ] sig = c [ len ( c ) - sigLen : ] return }

// UnpackSignature unpacks msg from signature.

UnpackSignature unpacks msg from signature .


func VerifySignature(pubk, msg, sig []byte) bool {
	return ethcrypto.VerifySignature(pubk, msg, sig)
}

func VerifySignature ( pubk , msg , sig [ ] byte ) bool { return ethcrypto . VerifySignature ( pubk , msg , sig ) }

// VerifySignature returns true if signature is correct.

VerifySignature returns true if signature is correct .


func signature(key *ecdsa.PrivateKey, msg []byte) ([]byte, error) {
	hash := ethcrypto.Keccak256(msg)
	sig, err := ethcrypto.Sign(hash, key)
	if err != nil {
		return nil, err
	}
	sig = sig[:len(sig)-1]
	return sig, nil
}

func signature ( key * ecdsa . PrivateKey , msg [ ] byte ) ( [ ] byte , error ) { hash := ethcrypto . Keccak256 ( msg ) sig , err := ethcrypto . Sign ( hash , key ) if err != nil { return nil , err } sig = sig [ : len ( sig ) - 1 ] return sig , nil }

// signature computes and returns signature.

signature computes and returns signature .


func (h *Handler) GetObject(
	tkn, objectType, id string) (json.RawMessage, error) {
	logger := h.logger.Add("method", "GetObject",
		"type", objectType, "id", id)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	table, ok := objectTypes[objectType]
	if !ok {
		logger.Warn(ErrBadObjectType.Error())
		return nil, ErrBadObjectType
	}

	obj, err := h.db.FindByPrimaryKeyFrom(table, id)
	if err != nil {
		logger.Error(err.Error())
		return nil, ErrObjectNotFound
	}

	raw, err := json.Marshal(obj)
	if err != nil {
		logger.Error(err.Error())
		return nil, ErrInternal
	}

	return raw, nil
}

func ( h * Handler ) GetObject ( tkn , objectType , id string ) ( json . RawMessage , error ) { logger := h . logger . Add ( " " , " " , " " , objectType , " " , id ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return nil , ErrAccessDenied } table , ok := objectTypes [ objectType ] if ! ok { logger . Warn ( ErrBadObjectType . Error ( ) ) return nil , ErrBadObjectType } obj , err := h . db . FindByPrimaryKeyFrom ( table , id ) if err != nil { logger . Error ( err . Error ( ) ) return nil , ErrObjectNotFound } raw , err := json . Marshal ( obj ) if err != nil { logger . Error ( err . Error ( ) ) return nil , ErrInternal } return raw , nil }

// GetObject finds object in a database by id,
// then returns an object on raw JSON format.

GetObject finds object in a database by id then returns an object on raw JSON format .


func (h *Handler) GetObjectByHash(
	tkn, objectType, hash string) (json.RawMessage, error) {
	logger := h.logger.Add("method", "GetObjectByHash",
		"type", objectType, "hash", hash)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	table, ok := objectWithHashTypes[objectType]
	if !ok {
		logger.Warn(ErrBadObjectType.Error())
		return nil, ErrBadObjectType
	}

	obj, err := h.db.FindOneFrom(table, "hash", hash)
	if err != nil {
		logger.Error(err.Error())
		return nil, ErrObjectNotFound
	}

	raw, err := json.Marshal(obj)
	if err != nil {
		logger.Error(err.Error())
		return nil, ErrInternal
	}

	return raw, nil
}

func ( h * Handler ) GetObjectByHash ( tkn , objectType , hash string ) ( json . RawMessage , error ) { logger := h . logger . Add ( " " , " " , " " , objectType , " " , hash ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return nil , ErrAccessDenied } table , ok := objectWithHashTypes [ objectType ] if ! ok { logger . Warn ( ErrBadObjectType . Error ( ) ) return nil , ErrBadObjectType } obj , err := h . db . FindOneFrom ( table , " " , hash ) if err != nil { logger . Error ( err . Error ( ) ) return nil , ErrObjectNotFound } raw , err := json . Marshal ( obj ) if err != nil { logger . Error ( err . Error ( ) ) return nil , ErrInternal } return raw , nil }

// GetObjectByHash finds object in a database by hash,
// then returns an object on raw JSON format.

GetObjectByHash finds object in a database by hash then returns an object on raw JSON format .


func ToError(err error) *Error {
	if err == nil {
		return nil
	}

	if err, ok := err.(rpc.Error); ok {
		return &Error{Code: err.ErrorCode(), Message: err.Error()}
	}

	return &Error{Message: err.Error()}
}

func ToError ( err error ) * Error { if err == nil { return nil } if err , ok := err . ( rpc . Error ) ; ok { return & Error { Code : err . ErrorCode ( ) , Message : err . Error ( ) } } return & Error { Message : err . Error ( ) } }

// ToError converts error into Error pointer.

ToError converts error into Error pointer .


func (h *Handler) SetPassword(password string) error {
	logger := h.logger.Add("method", "SetPassword")

	logger.Debug("trying to set password")

	if password == "" {
		logger.Warn("received empty password")
		return ErrEmptyPassword
	}

	if err := h.validatePasswordNotSet(logger); err != nil {
		return err
	}

	salt := util.NewUUID()

	hashed, err := hashedPassword(logger, password, salt)
	if err != nil {
		return err
	}

	tx, err := beginTX(logger, h.db)
	if err != nil {
		return err
	}
	defer tx.Rollback()

	if err := insert(logger, tx.Querier,
		saltSetting(salt), passwordHashSetting(hashed)); err != nil {
		return err
	}

	return commitTX(logger, tx)
}

func ( h * Handler ) SetPassword ( password string ) error { logger := h . logger . Add ( " " , " " ) logger . Debug ( " " ) if password == " " { logger . Warn ( " " ) return ErrEmptyPassword } if err := h . validatePasswordNotSet ( logger ) ; err != nil { return err } salt := util . NewUUID ( ) hashed , err := hashedPassword ( logger , password , salt ) if err != nil { return err } tx , err := beginTX ( logger , h . db ) if err != nil { return err } defer tx . Rollback ( ) if err := insert ( logger , tx . Querier , saltSetting ( salt ) , passwordHashSetting ( hashed ) ) ; err != nil { return err } return commitTX ( logger , tx ) }

// SetPassword sets the password only on the first call.
// Returns error if password already exists.

SetPassword sets the password only on the first call . Returns error if password already exists .


func (h *Handler) UpdatePassword(current, new string) error {
	logger := h.logger.Add("method", "UpdatePassword")

	if err := h.checkPassword(logger, current); err != nil {
		return err
	}

	logger.Debug("updating password")

	if new == "" {
		logger.Warn("received empty password for update")
		return ErrEmptyPassword
	}

	salt := util.NewUUID()

	hashed, err := hashedPassword(logger, new, salt)
	if err != nil {
		return err
	}

	tx, err := beginTX(logger, h.db)
	if err != nil {
		return err
	}
	defer tx.Rollback()

	if err := h.updatePrivateKeys(logger, tx, current, new); err != nil {
		return err
	}

	if err := update(logger, tx.Querier,
		saltSetting(salt), passwordHashSetting(hashed)); err != nil {
		return err
	}

	err = commitTX(logger, tx)
	if err != nil {
		return err
	}

	h.token.Make()

	return nil
}

func ( h * Handler ) UpdatePassword ( current , new string ) error { logger := h . logger . Add ( " " , " " ) if err := h . checkPassword ( logger , current ) ; err != nil { return err } logger . Debug ( " " ) if new == " " { logger . Warn ( " " ) return ErrEmptyPassword } salt := util . NewUUID ( ) hashed , err := hashedPassword ( logger , new , salt ) if err != nil { return err } tx , err := beginTX ( logger , h . db ) if err != nil { return err } defer tx . Rollback ( ) if err := h . updatePrivateKeys ( logger , tx , current , new ) ; err != nil { return err } if err := update ( logger , tx . Querier , saltSetting ( salt ) , passwordHashSetting ( hashed ) ) ; err != nil { return err } err = commitTX ( logger , tx ) if err != nil { return err } h . token . Make ( ) return nil }


func (h *Handler) GetToken(password string) (*string, error) {
	logger := h.logger.Add("method", "GetToken")

	if err := h.checkPassword(logger, password); err != nil {
		return nil, err
	}

	logger.Debug("making access token")

	v, err := h.token.Make()
	if err != nil {
		logger.Error(err.Error())
		return nil, ErrInternal
	}

	return &v, nil
}

func ( h * Handler ) GetToken ( password string ) ( * string , error ) { logger := h . logger . Add ( " " , " " ) if err := h . checkPassword ( logger , password ) ; err != nil { return nil , err } logger . Debug ( " " ) v , err := h . token . Make ( ) if err != nil { logger . Error ( err . Error ( ) ) return nil , ErrInternal } return & v , nil }

// GetToken returns token if password is correct.

GetToken returns token if password is correct .


func NewProcessor(
	conf *Config, db *reform.DB, queue job.Queue) *Processor {
	return &Processor{
		conf:  conf,
		db:    db,
		queue: queue,
	}
}

func NewProcessor ( conf * Config , db * reform . DB , queue job . Queue ) * Processor { return & Processor { conf : conf , db : db , queue : queue , } }

// NewProcessor creates a new processor.


func NewConfig() *Config {
	return &Config{
		CollectJobs:   100,
		CollectPeriod: 1000,
		WorkerBufLen:  10,
		Workers:       0,

		TypeConfig: TypeConfig{
			TryLimit:  3,
			TryPeriod: 60000,
		},
		Types: make(map[string]TypeConfig),
	}
}

func NewConfig ( ) * Config { return & Config { CollectJobs : 100 , CollectPeriod : 1000 , WorkerBufLen : 10 , Workers : 0 , TypeConfig : TypeConfig { TryLimit : 3 , TryPeriod : 60000 , } , Types : make ( map [ string ] TypeConfig ) , } }

// NewConfig creates a default job queue configuration.

NewConfig creates a default job queue configuration .


func NewQueue(conf *Config, logger log.Logger, db *reform.DB,
	handlers HandlerMap) Queue {
	l := logger.Add("type", "job.Queue")
	return &queue{
		conf:     conf,
		logger:   l,
		db:       db,
		handlers: handlers,
		subs:     map[string][]subEntry{},
	}
}

func NewQueue ( conf * Config , logger log . Logger , db * reform . DB , handlers HandlerMap ) Queue { l := logger . Add ( " " , " " ) return & queue { conf : conf , logger : l , db : db , handlers : handlers , subs : map [ string ] [ ] subEntry { } , } }


func AddWithDataAndDelay(q Queue, tx *reform.TX,
	jobType, relatedType, relatedID, creator string,
	jobData interface{}, delay time.Duration) error {
	data2, err := json.Marshal(jobData)
	if err != nil {
		return err
	}

	return q.Add(tx, &data.Job{
		Type:        jobType,
		RelatedType: relatedType,
		RelatedID:   relatedID,
		CreatedBy:   creator,
		Data:        data2,
		NotBefore:   time.Now().Add(delay),
	})
}

func AddWithDataAndDelay ( q Queue , tx * reform . TX , jobType , relatedType , relatedID , creator string , jobData interface { } , delay time . Duration ) error { data2 , err := json . Marshal ( jobData ) if err != nil { return err } return q . Add ( tx , & data . Job { Type : jobType , RelatedType : relatedType , RelatedID : relatedID , CreatedBy : creator , Data : data2 , NotBefore : time . Now ( ) . Add ( delay ) , } ) }

// AddWithDataAndDelay is convenience method to add a job with given data
// and delay.

AddWithDataAndDelay is convenience method to add a job with given data and delay .


func AddWithData(q Queue, tx *reform.TX,
	jobType, relatedType, relatedID, creator string,
	jobData interface{}) error {
	return AddWithDataAndDelay(q, tx, jobType,
		relatedType, relatedID, creator, jobData, time.Duration(0))
}

func AddWithData ( q Queue , tx * reform . TX , jobType , relatedType , relatedID , creator string , jobData interface { } ) error { return AddWithDataAndDelay ( q , tx , jobType , relatedType , relatedID , creator , jobData , time . Duration ( 0 ) ) }

// AddWithData is convenience method to add a job with given data.

AddWithData is convenience method to add a job with given data .


func AddSimple(q Queue, tx *reform.TX,
	jobType, relatedType, relatedID, creator string) error {
	return AddWithData(q, tx,
		jobType, relatedType, relatedID, creator, &struct{}{})
}

func AddSimple ( q Queue , tx * reform . TX , jobType , relatedType , relatedID , creator string ) error { return AddWithData ( q , tx , jobType , relatedType , relatedID , creator , & struct { } { } ) }

// AddSimple is convenience method to add a job.

AddSimple is convenience method to add a job .


func AddWithDelay(q Queue, tx *reform.TX,
	jobType, relatedType, relatedID, creator string,
	delay time.Duration) error {
	return AddWithDataAndDelay(q, tx,
		jobType, relatedType, relatedID, creator, &struct{}{}, delay)
}

func AddWithDelay ( q Queue , tx * reform . TX , jobType , relatedType , relatedID , creator string , delay time . Duration ) error { return AddWithDataAndDelay ( q , tx , jobType , relatedType , relatedID , creator , & struct { } { } , delay ) }

// AddWithDelay is convenience method to add a job with given data delay.

AddWithDelay is convenience method to add a job with given data delay .


func (q *queue) Subscribe(
	subKeys []string, subID string, subFunc SubFunc) error {
	q.subsMtx.Lock()
	defer q.subsMtx.Unlock()

	for i, v := range subKeys {
		if err := q.subscribe(v, subID, subFunc); err != nil {
			for j := 0; j < i; j++ {
				q.unsubscribe(subKeys[j], subID)
			}
			return err
		}
	}

	return nil
}

func ( q * queue ) Subscribe ( subKeys [ ] string , subID string , subFunc SubFunc ) error { q . subsMtx . Lock ( ) defer q . subsMtx . Unlock ( ) for i , v := range subKeys { if err := q . subscribe ( v , subID , subFunc ) ; err != nil { for j := 0 ; j < i ; j ++ { q . unsubscribe ( subKeys [ j ] , subID ) } return err } } return nil }

// Subscribe adds a subscription to job result notifications for given keys.
// Each subscription key can be be a job type or a job related id. SubID is
// used to distinguish between different subscriptions.

Subscribe adds a subscription to job result notifications for given keys . Each subscription key can be be a job type or a job related id . SubID is used to distinguish between different subscriptions .


func (q *queue) Unsubscribe(subKeys []string, subID string) error {
	q.subsMtx.Lock()
	defer q.subsMtx.Unlock()

	var err error
	for _, v := range subKeys {
		if err2 := q.unsubscribe(v, subID); err == nil {
			err = err2
		}
	}

	return err
}

func ( q * queue ) Unsubscribe ( subKeys [ ] string , subID string ) error { q . subsMtx . Lock ( ) defer q . subsMtx . Unlock ( ) var err error for _ , v := range subKeys { if err2 := q . unsubscribe ( v , subID ) ; err == nil { err = err2 } } return err }

// Unsubscribe removes a subscription from job result notifications for given
// ids of related objects. SubID is used to distinguish between different
// subscriptions to a same related object.

Unsubscribe removes a subscription from job result notifications for given ids of related objects . SubID is used to distinguish between different subscriptions to a same related object .


func (h *Handler) TopUpChannel(
	tkn, channel string, deposit, gasPrice uint64) error {
	logger := h.logger.Add("method", "TopUpChannel",
		"channel", channel, "deposit", deposit, "gasPrice", gasPrice)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return ErrAccessDenied
	}

	ch := &data.Channel{}
	if err := h.findByPrimaryKey(logger,
		ErrChannelNotFound, ch, channel); err != nil {
		return err
	}

	jobData, err := h.topUpChannelJobData(logger, deposit, gasPrice)
	if err != nil {
		return err
	}

	return job.AddWithData(h.queue, nil, data.JobClientPreChannelTopUp,
		data.JobChannel, ch.ID, data.JobUser, jobData)
}

func ( h * Handler ) TopUpChannel ( tkn , channel string , deposit , gasPrice uint64 ) error { logger := h . logger . Add ( " " , " " , " " , channel , " " , deposit , " " , gasPrice ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return ErrAccessDenied } ch := & data . Channel { } if err := h . findByPrimaryKey ( logger , ErrChannelNotFound , ch , channel ) ; err != nil { return err } jobData , err := h . topUpChannelJobData ( logger , deposit , gasPrice ) if err != nil { return err } return job . AddWithData ( h . queue , nil , data . JobClientPreChannelTopUp , data . JobChannel , ch . ID , data . JobUser , jobData ) }

// TopUpChannel initiates JobClientPreChannelTopUp job.

TopUpChannel initiates JobClientPreChannelTopUp job .


func (h *Handler) ChangeChannelStatus(tkn, channel, action string) error {
	logger := h.logger.Add("method", "ChangeChannelStatus",
		"channel", channel, "action", action, "userRole", h.userRole)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return ErrAccessDenied
	}

	condition := fmt.Sprintf("WHERE id = %s ", h.db.Placeholder(1))

	isAgent := h.userRole == data.RoleAgent

	if !isAgent {
		condition = fmt.Sprintf("%s AND %s",
			condition, clientChannelsCondition)
	}

	items, err := h.selectAllFrom(
		logger, data.ChannelTable, condition, channel)
	if err != nil {
		logger.Error(err.Error())
		return ErrInternal
	}

	if len(items) != 1 {
		logger.Error(ErrChannelNotFound.Error())
		return ErrChannelNotFound
	}

	switch action {
	case ChannelPauseAction:
		_, err = h.processor.SuspendChannel(
			channel, data.JobUser, isAgent)
	case ChannelResumeAction:
		_, err = h.processor.ActivateChannel(
			channel, data.JobUser, isAgent)
	case ChannelTerminateAction:
		_, err = h.processor.TerminateChannel(
			channel, data.JobUser, isAgent)
	case ChannelCloseAction:
		if isAgent {
			logger.Error(ErrNotAllowedForAgent.Error())
			return ErrNotAllowedForAgent
		}
		if err := h.createPreUncooperativeCloseRequest(
			channel, logger); err != nil {
			return ErrInternal
		}
	default:
		logger.Warn(ErrBadAction.Error())
		return ErrBadAction
	}

	if err != nil {
		logger.Error(err.Error())
		return ErrInternal
	}

	return nil
}

func ( h * Handler ) ChangeChannelStatus ( tkn , channel , action string ) error { logger := h . logger . Add ( " " , " " , " " , channel , " " , action , " " , h . userRole ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return ErrAccessDenied } condition := fmt . Sprintf ( " " , h . db . Placeholder ( 1 ) ) isAgent := h . userRole == data . RoleAgent if ! isAgent { condition = fmt . Sprintf ( " " , condition , clientChannelsCondition ) } items , err := h . selectAllFrom ( logger , data . ChannelTable , condition , channel ) if err != nil { logger . Error ( err . Error ( ) ) return ErrInternal } if len ( items ) != 1 { logger . Error ( ErrChannelNotFound . Error ( ) ) return ErrChannelNotFound } switch action { case ChannelPauseAction : _ , err = h . processor . SuspendChannel ( channel , data . JobUser , isAgent ) case ChannelResumeAction : _ , err = h . processor . ActivateChannel ( channel , data . JobUser , isAgent ) case ChannelTerminateAction : _ , err = h . processor . TerminateChannel ( channel , data . JobUser , isAgent ) case ChannelCloseAction : if isAgent { logger . Error ( ErrNotAllowedForAgent . Error ( ) ) return ErrNotAllowedForAgent } if err := h . createPreUncooperativeCloseRequest ( channel , logger ) ; err != nil { return ErrInternal } default : logger . Warn ( ErrBadAction . Error ( ) ) return ErrBadAction } if err != nil { logger . Error ( err . Error ( ) ) return ErrInternal } return nil }

// ChangeChannelStatus updates channel state.

ChangeChannelStatus updates channel state .


func (h *Handler) GetAgentChannels(tkn string,
	channelStatus, serviceStatus []string,
	offset, limit uint) (*GetAgentChannelsResult, error) {
	logger := h.logger.Add("method", "GetAgentChannels",
		"channelStatus", channelStatus, "serviceStatus", serviceStatus)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	channels, total, err := h.getChannels(
		logger, channelStatus, serviceStatus,
		agentChannelsCondition, offset, limit)
	if err != nil {
		return nil, err
	}

	return &GetAgentChannelsResult{channels, total}, err
}

func ( h * Handler ) GetAgentChannels ( tkn string , channelStatus , serviceStatus [ ] string , offset , limit uint ) ( * GetAgentChannelsResult , error ) { logger := h . logger . Add ( " " , " " , " " , channelStatus , " " , serviceStatus ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return nil , ErrAccessDenied } channels , total , err := h . getChannels ( logger , channelStatus , serviceStatus , agentChannelsCondition , offset , limit ) if err != nil { return nil , err } return & GetAgentChannelsResult { channels , total } , err }

// GetAgentChannels gets channels for agent.

GetAgentChannels gets channels for agent .


func (h *Handler) GetChannelsUsage(tkn string, ids []string) (map[string]Usage, error) {
	logger := h.logger.Add("method", "GetChannelsUsage", "objectType", "channel", "objectIDs", ids)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	return h.getChannelsUsages(logger, ids)
}

func ( h * Handler ) GetChannelsUsage ( tkn string , ids [ ] string ) ( map [ string ] Usage , error ) { logger := h . logger . Add ( " " , " " , " " , " " , " " , ids ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return nil , ErrAccessDenied } return h . getChannelsUsages ( logger , ids ) }

// GetChannelsUsage returns detailed usage on channels.

GetChannelsUsage returns detailed usage on channels .


func (h *Handler) GetClientChannels(tkn string, channelStatus,
	serviceStatus []string, offset,
	limit uint) (*GetClientChannelsResult, error) {
	logger := h.logger.Add("method", "GetClientChannels",
		"channelStatus", channelStatus, "serviceStatus", serviceStatus)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	chs, total, err := h.getChannels(logger, channelStatus, serviceStatus,
		clientChannelsCondition, offset, limit)
	if err != nil {
		return nil, err
	}

	items := make([]ClientChannelInfo, 0)
	for _, channel := range chs {
		result, err := h.createClientChannelResult(logger, &channel)
		if err != nil {
			return nil, err
		}

		items = append(items, *result)
	}

	return &GetClientChannelsResult{items, total}, nil
}

func ( h * Handler ) GetClientChannels ( tkn string , channelStatus , serviceStatus [ ] string , offset , limit uint ) ( * GetClientChannelsResult , error ) { logger := h . logger . Add ( " " , " " , " " , channelStatus , " " , serviceStatus ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return nil , ErrAccessDenied } chs , total , err := h . getChannels ( logger , channelStatus , serviceStatus , clientChannelsCondition , offset , limit ) if err != nil { return nil , err } items := make ( [ ] ClientChannelInfo , 0 ) for _ , channel := range chs { result , err := h . createClientChannelResult ( logger , & channel ) if err != nil { return nil , err } items = append ( items , * result ) } return & GetClientChannelsResult { items , total } , nil }

// GetClientChannels gets client channel information.

GetClientChannels gets client channel information .


func ReadSetting(db *reform.Querier, key string) (string, error) {
	var st Setting
	if err := FindByPrimaryKeyTo(db, &st, key); err != nil {
		return "", fmt.Errorf(
			"failed to find '%s' setting: %s", key, err)
	}
	return st.Value, nil
}

func ReadSetting ( db * reform . Querier , key string ) ( string , error ) { var st Setting if err := FindByPrimaryKeyTo ( db , & st , key ) ; err != nil { return " " , fmt . Errorf ( " " , key , err ) } return st . Value , nil }

// ReadSetting reads value of a given setting.

ReadSetting reads value of a given setting .


func ReadUintSetting(db *reform.Querier, key string) (uint, error) {
	val, err := ReadSetting(db, key)
	if err != nil {
		return 0, err
	}

	val2, err := strconv.ParseUint(val, 10, 32)
	if err != nil {
		return 0, newSettingParseError(key, err)
	}

	return uint(val2), nil
}

func ReadUintSetting ( db * reform . Querier , key string ) ( uint , error ) { val , err := ReadSetting ( db , key ) if err != nil { return 0 , err } val2 , err := strconv . ParseUint ( val , 10 , 32 ) if err != nil { return 0 , newSettingParseError ( key , err ) } return uint ( val2 ) , nil }

// ReadUintSetting reads value of a given uint setting.

ReadUintSetting reads value of a given uint setting .


func ReadBoolSetting(db *reform.Querier, key string) (bool, error) {
	val, err := ReadSetting(db, key)
	if err != nil {
		return false, err
	}

	val2, err := strconv.ParseBool(val)
	if err != nil {
		return false, newSettingParseError(key, err)
	}

	return bool(val2), nil
}

func ReadBoolSetting ( db * reform . Querier , key string ) ( bool , error ) { val , err := ReadSetting ( db , key ) if err != nil { return false , err } val2 , err := strconv . ParseBool ( val ) if err != nil { return false , newSettingParseError ( key , err ) } return bool ( val2 ) , nil }

// ReadBoolSetting reads value of a given bool setting.

ReadBoolSetting reads value of a given bool setting .


func (p *Processor) SuspendChannel(id, jobCreator string,
	agent bool) (string, error) {
	var jobType string
	if agent {
		jobType = data.JobAgentPreServiceSuspend
	} else {
		jobType = data.JobClientPreServiceSuspend
	}

	return p.alterServiceStatus(id, jobCreator,
		jobType, "", suspendTransitions, false)
}

func ( p * Processor ) SuspendChannel ( id , jobCreator string , agent bool ) ( string , error ) { var jobType string if agent { jobType = data . JobAgentPreServiceSuspend } else { jobType = data . JobClientPreServiceSuspend } return p . alterServiceStatus ( id , jobCreator , jobType , " " , suspendTransitions , false ) }

// SuspendChannel tries to suspend a given channel.

SuspendChannel tries to suspend a given channel .


func (p *Processor) ActivateChannel(id, jobCreator string,
	agent bool) (string, error) {
	var jobType string
	if agent {
		jobType = data.JobAgentPreServiceUnsuspend
	} else {
		jobType = data.JobClientPreServiceUnsuspend
	}

	return p.alterServiceStatus(id, jobCreator,
		jobType, "", activateTransitions, false)
}

func ( p * Processor ) ActivateChannel ( id , jobCreator string , agent bool ) ( string , error ) { var jobType string if agent { jobType = data . JobAgentPreServiceUnsuspend } else { jobType = data . JobClientPreServiceUnsuspend } return p . alterServiceStatus ( id , jobCreator , jobType , " " , activateTransitions , false ) }

// ActivateChannel tries to activate a given channel.

ActivateChannel tries to activate a given channel .


func (p *Processor) TerminateChannel(id, jobCreator string,
	agent bool) (string, error) {
	var jobType string
	if agent {
		jobType = data.JobAgentPreServiceTerminate
	} else {
		jobType = data.JobClientPreServiceTerminate
	}

	return p.alterServiceStatus(id, jobCreator,
		jobType, jobType, terminateTransitions, true)
}

func ( p * Processor ) TerminateChannel ( id , jobCreator string , agent bool ) ( string , error ) { var jobType string if agent { jobType = data . JobAgentPreServiceTerminate } else { jobType = data . JobClientPreServiceTerminate } return p . alterServiceStatus ( id , jobCreator , jobType , jobType , terminateTransitions , true ) }

// TerminateChannel tries to terminate a given channel.

TerminateChannel tries to terminate a given channel .


func (h *Handler) ExportPrivateKey(tkn, account string) ([]byte, error) {
	logger := h.logger.Add("method", "ExportPrivateKey",
		"account", account)
	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	var acc data.Account
	err := h.db.FindByPrimaryKeyTo(&acc, account)
	if err != nil {
		logger.Error(err.Error())
		if err == reform.ErrNoRows {
			return nil, ErrAccountNotFound
		}
		return nil, ErrInternal
	}
	key, err := data.ToBytes(acc.PrivateKey)
	if err != nil {
		logger.Error(err.Error())
		return nil, ErrInternal
	}

	return key, nil
}

func ( h * Handler ) ExportPrivateKey ( tkn , account string ) ( [ ] byte , error ) { logger := h . logger . Add ( " " , " " , " " , account ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return nil , ErrAccessDenied } var acc data . Account err := h . db . FindByPrimaryKeyTo ( & acc , account ) if err != nil { logger . Error ( err . Error ( ) ) if err == reform . ErrNoRows { return nil , ErrAccountNotFound } return nil , ErrInternal } key , err := data . ToBytes ( acc . PrivateKey ) if err != nil { logger . Error ( err . Error ( ) ) return nil , ErrInternal } return key , nil }

// ExportPrivateKey returns a private key in base64 encoding by account id.

ExportPrivateKey returns a private key in base64 encoding by account id .


func (h *Handler) GetAccounts(tkn string) ([]data.Account, error) {
	logger := h.logger.Add("method", "GetAccounts")

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	accounts, err := h.selectAllFrom(logger, data.AccountTable, "")
	if err != nil {
		return nil, err
	}

	result := make([]data.Account, len(accounts))

	for k, v := range accounts {
		result[k] = *v.(*data.Account)
	}

	return result, nil
}

func ( h * Handler ) GetAccounts ( tkn string ) ( [ ] data . Account , error ) { logger := h . logger . Add ( " " , " " ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return nil , ErrAccessDenied } accounts , err := h . selectAllFrom ( logger , data . AccountTable , " " ) if err != nil { return nil , err } result := make ( [ ] data . Account , len ( accounts ) ) for k , v := range accounts { result [ k ] = * v . ( * data . Account ) } return result , nil }


func (h *Handler) GenerateAccount(
	tkn string, params *AccountParams) (*string, error) {
	logger := h.logger.Add("method", "GenerateAccount")

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	account := params.prefilledAccount()

	id, err := h.fillAndSaveAccount(
		logger, account, crypto.GenerateKey, false)
	if err != nil {
		return nil, err
	}

	return &id, nil
}

func ( h * Handler ) GenerateAccount ( tkn string , params * AccountParams ) ( * string , error ) { logger := h . logger . Add ( " " , " " ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return nil , ErrAccessDenied } account := params . prefilledAccount ( ) id , err := h . fillAndSaveAccount ( logger , account , crypto . GenerateKey , false ) if err != nil { return nil , err } return & id , nil }

// GenerateAccount generates new private key and creates new account.

GenerateAccount generates new private key and creates new account .


func (h *Handler) ImportAccountFromHex(
	tkn string, params *AccountParamsWithHexKey) (*string, error) {
	logger := h.logger.Add("method", "ImportAccountFromHex")

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	makeECDSAFunc := h.hexPrivateKeyToECDSA(params.PrivateKeyHex)

	account := params.prefilledAccount()

	id, err := h.fillAndSaveAccount(logger, account, makeECDSAFunc, true)
	if err != nil {
		return nil, err
	}

	return &id, nil
}

func ( h * Handler ) ImportAccountFromHex ( tkn string , params * AccountParamsWithHexKey ) ( * string , error ) { logger := h . logger . Add ( " " , " " ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return nil , ErrAccessDenied } makeECDSAFunc := h . hexPrivateKeyToECDSA ( params . PrivateKeyHex ) account := params . prefilledAccount ( ) id , err := h . fillAndSaveAccount ( logger , account , makeECDSAFunc , true ) if err != nil { return nil , err } return & id , nil }

// ImportAccountFromHex imports private key from hex, creates account
// and initiates JobAccountUpdateBalances job.

ImportAccountFromHex imports private key from hex creates account and initiates JobAccountUpdateBalances job .


func (h *Handler) ImportAccountFromJSON(
	tkn string, params *AccountParams, jsonBlob json.RawMessage,
	jsonKeyStorePassword string) (*string, error) {
	logger := h.logger.Add("method", "ImportAccountFromJSON")

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return nil, ErrAccessDenied
	}

	account := params.prefilledAccount()

	makeECDSAFunc := h.jsonPrivateKeyToECDSA(
		jsonBlob, jsonKeyStorePassword)

	id, err := h.fillAndSaveAccount(
		logger, account, makeECDSAFunc, true)
	if err != nil {
		return nil, err
	}

	return &id, nil
}

func ( h * Handler ) ImportAccountFromJSON ( tkn string , params * AccountParams , jsonBlob json . RawMessage , jsonKeyStorePassword string ) ( * string , error ) { logger := h . logger . Add ( " " , " " ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return nil , ErrAccessDenied } account := params . prefilledAccount ( ) makeECDSAFunc := h . jsonPrivateKeyToECDSA ( jsonBlob , jsonKeyStorePassword ) id , err := h . fillAndSaveAccount ( logger , account , makeECDSAFunc , true ) if err != nil { return nil , err } return & id , nil }

// ImportAccountFromJSON imports private key from JSON blob with password,
// creates account and initiates JobAccountUpdateBalances job.

ImportAccountFromJSON imports private key from JSON blob with password creates account and initiates JobAccountUpdateBalances job .


func (h *Handler) TransferTokens(
	tkn, account, destination string, amount, gasPrice uint64) error {
	logger := h.logger.Add("method", "TransferTokens", "destination",
		destination, "amount", amount, "gasPrice", gasPrice)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return ErrAccessDenied
	}

	if amount == 0 {
		logger.Error(ErrTokenAmountTooSmall.Error())
		return ErrTokenAmountTooSmall
	}

	if destination != data.ContractPSC && destination != data.ContractPTC {
		logger.Error(ErrBadDestination.Error())
		return ErrBadDestination
	}

	err := h.findByPrimaryKey(
		logger, ErrAccountNotFound, &data.Account{}, account)
	if err != nil {
		return err
	}

	jobType := data.JobPreAccountAddBalanceApprove
	if destination == data.ContractPTC {
		jobType = data.JobPreAccountReturnBalance
	}

	jobData := &data.JobBalanceData{
		Amount:   amount,
		GasPrice: gasPrice,
	}

	err = job.AddWithData(h.queue, nil, jobType,
		data.JobAccount, account, data.JobUser, jobData)
	if err != nil {
		logger.Error(err.Error())
		return ErrInternal
	}

	return nil
}

func ( h * Handler ) TransferTokens ( tkn , account , destination string , amount , gasPrice uint64 ) error { logger := h . logger . Add ( " " , " " , " " , destination , " " , amount , " " , gasPrice ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return ErrAccessDenied } if amount == 0 { logger . Error ( ErrTokenAmountTooSmall . Error ( ) ) return ErrTokenAmountTooSmall } if destination != data . ContractPSC && destination != data . ContractPTC { logger . Error ( ErrBadDestination . Error ( ) ) return ErrBadDestination } err := h . findByPrimaryKey ( logger , ErrAccountNotFound , & data . Account { } , account ) if err != nil { return err } jobType := data . JobPreAccountAddBalanceApprove if destination == data . ContractPTC { jobType = data . JobPreAccountReturnBalance } jobData := & data . JobBalanceData { Amount : amount , GasPrice : gasPrice , } err = job . AddWithData ( h . queue , nil , jobType , data . JobAccount , account , data . JobUser , jobData ) if err != nil { logger . Error ( err . Error ( ) ) return ErrInternal } return nil }

// TransferTokens initiates JobPreAccountAddBalanceApprove
// or JobPreAccountReturnBalance job depending on the direction of the transfer.

TransferTokens initiates JobPreAccountAddBalanceApprove or JobPreAccountReturnBalance job depending on the direction of the transfer .


func (h *Handler) UpdateBalance(tkn, account string) error {
	logger := h.logger.Add("method", "UpdateBalance",
		"account", account)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return ErrAccessDenied
	}

	err := h.findByPrimaryKey(
		logger, ErrAccountNotFound, &data.Account{}, account)
	if err != nil {
		return err
	}

	err = job.AddSimple(h.queue, nil, data.JobAccountUpdateBalances,
		data.JobAccount, account, data.JobUser)
	if err != nil {
		logger.Error(err.Error())
		return ErrInternal
	}

	return nil
}

func ( h * Handler ) UpdateBalance ( tkn , account string ) error { logger := h . logger . Add ( " " , " " , " " , account ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return ErrAccessDenied } err := h . findByPrimaryKey ( logger , ErrAccountNotFound , & data . Account { } , account ) if err != nil { return err } err = job . AddSimple ( h . queue , nil , data . JobAccountUpdateBalances , data . JobAccount , account , data . JobUser ) if err != nil { logger . Error ( err . Error ( ) ) return ErrInternal } return nil }

// UpdateBalance initiates JobAccountUpdateBalances job.

UpdateBalance initiates JobAccountUpdateBalances job .


func (h *Handler) UpdateAccount(tkn, account, name string,
	isDefault, inUse bool) error {
	logger := h.logger.Add("method", "UpdateAccount",
		"account", account)

	if !h.token.Check(tkn) {
		logger.Warn("access denied")
		return ErrAccessDenied
	}

	acc := data.Account{}
	err := h.findByPrimaryKey(
		logger, ErrAccountNotFound, &acc, account)
	if err != nil {
		return err
	}

	if name != "" {
		acc.Name = name
	}

	acc.IsDefault = isDefault
	acc.InUse = inUse

	return update(logger, h.db.Querier, &acc)
}

func ( h * Handler ) UpdateAccount ( tkn , account , name string , isDefault , inUse bool ) error { logger := h . logger . Add ( " " , " " , " " , account ) if ! h . token . Check ( tkn ) { logger . Warn ( " " ) return ErrAccessDenied } acc := data . Account { } err := h . findByPrimaryKey ( logger , ErrAccountNotFound , & acc , account ) if err != nil { return err } if name != " " { acc . Name = name } acc . IsDefault = isDefault acc . InUse = inUse return update ( logger , h . db . Querier , & acc ) }