Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mybee
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
mybee
Commits
7aa2db90
Unverified
Commit
7aa2db90
authored
Jan 28, 2021
by
acud
Committed by
GitHub
Jan 28, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
settlement: add available balance metric (#1172)
parent
1bad8c23
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
44 additions
and
36 deletions
+44
-36
chequebook.go
pkg/settlement/swap/chequebook/chequebook.go
+18
-16
chequebook_test.go
pkg/settlement/swap/chequebook/chequebook_test.go
+5
-5
chequebook.go
pkg/settlement/swap/chequebook/mock/chequebook.go
+4
-4
metrics.go
pkg/settlement/swap/metrics.go
+10
-6
swap.go
pkg/settlement/swap/swap.go
+3
-1
swap_test.go
pkg/settlement/swap/swap_test.go
+4
-4
No files found.
pkg/settlement/swap/chequebook/chequebook.go
View file @
7aa2db90
...
@@ -50,7 +50,7 @@ type Service interface {
...
@@ -50,7 +50,7 @@ type Service interface {
// Address returns the address of the used chequebook contract.
// Address returns the address of the used chequebook contract.
Address
()
common
.
Address
Address
()
common
.
Address
// Issue a new cheque for the beneficiary with an cumulativePayout amount higher than the last.
// Issue a new cheque for the beneficiary with an cumulativePayout amount higher than the last.
Issue
(
ctx
context
.
Context
,
beneficiary
common
.
Address
,
amount
*
big
.
Int
,
sendChequeFunc
SendChequeFunc
)
error
Issue
(
ctx
context
.
Context
,
beneficiary
common
.
Address
,
amount
*
big
.
Int
,
sendChequeFunc
SendChequeFunc
)
(
*
big
.
Int
,
error
)
// LastCheque returns the last cheque we issued for the beneficiary.
// LastCheque returns the last cheque we issued for the beneficiary.
LastCheque
(
beneficiary
common
.
Address
)
(
*
SignedCheque
,
error
)
LastCheque
(
beneficiary
common
.
Address
)
(
*
SignedCheque
,
error
)
// LastCheque returns the last cheques for all beneficiaries.
// LastCheque returns the last cheques for all beneficiaries.
...
@@ -204,21 +204,21 @@ func lastIssuedChequeKey(beneficiary common.Address) string {
...
@@ -204,21 +204,21 @@ func lastIssuedChequeKey(beneficiary common.Address) string {
return
fmt
.
Sprintf
(
"chequebook_last_issued_cheque_%x"
,
beneficiary
)
return
fmt
.
Sprintf
(
"chequebook_last_issued_cheque_%x"
,
beneficiary
)
}
}
func
(
s
*
service
)
reserveTotalIssued
(
ctx
context
.
Context
,
amount
*
big
.
Int
)
error
{
func
(
s
*
service
)
reserveTotalIssued
(
ctx
context
.
Context
,
amount
*
big
.
Int
)
(
*
big
.
Int
,
error
)
{
s
.
lock
.
Lock
()
s
.
lock
.
Lock
()
defer
s
.
lock
.
Unlock
()
defer
s
.
lock
.
Unlock
()
availableBalance
,
err
:=
s
.
AvailableBalance
(
ctx
)
availableBalance
,
err
:=
s
.
AvailableBalance
(
ctx
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
nil
,
err
}
}
if
amount
.
Cmp
(
big
.
NewInt
(
0
)
.
Sub
(
availableBalance
,
s
.
totalIssuedReserved
))
>
0
{
if
amount
.
Cmp
(
big
.
NewInt
(
0
)
.
Sub
(
availableBalance
,
s
.
totalIssuedReserved
))
>
0
{
return
ErrOutOfFunds
return
nil
,
ErrOutOfFunds
}
}
s
.
totalIssuedReserved
=
s
.
totalIssuedReserved
.
Add
(
s
.
totalIssuedReserved
,
amount
)
s
.
totalIssuedReserved
=
s
.
totalIssuedReserved
.
Add
(
s
.
totalIssuedReserved
,
amount
)
return
nil
return
big
.
NewInt
(
0
)
.
Sub
(
availableBalance
,
amount
),
nil
}
}
func
(
s
*
service
)
unreserveTotalIssued
(
amount
*
big
.
Int
)
{
func
(
s
*
service
)
unreserveTotalIssued
(
amount
*
big
.
Int
)
{
...
@@ -227,12 +227,14 @@ func (s *service) unreserveTotalIssued(amount *big.Int) {
...
@@ -227,12 +227,14 @@ func (s *service) unreserveTotalIssued(amount *big.Int) {
s
.
totalIssuedReserved
=
s
.
totalIssuedReserved
.
Sub
(
s
.
totalIssuedReserved
,
amount
)
s
.
totalIssuedReserved
=
s
.
totalIssuedReserved
.
Sub
(
s
.
totalIssuedReserved
,
amount
)
}
}
// Issue issues a new cheque and passes it to sendChequeFunc
// Issue issues a new cheque and passes it to sendChequeFunc.
// if sendChequeFunc succeeds the cheque is considered sent and saved
// The cheque is considered sent and saved when sendChequeFunc succeeds.
func
(
s
*
service
)
Issue
(
ctx
context
.
Context
,
beneficiary
common
.
Address
,
amount
*
big
.
Int
,
sendChequeFunc
SendChequeFunc
)
error
{
// The available balance which is available after sending the cheque is passed
err
:=
s
.
reserveTotalIssued
(
ctx
,
amount
)
// to the caller for it to be communicated over metrics.
func
(
s
*
service
)
Issue
(
ctx
context
.
Context
,
beneficiary
common
.
Address
,
amount
*
big
.
Int
,
sendChequeFunc
SendChequeFunc
)
(
*
big
.
Int
,
error
)
{
availableBalance
,
err
:=
s
.
reserveTotalIssued
(
ctx
,
amount
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
nil
,
err
}
}
defer
s
.
unreserveTotalIssued
(
amount
)
defer
s
.
unreserveTotalIssued
(
amount
)
...
@@ -240,7 +242,7 @@ func (s *service) Issue(ctx context.Context, beneficiary common.Address, amount
...
@@ -240,7 +242,7 @@ func (s *service) Issue(ctx context.Context, beneficiary common.Address, amount
lastCheque
,
err
:=
s
.
LastCheque
(
beneficiary
)
lastCheque
,
err
:=
s
.
LastCheque
(
beneficiary
)
if
err
!=
nil
{
if
err
!=
nil
{
if
err
!=
ErrNoCheque
{
if
err
!=
ErrNoCheque
{
return
err
return
nil
,
err
}
}
cumulativePayout
=
big
.
NewInt
(
0
)
cumulativePayout
=
big
.
NewInt
(
0
)
}
else
{
}
else
{
...
@@ -263,7 +265,7 @@ func (s *service) Issue(ctx context.Context, beneficiary common.Address, amount
...
@@ -263,7 +265,7 @@ func (s *service) Issue(ctx context.Context, beneficiary common.Address, amount
Beneficiary
:
beneficiary
,
Beneficiary
:
beneficiary
,
})
})
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
nil
,
err
}
}
// actually send the check before saving to avoid double payment
// actually send the check before saving to avoid double payment
...
@@ -272,12 +274,12 @@ func (s *service) Issue(ctx context.Context, beneficiary common.Address, amount
...
@@ -272,12 +274,12 @@ func (s *service) Issue(ctx context.Context, beneficiary common.Address, amount
Signature
:
sig
,
Signature
:
sig
,
})
})
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
nil
,
err
}
}
err
=
s
.
store
.
Put
(
lastIssuedChequeKey
(
beneficiary
),
cheque
)
err
=
s
.
store
.
Put
(
lastIssuedChequeKey
(
beneficiary
),
cheque
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
nil
,
err
}
}
s
.
lock
.
Lock
()
s
.
lock
.
Lock
()
...
@@ -285,10 +287,10 @@ func (s *service) Issue(ctx context.Context, beneficiary common.Address, amount
...
@@ -285,10 +287,10 @@ func (s *service) Issue(ctx context.Context, beneficiary common.Address, amount
totalIssued
,
err
:=
s
.
totalIssued
()
totalIssued
,
err
:=
s
.
totalIssued
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
nil
,
err
}
}
totalIssued
=
totalIssued
.
Add
(
totalIssued
,
amount
)
totalIssued
=
totalIssued
.
Add
(
totalIssued
,
amount
)
return
s
.
store
.
Put
(
totalIssuedKey
,
totalIssued
)
return
availableBalance
,
s
.
store
.
Put
(
totalIssuedKey
,
totalIssued
)
}
}
// returns the total amount in cheques issued so far
// returns the total amount in cheques issued so far
...
...
pkg/settlement/swap/chequebook/chequebook_test.go
View file @
7aa2db90
...
@@ -292,7 +292,7 @@ func TestChequebookIssue(t *testing.T) {
...
@@ -292,7 +292,7 @@ func TestChequebookIssue(t *testing.T) {
return
sig
,
nil
return
sig
,
nil
}
}
err
=
chequebookService
.
Issue
(
context
.
Background
(),
beneficiary
,
amount
,
func
(
cheque
*
chequebook
.
SignedCheque
)
error
{
_
,
err
=
chequebookService
.
Issue
(
context
.
Background
(),
beneficiary
,
amount
,
func
(
cheque
*
chequebook
.
SignedCheque
)
error
{
if
!
cheque
.
Equal
(
expectedCheque
)
{
if
!
cheque
.
Equal
(
expectedCheque
)
{
t
.
Fatalf
(
"wrong cheque. wanted %v got %v"
,
expectedCheque
,
cheque
)
t
.
Fatalf
(
"wrong cheque. wanted %v got %v"
,
expectedCheque
,
cheque
)
}
}
...
@@ -328,7 +328,7 @@ func TestChequebookIssue(t *testing.T) {
...
@@ -328,7 +328,7 @@ func TestChequebookIssue(t *testing.T) {
return
sig
,
nil
return
sig
,
nil
}
}
err
=
chequebookService
.
Issue
(
context
.
Background
(),
beneficiary
,
amount2
,
func
(
cheque
*
chequebook
.
SignedCheque
)
error
{
_
,
err
=
chequebookService
.
Issue
(
context
.
Background
(),
beneficiary
,
amount2
,
func
(
cheque
*
chequebook
.
SignedCheque
)
error
{
if
!
cheque
.
Equal
(
expectedCheque
)
{
if
!
cheque
.
Equal
(
expectedCheque
)
{
t
.
Fatalf
(
"wrong cheque. wanted %v got %v"
,
expectedCheque
,
cheque
)
t
.
Fatalf
(
"wrong cheque. wanted %v got %v"
,
expectedCheque
,
cheque
)
}
}
...
@@ -364,7 +364,7 @@ func TestChequebookIssue(t *testing.T) {
...
@@ -364,7 +364,7 @@ func TestChequebookIssue(t *testing.T) {
return
sig
,
nil
return
sig
,
nil
}
}
err
=
chequebookService
.
Issue
(
context
.
Background
(),
ownerAdress
,
amount
,
func
(
cheque
*
chequebook
.
SignedCheque
)
error
{
_
,
err
=
chequebookService
.
Issue
(
context
.
Background
(),
ownerAdress
,
amount
,
func
(
cheque
*
chequebook
.
SignedCheque
)
error
{
if
!
cheque
.
Equal
(
expectedChequeOwner
)
{
if
!
cheque
.
Equal
(
expectedChequeOwner
)
{
t
.
Fatalf
(
"wrong cheque. wanted %v got %v"
,
expectedChequeOwner
,
cheque
)
t
.
Fatalf
(
"wrong cheque. wanted %v got %v"
,
expectedChequeOwner
,
cheque
)
}
}
...
@@ -430,7 +430,7 @@ func TestChequebookIssueErrorSend(t *testing.T) {
...
@@ -430,7 +430,7 @@ func TestChequebookIssueErrorSend(t *testing.T) {
return
sig
,
nil
return
sig
,
nil
}
}
err
=
chequebookService
.
Issue
(
context
.
Background
(),
beneficiary
,
amount
,
func
(
cheque
*
chequebook
.
SignedCheque
)
error
{
_
,
err
=
chequebookService
.
Issue
(
context
.
Background
(),
beneficiary
,
amount
,
func
(
cheque
*
chequebook
.
SignedCheque
)
error
{
return
errors
.
New
(
"err"
)
return
errors
.
New
(
"err"
)
})
})
if
err
==
nil
{
if
err
==
nil
{
...
@@ -474,7 +474,7 @@ func TestChequebookIssueOutOfFunds(t *testing.T) {
...
@@ -474,7 +474,7 @@ func TestChequebookIssueOutOfFunds(t *testing.T) {
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
err
=
chequebookService
.
Issue
(
context
.
Background
(),
beneficiary
,
amount
,
func
(
cheque
*
chequebook
.
SignedCheque
)
error
{
_
,
err
=
chequebookService
.
Issue
(
context
.
Background
(),
beneficiary
,
amount
,
func
(
cheque
*
chequebook
.
SignedCheque
)
error
{
return
nil
return
nil
})
})
if
!
errors
.
Is
(
err
,
chequebook
.
ErrOutOfFunds
)
{
if
!
errors
.
Is
(
err
,
chequebook
.
ErrOutOfFunds
)
{
...
...
pkg/settlement/swap/chequebook/mock/chequebook.go
View file @
7aa2db90
...
@@ -18,7 +18,7 @@ type Service struct {
...
@@ -18,7 +18,7 @@ type Service struct {
chequebookBalanceFunc
func
(
context
.
Context
)
(
*
big
.
Int
,
error
)
chequebookBalanceFunc
func
(
context
.
Context
)
(
*
big
.
Int
,
error
)
chequebookAvailableBalanceFunc
func
(
context
.
Context
)
(
*
big
.
Int
,
error
)
chequebookAvailableBalanceFunc
func
(
context
.
Context
)
(
*
big
.
Int
,
error
)
chequebookAddressFunc
func
()
common
.
Address
chequebookAddressFunc
func
()
common
.
Address
chequebookIssueFunc
func
(
ctx
context
.
Context
,
beneficiary
common
.
Address
,
amount
*
big
.
Int
,
sendChequeFunc
chequebook
.
SendChequeFunc
)
error
chequebookIssueFunc
func
(
ctx
context
.
Context
,
beneficiary
common
.
Address
,
amount
*
big
.
Int
,
sendChequeFunc
chequebook
.
SendChequeFunc
)
(
*
big
.
Int
,
error
)
chequebookWithdrawFunc
func
(
ctx
context
.
Context
,
amount
*
big
.
Int
)
(
hash
common
.
Hash
,
err
error
)
chequebookWithdrawFunc
func
(
ctx
context
.
Context
,
amount
*
big
.
Int
)
(
hash
common
.
Hash
,
err
error
)
chequebookDepositFunc
func
(
ctx
context
.
Context
,
amount
*
big
.
Int
)
(
hash
common
.
Hash
,
err
error
)
chequebookDepositFunc
func
(
ctx
context
.
Context
,
amount
*
big
.
Int
)
(
hash
common
.
Hash
,
err
error
)
}
}
...
@@ -48,7 +48,7 @@ func WithChequebookDepositFunc(f func(ctx context.Context, amount *big.Int) (has
...
@@ -48,7 +48,7 @@ func WithChequebookDepositFunc(f func(ctx context.Context, amount *big.Int) (has
})
})
}
}
func
WithChequebookIssueFunc
(
f
func
(
ctx
context
.
Context
,
beneficiary
common
.
Address
,
amount
*
big
.
Int
,
sendChequeFunc
chequebook
.
SendChequeFunc
)
error
)
Option
{
func
WithChequebookIssueFunc
(
f
func
(
ctx
context
.
Context
,
beneficiary
common
.
Address
,
amount
*
big
.
Int
,
sendChequeFunc
chequebook
.
SendChequeFunc
)
(
*
big
.
Int
,
error
)
)
Option
{
return
optionFunc
(
func
(
s
*
Service
)
{
return
optionFunc
(
func
(
s
*
Service
)
{
s
.
chequebookIssueFunc
=
f
s
.
chequebookIssueFunc
=
f
})
})
...
@@ -105,11 +105,11 @@ func (s *Service) Address() common.Address {
...
@@ -105,11 +105,11 @@ func (s *Service) Address() common.Address {
return
common
.
Address
{}
return
common
.
Address
{}
}
}
func
(
s
*
Service
)
Issue
(
ctx
context
.
Context
,
beneficiary
common
.
Address
,
amount
*
big
.
Int
,
sendChequeFunc
chequebook
.
SendChequeFunc
)
error
{
func
(
s
*
Service
)
Issue
(
ctx
context
.
Context
,
beneficiary
common
.
Address
,
amount
*
big
.
Int
,
sendChequeFunc
chequebook
.
SendChequeFunc
)
(
*
big
.
Int
,
error
)
{
if
s
.
chequebookIssueFunc
!=
nil
{
if
s
.
chequebookIssueFunc
!=
nil
{
return
s
.
chequebookIssueFunc
(
ctx
,
beneficiary
,
amount
,
sendChequeFunc
)
return
s
.
chequebookIssueFunc
(
ctx
,
beneficiary
,
amount
,
sendChequeFunc
)
}
}
return
nil
return
big
.
NewInt
(
0
),
nil
}
}
func
(
s
*
Service
)
LastCheque
(
beneficiary
common
.
Address
)
(
*
chequebook
.
SignedCheque
,
error
)
{
func
(
s
*
Service
)
LastCheque
(
beneficiary
common
.
Address
)
(
*
chequebook
.
SignedCheque
,
error
)
{
...
...
pkg/settlement/swap/metrics.go
View file @
7aa2db90
...
@@ -10,12 +10,10 @@ import (
...
@@ -10,12 +10,10 @@ import (
)
)
type
metrics
struct
{
type
metrics
struct
{
// all metrics fields must be exported
TotalReceived
prometheus
.
Counter
// to be able to return them by Metrics()
TotalSent
prometheus
.
Counter
// using reflection
ChequesRejected
prometheus
.
Counter
TotalReceived
prometheus
.
Counter
AvailableBalance
prometheus
.
Gauge
TotalSent
prometheus
.
Counter
ChequesRejected
prometheus
.
Counter
}
}
func
newMetrics
()
metrics
{
func
newMetrics
()
metrics
{
...
@@ -40,6 +38,12 @@ func newMetrics() metrics {
...
@@ -40,6 +38,12 @@ func newMetrics() metrics {
Name
:
"cheques_rejected"
,
Name
:
"cheques_rejected"
,
Help
:
"Number of cheques rejected"
,
Help
:
"Number of cheques rejected"
,
}),
}),
AvailableBalance
:
prometheus
.
NewGauge
(
prometheus
.
GaugeOpts
{
Namespace
:
m
.
Namespace
,
Subsystem
:
subsystem
,
Name
:
"available_balance"
,
Help
:
"Currently availeble chequebook balance."
,
}),
}
}
}
}
...
...
pkg/settlement/swap/swap.go
View file @
7aa2db90
...
@@ -119,12 +119,14 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) er
...
@@ -119,12 +119,14 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) er
}
}
return
ErrUnknownBeneficary
return
ErrUnknownBeneficary
}
}
err
=
s
.
chequebook
.
Issue
(
ctx
,
beneficiary
,
big
.
NewInt
(
int64
(
amount
)),
func
(
signedCheque
*
chequebook
.
SignedCheque
)
error
{
balance
,
err
:
=
s
.
chequebook
.
Issue
(
ctx
,
beneficiary
,
big
.
NewInt
(
int64
(
amount
)),
func
(
signedCheque
*
chequebook
.
SignedCheque
)
error
{
return
s
.
proto
.
EmitCheque
(
ctx
,
peer
,
signedCheque
)
return
s
.
proto
.
EmitCheque
(
ctx
,
peer
,
signedCheque
)
})
})
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
bal
,
_
:=
big
.
NewFloat
(
0
)
.
SetInt
(
balance
)
.
Float64
()
s
.
metrics
.
AvailableBalance
.
Set
(
bal
)
s
.
metrics
.
TotalSent
.
Add
(
float64
(
amount
))
s
.
metrics
.
TotalSent
.
Add
(
float64
(
amount
))
return
nil
return
nil
}
}
...
...
pkg/settlement/swap/swap_test.go
View file @
7aa2db90
...
@@ -285,7 +285,7 @@ func TestPay(t *testing.T) {
...
@@ -285,7 +285,7 @@ func TestPay(t *testing.T) {
peer
:=
swarm
.
MustParseHexAddress
(
"abcd"
)
peer
:=
swarm
.
MustParseHexAddress
(
"abcd"
)
var
chequebookCalled
bool
var
chequebookCalled
bool
chequebookService
:=
mockchequebook
.
NewChequebook
(
chequebookService
:=
mockchequebook
.
NewChequebook
(
mockchequebook
.
WithChequebookIssueFunc
(
func
(
ctx
context
.
Context
,
b
common
.
Address
,
a
*
big
.
Int
,
sendChequeFunc
chequebook
.
SendChequeFunc
)
error
{
mockchequebook
.
WithChequebookIssueFunc
(
func
(
ctx
context
.
Context
,
b
common
.
Address
,
a
*
big
.
Int
,
sendChequeFunc
chequebook
.
SendChequeFunc
)
(
*
big
.
Int
,
error
)
{
if
b
!=
beneficiary
{
if
b
!=
beneficiary
{
t
.
Fatalf
(
"issuing cheque for wrong beneficiary. wanted %v, got %v"
,
beneficiary
,
b
)
t
.
Fatalf
(
"issuing cheque for wrong beneficiary. wanted %v, got %v"
,
beneficiary
,
b
)
}
}
...
@@ -293,7 +293,7 @@ func TestPay(t *testing.T) {
...
@@ -293,7 +293,7 @@ func TestPay(t *testing.T) {
t
.
Fatalf
(
"issuing cheque with wrong amount. wanted %d, got %d"
,
amount
,
a
)
t
.
Fatalf
(
"issuing cheque with wrong amount. wanted %d, got %d"
,
amount
,
a
)
}
}
chequebookCalled
=
true
chequebookCalled
=
true
return
sendChequeFunc
(
&
cheque
)
return
big
.
NewInt
(
0
),
sendChequeFunc
(
&
cheque
)
}),
}),
)
)
...
@@ -355,8 +355,8 @@ func TestPayIssueError(t *testing.T) {
...
@@ -355,8 +355,8 @@ func TestPayIssueError(t *testing.T) {
peer
:=
swarm
.
MustParseHexAddress
(
"abcd"
)
peer
:=
swarm
.
MustParseHexAddress
(
"abcd"
)
errReject
:=
errors
.
New
(
"reject"
)
errReject
:=
errors
.
New
(
"reject"
)
chequebookService
:=
mockchequebook
.
NewChequebook
(
chequebookService
:=
mockchequebook
.
NewChequebook
(
mockchequebook
.
WithChequebookIssueFunc
(
func
(
ctx
context
.
Context
,
b
common
.
Address
,
a
*
big
.
Int
,
sendChequeFunc
chequebook
.
SendChequeFunc
)
error
{
mockchequebook
.
WithChequebookIssueFunc
(
func
(
ctx
context
.
Context
,
b
common
.
Address
,
a
*
big
.
Int
,
sendChequeFunc
chequebook
.
SendChequeFunc
)
(
*
big
.
Int
,
error
)
{
return
errReject
return
big
.
NewInt
(
0
),
errReject
}),
}),
)
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment