From 1b974e52d2a5c91c295987eafa595e25316c3112 Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Wed, 7 Jan 2026 16:26:53 +0100 Subject: [PATCH 1/2] endorse_test improvements Signed-off-by: Angelo De Caro --- token/services/ttx/endorse_test.go | 332 +++++++++++++++++++++++++++-- 1 file changed, 318 insertions(+), 14 deletions(-) diff --git a/token/services/ttx/endorse_test.go b/token/services/ttx/endorse_test.go index 505d64d2e0..805f43a937 100644 --- a/token/services/ttx/endorse_test.go +++ b/token/services/ttx/endorse_test.go @@ -7,6 +7,9 @@ SPDX-License-Identifier: Apache-2.0 package ttx_test import ( + "context" + "math/rand" + "strconv" "testing" "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors" @@ -28,12 +31,78 @@ type TestEndorseViewContextInput struct { } type TestEndorseViewContext struct { - ctx *mock2.Context - tx *ttx.Transaction - options []ttx.TxOption - storageProvider *mock2.StorageProvider - storage *mock2.Storage - session *mock2.Session + ctx *mock2.Context + tx *ttx.Transaction + options []ttx.TxOption + storageProvider *mock2.StorageProvider + storage *mock2.Storage + session *mock2.Session + tokenSigner *mock.Signer + networkIdentitySigner *mock2.NetworkIdentitySigner + ch chan *view.Message + tokenIP *mock.IdentityProvider + networkIdentityProvider *mock2.NetworkIdentityProvider +} + +func newTransaction(t *testing.T) *ttx.Transaction { + t.Helper() + + session := &mock2.Session{} + ch := make(chan *view.Message, 2) + session.ReceiveReturns(ch) + + seed := strconv.Itoa(rand.Int()) + + tms := &mock2.TokenManagementServiceWithExtensions{} + tms.NetworkReturns("a_network" + seed) + tms.ChannelReturns("a_channel" + seed) + tmsID := token.TMSID{ + Network: "a_network" + seed, + Channel: "a_channel" + seed, + Namespace: "a_namespace" + seed, + } + tms.IDReturns(tmsID) + tokenDes := &mock.Deserializer{} + tokenIP := &mock.IdentityProvider{} + tokenIP.IsMeReturns(true) + tokenSigner := &mock.Signer{} + tokenSigner.SignReturns([]byte("a_token_sigma"+seed), nil) + tokenIP.GetSignerReturns(tokenSigner, nil) + tms.SigServiceReturns(token.NewSignatureService(tokenDes, tokenIP)) + tokenAPITMS := tokenapi.NewMockedManagementService(t, tmsID) + tms.SetTokenManagementServiceStub = func(arg1 *token.Request) error { + arg1.SetTokenService(tokenAPITMS) + return nil + } + tmsp := &mock2.TokenManagementServiceProvider{} + tmsp.TokenManagementServiceReturns(tms, nil) + network := &mock2.Network{} + network.ComputeTxIDReturns("an_anchor" + seed) + np := &mock2.NetworkProvider{} + np.GetNetworkReturns(network, nil) + + req := token.NewRequest(nil, token.RequestAnchor("an_anchor"+seed)) + req.Metadata.Issues = []*driver.IssueMetadata{ + { + Issuer: driver.AuditableIdentity{ + Identity: []byte("an_issuer" + seed), + }, + }, + } + tms.NewRequestReturns(req, nil) + + ctx := &mock2.Context{} + ctx.SessionReturns(session) + ctx.ContextReturns(t.Context()) + ctx.GetServiceReturnsOnCall(0, tmsp, nil) + ctx.GetServiceReturnsOnCall(1, np, nil) + ctx.GetServiceReturnsOnCall(2, &endpoint.Service{}, nil) + ctx.GetServiceReturnsOnCall(3, np, nil) + ctx.GetServiceReturnsOnCall(4, tmsp, nil) + tx, err := ttx.NewTransaction(ctx, []byte("a_signer")) + require.NoError(t, err) + + return tx } func newTestEndorseViewContext(t *testing.T, input *TestEndorseViewContextInput) *TestEndorseViewContext { @@ -130,8 +199,17 @@ func newTestEndorseViewContext(t *testing.T, input *TestEndorseViewContextInput) Payload: signatureRequestRaw, } // then the transaction - ch <- &view.Message{ - Payload: txRaw, + if input.AnotherReceivedTx { + tx2 := newTransaction(t) + txRaw2, err := tx2.Bytes() + require.NoError(t, err) + ch <- &view.Message{ + Payload: txRaw2, + } + } else { + ch <- &view.Message{ + Payload: txRaw, + } } ctx.RunViewStub = func(v view.View, option ...view.RunViewOption) (interface{}, error) { @@ -139,11 +217,16 @@ func newTestEndorseViewContext(t *testing.T, input *TestEndorseViewContextInput) } c := &TestEndorseViewContext{ - ctx: ctx, - tx: tx, - storage: storage, - storageProvider: storageProvider, - session: session, + ctx: ctx, + tx: tx, + storage: storage, + storageProvider: storageProvider, + session: session, + tokenSigner: tokenSigner, + networkIdentitySigner: nis, + ch: ch, + tokenIP: tokenIP, + networkIdentityProvider: networkIdentityProvider, } return c } @@ -226,11 +309,232 @@ func TestEndorseView(t *testing.T) { }, expectError: true, errorContains: "signature request's signer does not match the expected signer", - expectErr: ttx.ErrSignerIdentityMismatch, + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 1, ctx.session.SendWithContextCallCount()) + }, + }, + { + name: "failed unmarshalling signature request", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + for len(c.ch) > 0 { + <-c.ch + } + c.ch <- &view.Message{Payload: []byte("garbage")} + return c + }, + expectError: true, + errorContains: "failed unmarshalling signature request", + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 0, ctx.session.SendWithContextCallCount()) + }, + }, + { + name: "failed signing request", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + c.tokenSigner.SignReturns(nil, errors.New("sign error")) + return c + }, + expectError: true, + errorContains: "failed signing request", + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 0, ctx.session.SendWithContextCallCount()) + }, + }, + { + name: "failed sending signature back", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + c.session.SendWithContextReturns(errors.New("send error")) + return c + }, + expectError: true, + errorContains: "failed sending signature back", + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 1, ctx.session.SendWithContextCallCount()) + }, + }, + { + name: "failed receiving transaction", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + sigReq := <-c.ch + <-c.ch + c.ch <- sigReq + c.ch <- &view.Message{Payload: []byte("garbage transaction")} + return c + }, + expectError: true, + errorContains: "failed receiving transaction", + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 1, ctx.session.SendWithContextCallCount()) + }, + }, + { + name: "failed acknowledging transaction (signing)", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + c.networkIdentitySigner.SignReturns(nil, errors.New("ack sign error")) + return c + }, + expectError: true, + errorContains: "failed to sign ack response", + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 1, ctx.session.SendWithContextCallCount()) + }, + }, + { + name: "failed acknowledging transaction (sending)", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + count := 0 + c.session.SendWithContextStub = func(ctx context.Context, payload []byte) error { + count++ + if count == 2 { + return errors.New("ack send error") + } + return nil + } + return c + }, + expectError: true, + errorContains: "failed sending ack", + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 2, ctx.session.SendWithContextCallCount()) + }, + }, + { + name: "failed getting storage provider", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + c.ctx.GetServiceReturnsOnCall(4, nil, errors.New("storage provider error")) + return c + }, + expectError: true, + errorContains: "failed to storage provider", + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 2, ctx.session.SendWithContextCallCount()) + }, + }, + { + name: "failed getting identity provider", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + c.ctx.GetServiceReturnsOnCall(3, nil, errors.New("identity provider error")) + return c + }, + expectError: true, + errorContains: "failed getting identity provider", + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 1, ctx.session.SendWithContextCallCount()) + }, + }, + { + name: "failed getting signer", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + c.tokenIP.GetSignerReturns(nil, errors.New("signer error")) + return c + }, + expectError: true, + errorContains: "cannot find signer for", + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 0, ctx.session.SendWithContextCallCount()) + }, + }, + { + name: "success with FromSignatureRequest", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + c.tx.FromSignatureRequest = &ttx.SignatureRequest{ + Signer: []byte("an_issuer"), + } + // Clear channel and put only transaction + for len(c.ch) > 0 { + <-c.ch + } + txRaw, _ := c.tx.Bytes() + c.ch <- &view.Message{Payload: txRaw} + return c + }, + expectError: false, + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 2, ctx.session.SendWithContextCallCount()) + }, + }, + { + name: "failed cache request", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + c.storageProvider.CacheRequestReturns(errors.New("cache error")) + return c + }, + expectError: false, + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 2, ctx.session.SendWithContextCallCount()) + assert.Equal(t, 1, ctx.storageProvider.CacheRequestCallCount()) + }, + }, + { + name: "failed getting signer for ack", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + c.networkIdentityProvider.GetSignerReturns(nil, errors.New("ack signer error")) + return c + }, + expectError: true, + errorContains: "failed to get signer for default identity", + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 1, ctx.session.SendWithContextCallCount()) + }, + }, + { + name: "failed reading signature request (closed channel)", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + close(c.ch) + return c + }, + expectError: true, + errorContains: "failed reading signature request", verify: func(ctx *TestEndorseViewContext, _ any) { assert.Equal(t, 0, ctx.session.SendWithContextCallCount()) }, }, + { + name: "multiple signers", + prepare: func() *TestEndorseViewContext { + c := newTestEndorseViewContext(t, nil) + c.tx.TokenRequest.Metadata.Issues = append(c.tx.TokenRequest.Metadata.Issues, &driver.IssueMetadata{ + Issuer: driver.AuditableIdentity{ + Identity: []byte("another_issuer"), + }, + }) + + req1 := <-c.ch + tx := <-c.ch + + c.ch = make(chan *view.Message, 3) + c.session.ReceiveReturns(c.ch) + + c.ch <- req1 + + sigReq := &ttx.SignatureRequest{ + Signer: []byte("another_issuer"), + } + sigReqRaw, _ := sigReq.Bytes() + c.ch <- &view.Message{Payload: sigReqRaw} + + c.ch <- tx + + return c + }, + expectError: false, + verify: func(ctx *TestEndorseViewContext, _ any) { + assert.Equal(t, 3, ctx.session.SendWithContextCallCount()) + }, + }, } for _, tc := range testCases { From 17d00d6f383f4efb83837570a43b698fa97cdbf0 Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Wed, 7 Jan 2026 16:49:25 +0100 Subject: [PATCH 2/2] more tests Signed-off-by: Angelo De Caro --- token/services/network/network.go | 4 ++ token/services/ttx/dep/mock/network.go | 75 ++++++++++++++++++++++++++ token/services/ttx/dep/providers.go | 1 + token/services/ttx/endorse.go | 4 +- token/services/ttx/endorse_test.go | 19 ++----- token/services/ttx/ordering.go | 27 +++++----- token/services/ttx/storage.go | 6 ++- token/services/ttx/transaction.go | 9 ++-- 8 files changed, 107 insertions(+), 38 deletions(-) diff --git a/token/services/network/network.go b/token/services/network/network.go index 1a1a905bee..1084a5fa4a 100644 --- a/token/services/network/network.go +++ b/token/services/network/network.go @@ -98,6 +98,10 @@ type Envelope struct { e driver.Envelope } +func NewEnvelope(e driver.Envelope) *Envelope { + return &Envelope{e: e} +} + func (e *Envelope) Bytes() ([]byte, error) { return e.e.Bytes() } diff --git a/token/services/ttx/dep/mock/network.go b/token/services/ttx/dep/mock/network.go index a4ef18cd3c..b6ff0ea5cc 100644 --- a/token/services/ttx/dep/mock/network.go +++ b/token/services/ttx/dep/mock/network.go @@ -2,6 +2,7 @@ package mock import ( + "context" "sync" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" @@ -35,6 +36,18 @@ type Network struct { result1 view.Identity result2 error } + BroadcastStub func(context.Context, interface{}) error + broadcastMutex sync.RWMutex + broadcastArgsForCall []struct { + arg1 context.Context + arg2 interface{} + } + broadcastReturns struct { + result1 error + } + broadcastReturnsOnCall map[int]struct { + result1 error + } ComputeTxIDStub func(*network.TxID) string computeTxIDMutex sync.RWMutex computeTxIDArgsForCall []struct { @@ -189,6 +202,68 @@ func (fake *Network) AnonymousIdentityReturnsOnCall(i int, result1 view.Identity }{result1, result2} } +func (fake *Network) Broadcast(arg1 context.Context, arg2 interface{}) error { + fake.broadcastMutex.Lock() + ret, specificReturn := fake.broadcastReturnsOnCall[len(fake.broadcastArgsForCall)] + fake.broadcastArgsForCall = append(fake.broadcastArgsForCall, struct { + arg1 context.Context + arg2 interface{} + }{arg1, arg2}) + stub := fake.BroadcastStub + fakeReturns := fake.broadcastReturns + fake.recordInvocation("Broadcast", []interface{}{arg1, arg2}) + fake.broadcastMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *Network) BroadcastCallCount() int { + fake.broadcastMutex.RLock() + defer fake.broadcastMutex.RUnlock() + return len(fake.broadcastArgsForCall) +} + +func (fake *Network) BroadcastCalls(stub func(context.Context, interface{}) error) { + fake.broadcastMutex.Lock() + defer fake.broadcastMutex.Unlock() + fake.BroadcastStub = stub +} + +func (fake *Network) BroadcastArgsForCall(i int) (context.Context, interface{}) { + fake.broadcastMutex.RLock() + defer fake.broadcastMutex.RUnlock() + argsForCall := fake.broadcastArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *Network) BroadcastReturns(result1 error) { + fake.broadcastMutex.Lock() + defer fake.broadcastMutex.Unlock() + fake.BroadcastStub = nil + fake.broadcastReturns = struct { + result1 error + }{result1} +} + +func (fake *Network) BroadcastReturnsOnCall(i int, result1 error) { + fake.broadcastMutex.Lock() + defer fake.broadcastMutex.Unlock() + fake.BroadcastStub = nil + if fake.broadcastReturnsOnCall == nil { + fake.broadcastReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.broadcastReturnsOnCall[i] = struct { + result1 error + }{result1} +} + func (fake *Network) ComputeTxID(arg1 *network.TxID) string { fake.computeTxIDMutex.Lock() ret, specificReturn := fake.computeTxIDReturnsOnCall[len(fake.computeTxIDArgsForCall)] diff --git a/token/services/ttx/dep/providers.go b/token/services/ttx/dep/providers.go index d2aeeffb53..a7275e9885 100644 --- a/token/services/ttx/dep/providers.go +++ b/token/services/ttx/dep/providers.go @@ -34,6 +34,7 @@ type Network interface { AnonymousIdentity() (view.Identity, error) LocalMembership() *network.LocalMembership ComputeTxID(n *network.TxID) string + Broadcast(ctx context.Context, blob interface{}) error } // NetworkProvider given access to instances of the Network interface. diff --git a/token/services/ttx/endorse.go b/token/services/ttx/endorse.go index 39502c84d3..a95eb19479 100644 --- a/token/services/ttx/endorse.go +++ b/token/services/ttx/endorse.go @@ -72,7 +72,7 @@ func (s *EndorseView) Call(context view.Context) (interface{}, error) { // cache the token request into the tokens db, should we use the received token request? sp, err := GetStorageProvider(context) if err != nil { - return nil, errors.Wrapf(err, "failed to storage provider") + return nil, errors.Wrapf(errors.Join(err, ErrDepNotAvailableInContext), "storage provider") } if err := sp.CacheRequest(context.Context(), s.tx.TMSID(), s.tx.TokenRequest); err != nil { logger.Warnf("failed to cache token request [%s], this might cause delay, investigate when possible: [%s]", s.tx.TokenRequest.Anchor, err) @@ -180,7 +180,7 @@ func (s *EndorseView) ack(context view.Context, msg []byte) error { // Send back an acknowledgement idProvider, err := dep.GetNetworkIdentityProvider(context) if err != nil { - return errors.Wrapf(err, "failed getting identity provider") + return errors.Wrapf(errors.Join(err, ErrDepNotAvailableInContext), "network identity provider") } defaultIdentity := idProvider.DefaultIdentity() logger.DebugfContext(context.Context(), "signing ack response [%s] with identity [%s]", utils.Hashable(msg), defaultIdentity) diff --git a/token/services/ttx/endorse_test.go b/token/services/ttx/endorse_test.go index 805f43a937..dbe74c3620 100644 --- a/token/services/ttx/endorse_test.go +++ b/token/services/ttx/endorse_test.go @@ -412,7 +412,8 @@ func TestEndorseView(t *testing.T) { return c }, expectError: true, - errorContains: "failed to storage provider", + expectErr: ttx.ErrDepNotAvailableInContext, + errorContains: "storage provider", verify: func(ctx *TestEndorseViewContext, _ any) { assert.Equal(t, 2, ctx.session.SendWithContextCallCount()) }, @@ -425,7 +426,8 @@ func TestEndorseView(t *testing.T) { return c }, expectError: true, - errorContains: "failed getting identity provider", + expectErr: ttx.ErrDepNotAvailableInContext, + errorContains: "identity provider", verify: func(ctx *TestEndorseViewContext, _ any) { assert.Equal(t, 1, ctx.session.SendWithContextCallCount()) }, @@ -489,19 +491,6 @@ func TestEndorseView(t *testing.T) { assert.Equal(t, 1, ctx.session.SendWithContextCallCount()) }, }, - { - name: "failed reading signature request (closed channel)", - prepare: func() *TestEndorseViewContext { - c := newTestEndorseViewContext(t, nil) - close(c.ch) - return c - }, - expectError: true, - errorContains: "failed reading signature request", - verify: func(ctx *TestEndorseViewContext, _ any) { - assert.Equal(t, 0, ctx.session.SendWithContextCallCount()) - }, - }, { name: "multiple signers", prepare: func() *TestEndorseViewContext { diff --git a/token/services/ttx/ordering.go b/token/services/ttx/ordering.go index 94eabc4975..b5a16d5a98 100644 --- a/token/services/ttx/ordering.go +++ b/token/services/ttx/ordering.go @@ -11,8 +11,7 @@ import ( "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors" "github.com/hyperledger-labs/fabric-smart-client/platform/view/view" - "github.com/hyperledger-labs/fabric-token-sdk/token/services/network" - "github.com/hyperledger-labs/fabric-token-sdk/token/services/tokens" + "github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep" ) type orderingView struct { @@ -23,11 +22,7 @@ type orderingView struct { // The view does the following: // 1. It broadcasts the token transaction to the proper backend. func NewOrderingView(tx *Transaction, opts ...TxOption) *orderingView { - return NewOrderingViewWithOpts(append([]TxOption{WithTransactions(tx)}, opts...)...) -} - -func NewOrderingViewWithOpts(opts ...TxOption) *orderingView { - return &orderingView{opts: opts} + return &orderingView{opts: append([]TxOption{WithTransactions(tx)}, opts...)} } // Call execute the view. @@ -44,12 +39,12 @@ func (o *orderingView) Call(context view.Context) (interface{}, error) { } // cache the token request into the tokens db - t, err := tokens.GetService(context, options.Transaction.TMSID()) + storageProvider, err := GetStorageProvider(context) if err != nil { - return nil, errors.Wrapf(err, "failed to get tokens db for [%s]", options.Transaction.TMSID()) + return nil, errors.Wrapf(err, "failed to get storage provider") } if !options.NoCachingRequest { - if err := t.CacheRequest(context.Context(), options.Transaction.TMSID(), options.Transaction.TokenRequest); err != nil { + if err := storageProvider.CacheRequest(context.Context(), options.Transaction.TMSID(), options.Transaction.TokenRequest); err != nil { logger.WarnfContext(context.Context(), "failed to cache token request [%s], this might cause delay, investigate when possible: [%s]", options.Transaction.TokenRequest.Anchor, err) } } @@ -60,11 +55,15 @@ func (o *orderingView) broadcast(context view.Context, transaction *Transaction) if transaction == nil { return errors.Errorf("transaction is nil") } - nw := network.GetInstance(context, transaction.Network(), transaction.Channel()) - if nw == nil { - return errors.Errorf("network [%s] not found", transaction.Network()) + np, err := dep.GetNetworkProvider(context) + if err != nil { + return errors.Join(err, ErrDepNotAvailableInContext) + } + network, err := np.GetNetwork(transaction.Network(), transaction.Channel()) + if err != nil { + return errors.WithMessagef(err, "failed to get network [%s]", transaction.Network()) } - if err := nw.Broadcast(context.Context(), transaction.Envelope); err != nil { + if err := network.Broadcast(context.Context(), transaction.Envelope); err != nil { return errors.WithMessagef(err, "failed to broadcast token transaction [%s]", transaction.ID()) } return nil diff --git a/token/services/ttx/storage.go b/token/services/ttx/storage.go index 2fdbdeb364..58744cf746 100644 --- a/token/services/ttx/storage.go +++ b/token/services/ttx/storage.go @@ -40,7 +40,11 @@ func GetStorageProvider(sp token.ServiceProvider) (StorageProvider, error) { if err != nil { return nil, err } - return s.(StorageProvider), nil + provider, ok := s.(StorageProvider) + if !ok { + panic("implementation error, type must be StorageProvider") + } + return provider, nil } // StoreTransactionRecords stores the transaction records extracted from the passed transaction to the diff --git a/token/services/ttx/transaction.go b/token/services/ttx/transaction.go index 76691c17fc..b7bfe27df2 100644 --- a/token/services/ttx/transaction.go +++ b/token/services/ttx/transaction.go @@ -85,12 +85,9 @@ func NewTransaction(context view.Context, signer view.Identity, opts ...TxOption return nil, errors.WithMessagef(err, "failed compiling tx options") } - tms, err := dep.GetManagementService( - context, - token.WithTMSID(txOpts.TMSID), - ) + tms, err := dep.GetManagementService(context, token.WithTMSID(txOpts.TMSID)) if err != nil { - return nil, errors.Wrap(err, "failed to get token management service") + return nil, errors.Join(err, ErrDepNotAvailableInContext) } networkProvider, err := dep.GetNetworkProvider(context) @@ -166,7 +163,7 @@ func NewTransactionFromBytes(context view.Context, raw []byte) (*Transaction, er // check there exists a tms for this payload tms, err := dep.GetManagementService(context, token.WithTMSID(payload.tmsID)) if err != nil { - return nil, errors.Wrap(err, "failed to get token management service") + return nil, errors.Join(err, ErrDepNotAvailableInContext) } if !tms.ID().Equal(payload.tmsID) { return nil, errors.Errorf("failed to find tms for tmsID [%s], got [%s]", payload.tmsID, tms.ID())