From e0416b51bfe643b05ead18113121fd510392e811 Mon Sep 17 00:00:00 2001 From: x1m3 Date: Tue, 3 Dec 2024 15:50:09 +0100 Subject: [PATCH 1/4] feat: Changed PaymentRequestInfoData from a struct to a slice type ([]PaymentRequestInfoDataItem) fix: PaymentProof is now a list of PaymentProofItem and can be constructed feat: Added a test with mixed types of payment data and a test that showcase how to construct a payment data chore: Tests are running outside package. --- .github/workflows/ci-lint.yaml | 9 +- .golangci.yml | 2 +- protocol/payment.go | 214 ++++++++++----------------- protocol/payment_test.go | 258 +++++++++++++++++++++++++++++++++ 4 files changed, 344 insertions(+), 139 deletions(-) diff --git a/.github/workflows/ci-lint.yaml b/.github/workflows/ci-lint.yaml index 14f78f2..7edd0ea 100644 --- a/.github/workflows/ci-lint.yaml +++ b/.github/workflows/ci-lint.yaml @@ -9,13 +9,14 @@ jobs: lint: runs-on: ubuntu-latest steps: + - name: Checkout code + uses: actions/checkout@v3 - name: Install Go uses: actions/setup-go@v4 with: - go-version: 1.21.0 - - name: Checkout code - uses: actions/checkout@v3 + go-version-file: go.mod + cache: true - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.54.2 + version: v1.60.3 diff --git a/.golangci.yml b/.golangci.yml index 037f4d5..5f31576 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,5 @@ service: - golangci-lint-version: 1.45.x + golangci-lint-version: 1.60.3 run: timeout: 2m diff --git a/protocol/payment.go b/protocol/payment.go index 4b737f4..b7986ed 100644 --- a/protocol/payment.go +++ b/protocol/payment.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" + "github.com/iden3/driver-did-iden3/pkg/document" "github.com/iden3/go-schema-processor/v2/verifiable" "github.com/pkg/errors" @@ -34,9 +35,6 @@ const ( // Iden3PaymentRailsERC20V1Type is a Iden3PaymentRailsERC20V1 payment type Iden3PaymentRailsERC20V1Type PaymentType = "Iden3PaymentRailsERC20V1" - - // Eip712SignatureProofType is a EthereumEip712Signature2021 proof type - Eip712SignatureProofType ProofType = "EthereumEip712Signature2021" ) // PaymentType is type for Payment @@ -45,9 +43,6 @@ type PaymentType string // PaymentRequestType is type for Payment request type PaymentRequestType string -// ProofType is type for Proof -type ProofType string - // PaymentRequestMessage represents Iden3message for payment request. type PaymentRequestMessage struct { ID string `json:"id"` @@ -72,147 +67,88 @@ type PaymentRequestMessageBody struct { // PaymentRequestInfo represents the payments request information. type PaymentRequestInfo struct { - Type string `json:"type,omitempty"` Credentials []PaymentRequestInfoCredentials `json:"credentials"` Description string `json:"description"` Data PaymentRequestInfoData `json:"data"` } // PaymentRequestInfoData is a union type for field Data in PaymentRequestInfo. -// Only one of the fields can be set at a time. -type PaymentRequestInfoData struct { - dataType PaymentRequestType - crypto []Iden3PaymentRequestCryptoV1 - rails []Iden3PaymentRailsRequestV1 - railsERC20 []Iden3PaymentRailsERC20RequestV1 -} - -// NewPaymentRequestInfoDataCrypto creates a new PaymentRequestInfoData with Iden3PaymentRequestCryptoV1 data. -func NewPaymentRequestInfoDataCrypto(data Iden3PaymentRequestCryptoV1) PaymentRequestInfoData { - return PaymentRequestInfoData{ - dataType: Iden3PaymentRequestCryptoV1Type, - crypto: []Iden3PaymentRequestCryptoV1{data}, - } -} +type PaymentRequestInfoData []PaymentRequestInfoDataItem -// NewPaymentRequestInfoDataRails creates a new PaymentRequestInfoData with Iden3PaymentRailsRequestV1 data. -func NewPaymentRequestInfoDataRails(data Iden3PaymentRailsRequestV1) PaymentRequestInfoData { - return PaymentRequestInfoData{ - dataType: Iden3PaymentRailsRequestV1Type, - rails: []Iden3PaymentRailsRequestV1{data}, - } -} - -// NewPaymentRequestInfoDataRailsERC20 creates a new PaymentRequestInfoData with Iden3PaymentRailsERC20RequestV1 data. -func NewPaymentRequestInfoDataRailsERC20(data Iden3PaymentRailsERC20RequestV1) PaymentRequestInfoData { - return PaymentRequestInfoData{ - dataType: Iden3PaymentRailsERC20RequestV1Type, - railsERC20: []Iden3PaymentRailsERC20RequestV1{data}, - } -} - -// Type returns the type of the data in the union. You can use Data() to get the data. -func (p *PaymentRequestInfoData) Type() PaymentRequestType { - return p.dataType -} - -// Data returns the data in the union. You can use Type() to determine the type of the data. -func (p *PaymentRequestInfoData) Data() interface{} { - switch p.dataType { - case Iden3PaymentRequestCryptoV1Type: - return p.crypto - case Iden3PaymentRailsRequestV1Type: - return p.rails - case Iden3PaymentRailsERC20RequestV1Type: - return p.railsERC20 - } - return nil +// PaymentRequestInfoDataItem is the interface that any PaymentRequestInfoData.Data item must implement. +type PaymentRequestInfoDataItem interface { + PaymentRequestType() PaymentRequestType } // MarshalJSON marshals the PaymentRequestInfoData into JSON. func (p PaymentRequestInfoData) MarshalJSON() ([]byte, error) { - switch p.dataType { - case Iden3PaymentRequestCryptoV1Type: - return json.Marshal(p.crypto[0]) - case Iden3PaymentRailsRequestV1Type: - return json.Marshal(p.rails) - case Iden3PaymentRailsERC20RequestV1Type: - return json.Marshal(p.railsERC20) + if len(p) == 1 && p[0].PaymentRequestType() == Iden3PaymentRequestCryptoV1Type { + return json.Marshal(p[0]) } - return nil, errors.New("failed to marshal not initialized PaymentRequestInfoData") + return json.Marshal([]PaymentRequestInfoDataItem(p)) } // UnmarshalJSON unmarshal the PaymentRequestInfoData from JSON. func (p *PaymentRequestInfoData) UnmarshalJSON(data []byte) error { - var item struct { - Type PaymentRequestType `json:"type"` - } - var collection []struct { + type rawItem struct { Type PaymentRequestType `json:"type"` } - p.crypto, p.rails, p.railsERC20 = nil, nil, nil + var item rawItem + var collection []json.RawMessage - if err := json.Unmarshal(data, &item); err == nil { - p.dataType = item.Type - return p.unmarshalFromItem(item.Type, data) + // Let's see if this is a single item + err := json.Unmarshal(data, &item) + if err == nil { + o, errItem := p.unmarshalFromItem(item.Type, data) + if errItem != nil { + return errItem + } + *p = append(*p, o) + return nil } - if err := json.Unmarshal(data, &collection); err == nil { - if len(collection) == 0 { - return nil + // Let's see if this is a collection. Then we will unmarshal each single item + err = json.Unmarshal(data, &collection) + if err != nil { + return fmt.Errorf("PaymentRequestInfoData must be a PaymentRequestInfoDataItem or a collection: %w", err) + } + for n, rawItem := range collection { + if err := json.Unmarshal(rawItem, &item); err != nil { + return fmt.Errorf("field PaymentRequestInfoData[%d].Type not found: %w", n, err) } - - p.dataType = collection[0].Type - return p.unmarshalFromCollection(p.dataType, data) + o, err := p.unmarshalFromItem(item.Type, rawItem) + if err != nil { + return err + } + *p = append(*p, o) } - return errors.New("failed to unmarshal PaymentRequestInfoData. not a single item nor a collection") + return nil } -func (p *PaymentRequestInfoData) unmarshalFromItem(typ PaymentRequestType, data []byte) error { +func (p *PaymentRequestInfoData) unmarshalFromItem(typ PaymentRequestType, data []byte) (PaymentRequestInfoDataItem, error) { switch typ { case Iden3PaymentRequestCryptoV1Type: var o Iden3PaymentRequestCryptoV1 if err := json.Unmarshal(data, &o); err != nil { - return fmt.Errorf("unmarshalling PaymentRequestInfoData: %w", err) + return nil, fmt.Errorf("unmarshalling PaymentRequestInfoData: %w", err) } - p.crypto = []Iden3PaymentRequestCryptoV1{o} + return o, nil case Iden3PaymentRailsRequestV1Type: var o Iden3PaymentRailsRequestV1 if err := json.Unmarshal(data, &o); err != nil { - return fmt.Errorf("unmarshalling PaymentRequestInfoData: %w", err) + return nil, fmt.Errorf("unmarshalling PaymentRequestInfoData: %w", err) } - p.rails = []Iden3PaymentRailsRequestV1{o} + return o, nil case Iden3PaymentRailsERC20RequestV1Type: var o Iden3PaymentRailsERC20RequestV1 if err := json.Unmarshal(data, &o); err != nil { - return fmt.Errorf("unmarshalling PaymentRequestInfoData: %w", err) - } - p.railsERC20 = []Iden3PaymentRailsERC20RequestV1{o} - default: - return errors.Errorf("unmarshalling PaymentRequestInfoData. unknown type: %s", typ) - } - return nil -} - -func (p *PaymentRequestInfoData) unmarshalFromCollection(typ PaymentRequestType, data []byte) error { - switch typ { - case Iden3PaymentRequestCryptoV1Type: - if err := json.Unmarshal(data, &p.crypto); err != nil { - return fmt.Errorf("unmarshalling PaymentRequestInfoData: %w", err) - } - case Iden3PaymentRailsRequestV1Type: - if err := json.Unmarshal(data, &p.rails); err != nil { - return fmt.Errorf("unmarshalling PaymentRequestInfoData: %w", err) - } - case Iden3PaymentRailsERC20RequestV1Type: - if err := json.Unmarshal(data, &p.railsERC20); err != nil { - return fmt.Errorf("unmarshalling PaymentRequestInfoData: %w", err) + return nil, fmt.Errorf("unmarshalling PaymentRequestInfoData: %w", err) } + return o, nil default: - return errors.Errorf("unmarshalling PaymentRequestInfoData. unknown type: %s", typ) + return nil, errors.Errorf("unmarshalling PaymentRequestInfoData. unknown type: %s", typ) } - return nil } // Iden3PaymentRequestCryptoV1 represents the Iden3PaymentRequestCryptoV1 payment request data. @@ -227,6 +163,11 @@ type Iden3PaymentRequestCryptoV1 struct { Expiration string `json:"expiration,omitempty"` } +// PaymentRequestType implements the PaymentRequestInfoDataItem interface. +func (i Iden3PaymentRequestCryptoV1) PaymentRequestType() PaymentRequestType { + return Iden3PaymentRequestCryptoV1Type +} + // Iden3PaymentRailsRequestV1 represents the Iden3PaymentRailsRequestV1 payment request data. type Iden3PaymentRailsRequestV1 struct { Nonce string `json:"nonce"` @@ -240,6 +181,11 @@ type Iden3PaymentRailsRequestV1 struct { Currency string `json:"currency"` } +// PaymentRequestType implements the PaymentRequestInfoDataItem interface. +func (i Iden3PaymentRailsRequestV1) PaymentRequestType() PaymentRequestType { + return Iden3PaymentRailsRequestV1Type +} + // Iden3PaymentRailsERC20RequestV1 represents the Iden3PaymentRailsERC20RequestV1 payment request data. type Iden3PaymentRailsERC20RequestV1 struct { Nonce string `json:"nonce"` @@ -255,44 +201,41 @@ type Iden3PaymentRailsERC20RequestV1 struct { Features []PaymentFeatures `json:"features,omitempty"` } +// PaymentRequestType implements the PaymentRequestInfoDataItem interface. +func (i Iden3PaymentRailsERC20RequestV1) PaymentRequestType() PaymentRequestType { + return Iden3PaymentRailsERC20RequestV1Type +} + // PaymentFeatures represents type Features used in ERC20 payment request. type PaymentFeatures string // PaymentProof represents a payment proof. -type PaymentProof struct { - dataType ProofType - eip712Signature []EthereumEip712Signature2021 -} +type PaymentProof []PaymentProofItem -// NewPaymentProofEip712Signature creates a new PaymentProof with EthereumEip712Signature2021 data. -func NewPaymentProofEip712Signature(data []EthereumEip712Signature2021) PaymentProof { - return PaymentProof{ - dataType: Eip712SignatureProofType, - eip712Signature: data, - } +// PaymentProofItem is the interface that any PaymentProof item must implement. +type PaymentProofItem interface { + PaymentProofItem() verifiable.ProofType } // UnmarshalJSON unmarshal the PaymentRequestInfoData from JSON. func (p *PaymentProof) UnmarshalJSON(data []byte) error { - p.dataType = Eip712SignatureProofType - var col []EthereumEip712Signature2021 + var col []*EthereumEip712Signature2021 if err := json.Unmarshal(data, &col); err != nil { var single EthereumEip712Signature2021 if err := json.Unmarshal(data, &single); err != nil { return fmt.Errorf("failed to unmarshal EthereumEip712Signature2021Col: %w", err) } - col = append(col, single) + col = append(col, &single) + } + for _, item := range col { + *p = append(*p, *item) } - p.eip712Signature = col return nil } // MarshalJSON marshals the PaymentProof into JSON. func (p PaymentProof) MarshalJSON() ([]byte, error) { - if p.dataType == Eip712SignatureProofType { - return json.Marshal(p.eip712Signature) - } - return nil, errors.New("failed to marshal not initialized PaymentProof") + return json.Marshal([]PaymentProofItem(p)) } // EthereumEip712Signature2021 represents the Ethereum EIP712 signature. @@ -305,6 +248,11 @@ type EthereumEip712Signature2021 struct { Eip712 Eip712Data `json:"eip712"` } +// PaymentProofItem implements the PaymentProofItem interface. +func (e EthereumEip712Signature2021) PaymentProofItem() verifiable.ProofType { + return document.EthereumEip712SignatureProof2021Type +} + // Eip712Data represents the EIP712 data. type Eip712Data struct { Types string `json:"types"` @@ -372,8 +320,8 @@ func NewPaymentRails(data Iden3PaymentRailsV1) Payment { } } -// NEwPaymentRailsERC20 creates a new Payment with Iden3PaymentRailsERC20V1 data. -func NEwPaymentRailsERC20(data Iden3PaymentRailsERC20V1) Payment { +// NewPaymentRailsERC20 creates a new Payment with Iden3PaymentRailsERC20V1 data. +func NewPaymentRailsERC20(data Iden3PaymentRailsERC20V1) Payment { return Payment{ dataType: Iden3PaymentRailsERC20V1Type, railsERC: &data, @@ -473,17 +421,15 @@ type PaymentContext struct { } // NewPaymentContextString creates a new PaymentContext with a string. -func NewPaymentContextString(str string) PaymentContext { - return PaymentContext{str: &str} -} - -// NewPaymentContextStringCol creates a new PaymentContext with a string collection. -func NewPaymentContextStringCol(strCol []string) PaymentContext { - return PaymentContext{strCol: strCol} +func NewPaymentContextString(str ...string) PaymentContext { + if len(str) == 1 { + return PaymentContext{str: &str[0]} + } + return PaymentContext{strCol: str} } // NewPaymentContextItemCol creates a new PaymentContext with an interface{} collection. -func NewPaymentContextItemCol(itemCol []interface{}) PaymentContext { +func NewPaymentContextItemCol(itemCol ...interface{}) PaymentContext { return PaymentContext{itemCol: itemCol} } diff --git a/protocol/payment_test.go b/protocol/payment_test.go index cd10d7f..492d9e6 100644 --- a/protocol/payment_test.go +++ b/protocol/payment_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "testing" + "github.com/iden3/driver-did-iden3/pkg/document" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -457,6 +458,111 @@ func TestPaymentRequestInfoDataUnmarshalMarshall(t *testing.T) { } ] ` + const paymentRequestMixedTypesInList = ` + [ + { + "@context": [ + "https://schema.iden3.io/core/jsonld/payment.jsonld#Iden3PaymentRailsRequestV1", + "https://w3id.org/security/suites/eip712sig-2021/v1" + ], + "type": "Iden3PaymentRailsRequestV1", + "recipient": "0xaddress", + "amount": "100", + "currency": "ETHWEI", + "expirationDate": "ISO string", + "nonce": "25", + "metadata": "0x", + "proof": [ + { + "type": "EthereumEip712Signature2021", + "proofPurpose": "assertionMethod", + "proofValue": "0xa05292e9874240c5c2bbdf5a8fefff870c9fc801bde823189fc013d8ce39c7e5431bf0585f01c7e191ea7bbb7110a22e018d7f3ea0ed81a5f6a3b7b828f70f2d1c", + "verificationMethod": "did:pkh:eip155:0:0x3e1cFE1b83E7C1CdB0c9558236c1f6C7B203C34e#blockchainAccountId", + "created": "2024-09-26T12:28:19.702580067Z", + "eip712": { + "types": "https://schema.iden3.io/core/json/Iden3PaymentRailsRequestV1.json", + "primaryType": "Iden3PaymentRailsRequestV1", + "domain": { + "name": "MCPayment", + "version": "1.0.0", + "chainId": "0x0", + "verifyingContract": "0x0000000000000000000000000000000000000000" + } + } + } + ] + }, + { + "type": "Iden3PaymentRailsERC20RequestV1", + "@context": [ + "https://schema.iden3.io/core/jsonld/payment.jsonld#Iden3PaymentRailsERC20RequestV1", + "https://w3id.org/security/suites/eip712sig-2021/v1" + ], + "tokenAddress": "0x2FE40749812FAC39a0F380649eF59E01bccf3a1A", + "features": [ + "EIP-2612" + ], + "recipient": "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", + "amount": "40", + "currency": "ERC20Token", + "expirationDate": "2024-10-28T16:02:36.816Z", + "nonce": "3008", + "metadata": "0x", + "proof": [ + { + "type": "EthereumEip712Signature2021", + "proofPurpose": "assertionMethod", + "proofValue": "0xc3d9d6fa9aa7af03863943f7568ce61303e84221e3e29277309fd42581742024402802816cca5542620c19895331f4bdc1ea6fed0d0c6a1cf8656556d3acfde61b", + "verificationMethod": "did:pkh:eip155:80002:0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a#blockchainAccountId", + "created": "2024-10-28T15:02:36.946Z", + "eip712": { + "types": "https://schema.iden3.io/core/json/Iden3PaymentRailsRequestV1.json", + "primaryType": "Iden3PaymentRailsRequestV1", + "domain": { + "name": "MCPayment", + "version": "1.0.0", + "chainId": "80002", + "verifyingContract": "0x6f742EBA99C3043663f995a7f566e9F012C07925" + } + } + } + ] + }, + { + "@context": [ + "https://schema.iden3.io/core/jsonld/payment.jsonld#Iden3PaymentRailsRequestV1", + "https://w3id.org/security/suites/eip712sig-2021/v1" + ], + "type": "Iden3PaymentRailsRequestV1", + "recipient": "0xaddress2", + "amount": "200", + "currency": "ETHWEI", + "expirationDate": "ISO string", + "nonce": "25", + "metadata": "0x", + "proof": [ + { + "type": "EthereumEip712Signature2021", + "proofPurpose": "assertionMethod", + "proofValue": "0xa05292e9874240c5c2bbdf5a8fefff870c9fc801bde823189fc013d8ce39c7e5431bf0585f01c7e191ea7bbb7110a22e018d7f3ea0ed81a5f6a3b7b828f70f2d1c", + "verificationMethod": "did:pkh:eip155:0:0x3e1cFE1b83E7C1CdB0c9558236c1f6C7B203C34e#blockchainAccountId", + "created": "2024-09-26T12:28:19.702580067Z", + "eip712": { + "types": "https://schema.iden3.io/core/json/Iden3PaymentRailsRequestV1.json", + "primaryType": "Iden3PaymentRailsRequestV1", + "domain": { + "name": "MCPayment", + "version": "1.0.0", + "chainId": "0x1", + "verifyingContract": "0x0000000000000000000000000000000000000002" + } + } + } + ] + } + ] + ` + for _, tc := range []struct { desc string payload []byte @@ -477,6 +583,11 @@ func TestPaymentRequestInfoDataUnmarshalMarshall(t *testing.T) { payload: []byte(paymentRequestRailsV1InList), expectedPayload: []byte(paymentRequestRailsV1InList), }, + { + desc: "Mixed types: Iden3PaymentRailsRequestV1 and Iden3PaymentRailsERC20RequestV1 in a list", + payload: []byte(paymentRequestMixedTypesInList), + expectedPayload: []byte(paymentRequestMixedTypesInList), + }, } { t.Run(tc.desc, func(t *testing.T) { var msg PaymentRequestInfoData @@ -488,6 +599,153 @@ func TestPaymentRequestInfoDataUnmarshalMarshall(t *testing.T) { } } +func TestPaymentRequestInfoData_Construction(t *testing.T) { + const paymentRequestMixedTypesInList = ` +[ + { + "@context": [ + "https://schema.iden3.io/core/jsonld/payment.jsonld#Iden3PaymentRailsRequestV1", + "https://w3id.org/security/suites/eip712sig-2021/v1" + ], + "type": "Iden3PaymentRailsRequestV1", + "recipient": "0xaddress", + "amount": "100", + "currency": "ETHWEI", + "proof": [ + { + "type": "EthereumEip712Signature2021", + "proofPurpose": "assertionMethod", + "proofValue": "0xa05292e9874240c5c2bbdf5a8fefff870c9fc801bde823189fc013d8ce39c7e5431bf0585f01c7e191ea7bbb7110a22e018d7f3ea0ed81a5f6a3b7b828f70f2d1c", + "verificationMethod": "did:pkh:eip155:0:0x3e1cFE1b83E7C1CdB0c9558236c1f6C7B203C34e#blockchainAccountId", + "created": "2024-09-26T12:28:19.702580067Z", + "eip712": { + "types": "https://schema.iden3.io/core/json/Iden3PaymentRailsRequestV1.json", + "primaryType": "Iden3PaymentRailsRequestV1", + "domain": { + "name": "MCPayment", + "version": "1.0.0", + "chainId": "0x0", + "verifyingContract": "0x0000000000000000000000000000000000000000" + } + } + } + ], + "expirationDate": "ISO string", + "nonce": "25", + "metadata": "0x" + }, + { + "type": "Iden3PaymentRailsERC20RequestV1", + "@context": [ + "https://schema.iden3.io/core/jsonld/payment.jsonld#Iden3PaymentRailsERC20RequestV1", + "https://w3id.org/security/suites/eip712sig-2021/v1" + ], + "tokenAddress": "0x2FE40749812FAC39a0F380649eF59E01bccf3a1A", + "features": [ + "EIP-2612" + ], + "recipient": "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", + "amount": "40", + "currency": "ERC20Token", + "proof": [ + { + "type": "EthereumEip712Signature2021", + "proofPurpose": "assertionMethod", + "proofValue": "0xc3d9d6fa9aa7af03863943f7568ce61303e84221e3e29277309fd42581742024402802816cca5542620c19895331f4bdc1ea6fed0d0c6a1cf8656556d3acfde61b", + "verificationMethod": "did:pkh:eip155:80002:0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a#blockchainAccountId", + "created": "2024-10-28T15:02:36.946Z", + "eip712": { + "types": "https://schema.iden3.io/core/json/Iden3PaymentRailsRequestV1.json", + "primaryType": "Iden3PaymentRailsRequestV1", + "domain": { + "name": "MCPayment", + "version": "1.0.0", + "chainId": "80002", + "verifyingContract": "0x6f742EBA99C3043663f995a7f566e9F012C07925" + } + } + } + ], + "expirationDate": "2024-10-28T16:02:36.816Z", + "nonce": "3008", + "metadata": "0x" + } +] +` + data := PaymentRequestInfoData{ + Iden3PaymentRailsRequestV1{ + Nonce: "25", + Type: Iden3PaymentRailsRequestV1Type, + Context: NewPaymentContextString( + "https://schema.iden3.io/core/jsonld/payment.jsonld#Iden3PaymentRailsRequestV1", + "https://w3id.org/security/suites/eip712sig-2021/v1", + ), + Recipient: "0xaddress", + Amount: "100", + ExpirationDate: "ISO string", + Proof: PaymentProof{ + EthereumEip712Signature2021{ + Type: document.EthereumEip712SignatureProof2021Type, + ProofPurpose: "assertionMethod", + ProofValue: "0xa05292e9874240c5c2bbdf5a8fefff870c9fc801bde823189fc013d8ce39c7e5431bf0585f01c7e191ea7bbb7110a22e018d7f3ea0ed81a5f6a3b7b828f70f2d1c", + VerificationMethod: "did:pkh:eip155:0:0x3e1cFE1b83E7C1CdB0c9558236c1f6C7B203C34e#blockchainAccountId", + Created: "2024-09-26T12:28:19.702580067Z", + Eip712: Eip712Data{ + Types: "https://schema.iden3.io/core/json/Iden3PaymentRailsRequestV1.json", + PrimaryType: "Iden3PaymentRailsRequestV1", + Domain: Eip712Domain{ + Name: "MCPayment", + Version: "1.0.0", + ChainID: "0x0", + VerifyingContract: "0x0000000000000000000000000000000000000000", + }, + }, + }, + }, + Metadata: "0x", + Currency: "ETHWEI", + }, + Iden3PaymentRailsERC20RequestV1{ + Nonce: "3008", + Type: Iden3PaymentRailsERC20RequestV1Type, + Context: NewPaymentContextString( + "https://schema.iden3.io/core/jsonld/payment.jsonld#Iden3PaymentRailsERC20RequestV1", + "https://w3id.org/security/suites/eip712sig-2021/v1", + ), + Recipient: "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", + Amount: "40", + ExpirationDate: "2024-10-28T16:02:36.816Z", + Proof: PaymentProof{ + EthereumEip712Signature2021{ + Type: document.EthereumEip712SignatureProof2021Type, + ProofPurpose: "assertionMethod", + ProofValue: "0xc3d9d6fa9aa7af03863943f7568ce61303e84221e3e29277309fd42581742024402802816cca5542620c19895331f4bdc1ea6fed0d0c6a1cf8656556d3acfde61b", + VerificationMethod: "did:pkh:eip155:80002:0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a#blockchainAccountId", + Created: "2024-10-28T15:02:36.946Z", + Eip712: Eip712Data{ + Types: "https://schema.iden3.io/core/json/Iden3PaymentRailsRequestV1.json", + PrimaryType: "Iden3PaymentRailsRequestV1", + Domain: Eip712Domain{ + Name: "MCPayment", + Version: "1.0.0", + ChainID: "80002", + VerifyingContract: "0x6f742EBA99C3043663f995a7f566e9F012C07925", + }, + }, + }, + }, + Metadata: "0x", + Currency: "ERC20Token", + TokenAddress: "0x2FE40749812FAC39a0F380649eF59E01bccf3a1A", + Features: []PaymentFeatures{"EIP-2612"}, + }, + } + payload, err := json.Marshal(data) + require.NoError(t, err) + + assert.JSONEq(t, paymentRequestMixedTypesInList, string(payload)) +} + func TestPaymentContext(t *testing.T) { for _, tc := range []struct { desc string From cf077f8c8fc2d0c47087037a3b603538b85f3e54 Mon Sep 17 00:00:00 2001 From: x1m3 Date: Tue, 3 Dec 2024 15:51:27 +0100 Subject: [PATCH 2/4] chore: remove unneded comment --- protocol/payment.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/protocol/payment.go b/protocol/payment.go index b7986ed..1cdbff7 100644 --- a/protocol/payment.go +++ b/protocol/payment.go @@ -97,7 +97,6 @@ func (p *PaymentRequestInfoData) UnmarshalJSON(data []byte) error { var item rawItem var collection []json.RawMessage - // Let's see if this is a single item err := json.Unmarshal(data, &item) if err == nil { o, errItem := p.unmarshalFromItem(item.Type, data) @@ -108,7 +107,6 @@ func (p *PaymentRequestInfoData) UnmarshalJSON(data []byte) error { return nil } - // Let's see if this is a collection. Then we will unmarshal each single item err = json.Unmarshal(data, &collection) if err != nil { return fmt.Errorf("PaymentRequestInfoData must be a PaymentRequestInfoDataItem or a collection: %w", err) From 5c082c18773e09199bcfe7836b86b49e9f5ffe19 Mon Sep 17 00:00:00 2001 From: x1m3 Date: Tue, 3 Dec 2024 15:56:34 +0100 Subject: [PATCH 3/4] chore: Run payment tests out of protocol package --- protocol/payment_test.go | 45 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/protocol/payment_test.go b/protocol/payment_test.go index 492d9e6..7e8135e 100644 --- a/protocol/payment_test.go +++ b/protocol/payment_test.go @@ -1,10 +1,11 @@ -package protocol +package protocol_test import ( "encoding/json" "testing" "github.com/iden3/driver-did-iden3/pkg/document" + "github.com/iden3/iden3comm/v2/protocol" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -251,7 +252,7 @@ func TestPaymentRequestMessagePaymentTypeUnmarshall(t *testing.T) { } { t.Run(tc.desc, func(t *testing.T) { - var msg PaymentRequestMessage + var msg protocol.PaymentRequestMessage err := json.Unmarshal(tc.payload, &msg) require.NoError(t, err) payload, err := json.Marshal(msg) @@ -321,7 +322,7 @@ func TestEthereumEip712Signature2021Col(t *testing.T) { }, } { t.Run(tc.desc, func(t *testing.T) { - var msg PaymentProof + var msg protocol.PaymentProof require.NoError(t, json.Unmarshal(tc.payload, &msg)) payload, err := json.Marshal(msg) require.NoError(t, err) @@ -590,7 +591,7 @@ func TestPaymentRequestInfoDataUnmarshalMarshall(t *testing.T) { }, } { t.Run(tc.desc, func(t *testing.T) { - var msg PaymentRequestInfoData + var msg protocol.PaymentRequestInfoData require.NoError(t, json.Unmarshal(tc.payload, &msg)) payload, err := json.Marshal(msg) require.NoError(t, err) @@ -672,28 +673,28 @@ func TestPaymentRequestInfoData_Construction(t *testing.T) { } ] ` - data := PaymentRequestInfoData{ - Iden3PaymentRailsRequestV1{ + data := protocol.PaymentRequestInfoData{ + protocol.Iden3PaymentRailsRequestV1{ Nonce: "25", - Type: Iden3PaymentRailsRequestV1Type, - Context: NewPaymentContextString( + Type: protocol.Iden3PaymentRailsRequestV1Type, + Context: protocol.NewPaymentContextString( "https://schema.iden3.io/core/jsonld/payment.jsonld#Iden3PaymentRailsRequestV1", "https://w3id.org/security/suites/eip712sig-2021/v1", ), Recipient: "0xaddress", Amount: "100", ExpirationDate: "ISO string", - Proof: PaymentProof{ - EthereumEip712Signature2021{ + Proof: protocol.PaymentProof{ + protocol.EthereumEip712Signature2021{ Type: document.EthereumEip712SignatureProof2021Type, ProofPurpose: "assertionMethod", ProofValue: "0xa05292e9874240c5c2bbdf5a8fefff870c9fc801bde823189fc013d8ce39c7e5431bf0585f01c7e191ea7bbb7110a22e018d7f3ea0ed81a5f6a3b7b828f70f2d1c", VerificationMethod: "did:pkh:eip155:0:0x3e1cFE1b83E7C1CdB0c9558236c1f6C7B203C34e#blockchainAccountId", Created: "2024-09-26T12:28:19.702580067Z", - Eip712: Eip712Data{ + Eip712: protocol.Eip712Data{ Types: "https://schema.iden3.io/core/json/Iden3PaymentRailsRequestV1.json", PrimaryType: "Iden3PaymentRailsRequestV1", - Domain: Eip712Domain{ + Domain: protocol.Eip712Domain{ Name: "MCPayment", Version: "1.0.0", ChainID: "0x0", @@ -705,27 +706,27 @@ func TestPaymentRequestInfoData_Construction(t *testing.T) { Metadata: "0x", Currency: "ETHWEI", }, - Iden3PaymentRailsERC20RequestV1{ + protocol.Iden3PaymentRailsERC20RequestV1{ Nonce: "3008", - Type: Iden3PaymentRailsERC20RequestV1Type, - Context: NewPaymentContextString( + Type: protocol.Iden3PaymentRailsERC20RequestV1Type, + Context: protocol.NewPaymentContextString( "https://schema.iden3.io/core/jsonld/payment.jsonld#Iden3PaymentRailsERC20RequestV1", "https://w3id.org/security/suites/eip712sig-2021/v1", ), Recipient: "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", Amount: "40", ExpirationDate: "2024-10-28T16:02:36.816Z", - Proof: PaymentProof{ - EthereumEip712Signature2021{ + Proof: protocol.PaymentProof{ + protocol.EthereumEip712Signature2021{ Type: document.EthereumEip712SignatureProof2021Type, ProofPurpose: "assertionMethod", ProofValue: "0xc3d9d6fa9aa7af03863943f7568ce61303e84221e3e29277309fd42581742024402802816cca5542620c19895331f4bdc1ea6fed0d0c6a1cf8656556d3acfde61b", VerificationMethod: "did:pkh:eip155:80002:0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a#blockchainAccountId", Created: "2024-10-28T15:02:36.946Z", - Eip712: Eip712Data{ + Eip712: protocol.Eip712Data{ Types: "https://schema.iden3.io/core/json/Iden3PaymentRailsRequestV1.json", PrimaryType: "Iden3PaymentRailsRequestV1", - Domain: Eip712Domain{ + Domain: protocol.Eip712Domain{ Name: "MCPayment", Version: "1.0.0", ChainID: "80002", @@ -737,7 +738,7 @@ func TestPaymentRequestInfoData_Construction(t *testing.T) { Metadata: "0x", Currency: "ERC20Token", TokenAddress: "0x2FE40749812FAC39a0F380649eF59E01bccf3a1A", - Features: []PaymentFeatures{"EIP-2612"}, + Features: []protocol.PaymentFeatures{"EIP-2612"}, }, } payload, err := json.Marshal(data) @@ -779,7 +780,7 @@ func TestPaymentContext(t *testing.T) { }, } { t.Run(tc.desc, func(t *testing.T) { - var msg PaymentContext + var msg protocol.PaymentContext require.NoError(t, json.Unmarshal(tc.payload, &msg)) payload, err := json.Marshal(msg) require.NoError(t, err) @@ -884,7 +885,7 @@ func TestPaymentMarshalUnmarshal(t *testing.T) { }, } { t.Run(tc.desc, func(t *testing.T) { - var msg PaymentMessage + var msg protocol.PaymentMessage require.NoError(t, json.Unmarshal(tc.payload, &msg)) payload, err := json.Marshal(msg) require.NoError(t, err) From 150691fe0395094bb9c9009a8de2509564b9f8a6 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Wed, 4 Dec 2024 18:11:30 +0200 Subject: [PATCH 4/4] remove Currency for Iden3PaymentRailsRequestV1 and Iden3PaymentRailsERC20RequestV1 --- protocol/payment.go | 2 -- protocol/payment_test.go | 14 -------------- 2 files changed, 16 deletions(-) diff --git a/protocol/payment.go b/protocol/payment.go index 1cdbff7..22a4f92 100644 --- a/protocol/payment.go +++ b/protocol/payment.go @@ -176,7 +176,6 @@ type Iden3PaymentRailsRequestV1 struct { ExpirationDate string `json:"expirationDate"` Proof PaymentProof `json:"proof"` Metadata string `json:"metadata"` - Currency string `json:"currency"` } // PaymentRequestType implements the PaymentRequestInfoDataItem interface. @@ -194,7 +193,6 @@ type Iden3PaymentRailsERC20RequestV1 struct { ExpirationDate string `json:"expirationDate"` Proof PaymentProof `json:"proof"` Metadata string `json:"metadata"` - Currency string `json:"currency"` TokenAddress string `json:"tokenAddress"` Features []PaymentFeatures `json:"features,omitempty"` } diff --git a/protocol/payment_test.go b/protocol/payment_test.go index 7e8135e..1e77e0b 100644 --- a/protocol/payment_test.go +++ b/protocol/payment_test.go @@ -65,7 +65,6 @@ func TestPaymentRequestMessagePaymentTypeUnmarshall(t *testing.T) { "@context": "https://schema.iden3.io/core/jsonld/payment.jsonld#Iden3PaymentRailsRequestV1", "recipient": "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", "amount": "30001", - "currency": "ETHWEI", "expirationDate": "2024-10-14T13:22:31.956Z", "nonce": "18", "metadata": "0x", @@ -97,7 +96,6 @@ func TestPaymentRequestMessagePaymentTypeUnmarshall(t *testing.T) { ], "recipient": "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", "amount": "60002", - "currency": "ETHWEI", "expirationDate": "2024-10-14T13:22:31.956Z", "nonce": "18", "metadata": "0x", @@ -129,7 +127,6 @@ func TestPaymentRequestMessagePaymentTypeUnmarshall(t *testing.T) { ], "recipient": "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", "amount": "90003", - "currency": "ETHWEI", "expirationDate": "2024-10-14T13:22:31.956Z", "nonce": "18", "metadata": "0x", @@ -191,7 +188,6 @@ func TestPaymentRequestMessagePaymentTypeUnmarshall(t *testing.T) { "features": ["EIP-2612"], "recipient": "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", "amount": "40", - "currency": "ERC20Token", "expirationDate": "2024-10-28T16:02:36.816Z", "nonce": "3008", "metadata": "0x", @@ -369,7 +365,6 @@ func TestPaymentRequestInfoDataUnmarshalMarshall(t *testing.T) { ], "recipient": "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", "amount": "30001", - "currency": "ETHWEI", "expirationDate": "2024-10-14T13:22:31.956Z", "nonce": "18", "metadata": "0x", @@ -401,7 +396,6 @@ func TestPaymentRequestInfoDataUnmarshalMarshall(t *testing.T) { ], "recipient": "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", "amount": "60002", - "currency": "ETHWEI", "expirationDate": "2024-10-14T13:22:31.956Z", "nonce": "18", "metadata": "0x", @@ -433,7 +427,6 @@ func TestPaymentRequestInfoDataUnmarshalMarshall(t *testing.T) { ], "recipient": "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", "amount": "90003", - "currency": "ETHWEI", "expirationDate": "2024-10-14T13:22:31.956Z", "nonce": "18", "metadata": "0x", @@ -469,7 +462,6 @@ func TestPaymentRequestInfoDataUnmarshalMarshall(t *testing.T) { "type": "Iden3PaymentRailsRequestV1", "recipient": "0xaddress", "amount": "100", - "currency": "ETHWEI", "expirationDate": "ISO string", "nonce": "25", "metadata": "0x", @@ -505,7 +497,6 @@ func TestPaymentRequestInfoDataUnmarshalMarshall(t *testing.T) { ], "recipient": "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", "amount": "40", - "currency": "ERC20Token", "expirationDate": "2024-10-28T16:02:36.816Z", "nonce": "3008", "metadata": "0x", @@ -537,7 +528,6 @@ func TestPaymentRequestInfoDataUnmarshalMarshall(t *testing.T) { "type": "Iden3PaymentRailsRequestV1", "recipient": "0xaddress2", "amount": "200", - "currency": "ETHWEI", "expirationDate": "ISO string", "nonce": "25", "metadata": "0x", @@ -611,7 +601,6 @@ func TestPaymentRequestInfoData_Construction(t *testing.T) { "type": "Iden3PaymentRailsRequestV1", "recipient": "0xaddress", "amount": "100", - "currency": "ETHWEI", "proof": [ { "type": "EthereumEip712Signature2021", @@ -647,7 +636,6 @@ func TestPaymentRequestInfoData_Construction(t *testing.T) { ], "recipient": "0xE9D7fCDf32dF4772A7EF7C24c76aB40E4A42274a", "amount": "40", - "currency": "ERC20Token", "proof": [ { "type": "EthereumEip712Signature2021", @@ -704,7 +692,6 @@ func TestPaymentRequestInfoData_Construction(t *testing.T) { }, }, Metadata: "0x", - Currency: "ETHWEI", }, protocol.Iden3PaymentRailsERC20RequestV1{ Nonce: "3008", @@ -736,7 +723,6 @@ func TestPaymentRequestInfoData_Construction(t *testing.T) { }, }, Metadata: "0x", - Currency: "ERC20Token", TokenAddress: "0x2FE40749812FAC39a0F380649eF59E01bccf3a1A", Features: []protocol.PaymentFeatures{"EIP-2612"}, },