Fabric網絡搭建好,合約部署好,接下來就是和合約互動。
我們上一章節中部署了官方給的fabcar合約項目,這裡我們還是以這套合約為例做簡單的互動介紹。
首先,fabcar的chaincode位址:https://github.com/hyperledger/fabric-samples/tree/main/chaincode/fabcar/javascript
部署的方法上一章節介紹過,使用
deployCC
即可。
這裡我們假設已經部署好了fabcar的合約。
接下來我們直接開始對合約進行操作,也就是調用合約裡面的方法。
建立項目
首先我們使用npm建立一個node項目,
npm init
,在
package.json
加入3個包:
{
"name": "fabcar",
"version": "1.0.0",
"description": "FabCar application implemented in JavaScript",
"engineStrict": true,
"author": "Hyperledger",
"license": "Apache-2.0",
"dependencies": {
"app-root-path": "^3.0.0",
"fabric-ca-client": "^2.2.4",
"fabric-network": "^2.2.4"
}
}
說明下,
fabric-network
用于合約互動,裡面有很重要的
contract
對象可以操作合約。
fabric-ca-client
用于fabric網絡層面的一些互動,可以注冊使用者等。
注冊Admin使用者
const FabricCAServices = require('fabric-ca-client');
const { Wallets } = require('fabric-network');
const ROOT = require('app-root-path');
const ccp = require(`${ROOT}/organizations/peerOrganizations/org1.example.com/connection-org1.json`);
const walletPath = `${ROOT}/wallet`;
async function main() {
try {
// Create a new CA client for interacting with the CA.
const caInfo = ccp.certificateAuthorities['ca.org1.example.com'];
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 wallet = await Wallets.newFileSystemWallet(walletPath);
// Enroll the admin user, and import the new identity into the wallet.
const enrollment = await ca.enroll({
enrollmentID: 'admin',
enrollmentSecret: 'adminpw',
});
const x509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put('admin', x509Identity);
console.log('Successfully enrolled admin user');
} catch (e) {
console.error(e);
}
}
main();
這裡我們注意到,需要引用一些外部檔案,首先項目目錄下建立一個
wallet
目錄,存儲使用者錢包,也就是私鑰,用于之後互動時的簽名權。另外一個就是引入連接配接節點的配置檔案,這個檔案在organization下,我們必須要把第一章中用
cryptogen
生成的那個organization目錄全部複制過來,注意是全部,否則會報錯,可能是有什麼關聯引用吧。
注冊普通使用者
上面已經注冊了admin使用者,是以可以用admin使用者再注冊普通使用者了,如下:
const { Wallets } = require('fabric-network');
const FabricCAServices = require('fabric-ca-client');
const ROOT = require('app-root-path');
const ccp = require(`${ROOT}/organizations/peerOrganizations/org1.example.com/connection-org1.json`);
const walletPath = `${ROOT}/wallet`;
async function main() {
try {
// Create a new CA client for interacting with the CA.
const caURL = ccp.certificateAuthorities['ca.org1.example.com'].url;
const ca = new FabricCAServices(caURL);
const wallet = await Wallets.newFileSystemWallet(walletPath);
const adminIdentity = await wallet.get('admin');
const provider = wallet
.getProviderRegistry()
.getProvider(adminIdentity.type);
const adminUser = await provider.getUserContext(adminIdentity, 'admin');
// Register the user, enroll the user, and import the new identity into the wallet.
const secret = await ca.register(
{
affiliation: 'org1.department1',
enrollmentID: 'appUser',
role: 'client',
},
adminUser
);
const enrollment = await ca.enroll({
enrollmentID: 'appUser',
enrollmentSecret: secret,
});
const x509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put('appUser', x509Identity);
console.log('Successfully registeredd');
} catch (error) {
console.error(error);
}
}
main();
合約讀寫
const { Gateway, Wallets } = require('fabric-network');
const ROOT = require('app-root-path');
const walletPath = `${ROOT}/wallet`;
const ccp = require(`${ROOT}/organizations/peerOrganizations/org1.example.com/connection-org1.json`);
let conf = null;
let contract = null;
async function query() {
const res = await contract.evaluateTransaction('queryCar', 'CAR1');
console.log(JSON.parse(res.toString()));
}
async function change(name) {
await contract.submitTransaction('changeCarOwner', 'CAR1', name);
}
async function main() {
try {
// load the network configuration
const wallet = await Wallets.newFileSystemWallet(walletPath);
conf = {
wallet,
identity: 'appUser',
discovery: { enabled: true, asLocalhost: true },
};
const gateway = new Gateway();
await gateway.connect(ccp, conf);
const network = await gateway.getNetwork('mychannel');
contract = network.getContract('fabcar');
await query();
await change('devil');
await query();
await gateway.disconnect();
} catch (error) {
console.error(error);
}
}
main();
對應輸出結果:
