使用Hyperledger Composer和React.js構建保險應用程式-part1

買賣虛擬貨幣
本教程介紹如何使用HyperledgeComposer和React.js作為前端Web應用程式構建簡單的HyperledgeFabric網路。該應用程式是一個保險應用程式,利用區塊鏈以更有效和安全的方式執行風險分析。Hyperledger ComposerHyperledger composer是一種在Hyperledger Fabric上構建區塊鏈業務網路的工具。它抽象了構建區塊鏈網路所涉及的許多複雜性。要安裝Hyperledger Composer,請按照此處的說明進行操作。https://hyperledger.github.io/composer/latest/installing/installing-prereqs概念
本系統是一種保險應用程式,利用區塊鏈進行更高效和安全的風險分析。這是透過保單持有人在保險公司之間傳遞資料來實現的,這意味著保單持有人將其資料提供給保險公司。系統中有兩個參與者:· 投保人· 保險公司系統的保單持有人希望執行以下操作:· 新增資產
· 接受/拒絕保險報價· 提出索賠保險公司希望能夠執行以下操作:· 檢視對保險開放的資產· 提供保險· 批准/拒絕索賠
投保人是購買保險的個人,或者已經為房產或汽車等資產購買了保險的投保人。保險公司是向保單持有人提供此保險的公司。與保單持有人尋找保險公司的傳統保險不同,保單持有人在區塊鏈網路輸入他們的保險需求,保險公司提供報價。風險分析使用鏈碼來實現,當投保人尋找保險時,鏈碼將自動執行。與過去的索賠和資產相關的所有資料均由保單持有人擁有和承載不同,資訊不會單獨留在保險公司。這些資料將用於對投保人及其資產要求進行簡單評估,以提供一個風險分析評分,保險公司可使用該評分來通知其保險報價。

由於此係統將包含我們不希望每個人都看到的敏感資料,因此我們需要實現控制對此個人資料的訪問許可權。

讓我們首先建立一個用於儲存應用程式的資料夾:

mkdir insurance-application && cd insurance-application

現在讓我們使用yeoman為我們的業務網路建立一個框架

yo hyperledger-composer:businessnetwork

Business network name: risk-analysis-tutorial
Description: 分線分析教程
Author name: 你的名字
Author email: 你的郵箱
License: Apache-2.0
Namespace: org.acme.riskanalysis

Do you want to generate an empty template network? (您想生成空模板網路嗎?)Yes

cd risk-analysis-tutorial

執行命令ls應顯示以下資料夾和檔案:

- models 
- package.json
- permissions.acl 
- README.md

因此,首先我們要定義我們網路中的參與者,誰是投保人和誰是保險人。我們開啟檔案org.acme.riskanalysis.cto,可以在models資料夾中找到該檔案。

participant Policyholder identified by id {
  o String id
  o String name
  o Double balance default = 0.0
  o Integer noClaimsYears default = 0
}

participant InsuranceCompany identified by id {
  o String id
  o String name
  o Double balance default = 0.0
  o Integer insuranceContracts default = 0
}

保單持有人還希望能夠新增房屋或汽車等資產,因此我們定義一個名為PrivateAsset的資產以及一個名為AssetType的列舉。PrivateAsset依賴於將成為建立資產的人的保單持有人。只有3種型別的資產可以新增到系統中,由enum AssetType定義。

asset PrivateAsset identified by id {
  o String id
  o AssetType assetType
  o Double value
  --> Policyholder policyholder
  o Integer durationInMonths
  o Double riskAnalysisScore default = 0.0
  --> InsuranceCompany insuranceCompany optional
}

enum AssetType {
  o CAR
  o HOUSE
  o PHONE
}

我們將增加兩種資產型別,一種用於保險報價,另一種用於索賠。

asset InsuranceOffer identified by id {
  o String id
  --> Policyholder policyholder
  --> InsuranceCompany insuranceCompany
  --> PrivateAsset privateAsset
  o Double monthlyCost
  o Integer durationInMonths
  o String status default = "pending"
}

asset Claim identified by id {
  o String id
  --> PrivateAsset privateAsset
  --> Policyholder policyholder
  --> InsuranceCompany insuranceCompany
  o String description
  o Double claimValue
  o String status default = "pending"
}

接下來,我們需要為網路定義我們的事務。

transaction AcceptInsuranceOffer {
  --> InsuranceOffer offer
}

