Skip to content

Commit

Permalink
FAB-11723 Developing Apps: Sample pt 1 -- contract
Browse files Browse the repository at this point in the history
Change-Id: Ia61aae9b83c3297dfe28fd475c585e021186a4aa
Signed-off-by: Anthony O'Dowd <a_o-dowd@uk.ibm.com>
  • Loading branch information
ODOWDAIBM committed Sep 5, 2018
1 parent bfdc0b6 commit d776651
Show file tree
Hide file tree
Showing 10 changed files with 523 additions and 0 deletions.
16 changes: 16 additions & 0 deletions commercial-paper/contract/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#
# SPDX-License-Identifier: Apache-2.0
#

root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
5 changes: 5 additions & 0 deletions commercial-paper/contract/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#
# SPDX-License-Identifier: Apache-2.0
#

coverage
37 changes: 37 additions & 0 deletions commercial-paper/contract/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
SPDX-License-Identifier: Apache-2.0
*/

module.exports = {
env: {
node: true,
mocha: true
},
parserOptions: {
ecmaVersion: 8,
sourceType: 'script'
},
extends: "eslint:recommended",
rules: {
indent: ['error', 4],
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'single'],
semi: ['error', 'always'],
'no-unused-vars': ['error', { args: 'none' }],
'no-console': 'off',
curly: 'error',
eqeqeq: 'error',
'no-throw-literal': 'error',
strict: 'error',
'no-var': 'error',
'dot-notation': 'error',
'no-tabs': 'error',
'no-trailing-spaces': 'error',
'no-use-before-define': 'error',
'no-useless-call': 'error',
'no-with': 'error',
'operator-linebreak': 'error',
yoda: 'error',
'quote-props': ['error', 'as-needed']
}
};
77 changes: 77 additions & 0 deletions commercial-paper/contract/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#
# SPDX-License-Identifier: Apache-2.0
#

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# 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

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

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

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# parcel-bundler cache (https://parceljs.org/)
.cache

# next.js build output
.next

# nuxt.js build output
.nuxt

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless
7 changes: 7 additions & 0 deletions commercial-paper/contract/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
SPDX-License-Identifier: Apache-2.0
*/

'use strict';

module.exports.contracts = require('./lib/cpcontract.js');
113 changes: 113 additions & 0 deletions commercial-paper/contract/lib/cpcontract.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
SPDX-License-Identifier: Apache-2.0
*/

'use strict';

// Smart contract API brought into scope
const {Contract} = require('fabric-contract-api');

// Commercial paper classes brought into scope
const {CommercialPaper, CommercialPaperList} = require('./cpstate.js');

/**
* Define the commercial paper smart contract extending Fabric Contract class
*/
class CommercialPaperContract extends Contract {

/**
* Each smart contract can have a unique namespace; useful when multiple
* smart contracts per file.
* Use transaction context (ctx) to access list of all commercial papers.
*/
constructor() {
super('org.papernet.commercialpaper');

this.setBeforeFn = (ctx)=>{
ctx.cpList = new CommercialPaperList(ctx, 'COMMERCIALPAPER');
return ctx;
};
}

/**
* Issue commercial paper
* @param {TxContext} ctx the transaction context
* @param {String} issuer commercial paper issuer
* @param {Integer} paperNumber paper number for this issuer
* @param {String} issueDateTime paper issue date
* @param {String} maturityDateTime paper maturity date
* @param {Integer} faceValue face value of paper
*/
async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) {

let cp = new CommercialPaper(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue);

// {issuer:"MagnetoCorp", paperNumber:"00001", "May31 2020", "Nov 30 2020", "5M USD"}

await ctx.cpList.addPaper(cp);
}

/**
* Buy commercial paper
* @param {TxContext} ctx the transaction context
* @param {String} issuer commercial paper issuer
* @param {Integer} paperNumber paper number for this issuer
* @param {String} currentOwner current owner of paper
* @param {String} newOwner new owner of paper
* @param {Integer} price price paid for this paper
* @param {String} purchaseDateTime time paper was purchased (i.e. traded)
*/
async buy(ctx, issuer, paperNumber, currentOwner, newOwner, price, purchaseDateTime) {

let cpKey = CommercialPaper.createKey(issuer, paperNumber);
let cp = await ctx.cpList.getPaper(cpKey);

if (cp.getOwner() !== currentOwner) {
throw new Error('Paper '+issuer+paperNumber+' is not owned by '+currentOwner);
}
// First buy moves state from ISSUED to TRADING
if (cp.isIssued()) {
cp.setTrading();
}
// Check paper is TRADING, not REDEEMED
if (cp.IsTrading()) {
cp.setOwner(newOwner);
} else {
throw new Error('Paper '+issuer+paperNumber+' is not trading. Current state = '+cp.getCurrentState());
}

await ctx.cpList.updatePaper(cp);
}

/**
* Redeem commercial paper
* @param {TxContext} ctx the transaction context
* @param {String} issuer commercial paper issuer
* @param {Integer} paperNumber paper number for this issuer
* @param {String} redeemingOwner redeeming owner of paper
* @param {String} redeemDateTime time paper was redeemed
*/
async redeem(ctx, issuer, paperNumber, redeemingOwner, redeemDateTime) {

let cpKey = CommercialPaper.createKey(issuer, paperNumber);
let cp = await ctx.cpList.getPaper(cpKey);

// Check paper is TRADING, not REDEEMED
if (cp.IsRedeemed()) {
throw new Error('Paper '+issuer+paperNumber+' already redeemed');
}

// Verify that the redeemer owns the commercial paper before redeeming it
if (cp.getOwner() === redeemingOwner) {
cp.setOwner(cp.getIssuer());
cp.setRedeemed();
} else {
throw new Error('Redeeming owner does not own paper'+issuer+paperNumber);
}

await ctx.cpList.updatePaper(cp);
}

}

module.exports = CommericalPaperContract;
Loading

0 comments on commit d776651

Please sign in to comment.