github.com/hyperledger/aries-framework-go@v0.3.2/pkg/client/outofband/example_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package outofband 8 9 import ( 10 "encoding/base64" 11 "encoding/json" 12 "fmt" 13 "time" 14 15 "github.com/google/uuid" 16 17 "github.com/hyperledger/aries-framework-go/component/storageutil/mem" 18 "github.com/hyperledger/aries-framework-go/pkg/client/didexchange" 19 "github.com/hyperledger/aries-framework-go/pkg/client/mediator" 20 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" 21 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" 22 didsvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/didexchange" 23 routesvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/mediator" 24 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/outofband" 25 mockdidexchange "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/didexchange" 26 mockroute "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/mediator" 27 mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms" 28 mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider" 29 ) 30 31 const ( 32 // Router is a router that sends an out-of-band invitation to the edge agent. 33 Router = "Router" 34 // Bob is an edge agent. 35 Bob = "Bob" 36 ) 37 38 var agentActions = make(map[string]chan service.DIDCommAction) //nolint:gochecknoglobals 39 40 // Example of an edge agent accepting an out-of-band invitation from a router. 41 func ExampleClient_AcceptInvitation() { //nolint:gocyclo,gocognit 42 // set up the router 43 routerCtx := getContext(Router) 44 45 router, err := New(routerCtx) 46 if err != nil { 47 panic(err) 48 } 49 50 routerDIDs, err := didexchange.New(routerCtx) 51 if err != nil { 52 panic(err) 53 } 54 55 routerClient, err := mediator.New(routerCtx) 56 if err != nil { 57 panic(err) 58 } 59 60 routerEvents := makeActionsChannel(Router) 61 62 err = routerDIDs.RegisterActionEvent(routerEvents) 63 if err != nil { 64 panic(err) 65 } 66 67 err = routerClient.RegisterActionEvent(routerEvents) 68 if err != nil { 69 panic(err) 70 } 71 72 // set up the edge agent 73 bobCtx := getContext(Bob) 74 75 bob, err := New(bobCtx) 76 if err != nil { 77 panic(err) 78 } 79 80 // router creates the route-request message 81 routeRequest, err := json.Marshal(mediator.NewRequest()) 82 if err != nil { 83 panic(err) 84 } 85 86 // router creates outofband request and embeds the route-request message in it 87 inv, err := router.CreateInvitation( 88 nil, 89 WithLabel(Router), 90 WithAttachments(&decorator.Attachment{ 91 ID: uuid.New().String(), 92 Data: decorator.AttachmentData{ 93 Base64: base64.StdEncoding.EncodeToString(routeRequest), 94 }, 95 }), 96 ) 97 if err != nil { 98 panic(err) 99 } 100 101 fmt.Printf("%s creates an out-of-band invitation with an embedded route-request message\n", Router) 102 103 // the edge agent accepts the outofband invitation 104 bobConnID, err := bob.AcceptInvitation(inv, Bob) 105 if err != nil { 106 panic(err) 107 } 108 109 fmt.Printf( 110 "%s accepts the out-of-band invitation received via an out of band channel and created connectionID %s\n", 111 Bob, bobConnID) 112 113 done := make(chan struct{}) // ends this example 114 115 go func() { 116 for event := range routerEvents { 117 fmt.Printf("%s received %s from %s\n", Router, event.Message.Type(), Bob) 118 119 switch event.ProtocolName { 120 case didexchange.ProtocolName: 121 if event.Message.Type() == didexchange.RequestMsgType { 122 didExchangeRequest := &didsvc.Request{} 123 124 err = event.Message.Decode(didExchangeRequest) 125 if err != nil { 126 panic(err) 127 } 128 129 if didExchangeRequest.Label != Bob { 130 err = fmt.Errorf( 131 "%s expected a didexchange request from %s but got %s", 132 Router, Bob, didExchangeRequest.Label, 133 ) 134 135 event.Stop(err) 136 panic(err) 137 } 138 139 props, ok := event.Properties.(didexchange.Event) 140 if !ok { 141 panic("failed to cast event properties (shouldn't happen)") 142 } 143 144 fmt.Printf("%s created connectionID %s\n", Router, props.ConnectionID()) 145 146 event.Continue(nil) 147 } 148 case mediator.ProtocolName: 149 if event.Message.Type() == mediator.RequestMsgType { 150 event.Continue(nil) 151 done <- struct{}{} 152 } 153 } 154 } 155 }() 156 157 select { 158 case <-done: 159 case <-time.After(time.Second): // timeout varies in your environment 160 panic("timeout") 161 } 162 163 bobRoutes, err := mediator.New(bobCtx) 164 if err != nil { 165 panic(err) 166 } 167 168 config, err := bobRoutes.GetConfig("xyz") 169 if err != nil { 170 panic(err) 171 } 172 173 fmt.Printf( 174 "%s has registered a route on %s with routerEndpoint %s and routingKeys %+v\n", 175 Bob, Router, config.Endpoint(), config.Keys()) 176 177 // Output: 178 // Router creates an out-of-band invitation with an embedded route-request message 179 // Bob accepts the out-of-band invitation received via an out of band channel and created connectionID xyz 180 // Router received https://didcomm.org/didexchange/1.0/request from Bob 181 // Router created connectionID xyz 182 // Router received https://didcomm.org/coordinatemediation/1.0/mediate-request from Bob 183 // Bob has registered a route on Router with routerEndpoint http://routers-r-us.com and routingKeys [key-1 key-2] 184 } 185 186 func getContext(agent string) *mockprovider.Provider { 187 return &mockprovider.Provider{ 188 KMSValue: &mockkms.KeyManager{}, 189 StorageProviderValue: mem.NewProvider(), 190 ProtocolStateStorageProviderValue: mem.NewProvider(), 191 ServiceMap: map[string]interface{}{ 192 outofband.Name: &stubOOBService{ 193 Event: nil, 194 acceptInvFunc: func(i *outofband.Invitation, options outofband.Options) (string, error) { 195 agentActions[i.Label] <- service.DIDCommAction{ 196 ProtocolName: didsvc.DIDExchange, 197 Message: service.NewDIDCommMsgMap(&didsvc.Request{ 198 Type: didsvc.RequestMsgType, 199 Label: agent, 200 }), 201 Continue: func(interface{}) { 202 agentActions[i.Label] <- service.DIDCommAction{ 203 ProtocolName: mediator.ProtocolName, 204 Message: service.NewDIDCommMsgMap(mediator.NewRequest()), 205 Continue: func(interface{}) {}, 206 } 207 }, 208 Properties: &didexchangeEvent{connID: "xyz"}, 209 } 210 211 return "xyz", nil 212 }, 213 saveInvFunc: func(*outofband.Invitation) error { return nil }, 214 }, 215 didsvc.DIDExchange: &mockdidexchange.MockDIDExchangeSvc{}, 216 routesvc.Coordination: &mockroute.MockMediatorSvc{ 217 RouterEndpoint: "http://routers-r-us.com", 218 RoutingKeys: []string{"key-1", "key-2"}, 219 }, 220 }, 221 } 222 } 223 224 func makeActionsChannel(agent string) chan service.DIDCommAction { 225 c := make(chan service.DIDCommAction, 5) 226 agentActions[agent] = c 227 228 return c 229 } 230 231 type didexchangeEvent struct { 232 connID string 233 invID string 234 } 235 236 func (d *didexchangeEvent) ConnectionID() string { 237 return d.connID 238 } 239 240 func (d *didexchangeEvent) InvitationID() string { 241 return d.invID 242 } 243 244 func (d *didexchangeEvent) All() map[string]interface{} { 245 return map[string]interface{}{ 246 "connectionID": d.ConnectionID(), 247 "invitationID": d.InvitationID(), 248 } 249 }