Repository navigation
Expand file tree
/
Copy pathfabricConnect.js
More file actions
89 lines (76 loc) · 3.34 KB
/
Copy pathfabricConnect.js
File metadata and controls
89 lines (76 loc) · 3.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
"use strict";
const grpc = require("@grpc/grpc-js");
const { connect, signers } = require("@hyperledger/fabric-gateway");
const fs = require("fs");
const path = require("path");
const crypto = require("crypto");
const CRYPTO_DIR =
process.env.CRYPTO_DIR || "/crypto/peerOrganizations/org.recordweb.dev";
const MSP_ID = process.env.MSP_ID || "TWSOrgMSP";
const ORG_DOMAIN = process.env.ORG_DOMAIN || "org.recordweb.dev";
const PEER_ENDPOINT = process.env.PEER_ENDPOINT || "peer0.tws.rwrrn.recordweb.dev:7051";
const PEER_HOST_ALIAS =
process.env.PEER_HOST_ALIAS || "peer0.tws.rwrrn.recordweb.dev";
const CHANNEL_NAME = process.env.CHANNEL_NAME || "rw-gnr-test";
const CHAINCODE_NAME = process.env.CHAINCODE_NAME || "namespace-registry";
// Live-CA networks (fabric-ca-client register/enroll) typically use a
// custom admin identity name and a plain cert.pem, unlike the fixed
// Admin@<org-domain> / Admin@<org-domain>-cert.pem naming cryptogen produces.
const ADMIN_IDENTITY = process.env.ADMIN_IDENTITY || `Admin@${ORG_DOMAIN}`;
const ADMIN_CERT_FILENAME = process.env.ADMIN_CERT_FILENAME || `${ADMIN_IDENTITY}-cert.pem`;
const TLS_CERT_PATH = path.join(CRYPTO_DIR, "peers", PEER_HOST_ALIAS, "tls", "ca.crt");
const ADMIN_MSP_DIR = path.join(CRYPTO_DIR, "users", ADMIN_IDENTITY, "msp");
const CERT_PATH = path.join(ADMIN_MSP_DIR, "signcerts", ADMIN_CERT_FILENAME);
const KEY_DIR = path.join(ADMIN_MSP_DIR, "keystore");
// Crypto material and gRPC client are process-lifetime constants: loading
// them once at startup (instead of per request, as the multi-peer
// RecordFinder does) keeps the hot path to a single evaluateTransaction call.
let cachedClient = null;
let cachedIdentity = null;
let cachedSigner = null;
function buildGrpcClient() {
const tlsRootCert = fs.readFileSync(TLS_CERT_PATH);
return new grpc.Client(PEER_ENDPOINT, grpc.credentials.createSsl(tlsRootCert), {
"grpc.ssl_target_name_override": PEER_HOST_ALIAS,
});
}
function buildIdentity() {
const credentials = fs.readFileSync(CERT_PATH);
return { mspId: MSP_ID, credentials };
}
function buildSigner() {
const keyFile = fs.readdirSync(KEY_DIR)[0];
const privateKeyPem = fs.readFileSync(path.join(KEY_DIR, keyFile));
const privateKey = crypto.createPrivateKey(privateKeyPem);
return signers.newPrivateKeySigner(privateKey);
}
function getGateway() {
if (!cachedClient) cachedClient = buildGrpcClient();
if (!cachedIdentity) cachedIdentity = buildIdentity();
if (!cachedSigner) cachedSigner = buildSigner();
return connect({
client: cachedClient,
identity: cachedIdentity,
signer: cachedSigner,
});
}
/**
* Calls ResolveNamespace(namespace) on the namespace-registry chaincode.
* The gRPC client connection is reused across calls; only the gateway
* session itself is scoped per call, per fabric-gateway's intended usage.
*
* @param {string} namespace Global Namespace Identifier (UUIDv4, RWP-23).
* @returns {Promise<{resolverEndpoint?: string}>}
*/
async function resolveNamespace(namespace) {
const gateway = getGateway();
try {
const network = gateway.getNetwork(CHANNEL_NAME);
const contract = network.getContract(CHAINCODE_NAME);
const resultBytes = await contract.evaluateTransaction("ResolveNamespace", namespace);
return JSON.parse(Buffer.from(resultBytes).toString("utf8"));
} finally {
gateway.close();
}
}
module.exports = { resolveNamespace };