transaction MakeInsuranceOffer {
  --> Policyholder policyholder
  --> InsuranceCompany insuranceCompany
  --> PrivateAsset privateAsset
  o Double monthlyCost
}

transaction RiskAnalysis {
  --> PrivateAsset privateAsset
}

transaction CreateNewAsset {
  --> Policyholder policyholder
  o AssetType assetType
  o Double value
  o Integer durationInMonths
}

transaction CreateClaim {
  --> PrivateAsset privateAsset
  --> Policyholder policyholder
  o String description
  o Double claimValue
}

transaction ProcessClaim {
  -->Claim claim
  o String status
}

您的完整模型檔案應該是這樣的:

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace org.acme.riskanalysis

participant Policyholder identified by id {
  o String id
  o String name
  o Double balance default = 0.0
  o Integer noClaimsYears default = 0
}

participant InsuranceCompany identified by id {
  o String id
  o String name
  o Double balance default = 0.0
  o Integer insuranceContracts default = 0
}

asset PrivateAsset identified by id {
  o String id
  o AssetType assetType
  o Double value
  --> Policyholder policyholder
  o Integer durationInMonths
  o Double riskAnalysisScore default = 0.0
  --> InsuranceCompany insuranceCompany optional
}

enum AssetType {
  o CAR
  o HOUSE
  o PHONE
}


asset InsuranceOffer identified by id {
  o String id
  --> Policyholder policyholder
  --> InsuranceCompany insuranceCompany
  --> PrivateAsset privateAsset
  o Double monthlyCost
  o Integer durationInMonths
  o String status default = "pending"
}

asset Claim identified by id {
  o String id
  --> PrivateAsset privateAsset
  --> Policyholder policyholder
  --> InsuranceCompany insuranceCompany
  o String description
  o Double claimValue
  o String status default = "pending"
}

transaction AcceptInsuranceOffer {
  --> InsuranceOffer offer
}
transaction MakeInsuranceOffer {
  --> Policyholder policyholder
  --> InsuranceCompany insuranceCompany
  --> PrivateAsset privateAsset
  o Double monthlyCost
}

transaction RiskAnalysis {
  --> PrivateAsset privateAsset
}

transaction CreateNewAsset {
  --> Policyholder policyholder
  o AssetType assetType
  o Double value
  o Integer durationInMonths
}

transaction CreateClaim {
  --> PrivateAsset privateAsset
  --> Policyholder policyholder
  o String description
  o Double claimValue
}

transaction ProcessClaim {
  -->Claim claim
  o String status
}

接下來,我們需要實現我們的事務,這是鏈程式碼完成。

首先,您需要在Hyperledger編寫器專案的主目錄中建立一個名為lib的新目錄,您將在其中看到諸如package.json之類的檔案,或者如果您位於終端的models目錄中,請執行以下命令:

mkdir ../lib/ && cd ../lib/

在lib目錄中,我們現在將建立一個名為logic.js的新檔案,它將成為我們的鏈程式碼檔案。

讓我們首先實現CreateNewAsset。您會注意到我們使用decorators 為我們的函式提供後設資料。

/**
 * Create a new asset
 * @param {org.acme.riskanalysis.CreateNewAsset} asset
 * @transaction
 */
async function createNewAsset(asset) {
    let assetRegistry = await getAssetRegistry('org.acme.riskanalysis.PrivateAsset');
    var factory = getFactory()

    num_id = (Math.floor(Math.random() * ( 999999 - 100000) + 100000)).toString(10)

    var assetID = asset.policyholder.id + num_id;
    var newAsset = factory.newResource('org.acme.riskanalysis', 'PrivateAsset', assetID)
    newAsset.policyholder = asset.policyholder;
    newAsset.assetType = asset.assetType;
    newAsset.value = asset.value;
    newAsset.durationInMonths = asset.durationInMonths;

    await assetRegistry.add(newAsset)
}

現在我們已經完成了,讓我們測試一下它是否有效。

首先,我們必須啟動Hyperledger Fabric。找到您已下載的目錄並執行指令碼,如下所示:

cd ~/fabric-dev-servers
./startFabric.sh
./createPeerAdminCard.sh

注意,如果以前沒有執行過Hyperledger Fabric或以前執行過/teardownfabric.sh,則只需執行/createpeeradincard.sh。

nvm use 8

