Skip to content

Commit

Permalink
Initial commit of the Loyalty Points Hyperledger Blockchain Network.
Browse files Browse the repository at this point in the history
  • Loading branch information
tyrell committed Dec 20, 2017
0 parents commit d4e01d4
Show file tree
Hide file tree
Showing 9 changed files with 392 additions and 0 deletions.
49 changes: 49 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Logs
logs
composer-logs
*.log
npm-debug.log*

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules
jspm_packages

# Optional npm cache directory
.npm

# Optional REPL history
.node_repl_history

# JSDoc
out

# Mac files.
**/.DS_Store

*.swp

# Build generated files should be ignored by git, but not by npm.
dist
13 changes: 13 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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.
*/
78 changes: 78 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Loyalty Network

> The Loyalty Network allows partners and members to transact using points earning offers. Members shop with the Partner businesses and will earn points for their loyalty. Members can then redem these points when Partner businesses off ponts redemption offers. The points are carried and tracked in a membership card.
This business network defines:

**Participants**
`Partner` `Member`

**Assets**
`Card` `Offer`

**Transactions**
`IssuePoints` `RedeemPoints`

The `IssuePoints` transaction between a `Member` and a `Partner` will add points to the `Member`'s `Card` as specified in the `Offer`.

The `RedeemPoints` transaction between a `Member` and a `Partner` will reduce points in the `Member`'s `Card` as specified in the `Offer`.

To test this Business Network Definition in the **Test** tab:

Create a `Member` participant:

```
{
"$class": "co.tyrell.loyalty.Member",
"email": "life@mars.com",
"firstName": "John",ß
"lastName": "Doe",
"dateOfBirth": "01-11-1975"
}
```

Create a `Partner` participant:

```
{
"$class": "co.tyrell.loyalty.Partner",
"partnerId": "4514",
"partnerName": "Coles Supermarkets"
}
```

Create a `Card` asset using the above new `Member`'s email as the id:

```
{
"$class": "co.tyrell.loyalty.Card",
"cardNumber": "8623",
"pointBalance": 0,
"owner": "resource:co.tyrell.loyalty.Member#life@mars.com"
}
```

Create a `Offer` asset using the above new `Partner`'s partnerId as the id and pointsAmount set to 1:

```
{
"$class": "co.tyrell.loyalty.Offer",
"offerId": "3832",
"pointsAmount": 1,
"partner": "resource:co.tyrell.loyalty.Partner#4514"
}
```

Submit a `IssuePoints` transaction using the offerId from the above new `Offer` and cardNumber from the above new `Card`:

```
{
"$class": "co.tyrell.loyalty.IssuePoints",
"pointsOffer": "resource:co.tyrell.loyalty.Offer#3832",
"receivingCard": "resource:co.tyrell.loyalty.Card#8623"
}
```

The `IssuePoints` transaction above will increase the pointBalance of the `Member`'s `Card` by 1 in the Asset Registry.

Congratulations!
2 changes: 2 additions & 0 deletions create-bna-file.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
composer archive create --sourceType dir --sourceName . -a ./dist/loyalty-network.bna
64 changes: 64 additions & 0 deletions lib/logic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* This file contains the javascript logic required to carry out transactions in our network. The transaction
* logic is automatically invoked by the runtime whenever the relevant transactions are submitted.
*
* Reference: https://hyperledger.github.io/composer/reference/js_scripts.html
*
* @author Tyrell Perera
*
*/


/**
* Issue points to a member.
* @param {co.tyrell.loyalty.IssuePoints} issuePointsTransaction - the points issuing transaction
* @transaction
*/
function issuePoints(issuePointsTransaction) {

// Increase the member's point balance
issuePointsTransaction.receivingCard.pointBalance += issuePointsTransaction.pointsOffer.pointsAmount;

// Create an IssuePointsEvent
var issuePointsEvent = getFactory().newEvent('co.tyrell.loyalty', 'IssuePointsEvent');
issuePointsEvent.receivingCard = issuePointsTransaction.receivingCard;
issuePointsEvent.pointsOffer = issuePointsTransaction.pointsOffer;

// Commit changes to the network
return getAssetRegistry('co.tyrell.loyalty.Card')
.then(function (cardRegistry) {
return cardRegistry.update(issuePointsTransaction.receivingCard);
}).then(function (receivingCard) {
// Emit the point issue event to the network.
emit(issuePointsEvent);
});
}

/**
* Redeem points by a member.
* @param {co.tyrell.loyalty.RedeemPoints} redeemPointsTransaction - the points redemption transaction
* @transaction
*/
function redeemPoints(redeemPointsTransaction) {

// Reduce the amount of points from the member's card if the card has enough points to redeeem the offer.
if (redeemPointsTransaction.redeemingCard.pointBalance >= redeemPointsTransaction.redemptionOffer.pointsAmount) {
redeemPointsTransaction.redeemingCard.pointBalance -= redeemPointsTransaction.redemptionOffer.pointsAmount;
} else {
throw new Error('Insufficient points balance to redeem this offer.');
}

// Create a RedeemPointsEvent
var redeemPointsEvent = getFactory().newEvent('co.tyrell.loyalty', 'RedeemPointsEvent');
redeemPointsEvent.redeemingCard = redeemPointsTransaction.redeemingCard;
redeemPointsEvent.redemptionOffer = redeemPointsTransaction.redemptionOffer;

// Commit changes to the network
return getAssetRegistry('co.tyrell.loyalty.Card')
.then(function (cardRegistry) {
return cardRegistry.update(redeemPointsTransaction.redeemingCard);
}).then(function (redeemingCard) {
// Emit the point redemption event to the network.
emit(redeemPointsEvent);
});
}
54 changes: 54 additions & 0 deletions models/loyalty.cto
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
This is the data model definition for our loyalty points network. The model is devleoped using the Hyperledger Composer Modeling Language.

