Parsing errors with openapi-generator (invalid type for type, set it to string)

Viewed 1923

I have the following openapi file schema

{
    "openapi": "3.0.3",
    "info": {
        "title": "Hyperledger Cactus Plugin - Connector Quorum",
        "description": "Can perform basic tasks on a Quorum ledger",
        "version": "0.0.1"
    },
    "servers": [
        {
            "url": "https://www.cactus.stream/{basePath}",
            "description": "Public test instance",
            "variables": {
                "basePath": {
                    "default": ""
                }
            }
        },
        {
            "url": "http://localhost:4000/{basePath}",
            "description": "Local test instance",
            "variables": {
                "basePath": {
                    "default": ""
                }
            }
        }
    ],
    "components": {
        "schemas": {
            "Web3SigningCredential": {
                "type": "object",
                "required": [
                    "type"
                ],
                "discriminator": {
                    "propertyName": "type"
                },
                "oneOf": [
                    {
                        "$ref": "#/components/schemas/Web3SigningCredentialGethKeychainPassword"
                    },
                    {
                        "$ref": "#/components/schemas/Web3SigningCredentialCactusKeychainRef"
                    },
                    {
                        "$ref": "#/components/schemas/Web3SigningCredentialPrivateKeyHex"
                    },
                    {
                        "$ref": "#/components/schemas/Web3SigningCredentialNone"
                    }
                ],
                "properties": {
                    "type": {
                        "$ref": "#/components/schemas/Web3SigningCredentialType"
                    }
                }
            },
            "Web3SigningCredentialGethKeychainPassword": {
                "type": "object",
                "required": [
                    "type",
                    "ethAccount",
                    "secret"
                ],
                "properties": {
                    "type": {
                        "$ref": "#/components/schemas/Web3SigningCredentialType"
                    },
                    "ethAccount": {
                        "type": "string",
                        "description": "The ethereum account (public key) that the credential  belongs to. Basically the username in the traditional terminology of authentication.",
                        "minLength": 64,
                        "maxLength": 64,
                        "nullable": false
                    },
                    "secret": {
                        "type": "string",
                        "description": "A geth keychain unlock password.",
                        "minLength": 0,
                        "maxLength": 65535
                    }
                }
            },
            "Web3SigningCredentialCactusKeychainRef": {
                "type": "object",
                "required": [
                    "type",
                    "ethAccount",
                    "keychainId",
                    "keychainEntryKey"
                ],
                "properties": {
                    "type": {
                        "$ref": "#/components/schemas/Web3SigningCredentialType"
                    },
                    "ethAccount": {
                        "type": "string",
                        "description": "The ethereum account (public key) that the credential  belongs to. Basically the username in the traditional  terminology of authentication.",
                        "minLength": 64,
                        "maxLength": 64,
                        "nullable": false
                    },
                    "keychainEntryKey": {
                        "type": "string",
                        "description": "The key to use when looking up the the keychain entry holding the secret pointed to by the  keychainEntryKey parameter.",
                        "minLength": 0,
                        "maxLength": 1024
                    },
                    "keychainId": {
                        "type": "string",
                        "description": "The keychain ID to use when looking up the the keychain plugin instance that will be used to retrieve the secret pointed to by the keychainEntryKey parameter.",
                        "minLength": 0,
                        "maxLength": 1024
                    }
                }
            },
            "Web3SigningCredentialPrivateKeyHex": {
                "type": "object",
                "required": [
                    "type",
                    "ethAccount",
                    "secret"
                ],
                "properties": {
                    "type": {
                        "$ref": "#/components/schemas/Web3SigningCredentialType"
                    },
                    "ethAccount": {
                        "type": "string",
                        "description": "The ethereum account (public key) that the credential belongs to. Basically the username in the traditional terminology of authentication.",
                        "minLength": 64,
                        "maxLength": 64,
                        "nullable": false
                    },
                    "secret": {
                        "type": "string",
                        "description": "The HEX encoded private key of an eth account.",
                        "minLength": 0,
                        "maxLength": 65535
                    }
                }
            },
            "Web3SigningCredentialNone": {
                "type": "object",
                "required": [
                    "type"
                ],
                "description": "Using this denotes that there is no signing required because the transaction is pre-signed.",
                "properties": {
                    "type": {
                        "$ref": "#/components/schemas/Web3SigningCredentialType"
                    }
                }
            },
            "Web3SigningCredentialType": {
                "type": "string",
                "enum": [
                    "CACTUS_KEYCHAIN_REF",
                    "GETH_KEYCHAIN_PASSWORD",
                    "PRIVATE_KEY_HEX",
                    "NONE"
                ]
            },
            "EthContractInvocationType": {
                "type": "string",
                "enum": [
                    "SEND",
                    "CALL"
                ]
            },
            "SolidityContractJsonArtifact": {
                "type": "object",
                "required": [
                    "contractName"
                ],
                "properties": {
                    "contractName": {
                        "type": "string",
                        "nullable": false
                    },
                    "metadata": {
                        "type": "string",
                        "nullable": false
                    },
                    "bytecode": {
                        "type": "string",
                        "nullable": false
                    },
                    "deployedBytecode": {
                        "type": "string",
                        "nullable": false
                    },
                    "sourceMap": {
                        "type": "string",
                        "nullable": false
                    },
                    "deployedSourceMap": {
                        "type": "string",
                        "nullable": false
                    },
                    "sourcePath": {
                        "type": "string"
                    },
                    "compiler": {
                        "type": "object",
                        "additionalProperties": true,
                        "properties": {
                            "name": {
                                "type": "string"
                            },
                            "version": {
                                "type": "string"
                            }
                        }
                    },
                    "functionHashes": {
                        "type": "object",
                        "additionalProperties": true
                    },
                    "gasEstimates": {
                        "properties": {
                            "creation": {
                                "type": "object",
                                "properties": {
                                    "codeDepositCost": {
                                        "type": "string"
                                    },
                                    "executionCost": {
                                        "type": "string"
                                    },
                                    "totalCost": {
                                        "type": "string"
                                    }
                                }
                            },
                            "external": {
                                "type": "object",
                                "additionalProperties": true
                            }
                        }
                    }
                }
            },
            "QuorumTransactionConfig": {
                "type": "object",
                "required": [],
                "additionalProperties": true,
                "properties": {
                    "rawTransaction": {
                        "type": "string",
                        "nullable": false
                    },
                    "from": {
                        "oneOf": [
                            {
                                "type": "string"
                            },
                            {
                                "type": "number"
                            }
                        ]
                    },
                    "to": {
                        "oneOf": [
                            {
                                "type": "string"
                            }
                        ]
                    },
                    "value": {
                        "oneOf": [
                            {
                                "type": "string"
                            },
                            {
                                "type": "number"
                            }
                        ]
                    },
                    "gas": {
                        "oneOf": [
                            {
                                "type": "string"
                            },
                            {
                                "type": "number"
                            }
                        ]
                    },
                    "gasPrice": {
                        "oneOf": [
                            {
                                "type": "string"
                            },
                            {
                                "type": "number"
                            }
                        ]
                    },
                    "data": {
                        "oneOf": [
                            {
                                "type": "string"
                            }
                        ]
                    }
                }
            },
            "Web3TransactionReceipt": {
                "type": "object",
                "required": [
                    "blockHash",
                    "blockNumber",
                    "transactionHash",
                    "transactionIndex",
                    "status",
                    "from",
                    "to",
                    "gasUsed"
                ],
                "additionalProperties": true,
                "properties": {
                    "status": {
                        "type": "boolean",
                        "nullable": false
                    },
                    "transactionHash": {
                        "type": "string",
                        "minLength": 64,
                        "maxLength": 64,
                        "pattern": "/^0x([A-Fa-f0-9]{64})$/"
                    },
                    "transactionIndex": {
                        "type": "number",
                        "nullable": false
                    },
                    "blockHash": {
                        "type": "string",
                        "minLength": 64,
                        "maxLength": 64,
                        "pattern": "/^0x([A-Fa-f0-9]{64})$/"
                    },
                    "blockNumber": {
                        "type": "number",
                        "nullable": false
                    },
                    "gasUsed": {
                        "type": "number",
                        "nullable": false
                    },
                    "contractAddress": {
                        "type": "string",
                        "nullable": true
                    },
                    "from": {
                        "type": "string",
                        "nullable": false
                    },
                    "to": {
                        "type": "string",
                        "nullable": false
                    }
                }
            },
            "RunTransactionRequest": {
                "type": "object",
                "required": [
                    "web3SigningCredential",
                    "transactionConfig"
                ],
                "properties": {
                    "web3SigningCredential": {
                        "$ref": "#/components/schemas/Web3SigningCredential",
                        "nullable": false
                    },
                    "transactionConfig": {
                        "$ref": "#/components/schemas/QuorumTransactionConfig",
                        "nullable": false
                    },
                    "timeoutMs": {
                        "type": "number",
                        "description": "The amount of milliseconds to wait for a transaction receipt with thehash of the transaction(which indicates successful execution) beforegiving up and crashing.",
                        "minimum": 0,
                        "default": 60000,
                        "nullable": false
                    }
                }
            },
            "RunTransactionResponse": {
                "type": "object",
                "required": [
                    "transactionReceipt"
                ],
                "properties": {
                    "transactionReceipt": {
                        "$ref": "#/components/schemas/Web3TransactionReceipt"
                    }
                }
            },
            "DeployContractSolidityBytecodeV1Request": {
                "type": "object",
                "required": [
                    "bytecode",
                    "web3SigningCredential"
                ],
                "properties": {
                    "web3SigningCredential": {
                        "$ref": "#/components/schemas/Web3SigningCredential",
                        "nullable": false
                    },
                    "bytecode": {
                        "type": "string",
                        "nullable": false,
                        "minLength": 1,
                        "maxLength": 24576,
                        "description": "See https://ethereum.stackexchange.com/a/47556 regarding the maximum length of the bytecode"
                    },
                    "gas": {
                        "type": "number",
                        "nullable": false
                    },
                    "gasPrice": {
                        "type": "string",
                        "nullable": false
                    },
                    "timeoutMs": {
                        "type": "number",
                        "description": "The amount of milliseconds to wait for a transaction receipt with theaddress of the contract(which indicates successful deployment) beforegiving up and crashing.",
                        "minimum": 0,
                        "default": 60000,
                        "nullable": false
                    }
                }
            },
            "DeployContractSolidityBytecodeV1Response": {
                "type": "object",
                "required": [
                    "transactionReceipt"
                ],
                "properties": {
                    "transactionReceipt": {
                        "$ref": "#/components/schemas/Web3TransactionReceipt"
                    }
                }
            },
            "InvokeContractV1Request": {
                "type": "object",
                "required": [
                    "contractAbi",
                    "web3SigningCredential",
                    "contractAddress",
                    "invocationType",
                    "methodName",
                    "params"
                ],
                "properties": {
                    "web3SigningCredential": {
                        "$ref": "#/components/schemas/Web3SigningCredential",
                        "nullable": false
                    },
                    "contractAbi": {
                        "description": "The application binary interface of the solidity contract",
                        "type": "array",
                        "items": {},
                        "nullable": false
                    },
                    "contractAddress": {
                        "type": "string",
                        "nullable": false
                    },
                    "invocationType": {
                        "$ref": "#/components/schemas/EthContractInvocationType",
                        "nullable": false,
                        "description": "Indicates wether it is a CALL or a SEND type of  invocation where only SEND ends up creating an actual transaction on the ledger."
                    },
                    "methodName": {
                        "description": "The name of the contract method to invoke.",
                        "type": "string",
                        "nullable": false,
                        "minLength": 1,
                        "maxLength": 2048
                    },
                    "params": {
                        "description": "The list of arguments to pass in to the contract method being invoked.",
                        "type": "array",
                        "default": [],
                        "items": {}
                    },
                    "gas": {
                        "oneOf": [
                            {
                                "type": "string"
                            },
                            {
                                "type": "number"
                            }
                        ]
                    },
                    "gasPrice": {
                        "oneOf": [
                            {
                                "type": "string"
                            },
                            {
                                "type": "number"
                            }
                        ]
                    },
                    "timeoutMs": {
                        "type": "number",
                        "description": "The amount of milliseconds to wait for a transaction receipt beforegiving up and crashing. Only has any effect if the invocation type is SEND",
                        "minimum": 0,
                        "default": 60000,
                        "nullable": false
                    }
                }
            },
            "InvokeContractV1Response": {
                "type": "object",
                "properties": {
                    "transactionReceipt": {
                        "$ref": "#/components/schemas/Web3TransactionReceipt"
                    },
                    "callOutput": {}
                }
            }
        }
    },
    "paths": {
        "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-quorum/deploy-contract-solidity-bytecode": {
            "post": {
                "operationId": "apiV1QuorumDeployContractSolidityBytecode",
                "summary": "Deploys the bytecode of a Solidity contract.",
                "parameters": [],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/DeployContractSolidityBytecodeV1Request"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DeployContractSolidityBytecodeV1Response"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-quorum/run-transaction": {
            "post": {
                "operationId": "apiV1QuorumRunTransaction",
                "summary": "Executes a transaction on a quorum ledger",
                "parameters": [],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/RunTransactionRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/RunTransactionResponse"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-quorum/invoke-contract": {
            "post": {
                "operationId": "apiV1QuorumInvokeContract",
                "summary": "Invokeds a contract on a quorum ledger",
                "parameters": [],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/InvokeContractV1Request"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/InvokeContractV1Response"
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Basically in short the schema (where the issue lies) is like
Web3SigningCredential -> either of { Web3SigningCredentialPrivateKeyHex, Web3SigningCredentialGethKeychainPassword, Web3SigningCredentialNone, Web3SigningCredentialCactusKeychainRef } -> Web3SigningCredentialType

When I am trying to parse it using

openapi-generator generate --input-spec file_mentioned_above -g go -o some_path

I am recieving an error stating

Exception in thread "main" java.lang.RuntimeException: Could not process model 'Web3SigningCredential'.Please make sure that your schema is correct!
        at org.openapitools.codegen.DefaultGenerator.generateModels(DefaultGenerator.java:477)
        at org.openapitools.codegen.DefaultGenerator.generate(DefaultGenerator.java:852)
        at org.openapitools.codegen.cmd.Generate.execute(Generate.java:432)
        at org.openapitools.codegen.cmd.OpenApiGeneratorCommand.run(OpenApiGeneratorCommand.java:32)
        at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:66)
Caused by: java.lang.RuntimeException: 'Web3SigningCredential' defines discriminator 'type', but the referenced schema 'Web3SigningCredentialGethKeychainPassword' is incorrect. invalid type for type, set it to string
        at org.openapitools.codegen.DefaultCodegen.getOneOfAnyOfDescendants(DefaultCodegen.java:2792)
        at org.openapitools.codegen.DefaultCodegen.createDiscriminator(DefaultCodegen.java:2897)
        at org.openapitools.codegen.DefaultCodegen.fromModel(DefaultCodegen.java:2249)
        at org.openapitools.codegen.DefaultGenerator.processModels(DefaultGenerator.java:1162)
        at org.openapitools.codegen.DefaultGenerator.generateModels(DefaultGenerator.java:472)

But the same work when I use the language typescript-axios in the above mentioned command as

openapi-generator generate --input-spec file_mentioned_above -g typescript-axios -o some_path

Am I doing anything wrong with the above mentioned spec file or it something to do with Go for openapi-generator?

1 Answers

Try reorganizing your schemas to use allOf inheritance instead of oneOf. Also make sure to specify the discriminator mapping in the base schema. Without mapping, the API definition assumes that child schemas have the same name as the discriminator property values, which is not the case in your example.

Here is a YAML version, you can use https://www.json2yaml.com/ to convert it to JSON.

components:
  schemas:
    Web3SigningCredential:
      type: object
      required:
        - type
      discriminator:
        propertyName: type
        mapping:
          CACTUS_KEYCHAIN_REF: Web3SigningCredentialCactusKeychainRef
          GETH_KEYCHAIN_PASSWORD: Web3SigningCredentialGethKeychainPassword
          PRIVATE_KEY_HEX: Web3SigningCredentialPrivateKeyHex
          NONE: Web3SigningCredentialNone
      properties:
        type:
          $ref: '#/components/schemas/Web3SigningCredentialType'

    Web3SigningCredentialGethKeychainPassword:
      allOf:
        - $ref: '#/components/schemas/Web3SigningCredential'
        - type: object
          required:
            - ethAccount
            - secret
          properties:
            ethAccount:
              type: string
              description: The ethereum account (public key) that the credential  belongs to. Basically the username in the traditional terminology of authentication.
              minLength: 64
              maxLength: 64
              nullable: false
            secret:
              type: string
              description: A geth keychain unlock password.
              minLength: 0
              maxLength: 65535

Update the Web3SigningCredentialCactusKeychainRef, Web3SigningCredentialPrivateKeyHex and Web3SigningCredentialNone schemas accordingly.

Related