現在回到risk-analysis-tutorial目錄,我們將開始部署我們網路的0.0.1版本。

執行此命令將生成名為admin@chaindaily的業務網路歸檔檔案

composer archive create -t dir -n .

接下來,我們將在我們設定的Hyperledger Fabric對等裝置上安裝Composer業務網路

composer network install --card admin@chaindaily 
--archiveFile admin@chaindaily

現在我們可以開始我們的業務網路,這可能需要幾分鐘

composer network start --networkName risk-analysis-tutorial 
--networkVersion 0.0.1 --networkAdmin admin --networkAdminEnrollSecret 
adminpw --card admin@chaindaily --file networkadmin.card

然後只需將網路管理員身份匯入為可用的業務網絡卡

composer card import --file networkadmin.card

要測試這是否全部成功,只需ping網路即可

composer network ping --card admin@chaindaily

檢查已部署的網路執行的當前版本

composer network ping -c admin@chaindaily | grep Business

Hyperledger Composer可以基於業務網路生成定製的REST API。對於我們的網路,我們現在只想保持簡單,所以只需執行以下命令即可建立REST API

composer-rest-server -c admin@chaindaily -n never -u true -w true

現在,您可以透過定位到測試REST API

http://localhost:3000/explorer

您應該看到以下螢幕

Hyperledger Composer REST Server

如果我們要測試我們的CreateNewAsset函式,我們首先需要建立一些保單持有人,所以選擇Policyholder,然後選擇post並輸入以下內容,然後單擊try out out

{
  "$class": "org.acme.riskanalysis.Policyholder",
  "id": "joe",
  "name": "Joe",
  "balance": "50000",
  "noClaimsYears": "2"
}

現在使用以下資訊以相同的方式建立另一個保單持有人

{
  "$class": "org.acme.riskanalysis.Policyholder",
  "id": "mary",
  "name": "Mary",
  "balance": "50000",
  "noClaimsYears": "5"
}

如果不出現錯誤訊息,則對兩者的響應應為200,並檢視程式碼是否存在任何潛在錯誤。

現在我們準備測試CreateNewAsset函式了。要執行此操作,請轉到CreateNewAsset> Post。讓我們為Joe創造一輛價值2000美元的氣車,並尋求12個月的保險。

{
  "$class": "org.acme.riskanalysis.CreateNewAsset",
  "policyholder": "resource:org.acme.riskanalysis.Policyholder#joe",
  "assetType": "CAR",
  "value": 2000,
  "durationInMonths": 12
}

如果一切正常,響應程式碼應為200。請注意它區分大小寫。

現在,如果您轉到PrivateAssets> Get,然後單擊“try it out”,您應該看到我們剛建立的資產。

現在讓我們透過單擊終端中的ctrl-c關閉REST伺服器,我們將完成其餘的事務處理。

RiskAnalysis交易的邏輯只是檢查資產型別以及保單持有人沒有索賠的年數和資產的價值。

/**
 * Risk Analysis
 * @param {org.acme.riskanalysis.RiskAnalysis} asset
 * @transaction
 */
async function riskAnalysis(asset) {
    let assetRegistry = await getAssetRegistry('org.acme.riskanalysis.PrivateAsset');
    let score = 0

    if (asset.privateAsset.policyholder.noClaimsYears == 1) {
        score += 1
    }

    if (asset.privateAsset.policyholder.noClaimsYears == 2) {
        score += 2
    }

    if (asset.privateAsset.policyholder.noClaimsYears > 2) {
        score += 4
    }

    if (asset.privateAsset.description == 'Phone') {
        score +=2
    }

    if (asset.privateAsset.description == 'House') {
        score +=3
    }

    if (asset.privateAsset.description == 'Car') {
        score +=2
    }

    if (asset.privateAsset.value < 10000.0) {
        score += 1
    }

    if (asset.privateAsset.value < 1000.0) {
        score += 1
    }

    asset.privateAsset.riskAnalysisScore = score

    assetRegistry.update(asset.privateAsset)

}

要對此進行測試,請轉到package.json檔案並將版本號從0.0.1更改為0.0.2,然後建立新的業務網路存檔檔案

composer archive create --sourceType dir --sourceName . -a admin@chaindaily

安裝新檔案

composer network install --card admin@chaindaily --archiveFile admin@chaindaily

更新網路

composer network upgrade -c admin@chaindaily -n risk-analysis-tutorial -V 0.0.2

