fabric-samples/full-stack-asset-transfer-guide/applications/ping-chaincode/src/jsonid-adapter.ts
jkneubuh a299e18e26
Moves the Full Stack Asset Transfer Development Guide to fabric-samples (#852)
* Import Full Stack Asset Transfer Guide at commit fb554befdbbeff9e69159b54fce0b811603f29c7

Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>

* Update the workshop with a new WORKSHOP_PATH under fabric-samples

Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>

* Update the workshop with a new WORKSHOP_PATH under fabric-samples

Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>

* missed a .git ignored directory on add

Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>

* Updates to run the workshop on the Apple M1

Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>

* Workaround for https://github.com/eslint/eslint/issues/15299 in the contract tslinter

Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>

* Build an arch-specific CC images on M1

Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>

* empty commit - force a build

Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>

* revert an accidental commit that was building the top-level asset-transfer as arm64

Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>

Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>
2022-11-10 10:40:27 -05:00

131 lines
4 KiB
TypeScript

/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Identity, Signer, signers } from '@hyperledger/fabric-gateway';
import { promises as fs } from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';
import { errorMonitor } from 'events';
/** Internal interface used to describe all the possible components
* of the identity
*/
interface JSONID {
name: string;
cert: string;
ca: string;
hsm: boolean;
private_key?: string;
privateKey?: string;
mspId: string;
}
/**
* This class can be used to map identities in a variety of JSON formats to the Identity and Signers required
* for the gateway. For example if you have an application wallet, or have exported IDs from SaaS
*
* ```
* const jsonAdapter: JSONIDAdapter = new JSONIDAdapter(path.resolve(__dirname,'..','wallet'))
*
* const gateway = connect({
* client,
* identity: await jsonAdapter.getIdentity("appuser"),
* signer: await jsonAdapter.getSigner("appuser"),
* });
* ```
*
* Though they are JSON files, typically they files will have the .id extension. Therefore
* if no extension is provided `.id` is added
*/
export default class JSONIDAdapter {
private idFilesDir: string;
private mspId = '';
/**
* @param idFilesDir Directory to load the files from
* @param mspId optional MSPID to apply to all identities returned if they are missing it
*/
public constructor(idFilesDir: string, mspId?: string) {
this.idFilesDir = path.resolve(idFilesDir);
if (mspId) {
this.mspId = mspId;
}
}
private async readIDFile(idFile: string): Promise<JSONID> {
let idJsonFile = path.resolve(path.join(this.idFilesDir, idFile));
// check if there's no extension probably means it's a waller id file
if (path.extname(idJsonFile) === '') {
idJsonFile = `${idJsonFile}.id`;
}
let id: JSONID;
const json = JSON.parse(await fs.readFile(idJsonFile, 'utf-8'));
// look for the nested credentials element
const credentials = json['credentials'];
if (credentials) {
// v2 SDK Wallet format
id = {
name: idFile,
cert: credentials['certificate'],
ca: '',
hsm: false,
private_key: credentials['privateKey'],
mspId: json.mspId,
};
} else {
// IBP exported ID style format
id = {
name: json.name,
cert: Buffer.from(json.cert, 'base64').toString(),
ca: Buffer.from(json.ca, 'base64').toString(),
hsm: json.js,
private_key: Buffer.from(json.private_key, 'base64').toString(),
mspId: this.mspId,
};
}
return id;
}
/**
*
* @param idFile the name of the identity to load (if no extension is provided `.id` is added)
* @returns Identity to use with the GatewayBuilder
*/
public async getIdentity(idFile: string): Promise<Identity> {
const id = await this.readIDFile(idFile);
const identity: Identity = {
credentials: Buffer.from(id.cert),
mspId: id.mspId,
};
return identity;
}
/**
*
* @param idFile the name of the identity to load (if no extension is provided `.id` is added)
* @returns Signer to use with the GatewayBuilder
*/
public async getSigner(idFile: string): Promise<Signer> {
const id = await this.readIDFile(idFile);
let pk;
if (id.private_key) {
pk = id.private_key;
} else if ('privateKey' in id) {
pk = id['privateKey'];
} else {
throw new Error('Unable to parse the identity json file');
}
const privateKey = crypto.createPrivateKey(pk as string);
return signers.newPrivateKeySigner(privateKey);
}
}