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 };