Skip to content

Commit 034dea5

Browse files
committed
feature: add initial chaincode
0 parents  commit 034dea5

File tree

9 files changed

+4668
-0
lines changed

9 files changed

+4668
-0
lines changed

.eslintignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
5+
coverage

.eslintrc.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*/
4+
5+
module.exports = {
6+
env: {
7+
node: true,
8+
mocha: true,
9+
es6: true
10+
},
11+
parserOptions: {
12+
ecmaVersion: 8,
13+
sourceType: 'script'
14+
},
15+
extends: "eslint:recommended",
16+
rules: {
17+
indent: ['error', 4],
18+
'linebreak-style': ['error', 'unix'],
19+
quotes: ['error', 'single'],
20+
semi: ['error', 'always'],
21+
'no-unused-vars': ['error', { args: 'none' }],
22+
'no-console': 'off',
23+
curly: 'error',
24+
eqeqeq: 'error',
25+
'no-throw-literal': 'error',
26+
strict: 'error',
27+
'no-var': 'error',
28+
'dot-notation': 'error',
29+
'no-tabs': 'error',
30+
'no-trailing-spaces': 'error',
31+
'no-use-before-define': 'error',
32+
'no-useless-call': 'error',
33+
'no-with': 'error',
34+
'operator-linebreak': 'error',
35+
yoda: 'error',
36+
'quote-props': ['error', 'as-needed'],
37+
'no-constant-condition': ["error", { "checkLoops": false }]
38+
}
39+
};

.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
5+
# Coverage directory used by tools like istanbul
6+
coverage
7+
8+
# Report cache used by istanbul
9+
.nyc_output
10+
11+
# Dependency directories
12+
node_modules/
13+
jspm_packages/
14+
15+
package-lock.json
16+
17+
# zip
18+
chaincode-javascript.zip

index.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright IBM Corp. All Rights Reserved.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
'use strict';
8+
9+
const propertyAsset = require('./lib/propertyAsset');
10+
11+
module.exports.PropertyAsset = propertyAsset;
12+
module.exports.contracts = [propertyAsset];

lib/propertyAsset.js

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
* Copyright IBM Corp. All Rights Reserved.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
'use strict';
8+
9+
// Deterministic JSON.stringify()
10+
const stringify = require('json-stringify-deterministic');
11+
const sortKeysRecursive = require('sort-keys-recursive');
12+
const { Contract } = require('fabric-contract-api');
13+
const { v4: uuidv4 } = require('uuid');
14+
15+
class PropertyAsset extends Contract {
16+
// Initialize Ledger
17+
async InitLedger(ctx) {
18+
// Create property IDs first
19+
const property1Id = uuidv4();
20+
const property2Id = uuidv4();
21+
const property3Id = uuidv4();
22+
23+
const assets = [
24+
{
25+
PropertyID: property1Id,
26+
Name: 'Asset One',
27+
Quantity: 100,
28+
Price: 299.99,
29+
Image: 'asset1.jpg',
30+
},
31+
{
32+
PropertyID: property1Id,
33+
Name: 'Asset Two',
34+
Quantity: 50,
35+
Price: 499.99,
36+
Image: 'asset2.jpg',
37+
},
38+
{
39+
PropertyID: property2Id,
40+
Name: 'Asset Three',
41+
Quantity: 75,
42+
Price: 199.99,
43+
Image: 'asset3.jpg',
44+
},
45+
{
46+
PropertyID: property2Id,
47+
Name: 'Asset Four',
48+
Quantity: 200,
49+
Price: 399.99,
50+
Image: 'asset4.jpg',
51+
},
52+
{
53+
PropertyID: property3Id,
54+
Name: 'Asset Five',
55+
Quantity: 150,
56+
Price: 599.99,
57+
Image: 'asset5.jpg',
58+
},
59+
{
60+
PropertyID: property3Id,
61+
Name: 'Asset Six',
62+
Quantity: 80,
63+
Price: 699.99,
64+
Image: 'asset6.jpg',
65+
},
66+
];
67+
68+
for (const asset of assets) {
69+
const id = uuidv4();
70+
asset.ID = id;
71+
asset.docType = 'asset';
72+
asset.CreatedAt = new Date().toISOString();
73+
74+
await ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(asset))));
75+
}
76+
}
77+
78+
// Asset CRUD Operations
79+
// ====================================
80+
81+
async CreateAsset(ctx, propertyId, name, quantity, price, image) {
82+
const id = uuidv4();
83+
const exists = await this.AssetExists(ctx, id);
84+
if (exists) {
85+
throw new Error(`The asset ${id} already exists`);
86+
}
87+
88+
const asset = {
89+
ID: id,
90+
PropertyID: propertyId,
91+
Name: name,
92+
Quantity: parseInt(quantity),
93+
Price: parseFloat(price),
94+
Image: image,
95+
docType: 'asset',
96+
CreatedAt: new Date().toISOString(),
97+
};
98+
99+
await ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(asset))));
100+
return JSON.stringify(asset);
101+
}
102+
103+
async ReadAsset(ctx, id) {
104+
const assetJSON = await ctx.stub.getState(id);
105+
if (!assetJSON || assetJSON.length === 0) {
106+
throw new Error(`The asset ${id} does not exist`);
107+
}
108+
return assetJSON.toString();
109+
}
110+
111+
async UpdateAsset(ctx, id, propertyId, name, quantity, price, image) {
112+
const exists = await this.AssetExists(ctx, id);
113+
if (!exists) {
114+
throw new Error(`The asset ${id} does not exist`);
115+
}
116+
117+
const updatedAsset = {
118+
ID: id,
119+
PropertyID: propertyId,
120+
Name: name,
121+
Quantity: parseInt(quantity),
122+
Price: parseFloat(price),
123+
Image: image,
124+
docType: 'asset',
125+
UpdatedAt: new Date().toISOString(),
126+
};
127+
128+
await ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(updatedAsset))));
129+
return JSON.stringify(updatedAsset);
130+
}
131+
132+
async DeleteAsset(ctx, id) {
133+
const exists = await this.AssetExists(ctx, id);
134+
if (!exists) {
135+
throw new Error(`The asset ${id} does not exist`);
136+
}
137+
return ctx.stub.deleteState(id);
138+
}
139+
140+
// Query Operations
141+
// ====================================
142+
143+
async GetAllAssets(ctx, propertyId) {
144+
const allResults = [];
145+
const iterator = await ctx.stub.getStateByRange('', '');
146+
let result = await iterator.next();
147+
while (!result.done) {
148+
const strValue = Buffer.from(result.value.value.toString()).toString('utf8');
149+
let record;
150+
try {
151+
record = JSON.parse(strValue);
152+
// Only add records that match the propertyId
153+
if (propertyId && record.PropertyID === propertyId) {
154+
allResults.push(record);
155+
} else if (!propertyId) {
156+
// If no propertyId is provided, return all assets
157+
allResults.push(record);
158+
}
159+
} catch (err) {
160+
console.log(err);
161+
record = strValue;
162+
}
163+
result = await iterator.next();
164+
}
165+
return JSON.stringify(allResults);
166+
}
167+
168+
// Helper Methods
169+
// ====================================
170+
171+
async AssetExists(ctx, id) {
172+
const assetJSON = await ctx.stub.getState(id);
173+
return assetJSON && assetJSON.length > 0;
174+
}
175+
}
176+
177+
module.exports = PropertyAsset;

0 commit comments

Comments
 (0)