github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/kat/src/handlers/payment-definitions.ts (about)

     1  // Copyright © 2021 Kaleido, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  import { v4 as uuidV4 } from 'uuid';
    16  import Ajv from 'ajv';
    17  import * as utils from '../lib/utils';
    18  import * as ipfs from '../clients/ipfs';
    19  import * as apiGateway from '../clients/api-gateway';
    20  import * as database from '../clients/database';
    21  import RequestError from '../lib/request-handlers';
    22  import { IAPIGatewayAsyncResponse, IAPIGatewaySyncResponse, IDBBlockchainData, IEventPaymentDefinitionCreated } from '../lib/interfaces';
    23  
    24  const ajv = new Ajv();
    25  
    26  export const handleGetPaymentDefinitionsRequest = (query: object, skip: number, limit: number) => {
    27    return database.retrievePaymentDefinitions(query, skip, limit);
    28  };
    29  
    30  export const handleCountPaymentDefinitionsRequest = async (query: object) => {
    31    return { count: await database.countPaymentDefinitions(query) };
    32  };
    33  
    34  export const handleGetPaymentDefinitionRequest = async (paymentDefinitionID: string) => {
    35    const paymentDefinition = await database.retrievePaymentDefinitionByID(paymentDefinitionID);
    36    if (paymentDefinition === null) {
    37      throw new RequestError('Payment definition not found', 404);
    38    }
    39    return paymentDefinition;
    40  };
    41  
    42  export const handleCreatePaymentDefinitionRequest = async (name: string, author: string, descriptionSchema: Object | undefined, sync: boolean) => {
    43    if (descriptionSchema !== undefined && !ajv.validateSchema(descriptionSchema)) {
    44      throw new RequestError('Invalid description schema', 400);
    45    }
    46    if (await database.retrievePaymentDefinitionByName(name) !== null) {
    47      throw new RequestError('Payment definition name conflict', 409);
    48    }
    49    let descriptionSchemaHash: string | undefined;
    50    let apiGatewayResponse: IAPIGatewayAsyncResponse | IAPIGatewaySyncResponse;
    51    const timestamp = utils.getTimestamp();
    52  
    53    const paymentDefinitionID = uuidV4();
    54    if (descriptionSchema) {
    55      descriptionSchemaHash = utils.ipfsHashToSha256(await ipfs.uploadString(JSON.stringify(descriptionSchema)));
    56      apiGatewayResponse = await apiGateway.createDescribedPaymentDefinition(paymentDefinitionID, name, author, descriptionSchemaHash, sync);
    57    } else {
    58      apiGatewayResponse = await apiGateway.createPaymentDefinition(paymentDefinitionID, name, author, sync);
    59    }
    60    const receipt = apiGatewayResponse.type === 'async' ? apiGatewayResponse.id : undefined;
    61    await database.upsertPaymentDefinition({
    62      paymentDefinitionID,
    63      name,
    64      author,
    65      descriptionSchemaHash,
    66      descriptionSchema,
    67      submitted: timestamp,
    68      receipt
    69    });
    70    return paymentDefinitionID;
    71  };
    72  
    73  export const handlePaymentDefinitionCreatedEvent = async (event: IEventPaymentDefinitionCreated, { blockNumber, transactionHash }: IDBBlockchainData) => {
    74    const paymentDefinitionID = utils.hexToUuid(event.paymentDefinitionID);
    75    const dbPaymentDefinitionByID = await database.retrievePaymentDefinitionByID(paymentDefinitionID);
    76    if (dbPaymentDefinitionByID !== null) {
    77      if (dbPaymentDefinitionByID.transactionHash !== undefined) {
    78        throw new Error(`Payment definition ID conflict ${paymentDefinitionID}`);
    79      }
    80    } else {
    81      const dbpaymentDefinitionByName = await database.retrievePaymentDefinitionByName(event.name);
    82      if (dbpaymentDefinitionByName !== null) {
    83        if (dbpaymentDefinitionByName.transactionHash !== undefined) {
    84          throw new Error(`Payment definition name conflict ${event.name}`);
    85        } else {
    86          await database.markPaymentDefinitionAsConflict(dbpaymentDefinitionByName.paymentDefinitionID, Number(event.timestamp));
    87        }
    88      }
    89    }
    90    let descriptionSchema;
    91    if (event.descriptionSchemaHash) {
    92      if (event.descriptionSchemaHash === dbPaymentDefinitionByID?.descriptionSchemaHash) {
    93        descriptionSchema = dbPaymentDefinitionByID?.descriptionSchema
    94      } else {
    95        descriptionSchema = await ipfs.downloadJSON<Object>(utils.sha256ToIPFSHash(event.descriptionSchemaHash));
    96      }
    97    }
    98    database.upsertPaymentDefinition({
    99      paymentDefinitionID,
   100      author: event.author,
   101      name: event.name,
   102      descriptionSchemaHash: event.descriptionSchemaHash,
   103      descriptionSchema,
   104      timestamp: Number(event.timestamp),
   105      blockNumber,
   106      transactionHash
   107    });
   108  };