26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/web/gulpfile.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Stripped from Google Web Starter Kit
3 | */
4 |
5 | 'use strict';
6 |
7 | // Include Gulp & tools we'll use
8 | var gulp = require('gulp');
9 | var $ = require('gulp-load-plugins')();
10 | var del = require('del');
11 | var runSequence = require('run-sequence');
12 | var browserSync = require('browser-sync');
13 | var pagespeed = require('psi');
14 | var reload = browserSync.reload;
15 |
16 | // Lint JavaScript
17 | gulp.task('jshint', function () {
18 | return gulp.src('app/scripts/**/*.js')
19 | .pipe(reload({stream: true, once: true}))
20 | .pipe($.jshint())
21 | .pipe($.jshint.reporter('jshint-stylish'))
22 | .pipe($.if(!browserSync.active, $.jshint.reporter('fail')));
23 | });
24 |
25 | // Optimize images
26 | gulp.task('images', function () {
27 | return gulp.src('app/images/**/*')
28 | .pipe($.cache($.imagemin({
29 | progressive: true,
30 | interlaced: true
31 | })))
32 | .pipe(gulp.dest('dist/images'))
33 | .pipe($.size({title: 'images'}));
34 | });
35 |
36 | // Copy all non html files at the root level (app)
37 | gulp.task('copy', function () {
38 | return gulp.src([
39 | 'app/*.*',
40 | '!app/*.html'
41 | ], {
42 | dot: true
43 | }).pipe(gulp.dest('dist'))
44 | .pipe($.size({title: 'copy'}));
45 | });
46 |
47 | var minify = function(path, env) {
48 | gulp.src([path])
49 | .pipe($.replace(/scripts\/config.js/g,
50 | env ? 'scripts/config-'.concat(env).concat('.js') : 'scripts/config.js'))
51 | .pipe($.usemin({
52 | html: [$.minifyHtml({empty: true})],
53 | css: [$.minifyCss(),
54 | $.size({title: 'css ' + path}),
55 | 'concat'],
56 | vendor: [$.uglify(),
57 | $.size({title: 'vendor ' + path}),
58 | 'concat'],
59 | js: [$.ngAnnotate(),
60 | $.uglify(),
61 | $.size({title: 'js ' + path}),
62 | 'concat']
63 | }))
64 | .pipe(gulp.dest('dist'));
65 | };
66 |
67 | //Minify css and js marked in html for build
68 | gulp.task('minify', function() {
69 | minify('app/app.html');
70 | });
71 |
72 | //Minify css and js marked in html for build, for prod env
73 | gulp.task('minify-prod', function() {
74 | minify('app/app.html', 'prod');
75 | });
76 |
77 | // Minify partials html
78 | gulp.task('partials', function() {
79 | gulp.src('app/partials/*.html')
80 | .pipe($.minifyHtml({empty: true}))
81 | .pipe(gulp.dest('dist/partials/'));
82 | });
83 |
84 | // Copy icon fonts
85 | gulp.task('icons', function() {
86 | gulp.src(['app/bower_components/font-awesome/fonts/**.*'])
87 | .pipe(gulp.dest('dist/fonts'));
88 | });
89 |
90 | // Clean output directory
91 | gulp.task('clean', del.bind(null, ['dist/*', '!dist/.git'], {dot: true}));
92 |
93 | // Watch files for changes & reload web app
94 | gulp.task('serve', [], function () {
95 | browserSync({
96 | notify: false,
97 | logPrefix: 'gulp serve',
98 | server: {baseDir: 'app', index: 'app.html'},
99 | port: 8103
100 | });
101 |
102 | //gulp.watch(['app/**.html'], reload);*/
103 | gulp.watch(['app/app.html'], reload);
104 | gulp.watch(['app/partials/*.html'], reload);
105 | gulp.watch(['app/styles/*.css'], reload);
106 | gulp.watch(['app/scripts/**/*.js'], ['jshint']);
107 | gulp.watch(['app/images/**/*'], reload);
108 | });
109 |
110 | // Watch files for changes & reload mobile app
111 | gulp.task('serve:ionic', [], function () {
112 | browserSync({
113 | notify: false,
114 | logPrefix: 'gulp serve:ionic',
115 | server: {baseDir: 'ionic/www', index: 'index.html',
116 | routes: {
117 | '/scripts': 'app/scripts',
118 | '/bower_components': 'app/bower_components',
119 | '/vendor_mods': 'app/vendor_mods'
120 | }},
121 | port: 8100
122 | });
123 |
124 | gulp.watch(['ionic/www/**/*.html'], reload);
125 | gulp.watch(['ionic/www/css/*.css'], reload);
126 | gulp.watch(['ionic/www/js/**/*.js'], ['jshint']);
127 |
128 | gulp.watch(['app/scripts/**/*.js'], ['jshint']);
129 | });
130 |
131 | // Build and serve the output from the dist build
132 | gulp.task('serve:dist', [], function () {
133 | browserSync({
134 | notify: false,
135 | logPrefix: 'gulp serve:dist',
136 | server: {baseDir: 'dist', index: 'app.html'},
137 | port: 8104
138 | });
139 | });
140 |
141 | var dist = function(env) {
142 | var seq = ['jshint', 'partials', 'icons', 'images', 'copy'];
143 | if(env) {
144 | seq.push('minify-'.concat(env));
145 | }
146 | else {
147 | seq.push('minify');
148 | }
149 | runSequence('clean', seq);
150 | }
151 |
152 | //Build minified files, the default task
153 | gulp.task('default', function(cb) {
154 | dist();
155 | });
156 |
157 | //Build minified files for prod
158 | gulp.task('prod', function(cb) {
159 | dist('prod');
160 | });
161 |
162 | //Build minified files for dev
163 | gulp.task('dev', function(cb) {
164 | dist('dev');
165 | });
166 |
167 | // Run PageSpeed Insights
168 | gulp.task('pagespeed', function (cb) {
169 | // Update the below URL to the public URL of your site
170 | pagespeed.output('example.com', {
171 | strategy: 'mobile',
172 | // By default we use the PageSpeed Insights free (no API key) tier.
173 | // Use a Google Developer API key if you have one: http://goo.gl/RkN0vE
174 | // key: 'YOUR_API_KEY'
175 | }, cb);
176 | });
177 |
--------------------------------------------------------------------------------
/docs/p2p-insurance.md:
--------------------------------------------------------------------------------
1 | # Peer-to-peer Insurance Proof Of Concept
2 | This is a functional specification document for the Proof Of Concept of a system enabling users to organize into pools of mutual insurance and insurance companies to insure the risk not covered by the pool.
3 |
4 | Best viewed with [Markdown Reader Plugin for Chrome](https://chrome.google.com/webstore/detail/markdown-reader/gpoigdifkoadgajcincpilkjmejcaanc?utm_source=chrome-app-launcher-info-dialog).
5 | Present with [Markdown Slides Plugin for Chrome](https://chrome.google.com/webstore/detail/markdown-slides/ndpkdbdonkcnidnnmdgphflfcojnhoaa?utm_source=chrome-app-launcher-info-dialog).
6 |
7 | ---
8 | # Peer-to-peer Insurance
9 |
10 | > The aim of peer-to-peer insurance concepts is to make insurance cheaper. For this purpose, a certain number of policyholders pool together. In the event of any claim they support each other financially. If there is no claim, the insurance premiums are reduced.
11 | There are many types of peer-to-peer insurance. This article describes peer-to-peer insurance in the form of the creation of insurance brokers (as opposed to insurance companies). In this model, insurance policyholders will form small groups online. A part of the insurance premiums paid flow into a group fund, the other part to the insurer. Minor damages to the insured policyholder are firstly paid out of this group fund. For claims above the deductible limit the regular insurer is called upon. When there is no insurance claim, the policyholder gets his/her share refunded from the group pool or credited towards the next policy year. If the group pool happens to be empty, a special insurance comes into force.
12 |
13 | https://en.wikipedia.org/wiki/Peer-to-peer_insurance
14 |
15 | ---
16 | # Problem
17 |
18 | * Groups of people would like to insure themselves against risks not commonly insured such as ones in sports, travel, farming, small business.
19 | * The insured would like to simplify and automate the process of claiming and getting paid, especially when the insurance event is a matter of public record such as a delayed flight or a weather condition.
20 | * Insurance companies would like to find new revenue streams covering _long tail_ risks but not take the burden of processing small claims.
21 |
22 | ---
23 | # Solution
24 |
25 | * Permissioned Blockchain
26 | * immutable ledger
27 | * very low cost of deployment and maintenance
28 | * fully transparent to instill trust in consumers
29 | * identity obfuscated to other members
30 |
31 | * Chaincode
32 | * software executed on the blockchain trusted to change records in the ledger
33 | * automate payouts thru integration with systems of public record and payment
34 | * members execute chaincode functions based on their roles
35 |
36 | ---
37 | # Optimization of Insurance Premium
38 |
39 | In an ideal situation the sum of all premiums paid to the p2p insurance pool should equal the sum of all claim payouts. However, the number of claims is initially unknown and varies from year to year. A simple optimization mechanism is proposed where the premium is adjusted every year depending on the sum of payouts the previous year. If there's not enough money in the pool to pay for all claims the pool's insurer steps in and covers the difference.
40 |
41 | * if there's money left in the pool at the end of the year
42 | * the premium for the next year is reduced by a fraction of the remainder
43 | * the remainder is divided and paid back to the members
44 | * if claim payouts exceed the money in the pool
45 | * the premium for the next year is increased by a fraction of the difference between payouts and premiums
46 | * the pool's insurer pays the coverage amounts of the claims not paid by the pool
47 |
48 | ---
49 | # Money
50 |
51 | Users can pay for the insurance and get compensated via various mechanisms each having its pros and cons:
52 |
53 | * coins: tokens unique for this blockchain. Coins move between accounts representing payments. When users register in the system they convert fiat money to coins via a payment system such as credit card, bank transfer or PayPal. They can also withdraw: convert their coins back to fiat money.
54 | * _pros_ easy to develop
55 | * _cons_ for deposit and withdrawal the pool requires an account with a payment system and thus needs an operator registered as a legal entity
56 | * cryptocurrency: the chaincode can invoke gateways to popular cryptocurrency chains such as Bitcoin or Ethereum. These calls can be made within the same transaction and don't involve payment systems.
57 | * _pros_ does not require a pool operator as a legal entity with a bank account
58 | * _cons_ users may not have accounts in cryptocurrencies
59 |
60 | ---
61 |
62 | * payment oracle: fiat money is transferred outside of the blockchain by payment systems such as ACH for bank transfers, Stripe for credit cards or PayPal. Clients of these systems are trusted by the users and inform the blockchain of fiat money transferred between users' accounts.
63 | * _pros_ little friction with familiar payments: users provide their credit cards or bank accounts or PayPal
64 | * _cons_ requires an account with a payment system and thus needs an operator registered as a legal entity
65 |
66 | We choose the _payment oracle_ mechanism for this POC.
67 |
68 | ---
69 | # Records
70 |
71 | Records are stored on the blockchain either as the chaincode's key value sets or tables.
72 |
73 | * Pool
74 | insurance pool is policy created by members
75 |
76 | * MemberPool
77 | members may enter many pools so the many-to-many relationship is maintained in a separate table
78 |
79 | ---
80 | # Actors
81 |
82 | Actors are users of various roles in the system. Their ids and roles are defined in the blockchain's member services records. Other attributes may also be defined in the member services or on the blockchain or in a separate persistence store. For the POC it's sufficient to predefine a set of users with all of their attributes in the member services `yaml` files.
83 |
84 | * Member
85 | person organizing and entering insurance pools
86 |
87 | * Insurer
88 | insurance company insuring risks exceeding capacity of the pool
89 |
90 | ---
91 | # Oracles
92 |
93 | *Oracle* is a mechanism to inject events occurring outside of the blockchain. It is a third party agreed to be trusted by all members and operates as a node on the blockchain with special permissions to the chaincode methods.
94 |
95 | * Claim Oracle
96 | notifies the blockchain that a claim condition is triggered
97 | _example_ a public weather service reports no wind. Organizers of a yacht regatta insured themselves against this condition; their claim is processed automatically and they get paid right away to spend on a champaign and lobster lunch for sailors onshore.
98 | _example_ a flight tracking service reports a delayed flight. A traveller insured himself against this condition; his claim gets processed automatically and he spends the payout on a night in a hotel.
99 |
100 | ---
101 |
102 | _example_ a small crops farmer plants an internet connected moisture sensor, one per acre of his land. When the sensor reports low levels for 30 consecutive days a drought condition is triggered and the farmer gets paid automatically
103 | _example_ a hotelier in a developing country insured himself against a power blackout. When a smart electricity meter reports an outage the hotelier gets paid right away to spend on diesel for the hotel's generator to provide uninterrupted power for his guests.
104 |
105 | ---
106 |
107 | * Payment Oracle
108 | notifies the blockchain that a transfer of fiat money occurred between members' accounts. Can be a client listening on events in a payment system such as ACH network, Stripe, PayPal.
109 | _example_ an ACH client permissioned by the insurance pool operator to listen on events in their accounts payable.
110 | Calls the chaincode method to notify the blockchain that a payment of a claim to the insured occurred. The chaincode decrements the size of the pool and adds a record of the claim to the transaction history.
111 | _example_ an ACH client permissioned by the pool operator to listen on events in their accounts receivable.
112 | Notifies the blockchain of payment of a premium from a member. The chaincode increments the size of the pool and adds a record of the payment the to transaction history.
113 |
114 | ---
115 | # Member
116 |
117 | Both roles: members and insurers have these attributes.
118 |
119 | - id
120 | unique id chosen by members
121 | _example_ manuel, vladimir, Allianz
122 | - password
123 | a secret needs to be passed to the blockchain's member services to authenticate the member to transact
124 | - paymentAccount
125 | various payment oracles will identify members by accounts in respective payment systems
126 | - aba.account
127 | composite unique identifier of the member's fiat money bank account used by a bank transfer ACH oracle. When a payment of fiat money occurs the payment oracle will report to the blockchain a money transfer event with parties' bank aba and account numbers.
128 | aba: member bank identifier, account: member bank account identifier
129 | - paypalEmail
130 | for pools selecting PayPal as their payment mechanism
131 |
132 | ---
133 | # Pool
134 |
135 | - id
136 | sequential identifier unique within the chaincode
137 | - name
138 | descriptive name
139 | _example_ JFK flight delay
140 | - trigger
141 | a condition reported by claim oracle or approved by a claims processor that triggers a payout to the insured
142 | _example_ 1 hour delay of Jet Blue flight 101 on Jun 10 2016: a delay in flight departure making it impossible to board the next flight in a specific itinerary
143 | _example_ dryness level over 70% for 30 consecutive days in Arizona: indicates a drought condition
144 | - coverage
145 | amount paid to the insured per claim
146 | _example_ $300 per flight delayed
147 | _example_ $1,000 per acre of farm land affected by drought
148 |
149 | ---
150 |
151 | - premium
152 | one time or yearly payment by each member into the pool
153 | _example_ one time $10 fee insuring a traveller against a flight delayed in his specific itinerary
154 | _example_ yearly $100 fee per acre a small crops farmer pays insuring against drought
155 | - amount
156 | current total amount held in the pool
157 | - insurerId
158 | member id of the insurance company covering payouts exceeding pool's capacity. Initially not set until an insurer decides to insure the pool
159 | _example_ Allianz
160 | - insurerPremium
161 | part of the premium paid to the insurance company to insure claims exceeding pool's capacity
162 | _example_ $10 of the $100 member premium
163 |
164 | ---
165 | # Web Application
166 |
167 | The POC is presented as a web application with pages offering functionality to
168 | * Members: create and enter pools
169 | * Insurers: select pools to insure
170 |
171 | The following sections describe these pages per actor.
172 |
173 | ---
174 | # Member: Enter Pool
175 |
176 | A public page listing available insurance pools.
177 |
178 | name | trigger | coverage | premium | |
179 | ---|---|---|---|---
180 | Drought Arizona | 30 days dryness over 70%, per acre in Arizona in 2016 | $1000 | $100 | enter / insure
181 | JFK flight delay | flight out of JFK delayed over 1 hour in June 2016 | $200 | $10 | enter / insure
182 | No wind Long Island Regatta | wind below 5 knots June 10 2016 in Long Island Sound | $2000 | $100 | enter / insure
183 |
184 | When a user clicks _enter_ to select a pool a modal confirmation window comes up prompting to agree to terms and enter the pool.
185 |
186 | https://boughtbymany.com is a p2p insurance broker. Their home page serves as a good example.
187 |
188 | For the POC, the user is assumed to be logged in to the web site; otherwise the user is asked to login or create an account.
189 |
190 | ---
191 | # Member: Create Pool
192 |
193 | When a _Create Pool_ button is clicked on the public page a modal window comes up where the user can enter details of a new pool and propose it to other users.
194 |
195 | CREATE | Pool
196 | ---|---
197 | name | Drought Arizona
198 | trigger | (dropdown of conditions: `Drought Arizona 2016`, `JFK flight delay Jun 2016`)
199 | coverage | $1000
200 | premium | $100
201 |
202 | When _Create_ button is clicked a method of the chaincode is called to create a record of the new pool and a record in member-pool table with the creator as its first member.
203 |
204 | The pool appears on the Pools public page for other members to enter and for insurers to select to insure.
205 |
206 | ---
207 | # Insurer: Insure Pool
208 |
209 | A representative of an insurance company selects a pool the company finds profitable to insure. In the real world multiple insurance companies bid on a pool and the chaincode selects the one with better terms. For the POC the scenario is simplified.
210 |
211 | When _insure_ link is clicked on a row on the public Pools page a modal window comes up prompting the insurer to enter their terms to insure this pool.
212 |
213 | INSURE | Pool
214 | ---|---
215 | premium | $10
216 |
217 | When _Insure_ button is clicked a method of the chaincode is called to add the insurer to the record of the selected pool.
218 |
219 | ---
220 | # Payment Oracle
221 |
222 | For the POC this will be a simple demo page imitating a call from an ACH client informing the blockchain of a money transfer for a premium payment to the pool or a claim payout to member.
223 |
224 | TRANSFER | Money |
225 | ---|---
226 | from aba.account | 02100210.12345678
227 | to aba.account | 03200320.09876543
228 | amount | $500
229 | purpose | (dropdown of premium, insurerPremium, payout)
230 | id | id of pool, insurer or member
231 |
232 | Once the _Transfer_ button is clicked the chaincode's method is invoked with the transfer details entered. The chaincode in turn finds the pool by id and verifies parties of the transfer.
233 |
234 | ---
235 | # Claim Oracle
236 |
237 | For the POC this will be a simple demo page imitating a call from a public service client informing the blockchain of an insurance event.
238 |
239 | TRIGGER | Event |
240 | ---|---
241 | select | (dropdown of `Drought Arizona 2016`, `JFK flight delay Jun 2016`)
242 |
243 | Once the _Trigger_ button is clicked the chaincode's method is invoked to search for all pools whose trigger matches the one selected and marks them as needed to pay their members.
244 |
245 | ---
246 | # Timing Mechanism
247 |
248 | A mechanism: either an oracle or a service offered by the blockchain is to inform the chaincode of progression of time.
249 |
250 | For the POC that service can be imitated by an interval service of a browser calling the chaincode's method to progress time and at the same time displaying current month and year on every page. The progression of time in the demo needs to be accelerated so a month is changed every minute, and controlled via _start_ and _stop_ buttons.
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
--------------------------------------------------------------------------------