Skip to content

Commit d1c26a2

Browse files
committed
multi: surface server swap initiation grpc error codes
Formatting our error was stifling any grpc error returned by the server. Instead, we bubble up our grpc error, setting an unknown code if the server did not specifically return an error code.
1 parent e7ee29b commit d1c26a2

File tree

5 files changed

+59
-8
lines changed

5 files changed

+59
-8
lines changed

client.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/lightninglabs/loop/loopdb"
1616
"github.com/lightninglabs/loop/swap"
1717
"github.com/lightninglabs/loop/sweep"
18+
"google.golang.org/grpc/status"
1819
)
1920

2021
var (
@@ -610,3 +611,17 @@ func (s *Client) LoopInTerms(ctx context.Context) (
610611

611612
return s.Server.GetLoopInTerms(ctx)
612613
}
614+
615+
// wrapGrpcError wraps the non-nil error provided with a message providing
616+
// additional context, preserving the grpc code returned with the original
617+
// error. If the original error has no grpc code, then codes.Unknown is used.
618+
func wrapGrpcError(message string, err error) error {
619+
// Since our error is non-nil, we don't need to worry about a nil
620+
// grpcStatus, we'll just get an unknown one if no code was passed back.
621+
grpcStatus, _ := status.FromError(err)
622+
623+
return status.Error(
624+
grpcStatus.Code(), fmt.Sprintf("%v: %v", message,
625+
grpcStatus.Message()),
626+
)
627+
}

client_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import (
1717
"github.com/lightningnetwork/lnd/lnrpc"
1818
"github.com/lightningnetwork/lnd/lntypes"
1919
"github.com/stretchr/testify/require"
20+
"google.golang.org/grpc/codes"
21+
"google.golang.org/grpc/status"
2022
)
2123

2224
var (
@@ -372,3 +374,39 @@ func testSuccess(ctx *testContext, amt btcutil.Amount, hash lntypes.Hash,
372374

373375
ctx.finish()
374376
}
377+
378+
// TestWrapGrpcError tests grpc error wrapping in the case where a grpc error
379+
// code is present, and when it is absent.
380+
func TestWrapGrpcError(t *testing.T) {
381+
tests := []struct {
382+
name string
383+
original error
384+
expectedCode codes.Code
385+
}{
386+
{
387+
name: "out of range error",
388+
original: status.Error(
389+
codes.OutOfRange, "err string",
390+
),
391+
expectedCode: codes.OutOfRange,
392+
},
393+
{
394+
name: "no grpc code",
395+
original: errors.New("no error code"),
396+
expectedCode: codes.Unknown,
397+
},
398+
}
399+
400+
for _, testCase := range tests {
401+
testCase := testCase
402+
403+
t.Run(testCase.name, func(t *testing.T) {
404+
err := wrapGrpcError("", testCase.original)
405+
require.Error(t, err, "test only expects errors")
406+
407+
status, ok := status.FromError(err)
408+
require.True(t, ok, "test expects grpc code")
409+
require.Equal(t, testCase.expectedCode, status.Code())
410+
})
411+
}
412+
}

loopin.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ import (
99
"sync"
1010
"time"
1111

12-
"github.com/btcsuite/btcutil"
13-
1412
"github.com/btcsuite/btcd/chaincfg/chainhash"
1513
"github.com/btcsuite/btcd/mempool"
1614
"github.com/btcsuite/btcd/wire"
15+
"github.com/btcsuite/btcutil"
1716
"github.com/lightninglabs/lndclient"
1817
"github.com/lightninglabs/loop/labels"
1918
"github.com/lightninglabs/loop/loopdb"
@@ -86,7 +85,7 @@ func newLoopInSwap(globalCtx context.Context, cfg *swapConfig,
8685
// request that we send to the server.
8786
quote, err := cfg.server.GetLoopInQuote(globalCtx, request.Amount)
8887
if err != nil {
89-
return nil, fmt.Errorf("loop in terms: %v", err)
88+
return nil, wrapGrpcError("loop in terms", err)
9089
}
9190

9291
swapFee := quote.SwapFee
@@ -172,7 +171,7 @@ func newLoopInSwap(globalCtx context.Context, cfg *swapConfig,
172171
)
173172
probeWaitCancel()
174173
if err != nil {
175-
return nil, fmt.Errorf("cannot initiate swap: %v", err)
174+
return nil, wrapGrpcError("cannot initiate swap", err)
176175
}
177176

178177
// Because the context is cancelled, it is guaranteed that we will be

loopin_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ import (
44
"context"
55
"testing"
66

7+
"github.com/btcsuite/btcd/wire"
8+
"github.com/btcsuite/btcutil"
79
"github.com/lightninglabs/loop/loopdb"
810
"github.com/lightninglabs/loop/swap"
911
"github.com/lightninglabs/loop/test"
1012
"github.com/lightningnetwork/lnd/chainntnfs"
1113
"github.com/lightningnetwork/lnd/channeldb"
1214
"github.com/stretchr/testify/require"
13-
14-
"github.com/btcsuite/btcd/wire"
15-
"github.com/btcsuite/btcutil"
1615
)
1716

1817
var (

loopout.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func newLoopOutSwap(globalCtx context.Context, cfg *swapConfig,
128128
receiverKey, request.SwapPublicationDeadline, request.Initiator,
129129
)
130130
if err != nil {
131-
return nil, fmt.Errorf("cannot initiate swap: %v", err)
131+
return nil, wrapGrpcError("cannot initiate swap", err)
132132
}
133133

134134
err = validateLoopOutContract(

0 commit comments

Comments
 (0)