code.vegaprotocol.io/vega@v0.79.0/wallet/service/v1/policies.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package v1
    17  
    18  import (
    19  	"context"
    20  	"time"
    21  
    22  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    23  	v1 "code.vegaprotocol.io/vega/protos/vega/wallet/v1"
    24  )
    25  
    26  type ConsentConfirmation struct {
    27  	TxID     string
    28  	Decision bool
    29  }
    30  
    31  type ConsentRequest struct {
    32  	TxID         string
    33  	Tx           *v1.SubmitTransactionRequest
    34  	ReceivedAt   time.Time
    35  	Confirmation chan ConsentConfirmation
    36  }
    37  
    38  type SentTransaction struct {
    39  	TxHash string
    40  	TxID   string
    41  	Tx     *commandspb.Transaction
    42  	Error  error
    43  	SentAt time.Time
    44  }
    45  
    46  type Policy interface {
    47  	Ask(tx *v1.SubmitTransactionRequest, txID string, receivedAt time.Time) (bool, error)
    48  	Report(tx SentTransaction)
    49  }
    50  
    51  type AutomaticConsentPolicy struct{}
    52  
    53  func NewAutomaticConsentPolicy() Policy {
    54  	return &AutomaticConsentPolicy{}
    55  }
    56  
    57  func (p *AutomaticConsentPolicy) Ask(_ *v1.SubmitTransactionRequest, _ string, _ time.Time) (bool, error) {
    58  	return true, nil
    59  }
    60  
    61  func (p *AutomaticConsentPolicy) Report(_ SentTransaction) {
    62  	// Nothing to report as we expect this policy to be non-interactive.
    63  }
    64  
    65  type ExplicitConsentPolicy struct {
    66  	// ctx is used to interrupt the wait for consent confirmation
    67  	ctx context.Context
    68  
    69  	consentRequestsChan  chan ConsentRequest
    70  	sentTransactionsChan chan SentTransaction
    71  }
    72  
    73  func NewExplicitConsentPolicy(ctx context.Context, consentRequests chan ConsentRequest, sentTransactions chan SentTransaction) Policy {
    74  	return &ExplicitConsentPolicy{
    75  		ctx:                  ctx,
    76  		consentRequestsChan:  consentRequests,
    77  		sentTransactionsChan: sentTransactions,
    78  	}
    79  }
    80  
    81  func (p *ExplicitConsentPolicy) Ask(tx *v1.SubmitTransactionRequest, txID string, receivedAt time.Time) (bool, error) {
    82  	confirmationChan := make(chan ConsentConfirmation, 1)
    83  	defer close(confirmationChan)
    84  
    85  	consentRequest := ConsentRequest{
    86  		TxID:         txID,
    87  		Tx:           tx,
    88  		ReceivedAt:   receivedAt,
    89  		Confirmation: confirmationChan,
    90  	}
    91  
    92  	if err := p.sendConsentRequest(consentRequest); err != nil {
    93  		return false, err
    94  	}
    95  
    96  	return p.receiveConsentConfirmation(consentRequest)
    97  }
    98  
    99  func (p *ExplicitConsentPolicy) receiveConsentConfirmation(consentRequest ConsentRequest) (bool, error) {
   100  	for {
   101  		select {
   102  		case <-p.ctx.Done():
   103  			return false, ErrInterruptedConsentRequest
   104  		case decision := <-consentRequest.Confirmation:
   105  			return decision.Decision, nil
   106  		}
   107  	}
   108  }
   109  
   110  func (p *ExplicitConsentPolicy) sendConsentRequest(consentRequest ConsentRequest) error {
   111  	for {
   112  		select {
   113  		case <-p.ctx.Done():
   114  			return ErrInterruptedConsentRequest
   115  		case p.consentRequestsChan <- consentRequest:
   116  			return nil
   117  		}
   118  	}
   119  }
   120  
   121  func (p *ExplicitConsentPolicy) Report(tx SentTransaction) {
   122  	p.sentTransactionsChan <- tx
   123  }