diff --git a/go.mod b/go.mod index afa7a54..007c6e6 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,12 @@ go 1.18 require ( github.com/dustinxie/ecc v0.0.0-20210511000915-959544187564 github.com/google/uuid v1.6.0 - github.com/iden3/go-circuits/v2 v2.0.1 - github.com/iden3/go-iden3-core/v2 v2.0.3 + github.com/iden3/go-circuits/v2 v2.1.0 + github.com/iden3/go-iden3-core/v2 v2.0.4 github.com/iden3/go-iden3-crypto v0.0.15 github.com/iden3/go-jwz/v2 v2.0.1 github.com/iden3/go-rapidsnark/types v0.0.3 - github.com/iden3/go-schema-processor/v2 v2.3.0 + github.com/iden3/go-schema-processor/v2 v2.3.2 github.com/lestrrat-go/jwx/v2 v2.0.12 github.com/mr-tron/base58 v1.2.0 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 8b2e6b0..86b8195 100644 --- a/go.sum +++ b/go.sum @@ -15,10 +15,10 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/iden3/go-circuits/v2 v2.0.1 h1:tcJtBE8aLJsf9qpBoTUKE143Mne025cunQnSExMXaKo= -github.com/iden3/go-circuits/v2 v2.0.1/go.mod h1:VIFIp51+IH0hOzjnKhb84bCeyq7hq76zX/C14ua6zh4= -github.com/iden3/go-iden3-core/v2 v2.0.3 h1:ce9Jbw10zDsinWXFc05SiK2Hof/wu4zV4/ai5gQy29k= -github.com/iden3/go-iden3-core/v2 v2.0.3/go.mod h1:L9PxhWPvoS9qTb3inEkZBm1RpjHBt+VTwvxssdzbAdw= +github.com/iden3/go-circuits/v2 v2.1.0 h1:Dk+noXGXOJYFjj2iWu3KLPd/KLoIhZ3eT6qYEfKyocc= +github.com/iden3/go-circuits/v2 v2.1.0/go.mod h1:VIFIp51+IH0hOzjnKhb84bCeyq7hq76zX/C14ua6zh4= +github.com/iden3/go-iden3-core/v2 v2.0.4 h1:ggzC2zgOWgJAAcuG9X8bQG1r4gAoHZWqY7aLV8b1qgc= +github.com/iden3/go-iden3-core/v2 v2.0.4/go.mod h1:L9PxhWPvoS9qTb3inEkZBm1RpjHBt+VTwvxssdzbAdw= github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4= github.com/iden3/go-iden3-crypto v0.0.15/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= github.com/iden3/go-jwz/v2 v2.0.1 h1:y8HccYGaI5JULVTOfKRPsQ2pGRx8pfgkdCz0kQA8jQE= @@ -35,8 +35,8 @@ github.com/iden3/go-rapidsnark/witness/v2 v2.0.0 h1:mkY6VDfwKVJc83QGKmwVXY2LYepi github.com/iden3/go-rapidsnark/witness/v2 v2.0.0/go.mod h1:3JRjqUfW1hgI9hzLDO0v8z/DUkR0ZUehhYLlnIfRxnA= github.com/iden3/go-rapidsnark/witness/wazero v0.0.0-20230524142950-0986cf057d4e h1:WeiFCrpj5pLRtSA4Mg03yTrSZhHHqN/k5b6bwxd9/tY= github.com/iden3/go-rapidsnark/witness/wazero v0.0.0-20230524142950-0986cf057d4e/go.mod h1:UEBifEzw62T6VzIHJeHuUgeLg2U/J9ttf7hOwQEqnYk= -github.com/iden3/go-schema-processor/v2 v2.3.0 h1:86tnt1myHntcG+9pJ3I+0ycc6V59sITrsPSt0k7/DhU= -github.com/iden3/go-schema-processor/v2 v2.3.0/go.mod h1:BcHVDZyn8q8vUlL+XpOo7hpwXmEjxzO8ao1LkvFsM+k= +github.com/iden3/go-schema-processor/v2 v2.3.2 h1:y2MmE85LW4itEWloX0mYpH1maPUBWPUV3wMUlW1xy1k= +github.com/iden3/go-schema-processor/v2 v2.3.2/go.mod h1:BcHVDZyn8q8vUlL+XpOo7hpwXmEjxzO8ao1LkvFsM+k= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= diff --git a/protocol/credential_test.go b/protocol/credential_test.go new file mode 100644 index 0000000..1f7a451 --- /dev/null +++ b/protocol/credential_test.go @@ -0,0 +1,142 @@ +package protocol_test + +import ( + "encoding/json" + "fmt" + "testing" + + uuid "github.com/google/uuid" + "github.com/iden3/go-schema-processor/v2/verifiable" + "github.com/iden3/iden3comm/v2/packers" + "github.com/iden3/iden3comm/v2/protocol" + "github.com/stretchr/testify/require" +) + +func TestCredentialProposalRequestMessageCreation(t *testing.T) { + + var err error + id, err := uuid.Parse("f0885dd0-e60e-11ee-b3e8-de17148ce1ce") + require.NoError(t, err) + + thID, err := uuid.Parse("f08860d2-e60e-11ee-b3e8-de17148ce1ce") + require.NoError(t, err) + + didStr := "did:polygonid:polygon:mumbai:2qK2Rwf2zqzzhqVLqTWXetGUbs1Sc79woomP5cDLBE" + require.NoError(t, err) + + mobileService := verifiable.Service{ + ID: fmt.Sprintf("%s#%s", didStr, "wallet"), + Type: verifiable.Iden3MobileServiceType, + ServiceEndpoint: "iden3:v0.1:callbackHandler", + } + didDoc := &verifiable.DIDDocument{ + ID: didStr, + Context: "https://www.w3.org/ns/did/v1", + Service: []interface{}{mobileService}, + } + didDocBytes, err := json.Marshal(didDoc) + require.NoError(t, err) + proposalRequest := protocol.CredentialsProposalRequestMessage{ + ID: id.String(), + Typ: packers.MediaTypePlainMessage, + Type: protocol.CredentialProposalRequestMessageType, + ThreadID: thID.String(), + Body: protocol.CredentialsProposalRequestBody{ + Credentials: []protocol.CredentialInfo{ + { + Type: "KYCAgeCredential", + Context: "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v3.json-ld", + }, + }, + DIDDoc: didDocBytes, + }, + From: didStr, + To: "did:polygonid:polygon:mumbai:2qJ689kpoJxcSzB5sAFJtPsSBSrHF5dq722BHMqURL", + } + + marshalledReq, err := json.Marshal(proposalRequest) + require.NoError(t, err) + + require.JSONEq(t, `{"id":"f0885dd0-e60e-11ee-b3e8-de17148ce1ce","typ":"application/iden3comm-plain-json","type":"https://iden3-communication.io/credentials/0.1/proposal-request","thid":"f08860d2-e60e-11ee-b3e8-de17148ce1ce","body":{"credentials":[{"type":"KYCAgeCredential","context":"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v3.json-ld"}],"did_doc":{"@context":"https://www.w3.org/ns/did/v1","id":"did:polygonid:polygon:mumbai:2qK2Rwf2zqzzhqVLqTWXetGUbs1Sc79woomP5cDLBE","service":[{"id":"did:polygonid:polygon:mumbai:2qK2Rwf2zqzzhqVLqTWXetGUbs1Sc79woomP5cDLBE#wallet","type":"Iden3MobileServiceV1","serviceEndpoint":"iden3:v0.1:callbackHandler"}]}},"from":"did:polygonid:polygon:mumbai:2qK2Rwf2zqzzhqVLqTWXetGUbs1Sc79woomP5cDLBE","to":"did:polygonid:polygon:mumbai:2qJ689kpoJxcSzB5sAFJtPsSBSrHF5dq722BHMqURL"}`, string(marshalledReq)) +} +func TestCredentialProposalMessageCreation(t *testing.T) { + + var err error + id, err := uuid.Parse("f0885dd0-e60e-11ee-b3e8-de17148ce1ce") + require.NoError(t, err) + + thID, err := uuid.Parse("f08860d2-e60e-11ee-b3e8-de17148ce1ce") + require.NoError(t, err) + + didStr := "did:polygonid:polygon:mumbai:2qK2Rwf2zqzzhqVLqTWXetGUbs1Sc79woomP5cDLBE" + require.NoError(t, err) + + proposalRequest := protocol.CredentialsProposalMessage{ + ID: id.String(), + Typ: packers.MediaTypePlainMessage, + Type: protocol.CredentialProposalMessageType, + ThreadID: thID.String(), + Body: protocol.CredentialsProposalBody{ + Proposals: []protocol.CredentialProposalInfo{ + { + Credentials: []protocol.CredentialInfo{ + { + Type: "KYCAgeCredential", + Context: "https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v3.json-ld", + }}, + Type: protocol.CredentialProposalTypeWeb, + URL: "http://test.com?sessionId=1", + Description: "web page with some flow", + }, + }, + }, + From: "did:polygonid:polygon:mumbai:2qJ689kpoJxcSzB5sAFJtPsSBSrHF5dq722BHMqURL", + To: didStr, + } + + marshalledReq, err := json.Marshal(proposalRequest) + require.NoError(t, err) + require.JSONEq(t, `{"id":"f0885dd0-e60e-11ee-b3e8-de17148ce1ce","typ":"application/iden3comm-plain-json","type":"https://iden3-communication.io/credentials/0.1/proposal","thid":"f08860d2-e60e-11ee-b3e8-de17148ce1ce","body":{"proposals":[{"credentials":[{"type":"KYCAgeCredential","context":"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v3.json-ld"}],"type":"WebVerificationFormV1.0","url":"http://test.com?sessionId=1","description":"web page with some flow"}]},"from":"did:polygonid:polygon:mumbai:2qJ689kpoJxcSzB5sAFJtPsSBSrHF5dq722BHMqURL","to":"did:polygonid:polygon:mumbai:2qK2Rwf2zqzzhqVLqTWXetGUbs1Sc79woomP5cDLBE"}`, string(marshalledReq)) +} + +func TestCredentialOfferMessageCreation(t *testing.T) { + + var err error + id, err := uuid.Parse("f0885dd0-e60e-11ee-b3e8-de17148ce1ce") + require.NoError(t, err) + + thID, err := uuid.Parse("f08860d2-e60e-11ee-b3e8-de17148ce1ce") + require.NoError(t, err) + + didStr := "did:polygonid:polygon:mumbai:2qK2Rwf2zqzzhqVLqTWXetGUbs1Sc79woomP5cDLBE" + require.NoError(t, err) + + require.NoError(t, err) + proposalRequest := protocol.CredentialsOfferMessage{ + ID: id.String(), + Typ: packers.MediaTypePlainMessage, + Type: protocol.CredentialOfferMessageType, + ThreadID: thID.String(), + Body: protocol.CredentialsOfferMessageBody{ + URL: "http://test.com", + Credentials: []protocol.CredentialOffer{ + { + ID: id.String(), + Description: "test 1", + Status: protocol.CredentialOfferStatusPending, + }, + { + ID: thID.String(), + Description: "test 2", + // no status is completed + }, + }, + }, + From: didStr, + To: "did:polygonid:polygon:mumbai:2qJ689kpoJxcSzB5sAFJtPsSBSrHF5dq722BHMqURL", + } + + marshalledReq, err := json.Marshal(proposalRequest) + require.NoError(t, err) + require.JSONEq(t, `{"id":"f0885dd0-e60e-11ee-b3e8-de17148ce1ce","typ":"application/iden3comm-plain-json","type":"https://iden3-communication.io/credentials/1.0/offer","thid":"f08860d2-e60e-11ee-b3e8-de17148ce1ce","body":{"url":"http://test.com","credentials":[{"id":"f0885dd0-e60e-11ee-b3e8-de17148ce1ce","description":"test 1","status":"pending"},{"id":"f08860d2-e60e-11ee-b3e8-de17148ce1ce","description":"test 2"}]},"from":"did:polygonid:polygon:mumbai:2qK2Rwf2zqzzhqVLqTWXetGUbs1Sc79woomP5cDLBE","to":"did:polygonid:polygon:mumbai:2qJ689kpoJxcSzB5sAFJtPsSBSrHF5dq722BHMqURL"}`, string(marshalledReq)) +} diff --git a/protocol/credentials.go b/protocol/credentials.go index 10f95de..d41e950 100644 --- a/protocol/credentials.go +++ b/protocol/credentials.go @@ -29,6 +29,48 @@ const ( // CredentialOnchainOfferMessageType is type for message with a credential onchain offer CredentialOnchainOfferMessageType iden3comm.ProtocolMessage = iden3comm.Iden3Protocol + "credentials/1.0/onchain-offer" + + // CredentialProposalRequestMessageType is type for request of the credential proposal + // + // # Experimental + // + // Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. + CredentialProposalRequestMessageType iden3comm.ProtocolMessage = iden3comm.Iden3Protocol + "credentials/0.1/proposal-request" + + // CredentialProposalMessageType is type for proposal of the verifiable credential + // + // # Experimental + // + // Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. + CredentialProposalMessageType iden3comm.ProtocolMessage = iden3comm.Iden3Protocol + "credentials/0.1/proposal" + + // CredentialOfferStatusPending is a type when a credential issuance is in the process + // + // # Experimental + // + // Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. + CredentialOfferStatusPending = "pending" + + // CredentialOfferStatusCompleted if credential issuance is happened successfully + // + // # Experimental + // + // Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. + CredentialOfferStatusCompleted = "completed" + + // CredentialOfferStatusRejected - if credential issuance is not possible for some reason + // + // # Experimental + // + // Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. + CredentialOfferStatusRejected = "rejected" + + // CredentialProposalTypeWeb - if credential issuance is not possible for some reason + // + // # Experimental + // + // Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. + CredentialProposalTypeWeb = "WebVerificationFormV1.0" ) // CredentialIssuanceRequestMessage represent Iden3message for credential request @@ -74,6 +116,7 @@ type CredentialsOfferMessageBody struct { type CredentialOffer struct { ID string `json:"id"` Description string `json:"description"` + Status string `json:"status,omitempty"` } // CredentialIssuanceMessage represent Iden3message for credential issuance @@ -174,3 +217,90 @@ type CredentialsOnchainOfferMessageBody struct { Credentials []CredentialOffer `json:"credentials"` TransactionData TransactionData `json:"transaction_data"` } + +// CredentialsProposalRequestMessage represent Iden3message for credential proposal request +// +// # Experimental +// +// Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. +type CredentialsProposalRequestMessage struct { + ID string `json:"id"` + Typ iden3comm.MediaType `json:"typ,omitempty"` + Type iden3comm.ProtocolMessage `json:"type"` + ThreadID string `json:"thid,omitempty"` + + Body CredentialsProposalRequestBody `json:"body,omitempty"` + + From string `json:"from,omitempty"` + To string `json:"to,omitempty"` +} + +// CredentialsProposalMessage represents Iden3message for credential proposal +// +// # Experimental +// +// Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. +type CredentialsProposalMessage struct { + ID string `json:"id"` + Typ iden3comm.MediaType `json:"typ,omitempty"` + Type iden3comm.ProtocolMessage `json:"type"` + ThreadID string `json:"thid,omitempty"` + + Body CredentialsProposalBody `json:"body,omitempty"` + + From string `json:"from,omitempty"` + To string `json:"to,omitempty"` +} + +// CredentialsProposalRequestBody is msg body for proposal requests +// +// # Experimental +// +// Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. +type CredentialsProposalRequestBody struct { + Credentials []CredentialInfo `json:"credentials"` + Metadata *Metadata `json:"metadata,omitempty"` + DIDDoc json.RawMessage `json:"did_doc,omitempty"` +} + +// CredentialInfo is a part of credential proposal request bodys +// +// # Experimental +// +// Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. +type CredentialInfo struct { + Type string `json:"type"` + Context string `json:"context"` +} + +// Metadata is metadata for credential proposal +// +// # Experimental +// +// Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. +type Metadata struct { + Type string `json:"type"` + Data string `json:"data"` +} + +// CredentialsProposalBody is a body for a credential proposal message +// +// # Experimental +// +// Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. +type CredentialsProposalBody struct { + Proposals []CredentialProposalInfo `json:"proposals"` +} + +// CredentialProposalInfo is a info of specific proposal that can relate to many credentials +// +// # Experimental +// +// Notice: this functionality is in beta and can be deleted or be non-backward compatible in the future releases. +type CredentialProposalInfo struct { + Credentials []CredentialInfo `json:"credentials,omitempty"` + Type string `json:"type"` + URL string `json:"url"` + Expiration string `json:"expiration,omitempty"` + Description string `json:"description,omitempty"` +}