- Sample bank application to test the TIC deployment

- Refer README for more instructions
parent 7f5dccf3
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# 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
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://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/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Reference : https://github.com/mhart/alpine-node#example-dockerfile-for-your-own-nodejs-project
# This stage installs our modules
FROM mhart/alpine-node:12
LABEL stage=bank-app-stage1-docker-builder
WORKDIR /app
COPY package.json package-lock.json ./
# If you have native dependencies, you'll need extra tools
# RUN apk add --no-cache make gcc g++ python3
RUN apk add --no-cache make g++ python3
RUN npm ci --prod
# Then we copy over the modules from above onto a `slim` image
FROM mhart/alpine-node:slim-12
LABEL stage=bank-app-stage2-docker-builder
# If possible, run your container using `docker run --init`
# Otherwise, you can use `tini`:
# RUN apk add --no-cache tini
# ENTRYPOINT ["/sbin/tini", "--"]
WORKDIR /app
COPY --from=0 /app .
COPY . .
EXPOSE 3000
CMD [ "node", "app.js" ]
This diff is collapsed.
# Articonf bank Node App
# Requirements
1. Bityoga fabric sdk should be up and running
2. Node version
- Supports node version >=v11.0.0
- Tested with v11.0.0
# Run Instructions
1. ## Clone this repository
- git clone https://github.com/bityoga/articonf-bank-app.git
2. ## Run npm install
- cd articonf-bank-app/
- #### Set node version
- nvm use node v11.Updated REAdm0.0 (using nvm)
- **Execute Command :** npm install
3. ## Update fabric ip address in 'articonf-bank-app/fabric_node_sdk_helper/network_profile.json'
- (For other New App Developers) fabric_node_sdk_helper is available in git repository : https://github.com/bityoga/fabric_node_sdk_helper.git
- **update the url ip addresses of orderer, peer2, orgca, tlsca (4 places)**.
- update it with your prime manager's ip address
4. ## Retrieve hyperledger fabric tls certificates of 'orderer' and 'peer2'
#### Through shell script - needs ssh permission
- cd articonf-bank-app/fabric_node_sdk_helper
- In 'articonf-bank-app/fabric_node_sdk_helper/get_tls_certificates.sh' Replace **IP_ADDRESS="178.62.207.235"** with your fabric prime manager's ip address
- **Execute Command :** bash get_tls_certificates.sh
#### (OR) Through Manual scp commands - needs ssh permission
- Replace ipaddress in the below scp commands with your fabric prime manager's ip address.
- scp -r root@178.62.207.235:/root/hlft-store/orderer/tls-msp/tlscacerts/tls-tlsca-7054.pem .articonf-bank-app/fabric_node_sdk_helper/hlft-store/orderer/tls-msp/tlscacerts/tls-tlsca-7054.pem
- scp -r root@178.62.207.235:/root/hlft-store/peer2/tls-msp/tlscacerts/tls-tlsca-7054.pem .articonf-bank-app/fabric_node_sdk_helper/hlft-store/peer2/tls-msp/tlscacerts/tls-tlsca-7054.pem
#### (OR) Manually edit the following two files - no need of ssh permission
- articonf-bank-app/fabric_node_sdk_helper/hlft-store/orderer/tls-msp/tlscacerts/tls-tlsca-7054.pem
- articonf-bank-app/fabric_node_sdk_helper/hlft-store/peer2/tls-msp/tlscacerts/tls-tlsca-7054.pem
5. ## Start App
- cd articonf-bank-app/
- **Execute Command :** node app.js
- app will be running in 'localhost' at port 3000
- open in browser: http://localhost:3000/
## Dockerisation
### 1) Build Docker Image
```sh
$ git clone https://github.com/bityoga/articonf-bank-app.git
$ cd articonf-bank-app
```
Do step 3 & 4 as said above
```sh
$ docker build --tag bank-app .
```
### 2a) Run as a docker container
```sh
$ docker run -d --name bank-app -p 3000:3000 bank-app:latest
```
### 2b) Run as a docker service with replicas
```sh
$ docker service create --name bank-service --replicas 1 -p 3000:3000 bank-app:latest
```
This diff is collapsed.
#!/bin/bash
set -x #echo on
docker build --tag bank-app . &&
docker image prune --filter label=stage=bank-app-stage1-docker-builder --force &&
docker image prune --filter label=stage=bank-app-stage2-docker-builder --force &&
docker image rm mhart/alpine-node:12 --force &&
docker image rm mhart/alpine-node:slim-12 --force
var express = require("express");
//const sqlite3 = require('sqlite3').verbose();
let db_name = "bank.sqlite";
const sqlite3_async = require("sqlite-async");
var fs = require("fs").promises;
const { write_certificates_from_db_to_wallet } = require("./fileread");
//let table_name = "User";
// let json = {
// "User_Id": "2",
// "User_Name": "1",
// "User_Password": "1",
// "User_Enrollment_Certificate": "1",
// "User_Public_Key": "1",
// "User_Private_Key": "1",
// "User_Image": "1",
// "User_House_Number": "1",
// "User_Address": "1",
// "User_Geo_Location": "1",
// "User_Asset_Balance": 0,
// "Available_bank_Sources": "1",
// "Accumulated_Generated_Power": 0,
// "Accumulated_Consumed_Power": 0,
// "Smart_Meter_Reading_Updated_Timestamp": "1",
// "User_Profile_Rating": 0,
// "Sell_Count": 0,
// "Buy_Count" :0,
// "Profile_Updated_Timestamp":"1"
// };
async function sqlite_json_insert(json_dict, table_name) {
let insert_status;
try {
table_keys = Object.keys(json_dict).join(", ");
table_values = Object.values(json_dict).join("','");
let sql =
"INSERT INTO " +
table_name +
"(" +
table_keys +
") VALUES ('" +
table_values +
"')";
console.log(sql);
// open the database connection
let db_con = await sqlite3_async.open(db_name);
insert_status = await db_con.run(sql);
if ("changes" in insert_status) {
if (insert_status["changes"] > 0) {
insert_status = "success";
}
}
await db_con.close();
} catch (e) {
insert_status = e;
} finally {
return insert_status;
}
}
// const {load_certificates_from_wallet} = require('./fileread');
// async function check_insert(){
// let html_json_data = {
// "User_Name" : "ark",
// "user_Password": "ark",
// "User_House_Number" : "4A"
// }
// let user_certificates_json = await load_certificates_from_wallet(html_json_data["User_Name"]);
// let combined_user_data = {...html_json_data,...user_certificates_json};
// let insert_status = await sqlite_json_insert(combined_user_data,"User");
// console.log(insert_status);
// }
// check_insert();
async function check_login_and_load_certificates(user_name, user_password) {
let login_status = {};
login_status["status"] = "";
try {
console.log("1");
let db_con = await sqlite3_async.open(db_name);
let let_sql_query =
'SELECT * FROM User where User.User_Name = "' + user_name + '" ;';
console.log(let_sql_query);
const result = await db_con.all(let_sql_query);
await db_con.close();
console.log(result.length);
console.log("2");
if (result.length > 0) {
let user_info = result[0];
login_status["User_Id"] = user_info["User_Id"];
if (user_info["User_Password"] === user_password) {
let enrollment_json = JSON.parse(
user_info["User_Enrollment_Certificate"]
);
let enrollment_signingIdentity =
enrollment_json["enrollment"]["signingIdentity"];
console.log(
"enrollment_signingIdentity = " + enrollment_signingIdentity
);
console.log("3");
//console.log(user_info);
write_status = await write_certificates_from_db_to_wallet(
user_info,
enrollment_signingIdentity
);
console.log(write_status);
login_status["status"] = write_status;
console.log("4");
} else {
login_status["status"] = "Password is wrong";
}
} else {
login_status["status"] = "Account does not exist - Please register";
}
} catch (e) {
console.log(e);
login_status["status"] = e;
} finally {
console.log("5");
return login_status;
}
}
// async function check_login(){
// let login_status = await check_login_and_load_certificates("ark","ark");
// console.log(login_status);
// }
// check_login();
async function db_query(let_sql_query) {
let status;
try {
console.log("1");
let db_con = await sqlite3_async.open(db_name);
//let let_sql_query = 'SELECT * FROM '+table_name+';';
console.log(let_sql_query);
const result = await db_con.all(let_sql_query);
await db_con.close();
console.log(result.length);
console.log("2");
status = result;
} catch (e) {
console.log(e);
status = e;
} finally {
console.log("5");
return status;
}
}
module.exports = {
sqlite_json_insert: sqlite_json_insert,
check_login_and_load_certificates: check_login_and_load_certificates,
db_query: db_query,
};
# Fabric SDK Adaptor
Node sdk examples to interact with bityoga fabric set up
# Requirements
1. Bityoga fabric sdk should be up and running
2. Node version
- Supports node version >=8
- Tested with v8.10.0
# Run Instructions
1. ## Clone this repository into your app directory
- git clone https://github.com/bityoga/fabric_node_sdk_helper.git
2. ## Update your app's package.json
- Edit your app's **package.json with the "fabric_node_sdk_helper/package.json"** found in this repository.
3. ## Run npm install
- #### Set node version
- nvm use node v8.9.0 (using nvm)
- npm install
3. ## Update ip address in 'fabric_node_sdk_helper/network_profile.json'
- **update the url ip addresses of orderer, peer2, orgca, tlsca (4 places).**
- update it with your prime manager's ip address
4. ## Retrieve hyperledger fabric tls certificates of 'orderer' and 'peer2'
#### Through shell script - needs ssh permission
- cd fabric_node_sdk_helper/
- In 'fabric_node_sdk_helper/get_tls_certificates.sh' Replace **IP_ADDRESS="178.62.207.235"** with your fabric prime manager's ip address
- **Execute Command :** bash get_tls_certificates.sh
#### (OR) Through Manual scp commands - needs ssh permission
- Replace ipaddress in the below scp commands with your fabric prime manager's ip address.
- scp -r root@178.62.207.235:/root/hlft-store/orderer/tls-msp/tlscacerts/tls-tlsca-7054.pem ./fabric_node_sdk_helper/hlft-store/orderer/tls-msp/tlscacerts/tls-tlsca-7054.pem
- scp -r root@178.62.207.235:/root/hlft-store/peer2/tls-msp/tlscacerts/tls-tlsca-7054.pem ./fabric_node_sdk_helper/hlft-store/peer2/tls-msp/tlscacerts/tls-tlsca-7054.pem
#### (OR) Manually edit the following two files - no need of ssh permission
- fabric_node_sdk_helper/hlft-store/orderer/tls-msp/tlscacerts/tls-tlsca-7054.pem
- fabric_node_sdk_helper/hlft-store/peer2/tls-msp/tlscacerts/tls-tlsca-7054.pem
5. ## Enroll admin
- #### Call this function "once" when your app starts.
- When this function is called, a **wallet** directory will be created in the current directory
- Admin user will be enrolled and the certificates will availalble in **wallet** directory
- If fabric certificates are changed in future, this wallet directory should cleaned, and this function must be called again to get the new certificates
- check wallet directory
- a directory named 'admin' will be available
- certificates for admin will be available under this directory.
- sample :
``` Javascript
// import fabric node sdk helper functions
const enrollAdmin = require('./fabric_node_sdk_helper/enrollAdmin');
async function main() {
admin_enroll_status = await enrollAdmin();
console.log(admin_enroll_status);
}
main();
```
6. ## Register user
- sample :
``` Javascript
// import fabric node sdk helper functions
const registerUser = require('./fabric_node_sdk_helper/registerUser');
app.post('/register', async (req, res) => {
let user_name = req.body.uname;
let user_password = req.body.psw;
let user_role = "client";
let register_status = await registerUser(user_name,
user_password,
user_role);
let response = {
status:register_status
};
res.json(response);
});
```
- check wallet directory
- a directory with the name of the 'registerd user name' will be available
- certificates for the registerd user will be available under this directory.
7. ## Query a chaincode
- sample :
``` Javascript
// import fabric node sdk helper functions
const querychaincode = require('./fabric_node_sdk_helper/query');
app.post('/query', async (req, res) => {
let user_name = req.body.uname;
let CHANNEL_NAME = "appchannel";
let CHAIN_CODE_NAME = "carcc";
let CHAIN_CODE_FUNCTION_NAME = "listCars";
// Without Arguments
let query_result = await querychaincode(user_name,CHANNEL_NAME,CHAIN_CODE_NAME, CHAIN_CODE_FUNCTION_NAME);
// With Arguments
let query_result = await querychaincode(user_name,CHANNEL_NAME,CHAIN_CODE_NAME, CHAIN_CODE_FUNCTION_NAME , "a");
let response = {
"status":"success",
"data":query_result
};
console.log(response);
res.json(response);
});
```
8. ## Invoke a chaincode
- sample :
``` Javascript
// import fabric node sdk helper functions
const invokechaincode = require('./fabric_node_sdk_helper/invoke');
app.post('/invoke', async (req, res) => {
let user_name = req.body.uname;
let car_license_plate = req.body.car_license_plate;
let CHANNEL_NAME = "appchannel";
let CHAIN_CODE_NAME = "carcc";
let CHAIN_CODE_FUNCTION_NAME = "listCars";
let invoke_result = await invokechaincode(user_name,
CHANNEL_NAME,
CHAIN_CODE_NAME,
CHAIN_CODE_FUNCTION_NAME,
car_license_plate,
"Opel","Corsa","Light Blue","7","2050","1");
let response = {
"status":"success",
"data":invoke_result
};
console.log(response);
res.json(response);
});
```
/*
* SPDX-License-Identifier: Apache-2.0
*/
'use strict';
const FabricCAServices = require('fabric-ca-client');
const { FileSystemWallet, X509WalletMixin } = require('fabric-network');
const fs = require('fs');
const path = require('path');
const ccpPath = path.resolve(__dirname, '.', 'network_profile.json');
const ccpJSON = fs.readFileSync(ccpPath, 'utf8');
const ccp = JSON.parse(ccpJSON);
const admin_username = "ca-admin-orgca";
const admin_password = "orgcapw";
const ORGANISATION_MSP = "hlfMSP";
const CA_ORGANISATION_NAME = "orgca";
async function enrollAdmin() {
let return_value;
try {
// Create a new CA client for interacting with the CA.
const caInfo = ccp.certificateAuthorities[CA_ORGANISATION_NAME];
console.log(caInfo);
const caTLSCACerts = [];
//const caTLSCACerts = caInfo.tlsCACerts.pem;
const ca = new FabricCAServices(caInfo.url, { trustedRoots: caTLSCACerts, verify: false }, caInfo.caName);
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the admin user.
const adminExists = await wallet.exists('admin');
if (adminExists) {
return_value = 'An identity for the admin user "admin" already exists in the wallet';
}
else {
// Enroll the admin user, and import the new identity into the wallet.
const enrollment = await ca.enroll({ enrollmentID: admin_username, enrollmentSecret: admin_password });
const identity = X509WalletMixin.createIdentity(ORGANISATION_MSP, enrollment.certificate, enrollment.key.toBytes());
await wallet.import('admin', identity);
return_value = 'Successfully enrolled admin user "admin" and imported it into the wallet';
}
}
catch (error) {
return_value = `Failed to enroll admin user "admin": ${error}`;
}
finally {
console.log("'enrollAdmin' function -> returning value");
return return_value;
}
}
module.exports = enrollAdmin;
\ No newline at end of file
#!/bin/bash
set -x #echo on
IP_ADDRESS="46.101.220.140"
REMOTE_MACHINE_ORDERER_TLS_CERT_FILE="/root/hlft-store/orgca/orderer/msp/tls/ca.crt"
REMOTE_MACHINE_PEER2_TLS_CERT_FILE="/root/hlft-store/orgca/peer2/msp/tls/ca.crt"
LOCAL_ORDER_TLS_CERT_FILE="./hlft-store/orderer/tls-msp/tlscacerts/ca.crt"
LOCAL_ORDER_PEER2_CERT_FILE="./hlft-store/peer2/tls-msp/tlscacerts/ca.crt"
scp -r root@$IP_ADDRESS:$REMOTE_MACHINE_ORDERER_TLS_CERT_FILE $LOCAL_ORDER_TLS_CERT_FILE &&
scp -r root@$IP_ADDRESS:$REMOTE_MACHINE_PEER2_TLS_CERT_FILE $LOCAL_ORDER_PEER2_CERT_FILE
\ No newline at end of file
-----BEGIN CERTIFICATE-----
MIICATCCAaegAwIBAgIUHtIeXGIFSSSzdVv3i8OKtwTEoekwCgYIKoZIzj0EAwIw
XTELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRQwEgYDVQQK
EwtIeXBlcmxlZGdlcjEPMA0GA1UECxMGRmFicmljMQ4wDAYDVQQDEwV0bHNjYTAe
Fw0yMDEwMDcxOTA2MDBaFw0zNTEwMDQxOTA2MDBaMF0xCzAJBgNVBAYTAlVTMRcw
FQYDVQQIEw5Ob3J0aCBDYXJvbGluYTEUMBIGA1UEChMLSHlwZXJsZWRnZXIxDzAN
BgNVBAsTBkZhYnJpYzEOMAwGA1UEAxMFdGxzY2EwWTATBgcqhkjOPQIBBggqhkjO
PQMBBwNCAATiVMVg8vqfYkf33sVX5rsOO+RJr7gio3GQ4cRIBb9a0EL8ic8F40bG
R4/+cuFTVacUpC68JMPvIOXKZDPyL6Sdo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYD
VR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQU5SQIqQSqUa0S4iCIqW6D4F7BKakw
CgYIKoZIzj0EAwIDSAAwRQIhAOxtHlaXYbj/ptd0ncFWXa1fSeTfz2Ig06Nlx6c5
G+W4AiA1TbAWTspXu8dd/ky4w490fCj6nLbdvgE/uWT2npg/aA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICATCCAaegAwIBAgIUHtIeXGIFSSSzdVv3i8OKtwTEoekwCgYIKoZIzj0EAwIw
XTELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRQwEgYDVQQK
EwtIeXBlcmxlZGdlcjEPMA0GA1UECxMGRmFicmljMQ4wDAYDVQQDEwV0bHNjYTAe
Fw0yMDEwMDcxOTA2MDBaFw0zNTEwMDQxOTA2MDBaMF0xCzAJBgNVBAYTAlVTMRcw
FQYDVQQIEw5Ob3J0aCBDYXJvbGluYTEUMBIGA1UEChMLSHlwZXJsZWRnZXIxDzAN
BgNVBAsTBkZhYnJpYzEOMAwGA1UEAxMFdGxzY2EwWTATBgcqhkjOPQIBBggqhkjO
PQMBBwNCAATiVMVg8vqfYkf33sVX5rsOO+RJr7gio3GQ4cRIBb9a0EL8ic8F40bG
R4/+cuFTVacUpC68JMPvIOXKZDPyL6Sdo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYD
VR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQU5SQIqQSqUa0S4iCIqW6D4F7BKakw
CgYIKoZIzj0EAwIDSAAwRQIhAOxtHlaXYbj/ptd0ncFWXa1fSeTfz2Ig06Nlx6c5
G+W4AiA1TbAWTspXu8dd/ky4w490fCj6nLbdvgE/uWT2npg/aA==
-----END CERTIFICATE-----
/*
* SPDX-License-Identifier: Apache-2.0
*/
"use strict";
const { FileSystemWallet, Gateway } = require("fabric-network");
const fs = require("fs");
const path = require("path");
const ccpPath = path.resolve(__dirname, ".", "network_profile.json");
async function invokechaincode(
USER_NAME,
CHANNEL_NAME,
CHAIN_CODE_NAME,
CHAIN_CODE_FUNCTION_NAME,
...ARGS
) {
let return_value;
try {
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), "wallet");
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.exists(USER_NAME);
if (!userExists) {
//console.log('An identity for the user "user1" does not exist in the wallet');
//console.log('Run the registerUser.js application before retrying');
return_value =
'An identity for the user "user1" does not exist in the wallet. Run the registerUser.js application before retrying';
} else {
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccpPath, {
wallet,
identity: USER_NAME,
discovery: { enabled: false, asLocalhost: false },
});
// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork(CHANNEL_NAME);
// Get the contract from the network.
const contract = network.getContract(CHAIN_CODE_NAME);
// Submit the specified transaction.
// createCar transaction - requires 5 argument, ex: ('createCar', 'CAR12', 'Honda', 'Accord', 'Black', 'Tom')
// changeCarOwner transaction - requires 2 args , ex: ('changeCarOwner', 'CAR10', 'Dave')
//await contract.submitTransaction(CHAIN_CODE_FUNCTION_NAME, "BE8800","Opel","Corsa","Light Blue","7","2050","1");
return_value = await contract.submitTransaction(
CHAIN_CODE_FUNCTION_NAME,
...ARGS
);
return_value = return_value.toString();
//await contract.submitTransaction(CHAIN_CODE_FUNCTION_NAME, "b","a","1");
console.log("Transaction has been submitted");
// Disconnect from the gateway.
await gateway.disconnect();
}
} catch (error) {
return_value = `Failed to evaluate transaction: ${error}`;
//process.exit(1);
} finally {
return return_value;
}
}
module.exports = invokechaincode;
{
"name": "hlf-bityoga",
"version": "1.0.0",
"client": {
"organization": "hlf",
"connection": {
"timeout": {
"peer": {
"endorser": "300"
}
}
}
},
"channels": {
"appchannel": {
"orderers": ["orderer"],
"peers": {
"peer2": {
"endorsingPeer": "true",
"chaincodeQuery": "true",
"ledgerQuery": "true",
"eventSource": "true",
"discover": "true"
},
"peer1": {
"endorsingPeer": "false",
"chaincodeQuery": "false",
"ledgerQuery": "true",
"eventSource": "false",
"discover": "true"
}
}
}
},
"organizations": {
"hlf": {
"mspid": "hlfMSP",
"peers": ["peer2", "peer1"],
"certificateAuthorities": ["orgca", "tlsca"]
}
},
"orderers": {
"orderer": {
"url": "grpcs://46.101.220.140:8053",
"tlsCACerts": {
"path": "./hlft-store/orderer/tls-msp/tlscacerts/ca.crt"
},
"grpcOptions": {
"ssl-target-name-override": "orderer"
}
}
},
"peers": {
"peer2": {
"url": "grpcs://46.101.220.140:8055",
"tlsCACerts": {
"path": "./hlft-store/peer2/tls-msp/tlscacerts/ca.crt"
},
"grpcOptions": {
"ssl-target-name-override": "peer2"
}
}
},
"certificateAuthorities": {
"orgca": {
"caName": "orgca",
"url": "https://46.101.220.140:8052",
"httpOptions": {
"verify": false
}
},
"tlsca": {
"caName": "tlsca",
"url": "https://46.101.220.140:8081",
"httpOptions": {
"verify": false
}
}
}
}
This diff is collapsed.
{
"engines": {
"node": ">=8",
"npm": ">=5"
},
"scripts": {
"lint": "eslint .",
"pretest": "npm run lint",
"test": "nyc mocha --recursive"
},
"engineStrict": true,
"author": "Hyperledger",
"license": "Apache-2.0",
"dependencies": {
"fabric-ca-client": "~1.4.3",
"fabric-network": "~1.4.3"
},
"devDependencies": {
"chai": "^4.2.0",
"eslint": "^5.9.0",
"mocha": "^5.2.0",
"nyc": "^15.0.0",
"sinon": "^7.1.1",
"sinon-chai": "^3.3.0"
},
"nyc": {
"exclude": [
"coverage/**",
"test/**"
],
"reporter": [
"text-summary",
"html"
],
"all": true,
"check-coverage": true,
"statements": 100,
"branches": 100,
"functions": 100,
"lines": 100
}
}
/*
* SPDX-License-Identifier: Apache-2.0
*/
"use strict";
const { FileSystemWallet, Gateway } = require("fabric-network");
const fs = require("fs");
const path = require("path");
const ccpPath = path.resolve(__dirname, ".", "network_profile.json");
async function querychaincode(
USER_NAME,
CHANNEL_NAME,
CHAIN_CODE_NAME,
CHAIN_CODE_FUNCTION_NAME,
...ARGS
) {
let return_value;
try {
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), "wallet");
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.exists(USER_NAME);
if (!userExists) {
// console.log('An identity for the user "user1" does not exist in the wallet');
// console.log('Run the registerUser.js application before retrying');
return_value =
'An identity for the user "user1" does not exist in the wallet. Run the registerUser.js application before retrying';
} else {
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccpPath, {
wallet,
identity: USER_NAME,
discovery: { enabled: false, asLocalhost: false },
});
// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork(CHANNEL_NAME);
// Get the contract from the network.
const contract = network.getContract(CHAIN_CODE_NAME);
// Evaluate the specified transaction.
// queryCar transaction - requires 1 argument, ex: ('queryCar', 'CAR4')
// queryAllCars transaction - requires no arguments, ex: ('queryAllCars')
console.log(ARGS);
console.log(CHAIN_CODE_FUNCTION_NAME);
// if (ARGS.length > 0 ) {
// console.log(CHAIN_CODE_FUNCTION_NAME);
// return_value = await contract.evaluateTransaction(CHAIN_CODE_FUNCTION_NAME,ARGS);
// return_value = return_value.toString();
// }
// else {
// return_value = await contract.evaluateTransaction(CHAIN_CODE_FUNCTION_NAME);
// return_value = return_value.toString();
// }
return_value = await contract.evaluateTransaction(
CHAIN_CODE_FUNCTION_NAME,
...ARGS
);
return_value = return_value.toString();
//const result = await contract.evaluateTransaction(CHAIN_CODE_FUNCTION_NAME,"b");
//const result = await contract.evaluateTransaction(CHAIN_CODE_FUNCTION_NAME,"a");
console.log(
`Transaction has been evaluated, result is: ${return_value.toString()}`
);
//return_value = result;
}
//return result;
//process.exit(1);
} catch (error) {
return_value = `Failed to evaluate transaction: ${error}`;
//process.exit(1);
} finally {
return return_value;
}
}
module.exports = querychaincode;
/*
* SPDX-License-Identifier: Apache-2.0
*/
'use strict';
const { FileSystemWallet, Gateway, X509WalletMixin } = require('fabric-network');
const path = require('path');
const ccpPath = path.resolve(__dirname, '.', 'network_profile.json');
async function registerUser(user_name, user_password, user_role) {
let return_value;
try {
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.exists(user_name);
if (userExists) {
return_value = 'An identity for the user "'+user_name+'" already exists in the wallet';
}
else {
// Check to see if we've already enrolled the admin user.
const adminExists = await wallet.exists('admin');
if (!adminExists) {
return_value = "An identity for the admin user 'admin' does not exist in the wallet. Call 'enrollAdmin' function before retrying";
}
else {
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccpPath, { wallet, identity: 'admin', discovery: { enabled: true, asLocalhost: false } });
// Get the CA client object from the gateway for interacting with the CA.
const ca = gateway.getClient().getCertificateAuthority();
const adminIdentity = gateway.getCurrentIdentity();
// Register the user, enroll the user, and import the new identity into the wallet.
const secret = await ca.register({ enrollmentID: user_name,role: user_role,enrollmentSecret:user_password }, adminIdentity);
const enrollment = await ca.enroll({ enrollmentID: user_name, enrollmentSecret: secret });
const userIdentity = X509WalletMixin.createIdentity('hlfMSP', enrollment.certificate, enrollment.key.toBytes());
await wallet.import(user_name, userIdentity);
return_value = 'Successfully registered and enrolled user "'+user_name+'" with role "'+user_role+'" and imported it into the wallet';
}
}
}
catch (error) {
//return_value = `Failed to register user ${user_name}: ${error}`;
return_value = "Failed to register user "+user_name+": " + error;
}
finally{
console.log("'registerUser' function -> returning value");
return return_value;
}
}
module.exports = registerUser;
var fs = require('fs').promises;
async function load_certificates_from_wallet(user_name) {
let certificates_json = {};
let cert_path = './wallet/'+user_name+'/';
try {
//get all filenames under a directory
var file_list = await fs.readdir(cert_path);
console.log(file_list);
for (index = 0; index < file_list.length; index++) {
console.log(file_list[index]);
if (file_list[index].includes('-priv')) {
let full_file_path = cert_path + file_list[index];
//read file contents to a string
certificates_json['User_Private_Key'] = await fs.readFile(full_file_path, "utf8");
}
if (file_list[index].includes('-pub')) {
let full_file_path = cert_path + file_list[index];
//read file contents to a string
certificates_json['User_Public_Key'] = await fs.readFile(full_file_path, "utf8");
}
if (file_list[index].includes(user_name)) {
let full_file_path = cert_path + file_list[index];
//read file contents to a string
certificates_json['User_Enrollment_Certificate'] = await fs.readFile(full_file_path, "utf8");
}
}
}
catch(e) {
console.log(e);
}
finally {
return certificates_json;
}
}
async function checkDirectorySync(directory) {
try {
await fs.stat(directory);
} catch(e) {
await fs.mkdir(directory);
}
}
async function write_certificates_from_db_to_wallet(db_user_info,enrollment_signingIdentity) {
let write_status;
let user_name = db_user_info['User_Name'];
let cert_path = './wallet/'+user_name+'/';
try {
//get all filenames under a directory
await checkDirectorySync(cert_path);
var file_list = await fs.readdir(cert_path);
if(file_list.length==0){
console.log(db_user_info["User_Private_Key"]);
await fs.writeFile(cert_path+enrollment_signingIdentity+"-priv", db_user_info["User_Private_Key"]);
await fs.writeFile(cert_path+enrollment_signingIdentity+"-pub", db_user_info["User_Public_Key"]);
await fs.writeFile(cert_path+user_name, db_user_info["User_Enrollment_Certificate"]);
write_status = "success";
}
else {
write_status = "success";
}
}
catch(e) {
write_status = e;
}
finally {
return write_status;
}
}
// async function check_file_load_to_wallet(user_name) {
// let load_status = await write_certificates_from_db_to_wallet(user_name);
// console.log(load_status);
// }
// let user_info = {};
// user_info["User_Name"] = "ark";
// user_info["User_Password"] = "ark";
// check_file_load_to_wallet(user_info);
// async function check_file_load_to_db(user_name) {
// let load_status = await load_certificates_from_wallet(user_name);
// console.log(load_status);
// }
// await check_file_load_to_db('ark');
module.exports = {
load_certificates_from_wallet : load_certificates_from_wallet,
write_certificates_from_db_to_wallet : write_certificates_from_db_to_wallet
};
\ No newline at end of file
.loader {
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite; /* Safari */
animation: spin 2s linear infinite;
}
/* Safari */
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
html {
scroll-behavior: smooth;
/*overflow: hidden;*/
}
.tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
/* Position the tooltip */
position: absolute;
z-index: 1;
}
.tooltip:hover .tooltiptext {
visibility: visible;
}
body { margin:0; padding:0; text-align:center }
.iframe_holder {
padding:0px;
margin:0 auto;
width:100%;
/*height:89vh;*/
height: calc(100vh - 113px);
margin-top: 56px;
border: 0px;
/*margin-bottom: 52px;*/
}
.footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
color: white;
text-align: center;
}
body {font-family: Arial, Helvetica, sans-serif;}
/* Full-width input fields */
input[type=text], input[type=password] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
}
/* Set a style for all buttons */
#login button {
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
cursor: pointer;
width: 100%;
}
/* Set a style for all buttons */
#register button {
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
cursor: pointer;
width: 100%;
}
/* Set a style for all buttons */
#sell button {
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
cursor: pointer;
width: 100%;
}
/* Set a style for all buttons */
#query_chain_code_div button {
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
cursor: pointer;
width: 100%;
}
button:hover {
opacity: 0.8;
}
/* Extra styles for the cancel button */
.cancelbtn {
width: auto !important;
padding: 10px 18px !important;
background-color: #f44336 !important;
}
/* Center the image and position the close button */
.imgcontainer {
text-align: center;
margin: 24px 0 12px 0;
position: relative;
}
img.avatar {
width: 40%;
border-radius: 50%;
}
.container {
padding: 16px;
}
span.psw {
float: right;
padding-top: 16px;
}
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
padding-top: 60px;
}
/* Modal Content/Box */
.modal-content {
background-color: #fefefe;
margin: 5% auto 15% auto; /* 5% from the top, 15% from the bottom and centered */
border: 1px solid #888;
width: 40%; /* Could be more or less, depending on screen size */
}
/* The Close Button (x) */
.close {
position: absolute;
right: 25px;
top: 0;
color: #000;
font-size: 35px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: red;
cursor: pointer;
}
/* Add Zoom Animation */
.animate {
-webkit-animation: animatezoom 0.6s;
animation: animatezoom 0.6s
}
@-webkit-keyframes animatezoom {
from {-webkit-transform: scale(0)}
to {-webkit-transform: scale(1)}
}
@keyframes animatezoom {
from {transform: scale(0)}
to {transform: scale(1)}
}
/* Change styles for span and cancel button on extra small screens */
@media screen and (max-width: 300px) {
span.psw {
display: block;
float: none;
}
.cancelbtn {
width: 100%;
}
}
.modal-content {
max-height: 80vh;
overflow: auto;
}
/* Extra small devices (phones, 600px and down) */
@media only screen and (max-width: 600px) {
.modal-content {
width: 80%;
}
/* .iframe_holder {
height: calc(100vh - 153px);
} */
}
/* Small devices (portrait tablets and large phones, 600px and up) */
@media only screen and (min-width: 600px) {
.modal-content {
width: 80%;
}
}
/* Medium devices (landscape tablets, 768px and up) */
@media only screen and (min-width: 768px) {
.modal-content {
width: 60%;
}
}
/* Large devices (laptops/desktops, 992px and up) */
@media only screen and (min-width: 992px) {
.modal-content {
width: 40%;
}
}
/* Extra large devices (large laptops and desktops, 1200px and up) */
@media only screen and (min-width: 1200px) {
.modal-content {
width: 30%;
}
}
.alert {
padding: 20px;
color: white;
}
.alertclosebtn {
margin-left: 15px;
color: white;
font-weight: bold;
float: right;
font-size: 22px;
line-height: 20px;
cursor: pointer;
transition: 0.3s;
}
.w3-padding-24 {
padding-top: 24px!important;
padding-bottom: 24px!important;
}
\ No newline at end of file
function openLink(evt, animName) {
var i, x, tablinks;
x = document.getElementsByClassName("iframe_holder");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablink");
console.log(tablinks);
for (i = 0; i < x.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" w3-blue", " ");
tablinks[i].className = tablinks[i].className.replace("w3-blue", " ");
}
document.getElementById(animName).style.display = "block";
if(animName!="home") {
console.log(animName);
//evt.currentTarget.className += " w3-blue";
}
}
function myFunction() {
var x = document.getElementById("demo");
if (x.className.indexOf("w3-show") == -1) {
x.className += " w3-show";
} else {
x.className = x.className.replace(" w3-show", "");
}
}
function notification_function() {
var x = document.getElementById("notifications");
if (x.className.indexOf("w3-show") == -1) {
x.className += " w3-show";
} else {
x.className = x.className.replace(" w3-show", "");
}
}
function openLeftMenu() {
document.getElementById("leftMenu").style.display = "block";
}
function closeLeftMenu() {
document.getElementById("leftMenu").style.display = "none";
}
function openRightMenu() {
document.getElementById("rightMenu").style.display = "block";
}
function closeRightMenu() {
document.getElementById("rightMenu").style.display = "none";
}
\ No newline at end of file
// Get the modal
var modal = document.getElementById('id01');
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
// Get the modal
var login_modal = document.getElementById('login');
var register_modal = document.getElementById('register');
var sell_modal = document.getElementById('sell');
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == login_modal) {
login_modal.style.display = "none";
}
if (event.target == login_modal) {
register_modal.style.display = "none";
}
if (event.target == sell_modal) {
sell_modal.style.display = "none";
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<!DOCTYPE html>
<html>
<title>W3.CSS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<style>
div.sticky {
position: -webkit-sticky;
position: sticky;
top: 0;
}
html {
scroll-behavior: smooth;
}
#consumer_scroll_to_top_button {
display: none;
position: fixed;
bottom: 20px;
right: 2px;
z-index: 99;
font-size: 18px;
border: none;
outline: none;
color: white;
cursor: pointer;
padding: 15px;
border-radius: 4px;
}
/* The actual timeline (the vertical ruler) */
.timeline {
position: relative;
max-width: 1200px;
margin: 0 auto;
}
/* The actual timeline (the vertical ruler) */
.timeline::after {
content: '';
position: absolute;
width: 6px;
background-color: white;
top: 0;
bottom: 0;
left: 50%;
margin-left: -3px;
}
/* Container around content */
.container {
padding: 10px 40px;
position: relative;
background-color: inherit;
width: 50%;
}
/* The circles on the timeline */
.container::after {
content: '';
position: absolute;
width: 25px;
height: 25px;
right: -17px;
background-color: white;
border: 4px solid #FF9F55;
top: 15px;
border-radius: 50%;
z-index: 1;
}
/* Place the container to the left */
.left {
left: 0;
}
/* Place the container to the right */
.right {
left: 50%;
}
/* Add arrows to the left container (pointing right) */
.left::before {
content: " ";
height: 0;
position: absolute;
top: 22px;
width: 0;
z-index: 1;
right: 30px;
border: medium solid white;
border-width: 10px 0 10px 10px;
border-color: transparent transparent transparent white;
}
/* Add arrows to the right container (pointing left) */
.right::before {
content: " ";
height: 0;
position: absolute;
top: 22px;
width: 0;
z-index: 1;
left: 30px;
border: medium solid white;
border-width: 10px 10px 10px 0;
border-color: transparent white transparent transparent;
}
/* Fix the circle for containers on the right side */
.right::after {
left: -16px;
}
/* The actual content */
.content {
padding: 20px 30px;
background-color: white;
position: relative;
border-radius: 6px;
}
/* Media queries - Responsive timeline on screens less than 600px wide */
@media screen and (max-width: 600px) {
/* Place the timelime to the left */
.timeline::after {
left: 31px;
}
/* Full-width containers */
.container {
width: 100%;
padding-left: 70px;
padding-right: 25px;
}
/* Make sure that all arrows are pointing leftwards */
.container::before {
left: 60px;
border: medium solid white;
border-width: 10px 10px 10px 0;
border-color: transparent white transparent transparent;
}
/* Make sure all circles are at the same spot */
.left::after, .right::after {
left: 15px;
}
/* Make all right containers behave like the left ones */
.right {
left: 0%;
}
}
</style>
<body>
<button class="w3-hover-opacity w3-teal" onclick="topFunction()" id="consumer_scroll_to_top_button" title="Go to top"><i class="fa fa-arrow-circle-up" aria-hidden="true"></i> Top</button>
<div class="w3-sidebar w3-bar-block w3-card w3-animate-left w3-collapse" style="display:none;left:0;width: 300px;" id="leftMenu">
<button onclick="closeLeftMenu()" class="w3-bar-item w3-button w3-large">Close &times;</button>
<a href="#" class="w3-bar-item w3-button">Link 1</a>
<a href="#" class="w3-bar-item w3-button">Link 2</a>
<a href="#" class="w3-bar-item w3-button">Link 3</a>
</div>
<div class="w3-sidebar w3-bar-block w3-card w3-animate-right w3-collapse" style="display:none;right:0; width: 300px;" id="rightMenu">
<button onclick="closeRightMenu()" class="w3-bar-item w3-button w3-large">Close &times;</button>
<a href="#" class="w3-bar-item w3-button">Link 1</a>
<a href="#" class="w3-bar-item w3-button">Link 2</a>
<a href="#" class="w3-bar-item w3-button">Link 3</a>
</div>
<div class="w3-main w3-animate-opacity" style="margin-left: 300px; margin-right: 300px;">
<div class="w3-teal w3-blue sticky" style="z-index: 2;">
<button class="w3-button w3-teal w3-xlarge w3-left w3-hide-large" onclick="openLeftMenu()">&#9776;</button>
<button class="w3-button w3-teal w3-xlarge w3-right w3-hide-large" onclick="openRightMenu()">&#9776;</button>
<div class="w3-container">
<h1><i class="fa fa-shopping-cart" aria-hidden="true"></i> Buy</h1>
</div>
</div>
<div class="w3-container" style="background-color: #666;font-family: Helvetica, sans-serif;">
<div class="timeline">
<div class="container left">
<div class="content">
<h2>2017</h2>
<p>Lorem ipsum dolor sit amet, quo ei simul congue exerci, ad nec admodum perfecto mnesarchum, vim ea mazim fierent detracto. Ea quis iuvaret expetendis his, te elit voluptua dignissim per, habeo iusto primis ea eam.</p>
</div>
</div>
<div class="container right">
<div class="content">
<h2>2016</h2>
<p>Lorem ipsum dolor sit amet, quo ei simul congue exerci, ad nec admodum perfecto mnesarchum, vim ea mazim fierent detracto. Ea quis iuvaret expetendis his, te elit voluptua dignissim per, habeo iusto primis ea eam.</p>
</div>
</div>
<div class="container left">
<div class="content">
<h2>2015</h2>
<p>Lorem ipsum dolor sit amet, quo ei simul congue exerci, ad nec admodum perfecto mnesarchum, vim ea mazim fierent detracto. Ea quis iuvaret expetendis his, te elit voluptua dignissim per, habeo iusto primis ea eam.</p>
</div>
</div>
<div class="container right">
<div class="content">
<h2>2012</h2>
<p>Lorem ipsum dolor sit amet, quo ei simul congue exerci, ad nec admodum perfecto mnesarchum, vim ea mazim fierent detracto. Ea quis iuvaret expetendis his, te elit voluptua dignissim per, habeo iusto primis ea eam.</p>
</div>
</div>
<div class="container left">
<div class="content">
<h2>2011</h2>
<p>Lorem ipsum dolor sit amet, quo ei simul congue exerci, ad nec admodum perfecto mnesarchum, vim ea mazim fierent detracto. Ea quis iuvaret expetendis his, te elit voluptua dignissim per, habeo iusto primis ea eam.</p>
</div>
</div>
<div class="container right">
<div class="content">
<h2>2007</h2>
<p>Lorem ipsum dolor sit amet, quo ei simul congue exerci, ad nec admodum perfecto mnesarchum, vim ea mazim fierent detracto. Ea quis iuvaret expetendis his, te elit voluptua dignissim per, habeo iusto primis ea eam.</p>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="js/double_menu.js"> </script>
<script>
//Get the button
var mybutton = document.getElementById("consumer_scroll_to_top_button");
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
mybutton.style.display = "block";
} else {
mybutton.style.display = "none";
}
}
// When the user clicks on the button, scroll to the top of the document
function topFunction() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
</script>
<script type="text/javascript" src="js/send_ajax_request.js"> </script>
<script type="text/javascript">
//alert("consumer.html");
if ( window.location !== window.parent.location ) {
// The page is in an iframe
console.log("in iframe");
} else {
// The page is not in an iframe
console.log("out iframe");
check_iframe_session();
}
</script>
</body>
</html>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<!DOCTYPE html>
<html>
<title>Sell</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
div.sticky {
position: -webkit-sticky;
position: sticky;
top: 0;
}
</style>
<body>
<div class="w3-sidebar w3-bar-block w3-card w3-animate-left w3-collapse" style="display:none;left:0;width: 200px;" id="leftMenu">
<button onclick="closeLeftMenu()" class="w3-bar-item w3-button w3-large">Close &times;</button>
<a href="#" class="w3-bar-item w3-button">Link 1</a>
<a href="#" class="w3-bar-item w3-button">Link 2</a>
<a href="#" class="w3-bar-item w3-button">Link 3</a>
</div>
<div class="w3-sidebar w3-bar-block w3-card w3-animate-right w3-collapse" style="display:none;right:0; width: 200px;" id="rightMenu">
<button onclick="closeRightMenu()" class="w3-bar-item w3-button w3-large">Close &times;</button>
<a href="#" class="w3-bar-item w3-button">Link 1</a>
<a href="#" class="w3-bar-item w3-button">Link 2</a>
<a href="#" class="w3-bar-item w3-button">Link 3</a>
</div>
<div class="w3-main w3-animate-opacity" style="margin-left: 200px; margin-right: 200px;">
<div class="w3-teal w3-blue sticky">
<button class="w3-button w3-teal w3-xlarge w3-left w3-hide-large" onclick="openLeftMenu()">&#9776;</button>
<button class="w3-button w3-teal w3-xlarge w3-right w3-hide-large" onclick="openRightMenu()">&#9776;</button>
<div class="w3-container">
<h1><i class="fa fa-pencil" aria-hidden="true"></i> Sell</h1>
</div>
</div>
<div class="w3-container">
<div class="w3-row w3-padding-64">
<div class="w3-twothird w3-container">
<h1 class="w3-text-teal">Heading</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum
dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<div class="w3-third w3-container">
<p class="w3-border w3-padding-large w3-padding-32 w3-center">AD</p>
<p class="w3-border w3-padding-large w3-padding-64 w3-center">AD</p>
</div>
</div>
<div class="w3-row">
<div class="w3-twothird w3-container">
<h1 class="w3-text-teal">Heading</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum
dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<div class="w3-third w3-container">
<p class="w3-border w3-padding-large w3-padding-32 w3-center">AD</p>
<p class="w3-border w3-padding-large w3-padding-64 w3-center">AD</p>
</div>
</div>
<div class="w3-row w3-padding-64">
<div class="w3-twothird w3-container">
<h1 class="w3-text-teal">Heading</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum
dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<div class="w3-third w3-container">
<p class="w3-border w3-padding-large w3-padding-32 w3-center">AD</p>
<p class="w3-border w3-padding-large w3-padding-64 w3-center">AD</p>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="js/double_menu.js"> </script>
</body>
</html>
This diff is collapsed.
This diff is collapsed.
{
"name": "bank_app",
"version": "1.0.0",
"description": "Articonf Bank App Demo",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/bityoga/articonf-bank-app.git"
},
"keywords": [
"articonf",
"bank app"
],
"author": "anandhakumar palanisamy",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/bityoga/articonf-bank-app/issues"
},
"homepage": "https://github.com/bityoga/articonf-bank-app#readme",
"dependencies": {
"crypto": "^1.0.1",
"express": "^4.17.1",
"express-formidable": "^1.2.0",
"express-session": "^1.17.1",
"fabric-ca-client": "~1.4.3",
"fabric-network": "~1.4.3",
"fs": "0.0.1-security",
"jsonwebtoken": "^8.5.1",
"sqlite-async": "^1.1.0"
},
"devDependencies": {
"chai": "^4.2.0",
"eslint": "^5.9.0",
"mocha": "^5.2.0",
"nyc": "^15.0.0",
"sinon": "^7.1.1",
"sinon-chai": "^3.3.0"
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment