Skip to content
This repository was archived by the owner on Mar 27, 2024. It is now read-only.

Commit 0c41ff0

Browse files
authored
chore: Refactor sidetree client send operation request function (#292)
Refactor sidetree client send operation request function so it can be passed as an option. Closes #291 Signed-off-by: Sandra Vrtikapa <[email protected]> Signed-off-by: Sandra Vrtikapa <[email protected]>
1 parent fe7db74 commit 0c41ff0

File tree

3 files changed

+134
-79
lines changed

3 files changed

+134
-79
lines changed

component/vdr/sidetree/client.go

+23-58
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,15 @@ type Client struct {
4747
client *http.Client
4848
authToken string
4949
authTokenProvider authTokenProvider
50+
sendRequest func(req []byte, getEndpoints func() ([]string, error)) ([]byte, error)
5051
}
5152

52-
// New return did bloc client.
53+
// New return sidetree client.
5354
func New(opts ...Option) *Client {
5455
c := &Client{client: &http.Client{}}
5556

57+
c.sendRequest = c.defaultSendRequest
58+
5659
// Apply options
5760
for _, opt := range opts {
5861
opt(c)
@@ -74,21 +77,12 @@ func (c *Client) CreateDID(opts ...create.Option) (*docdid.DocResolution, error)
7477
return nil, err
7578
}
7679

77-
// TODO add logic for using different sidetree endpoint
78-
// for now will use the first one
79-
endpoints, err := createDIDOpts.GetEndpoints()
80-
if err != nil {
81-
return nil, err
82-
}
83-
84-
sidetreeEndpoint := endpoints[0]
85-
8680
req, err := buildCreateRequest(createDIDOpts.MultiHashAlgorithm, createDIDOpts)
8781
if err != nil {
8882
return nil, fmt.Errorf("failed to build sidetree request: %w", err)
8983
}
9084

91-
responseBytes, err := c.sendRequest(req, sidetreeEndpoint)
85+
responseBytes, err := c.sendRequest(req, createDIDOpts.GetEndpoints)
9286
if err != nil {
9387
return nil, fmt.Errorf("failed to send create sidetree request: %w", err)
9488
}
@@ -109,6 +103,7 @@ func (c *Client) CreateDID(opts ...create.Option) (*docdid.DocResolution, error)
109103
return nil, fmt.Errorf("failed to parse did document: %w", err)
110104
}
111105

106+
// TODO: Talk to Firas about not including document metadata in create
112107
return &docdid.DocResolution{DIDDocument: didDoc}, nil
113108
}
114109

@@ -125,21 +120,12 @@ func (c *Client) UpdateDID(did string, opts ...update.Option) error {
125120
return err
126121
}
127122

128-
// TODO add logic for using different sidetree endpoint
129-
// for now will use the first one
130-
endpoints, err := updateDIDOpts.GetEndpoints()
131-
if err != nil {
132-
return err
133-
}
134-
135-
sidetreeEndpoint := endpoints[0]
136-
137123
req, err := c.buildUpdateRequest(did, updateDIDOpts.MultiHashAlgorithm, updateDIDOpts)
138124
if err != nil {
139125
return fmt.Errorf("failed to build update request: %w", err)
140126
}
141127

142-
_, err = c.sendRequest(req, sidetreeEndpoint)
128+
_, err = c.sendRequest(req, updateDIDOpts.GetEndpoints)
143129
if err != nil {
144130
return fmt.Errorf("failed to send update did request: %w", err)
145131
}
@@ -160,21 +146,12 @@ func (c *Client) RecoverDID(did string, opts ...recovery.Option) error {
160146
return err
161147
}
162148

163-
// TODO add logic for using different sidetree endpoint
164-
// for now will use the first one
165-
endpoints, err := recoverDIDOpts.GetEndpoints()
166-
if err != nil {
167-
return err
168-
}
169-
170-
sidetreeEndpoint := endpoints[0]
171-
172149
req, err := buildRecoverRequest(did, recoverDIDOpts.MultiHashAlgorithm, recoverDIDOpts)
173150
if err != nil {
174151
return fmt.Errorf("failed to build sidetree request: %w", err)
175152
}
176153

177-
_, err = c.sendRequest(req, sidetreeEndpoint)
154+
_, err = c.sendRequest(req, recoverDIDOpts.GetEndpoints)
178155
if err != nil {
179156
return fmt.Errorf("failed to send recover sidetree request: %w", err)
180157
}
@@ -195,21 +172,12 @@ func (c *Client) DeactivateDID(did string, opts ...deactivate.Option) error {
195172
return err
196173
}
197174

198-
// TODO add logic for using different sidetree endpoint
199-
// for now will use the first one
200-
endpoints, err := deactivateDIDOpts.GetEndpoints()
201-
if err != nil {
202-
return err
203-
}
204-
205-
sidetreeEndpoint := endpoints[0]
206-
207175
req, err := buildDeactivateRequest(did, deactivateDIDOpts)
208176
if err != nil {
209177
return fmt.Errorf("failed to build sidetree request: %w", err)
210178
}
211179

212-
_, err = c.sendRequest(req, sidetreeEndpoint)
180+
_, err = c.sendRequest(req, deactivateDIDOpts.GetEndpoints)
213181
if err != nil {
214182
return fmt.Errorf("failed to send deactivate sidetree request: %w", err)
215183
}
@@ -226,10 +194,6 @@ func validateCreateReq(createDIDOpts *create.Opts) error {
226194
return fmt.Errorf("update public key is required")
227195
}
228196

229-
if createDIDOpts.GetEndpoints == nil {
230-
return fmt.Errorf("sidetree get endpoints func is required")
231-
}
232-
233197
return nil
234198
}
235199

@@ -246,10 +210,6 @@ func validateUpdateReq(updateDIDOpts *update.Opts) error {
246210
return fmt.Errorf("operation commitment is required")
247211
}
248212

249-
if updateDIDOpts.GetEndpoints == nil {
250-
return fmt.Errorf("sidetree get endpoints func is required")
251-
}
252-
253213
return nil
254214
}
255215

@@ -270,10 +230,6 @@ func validateRecoverReq(recoverDIDOpts *recovery.Opts) error {
270230
return fmt.Errorf("operation commitment is required")
271231
}
272232

273-
if recoverDIDOpts.GetEndpoints == nil {
274-
return fmt.Errorf("sidetree get endpoints func is required")
275-
}
276-
277233
return nil
278234
}
279235

@@ -286,10 +242,6 @@ func validateDeactivateReq(deactivateDIDOpts *deactivate.Opts) error {
286242
return fmt.Errorf("operation commitment is required")
287243
}
288244

289-
if deactivateDIDOpts.GetEndpoints == nil {
290-
return fmt.Errorf("sidetree get endpoints func is required")
291-
}
292-
293245
return nil
294246
}
295247

@@ -457,7 +409,20 @@ func buildDeactivateRequest(did string, deactivateDIDOpts *deactivate.Opts) ([]b
457409
})
458410
}
459411

