Este tema describe las partes clave de la aplicación cliente y cómo utiliza la API del cliente Fabric Gateway para interactuar con la red. Este conocimiento le permitirá extender la aplicación en los temas siguientes.
La conexión al servicio peer Gateway está controlada por la función runCommand() en app.ts. Esta llama a otras dos funciones para realizar las dos tareas necesarias antes de que la aplicación cliente pueda realizar transacciones con la red Fabric:
-
Crear conexión gRPC al punto de entrada del peer Gateway - esto es realizado en la función newGrpcConnection() en connect.ts:
const tlsCredentials = grpc.credentials.createSsl(tlsRootCert); return new grpc.Client(GATEWAY_ENDPOINT, tlsCredentials);
La conexión cliente gRPC es establecida utilizando el gRPC API y es manejada por la aplicación cliente. La aplicación puede utilizar la misma conexión gRPC connection para transaccionar en nombre de muchas identidades de clientes.
-
Crear conexión con peer Gateway - esto es realizado en la función newGatewayConnection() en connect.ts:
return connect({ client, identity: await newIdentity(), signer: await newSigner(), // Default timeouts for different gRPC calls evaluateOptions: () => { return { deadline: Date.now() + 5000 }; // 5 seconds }, endorseOptions: () => { return { deadline: Date.now() + 15000 }; // 15 seconds }, submitOptions: () => { return { deadline: Date.now() + 5000 }; // 5 seconds }, commitStatusOptions: () => { return { deadline: Date.now() + 60000 }; // 1 minute }, });
La conexión Gateway es establecida invocando la función de factoría connect() con una identidad cliente (certificado X.509 del usuario) y una implementación de firma (basado en la llave privada del usuario). Le permite a un usuario especifico interactuar con una red Fabric utilizando la conexión gRPC creada previamente. Una configuración opcional también puede ser suministrada, y es muy recomendado incluir tiempos de espera por defecto para las operaciones.
Todas las implementaciones de los comandos CLI están ubicados dentro del directorio commands. Los comandos son expuestos a app.ts por commands/index.ts.
Cuando es invocado, el comando recibe la instancia Gateway que debe utilizar para interactuar con la red Fabric. Para hacer un trabajo útil, la implementación de los comandos típicamente realizan estos pasos:
-
Obtener una Red - esto representa una red de nodos Fabric que perteneces a un canal específico de Fabric:
const network = gateway.getNetwork(CHANNEL_NAME);
-
Obtener un Contrato - esto representa un contrato inteligente específico desplegado en la Red:
const contract = network.getContract(CHAINCODE_NAME);
-
Crear un adaptador del contrato inteligente - esto provee una vista del contrato inteligente y las funciones de la transacción de una manera que es fácil de usar para la lógica de negocio de la aplicación cliente:
const smartContract = new AssetTransfer(contract);
-
Invocar las funciones de la transacción en un chaincode desplegado - por ejemplo:
- Crear un activo en commands/create.ts
await smartContract.createAsset({ ID: assetId, Owner: owner, Color: color, Size: 1, AppraisedValue: 1, });
- Leer todos los activos en commands/getAllAssets.ts
const assets = await smartContract.getAllAssets();
- Crear un activo en commands/create.ts
Los comandos CLI de la aplicación representan una aplicación simplificada que realiza una acción por llamada. Tenga en cuenta que las aplicaciones del mundo real generalmente serán de larga duración y reutilizarán una conexión al servicio peer Gateway cuando realicen solicitudes de transacciones en nombre de las aplicaciones cliente. La conexión puede utilizar una única identidad de organización en nombre de varias solicitudes de usuario.
La clase AssetTransfer en contract.ts presenta al contrato inteligente en un formato apropiado para la aplicación de negocio. Internamente, utiliza la API del cliente Fabric Gateway para invocar funciones de transacción y se encarga de la traducción entre la aplicación de negocio y la representación de parámetros y valores de retorno de la API.
Para mas detalles de las invocaciones disponibles se puede consultar la documentación de la API de Contratos.
La función de submit de transacciones enviará la solicitud al servicio peer Gateway. El servicio peer Gateway invocará el chaincode y recopilará los endosos necesarios de los peers de diferentes organizaciones para cumplir con la política de endosos del contrato. Luego enviará la transacción al servicio de ordenamiento en nombre de la aplicación cliente, para que el ledger de blockchain pueda ser actualizado.
Un ejemplo de envío de transacciones se encuentra en el método createAsset():
await this.#contract.submit('CreateAsset', {
arguments: [JSON.stringify(asset)],
});
La función de evaluación de transacciones solicitará al servicio peer Gateway que invoque el chaincode y devuelva los resultados al cliente, sin enviar una transacción al servicio de ordenamiento. Utilice la función de evaluación para consultar el estado del ledger de blockchain.
Un ejemplo de evaluación de una transacción se encuentra en el método getAllAssets():
const result = await this.#contract.evaluate('GetAllAssets');
La naturaleza del flujo de envío de transacciones en Fabric implica que pueden ocurrir fallos en diferentes puntos del flujo. Para ayudar al cliente a gestionar los fallos, la API de Gateway genera errores de tipos específicos para indicar el punto en el flujo donde ocurrió el fallo. La función submitWithRetry() en contract.ts reintenta las transacciones que no logran confirmarse exitosamente:
let lastError: unknown | undefined;
for (let retryCount = 0; retryCount < RETRIES; retryCount++) {
try {
return await submit();
} catch (err: unknown) {
lastError = err;
if (err instanceof CommitError) {
// Transaction failed validation and did not update the ledger. Handle specific transaction validation codes.
if (err.code === StatusCode.MVCC_READ_CONFLICT) {
continue; // Retry
}
}
break; // Failure -- don't retry
}
}
throw lastError;
Ver la documentación de la API de submit() para conocer los otros tipos de errores que puede arrojar.
Para algunos casos puede ser más útil reintentar solo un paso especifico dentro del flujo de envío de transacciones. La API de Gateway proporciona un flujo detallado para permitir esto. Ver la documentación de la API de Contratos para encontrar ejemplos de este flujo detallado.