檢查網路是否已升級到版本:0.0.2

composer network ping -c admin@chaindaily | grep Business

然後再次執行Composer REST SERVER

composer-rest-server -c admin@chaindaily -n never -u true -w true

您之前建立的所有保單持有人和資產仍將在此處,因此無需再次設定這些保單持有人和資產。 讓我們獲取之前為Joe新增的汽車的ID。 然後轉到RiskAnalysis> Post並輸入以下用您的資產ID替換ASSETID。

{
  "$class": "org.acme.riskanalysis.RiskAnalysis",
  "privateAsset": "resource:org.acme.riskanalysis.PrivateAsset#ASSETID"
}

現在回到PrivateAsset> Get,您應該看到風險分析得分從0變為3。

接下來,讓我們實現MakeInsuranceOffer

/**
 * Make an insurance offer
 * @param {org.acme.riskanalysis.MakeInsuranceOffer} insurance
 * @transaction
 */

async function makeInsuranceOffer(insurance) {
    let assetRegistry = await getAssetRegistry('org.acme.riskanalysis.InsuranceOffer');

    num_id = (Math.floor(Math.random() * ( 999999 - 100000) + 100000)).toString(10)

    var factory = getFactory()
    var insuranceId = insurance.policyholder.id + '' + num_id
    var insuranceOfferAsset = factory.newResource('org.acme.riskanalysis', 'InsuranceOffer', insuranceId)
    insuranceOfferAsset.policyholder = insurance.policyholder
    insuranceOfferAsset.insuranceCompany = insurance.insuranceCompany
    insuranceOfferAsset.privateAsset = insurance.privateAsset
    insuranceOfferAsset.durationInMonths = insurance.privateAsset.durationInMonths
    insuranceOfferAsset.monthlyCost = insurance.monthlyCost

    await assetRegistry.add(insuranceOfferAsset)
}

現在讓我們新增AcceptInsuranceOffer的功能

/**
 * Accepting an insurance offer
 * @param {org.acme.riskanalysis.AcceptInsuranceOffer} offer
 * @transaction
 */

async function acceptInsuranceOffer(offer) {
    let insuranceOfferAssetRegistry = await getAssetRegistry('org.acme.riskanalysis.InsuranceOffer');
    let policyholderParticipantRegistry = await getParticipantRegistry('org.acme.riskanalysis.Policyholder');
    let privateAssetParticipantRegistry = await getAssetRegistry('org.acme.riskanalysis.PrivateAsset');
    let insuranceCompanyParticipantRegistry = await getParticipantRegistry('org.acme.riskanalysis.InsuranceCompany');

    var costToDebit = offer.offer.monthlyCost;
    let insuranceCompany = "resource:org.acme.riskanalysis.InsuranceCompany#" + offer.offer.insuranceCompany.id;

    if (offer.offer.policyholder.balance < costToDebit) {
        throw new Error('Not enough funds in balance')
    }
    offer.offer.policyholder.balance -= costToDebit
    offer.offer.insuranceCompany.balance += costToDebit
    offer.offer.insuranceCompany.insuranceContracts += 1
    offer.offer.status = "accepted";
    offer.offer.privateAsset.insuranceCompany = offer.offer.insuranceCompany;

    await insuranceOfferAssetRegistry.update(offer.offer);
    await policyholderParticipantRegistry.update(offer.offer.policyholder)
    await insuranceCompanyParticipantRegistry.update(offer.offer.insuranceCompany)
    await privateAssetParticipantRegistry.update(offer.offer.privateAsset)

}

讓我們實現CreateClaim

/**
 * Create a claim
 * @param {org.acme.riskanalysis.CreateClaim} claim
 * @transaction
 */

async function makeClaim(claim) {
    let assetResource = "resource:org.acme.riskanalysis.PrivateAsset#" + claim.privateAsset.id;
    let assetInsuranceOffer = await query('selectInsuranceCompanyByInsuredAsset', { privateAsset: assetResource });

    num_id = (Math.floor(Math.random() * ( 999999 - 100000) + 100000)).toString(10)


    let assetRegistry = await getAssetRegistry('org.acme.riskanalysis.Claim');

    var factory = getFactory()
    var claimId = claim.policyholder.id + '' + num_id
    var newClaim = factory.newResource('org.acme.riskanalysis', 'Claim', claimId)

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;