460-
func (c *Client) sendRequest(req []byte, endpointURL string) ([]byte, error) {
412+
func (c *Client) defaultSendRequest(req []byte, getEndpoints func() ([]string, error)) ([]byte, error) {
413+
if getEndpoints == nil {
414+
return nil, fmt.Errorf("sidetree get endpoints func is required")
415+
}
416+
417+
endpoints, err := getEndpoints()
418+
if err != nil {
419+
return nil, fmt.Errorf("sidetree get endpoints: %w", err)
420+
}
421+
422+
// TODO add logic for using different sidetree endpoint
423+
// for now will use the first one
424+
endpointURL := endpoints[0]
425+
461426
httpReq, err := http.NewRequestWithContext(context.Background(),
462427
http.MethodPost, endpointURL, bytes.NewReader(req))
463428
if err != nil {

component/vdr/sidetree/client_test.go

+104-21
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,23 @@ func TestClient_DeactivateDID(t *testing.T) {
6868
t.Run("test error from get endpoints", func(t *testing.T) {
6969
v := sidetree.New()
7070

71-
_, privKey, err := ed25519.GenerateKey(rand.Reader)
71+
pubKey, privKey, err := ed25519.GenerateKey(rand.Reader)
7272
require.NoError(t, err)
7373

74-
err = v.DeactivateDID("did:ex:123", deactivate.WithSigner(newSignerMock(t, privKey)),
75-
deactivate.WithOperationCommitment("value"))
74+
signingPubKeyJWK, err := pubkey.GetPublicKeyJWK(pubKey)
75+
require.NoError(t, err)
76+
77+
rv, err := commitment.GetRevealValue(signingPubKeyJWK, 18)
78+
require.NoError(t, err)
79+
80+
err = v.DeactivateDID("did:ex:123",
81+
deactivate.WithSigner(newSignerMock(t, privKey)),
82+
deactivate.WithOperationCommitment(rv))
7683
require.Error(t, err)
7784
require.Contains(t, err.Error(), "sidetree get endpoints func is required")
7885

79-
err = v.DeactivateDID("did:ex:123", deactivate.WithOperationCommitment("value"),
86+
err = v.DeactivateDID("did:ex:123",
87+
deactivate.WithOperationCommitment(rv),
8088
deactivate.WithSigner(newSignerMock(t, privKey)),
8189
deactivate.WithSidetreeEndpoint(func() ([]string, error) {
8290
return nil, fmt.Errorf("failed to get endpoint")
@@ -213,20 +221,41 @@ func TestClient_RecoverDID(t *testing.T) {
213221
t.Run("test error from get endpoints", func(t *testing.T) {
214222
v := sidetree.New()
215223

216-
pubKey, privKey, err := ed25519.GenerateKey(rand.Reader)
224+
pubKey, _, err := ed25519.GenerateKey(rand.Reader)
217225
require.NoError(t, err)
218226

219-
err = v.RecoverDID("did:ex:123", recovery.WithOperationCommitment("value"),
220-
recovery.WithNextUpdatePublicKey(pubKey), recovery.WithNextRecoveryPublicKey(pubKey),
221-
recovery.WithSigner(newSignerMock(t, privKey)))
227+
signingKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
228+
require.NoError(t, err)
229+
230+
signingPubKeyJWK, err := pubkey.GetPublicKeyJWK(&signingKey.PublicKey)
231+
require.NoError(t, err)
232+
233+
rv, err := commitment.GetRevealValue(signingPubKeyJWK, 18)
234+
require.NoError(t, err)
235+
236+
err = v.RecoverDID("did:ex:123",
237+
recovery.WithSigner(newSignerMock(t, signingKey)), recovery.WithOperationCommitment(rv),
238+
recovery.WithNextRecoveryPublicKey(pubKey),
239+
recovery.WithNextUpdatePublicKey(pubKey), recovery.WithPublicKey(&doc.PublicKey{
240+
ID: "key3",
241+
Type: doc.Ed25519VerificationKey2018,
242+
JWK: jwk.JWK{JSONWebKey: gojose.JSONWebKey{Key: pubKey}},
243+
}))
222244
require.Error(t, err)
223245
require.Contains(t, err.Error(), "sidetree get endpoints func is required")
224246

225-
err = v.RecoverDID("did:ex:123", recovery.WithOperationCommitment("value"),
226-
recovery.WithNextUpdatePublicKey(pubKey), recovery.WithNextRecoveryPublicKey(pubKey),
227-
recovery.WithSigner(newSignerMock(t, privKey)), recovery.WithSidetreeEndpoint(func() ([]string, error) {
247+
err = v.RecoverDID("did:ex:123",
248+
recovery.WithSigner(newSignerMock(t, signingKey)), recovery.WithOperationCommitment(rv),
249+
recovery.WithNextRecoveryPublicKey(pubKey),
250+
recovery.WithNextUpdatePublicKey(pubKey), recovery.WithPublicKey(&doc.PublicKey{
251+
ID: "key3",
252+
Type: doc.Ed25519VerificationKey2018,
253+
JWK: jwk.JWK{JSONWebKey: gojose.JSONWebKey{Key: pubKey}},
254+
}),
255+
recovery.WithSidetreeEndpoint(func() ([]string, error) {
228256
return nil, fmt.Errorf("failed to get endpoint")
229257
}))
258+
230259
require.Error(t, err)
231260
require.Contains(t, err.Error(), "failed to get endpoint")
232261
})
@@ -438,18 +467,34 @@ func TestClient_UpdateDID(t *testing.T) {
438467
t.Run("test error from get endpoints", func(t *testing.T) {
439468
v := sidetree.New()
440469

441-
pubKey, privKey, err := ed25519.GenerateKey(rand.Reader)
470+
pubKey, _, err := ed25519.GenerateKey(rand.Reader)
471+
require.NoError(t, err)
472+
473+
signingKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
442474
require.NoError(t, err)
443475

444-
err = v.UpdateDID("did:ex:123", update.WithOperationCommitment("value"), update.WithNextUpdatePublicKey(pubKey),
445-
update.WithSigner(newSignerMock(t, privKey)))
476+
signingPubKeyJWK, err := pubkey.GetPublicKeyJWK(&signingKey.PublicKey)
477+
require.NoError(t, err)
478+
479+
rv, err := commitment.GetRevealValue(signingPubKeyJWK, 18)
480+
require.NoError(t, err)
481+
482+
err = v.UpdateDID("did:ex:123",
483+
update.WithSigner(newSignerMock(t, signingKey)),
484+
update.WithOperationCommitment(rv),
485+
update.WithNextUpdatePublicKey(pubKey),
486+
update.WithRemoveService("svc1"))
446487
require.Error(t, err)
447488
require.Contains(t, err.Error(), "sidetree get endpoints func is required")
448489

449-
err = v.UpdateDID("did:ex:123", update.WithOperationCommitment("value"), update.WithNextUpdatePublicKey(pubKey),
450-
update.WithSigner(newSignerMock(t, privKey)), update.WithSidetreeEndpoint(func() ([]string, error) {
490+
err = v.UpdateDID("did:ex:123",
491+
update.WithSigner(newSignerMock(t, signingKey)),
492+
update.WithOperationCommitment(rv),
493+
update.WithNextUpdatePublicKey(pubKey),
494+
update.WithSidetreeEndpoint(func() ([]string, error) {
451495
return nil, fmt.Errorf("failed to get endpoints")
452-
}))
496+
}),
497+
update.WithRemoveService("svc1"))
453498
require.Error(t, err)
454499
require.Contains(t, err.Error(), "failed to get endpoints")
455500
})
@@ -613,18 +658,36 @@ func TestClient_CreateDID(t *testing.T) {
613658
t.Run("test error from get endpoints", func(t *testing.T) {
614659
v := sidetree.New()
615660

616-
pubKey, _, err := ed25519.GenerateKey(rand.Reader)
661+
ed25519RecoveryPubKey, _, err := ed25519.GenerateKey(rand.Reader)
617662
require.NoError(t, err)
618663

619-
didResol, err := v.CreateDID(create.WithUpdatePublicKey(pubKey), create.WithRecoveryPublicKey(pubKey))
620-
require.Error(t, err)
664+
ecUpdatePrivKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
665+
require.NoError(t, err)
666+
667+
didResol, err := v.CreateDID(create.WithRecoveryPublicKey(ed25519RecoveryPubKey),
668+
create.WithUpdatePublicKey(ecUpdatePrivKey.Public()),
669+
create.WithPublicKey(&doc.PublicKey{
670+
ID: "key1",
671+
Type: doc.JWSVerificationKey2020,
672+
JWK: jwk.JWK{JSONWebKey: gojose.JSONWebKey{Key: ed25519RecoveryPubKey}},
673+
Purposes: []string{doc.KeyPurposeAuthentication},
674+
}))
675+
621676
require.Contains(t, err.Error(), "sidetree get endpoints func is required")
622677
require.Nil(t, didResol)
623678

624-
didResol, err = v.CreateDID(create.WithUpdatePublicKey(pubKey), create.WithRecoveryPublicKey(pubKey),
679+
didResol, err = v.CreateDID(create.WithRecoveryPublicKey(ed25519RecoveryPubKey),
680+
create.WithUpdatePublicKey(ecUpdatePrivKey.Public()),
681+
create.WithPublicKey(&doc.PublicKey{
682+
ID: "key1",
683+
Type: doc.JWSVerificationKey2020,
684+
JWK: jwk.JWK{JSONWebKey: gojose.JSONWebKey{Key: ed25519RecoveryPubKey}},
685+
Purposes: []string{doc.KeyPurposeAuthentication},
686+
}),
625687
create.WithSidetreeEndpoint(func() ([]string, error) {
626688
return nil, fmt.Errorf("failed to get endpoints")
627689
}))
690+
628691
require.Error(t, err)
629692
require.Contains(t, err.Error(), "failed to get endpoints")
630693
require.Nil(t, didResol)
@@ -679,6 +742,26 @@ func TestClient_CreateDID(t *testing.T) {
679742
require.Nil(t, didResol)
680743
})
681744

745+
t.Run("test error from sidetree operation request function", func(t *testing.T) {
746+
v := sidetree.New(sidetree.WithSidetreeOperationRequestFnc(func(req []byte, getEndpoints func() ([]string, error)) ([]byte, error) {
747+
return nil, fmt.Errorf("send operation request error")
748+
}))
749+
750+
ed25519RecoveryPubKey, _, err := ed25519.GenerateKey(rand.Reader)
751+
require.NoError(t, err)
752+
753+
ed25519UpdatePubKey, _, err := ed25519.GenerateKey(rand.Reader)
754+
require.NoError(t, err)
755+
756+
didResol, err := v.CreateDID(create.WithRecoveryPublicKey(ed25519RecoveryPubKey),
757+
create.WithUpdatePublicKey(ed25519UpdatePubKey), create.WithSidetreeEndpoint(func() ([]string, error) {
758+
return []string{"https://www.domain.com"}, nil
759+
}))
760+
require.Error(t, err)
761+
require.Contains(t, err.Error(), "failed to send create sidetree request: send operation request error")
762+
require.Nil(t, didResol)
763+
})
764+
682765
t.Run("test success", func(t *testing.T) {
683766
serv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
684767
bytes, err := (&did.Doc{ID: "did1", Context: []string{did.ContextV1}}).JSONBytes()

component/vdr/sidetree/option.go

+7
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,10 @@ func WithAuthTokenProvider(p authTokenProvider) Option {
3232
opts.authTokenProvider = p
3333
}
3434
}
35+
36+
// WithSidetreeOperationRequestFnc overrides default sidetree operation request.
37+
func WithSidetreeOperationRequestFnc(fnc func(req []byte, getEndpoints func() ([]string, error)) ([]byte, error)) Option {
38+
return func(opts *Client) {
39+
opts.sendRequest = fnc
40+
}
41+
}

0 commit comments

Comments
 (0)