Modeliing Language Reference: https://hyperledger.github.io/composer/reference/cto_language.html

@author Tyrell Perera
*/

namespace co.tyrell.loyalty

asset Card identified by cardNumber {
o String cardNumber
o Double pointBalance
--> Member owner
}

asset Offer identified by offerId {
o String offerId
o Double pointsAmount
--> Partner partner
}

participant Member identified by email {
o String email
o String firstName
o String lastName
o String dateOfBirth
}

participant Partner identified by partnerId {
o String partnerId
o String partnerName
}

transaction IssuePoints {
--> Offer pointsOffer
--> Card receivingCard
}

event IssuePointsEvent {
--> Offer pointsOffer
--> Card receivingCard
}

transaction RedeemPoints {
--> Offer redemptionOffer
--> Card redeemingCard
}

event RedeemPointsEvent{
--> Offer redemptionOffer
--> Card redeemingCard
}

62 changes: 62 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"engines": {
"composer": "^0.16.0"
},
"name": "loyalty-points-network",
"version": "0.1",
"description": "This is a business network for loyalty points.",
"networkImage": "https://hyperledger.github.io/composer-sample-networks/packages/bond-network/networkimage.svg",
"networkImageanimated": "https://hyperledger.github.io/composer-sample-networks/packages/bond-network/networkimageanimated.svg",
"scripts": {
"prepublish": "mkdirp ./dist && composer archive create --sourceType dir --sourceName . -a ./dist/loyalty-network.bna",
"pretest": "npm run lint",
"lint": "eslint .",
"postlint": "npm run licchk",
"licchk": "license-check",
"postlicchk": "npm run doc",
"doc": "jsdoc --pedantic --recurse -c jsdoc.json",
"test": "mocha -t 0 --recursive",
"deploy": "./scripts/deploy.sh"
},
"repository": {
"type": "git",
"url": "https://github.com/hyperledger/composer-sample-networks.git"
},
"keywords": [
"loyalty points",
"reference data",
"finance",
"composer",
"composer-network"
],
"author": "Tyrell Perera",
"license": "Apache-2.0",
"devDependencies": {
"chai": "^3.5.0",
"composer-admin": "^0.16.0",
"composer-cli": "^0.16.0",
"composer-client": "^0.16.0",
"composer-common": "^0.16.0",
"composer-connector-embedded": "^0.16.0",
"eslint": "^3.6.1",
"istanbul": "^0.4.5",
"jsdoc": "^3.5.5",
"license-check": "^1.1.5",
"mkdirp": "^0.5.1",
"mocha": "^3.2.0",
"moment": "^2.17.1"
},
"license-check-config": {
"src": [
"**/*.js",
"!./coverage/**/*",
"!./node_modules/**/*",
"!./out/**/*",
"!./scripts/**/*"
],
"path": "header.txt",
"blocking": true,
"logInfo": false,
"logError": true
}
}
52 changes: 52 additions & 0 deletions permissions.acl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Access Control List for the loyalty data
*/
rule OfferAllPartner {
description: "Allow full access for the participating partner to their offers"
participant(i): "co.tyrell.loyalty.Partner"
operation: ALL
resource(a): "co.tyrell.loyalty.Offer"
condition: (a.partner.partnerId === i.partnerId)
action: ALLOW
}

rule CardReadMember {
description: "Allow read access for a member to their card details"
participant(i): "co.tyrell.loyalty.Member"
operation: READ
resource(a): "co.tyrell.loyalty.Card"
condition: (a.owner.email === i.email)
action: ALLOW
}

rule OfferReadAll {
description: "Allow read access to all offers to everyone in the loyalty network"
participant: "co.tyrell.loyalty.*"
operation: READ
resource: "co.tyrell.loyalty.Offer"
action: ALLOW
}

rule SystemACL {
description: "System ACL to permit all access"
participant: "org.hyperledger.composer.system.Participant"
operation: ALL
resource: "org.hyperledger.composer.system.**"
action: ALLOW
}

rule NetworkAdminUser {
description: "Grant business network administrators full access to user resources"
participant: "org.hyperledger.composer.system.NetworkAdmin"
operation: ALL
resource: "**"
action: ALLOW
}

rule NetworkAdminSystem {
description: "Grant business network administrators full access to system resources"
participant: "org.hyperledger.composer.system.NetworkAdmin"
operation: ALL
resource: "org.hyperledger.composer.system.**"
action: ALLOW
}
Loading

0 comments on commit d4e01d4

Please sign in to comment.