Skip to content

Commit 9e5578c

Browse files
authored
Merge pull request #974 from ViktorTigerstrom/2025-02-credit-debit-accounts-impl
accounts: Add credit and debit account functionality
2 parents 4cc7bf2 + 0c520ce commit 9e5578c

19 files changed

+2797
-187
lines changed

accounts/checkers_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,18 @@ type mockService struct {
6363
*requestValuesStore
6464
}
6565

66+
func (m *mockService) CreditAccount(_ context.Context, _ AccountID,
67+
_ lnwire.MilliSatoshi) (*OffChainBalanceAccount, error) {
68+
69+
return nil, nil
70+
}
71+
72+
func (m *mockService) DebitAccount(_ context.Context, _ AccountID,
73+
_ lnwire.MilliSatoshi) (*OffChainBalanceAccount, error) {
74+
75+
return nil, nil
76+
}
77+
6678
func newMockService() *mockService {
6779
return &mockService{
6880
acctBalanceMsat: 0,

accounts/interface.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,16 @@ type Service interface {
331331
PaymentErrored(ctx context.Context, id AccountID,
332332
hash lntypes.Hash) error
333333

334+
// CreditAccount increases the balance of an existing account in the
335+
// database.
336+
CreditAccount(ctx context.Context, accountID AccountID,
337+
amount lnwire.MilliSatoshi) (*OffChainBalanceAccount, error)
338+
339+
// DebitAccount decreases the balance of an existing account in the
340+
// database.
341+
DebitAccount(ctx context.Context, accountID AccountID,
342+
amount lnwire.MilliSatoshi) (*OffChainBalanceAccount, error)
343+
334344
RequestValuesStore
335345
}
336346

accounts/rpcserver.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,83 @@ func (s *RPCServer) UpdateAccount(ctx context.Context,
130130
return marshalAccount(account), nil
131131
}
132132

133+
// CreditAccount increases the balance of an existing account in the account
134+
// database, by the given amount.
135+
func (s *RPCServer) CreditAccount(ctx context.Context,
136+
req *litrpc.CreditAccountRequest) (*litrpc.CreditAccountResponse,
137+
error) {
138+
139+
if req.GetAccount() == nil {
140+
return nil, fmt.Errorf("account param must be specified")
141+
}
142+
143+
var id, label string
144+
145+
switch idType := req.Account.Identifier.(type) {
146+
case *litrpc.AccountIdentifier_Id:
147+
id = idType.Id
148+
case *litrpc.AccountIdentifier_Label:
149+
label = idType.Label
150+
}
151+
152+
log.Infof("[creditaccount] id=%s, label=%v, amount=%d", id, label,
153+
req.Amount)
154+
155+
amount := lnwire.MilliSatoshi(req.Amount * 1000)
156+
157+
accountID, err := s.findAccount(ctx, id, label)
158+
if err != nil {
159+
return nil, err
160+
}
161+
162+
account, err := s.service.CreditAccount(ctx, accountID, amount)
163+
if err != nil {
164+
return nil, err
165+
}
166+
167+
return &litrpc.CreditAccountResponse{
168+
Account: marshalAccount(account),
169+
}, nil
170+
}
171+
172+
// DebitAccount decreases the balance of an existing account in the account
173+
// database, by the given amount.
174+
func (s *RPCServer) DebitAccount(ctx context.Context,
175+
req *litrpc.DebitAccountRequest) (*litrpc.DebitAccountResponse, error) {
176+
177+
if req.GetAccount() == nil {
178+
return nil, fmt.Errorf("account param must be specified")
179+
}
180+
181+
var id, label string
182+
183+
switch idType := req.Account.Identifier.(type) {
184+
case *litrpc.AccountIdentifier_Id:
185+
id = idType.Id
186+
case *litrpc.AccountIdentifier_Label:
187+
label = idType.Label
188+
}
189+
190+
log.Infof("[debitaccount] id=%s, label=%v, amount=%d", id, label,
191+
req.Amount)
192+
193+
amount := lnwire.MilliSatoshi(req.Amount * 1000)
194+
195+
accountID, err := s.findAccount(ctx, id, label)
196+
if err != nil {
197+
return nil, err
198+
}
199+
200+
account, err := s.service.DebitAccount(ctx, accountID, amount)
201+
if err != nil {
202+
return nil, err
203+
}
204+
205+
return &litrpc.DebitAccountResponse{
206+
Account: marshalAccount(account),
207+
}, nil
208+
}
209+
133210
// ListAccounts returns all accounts that are currently stored in the account
134211
// database.
135212
func (s *RPCServer) ListAccounts(ctx context.Context,

accounts/service.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,56 @@ func (s *InterceptorService) UpdateAccount(ctx context.Context,
345345
return s.store.Account(ctx, accountID)
346346
}
347347

348+
// CreditAccount increases the balance of an existing account in the database.
349+
func (s *InterceptorService) CreditAccount(ctx context.Context,
350+
accountID AccountID,
351+
amount lnwire.MilliSatoshi) (*OffChainBalanceAccount, error) {
352+
353+
s.Lock()
354+
defer s.Unlock()
355+
356+
// As this function updates account balances, we require that the
357+
// service is running before we execute it.
358+
if !s.isRunningUnsafe() {
359+
// This case can only happen if the service is disabled while
360+
// we're processing a request.
361+
return nil, ErrAccountServiceDisabled
362+
}
363+
364+
// Credit the account in the db.
365+
err := s.store.CreditAccount(ctx, accountID, amount)
366+
if err != nil {
367+
return nil, fmt.Errorf("unable to credit account: %w", err)
368+
}
369+
370+
return s.store.Account(ctx, accountID)
371+
}
372+
373+
// DebitAccount decreases the balance of an existing account in the database.
374+
func (s *InterceptorService) DebitAccount(ctx context.Context,
375+
accountID AccountID,
376+
amount lnwire.MilliSatoshi) (*OffChainBalanceAccount, error) {
377+
378+
s.Lock()
379+
defer s.Unlock()
380+
381+
// As this function updates account balances, we require that the
382+
// service is running before we execute it.
383+
if !s.isRunningUnsafe() {
384+
// This case can only happen if the service is disabled while
385+
// we're processing a request.
386+
return nil, ErrAccountServiceDisabled
387+
}
388+
389+
// Debit the account in the db.
390+
err := s.store.DebitAccount(ctx, accountID, amount)
391+
if err != nil {
392+
return nil, fmt.Errorf("unable to debit account: %w", err)
393+
}
394+
395+
return s.store.Account(ctx, accountID)
396+
}
397+
348398
// Account retrieves an account from the bolt DB and un-marshals it. If the
349399
// account cannot be found, then ErrAccNotFound is returned.
350400
func (s *InterceptorService) Account(ctx context.Context,

app/src/types/generated/lit-accounts_pb.d.ts

Lines changed: 131 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)