Proyecto de código de cadena de Go andamiaje

Blockchain App Builder toma la entrada de su archivo de especificación y genera un proyecto de código de cadena de andamios totalmente funcional. El proyecto contiene clases y funciones generadas automáticamente, métodos CRUD, métodos SDK, validación automática de argumentos, canalización/anulación de canalización y capacidad de persistencia transparente (ORM).

Si el proyecto chaincode está en el idioma Go, el proyecto andamiaje contiene tres archivos principales:
  • main.go
  • <chaincodeName>.model.go
  • <chaincodeName>.controller.go
Se instalan y empaquetan todas las bibliotecas necesarias.

El archivo <chaincodeName>.model.go del subdirectorio model contiene varias definiciones de activos y el archivo <chaincodeName>.controller.go del subdirectorio controller contiene el comportamiento del activo y los métodos CRUD. Las diversas etiquetas y paquetes de estructura Go de model.go y controller.go proporcionan soporte para funciones como la validación automática de argumentos, la canalización/anulación de canalización de argumentos, la capacidad de persistencia transparente (ORM) y la llamada a consultas enriquecidas.

El proyecto andamiaje se puede encontrar en $GOPATH/src/example.com/<chaincodeName>

Modelo

Propiedad de tipo de activo

Por defecto, cada estructura tendrá una propiedad adicional denominada AssetType. Esta propiedad puede ser útil para recuperar solo activos de este tipo. Cualquier cambio en esta propiedad se ignora durante la creación y actualización del activo. El valor de propiedad por defecto es <modelName>.
type Supplier struct {
AssetType string 'json:"AssetType" default:"TestGoProject.Supplier"'

SupplierId            string      'json:"SupplierId" validate:"string,mandatory" id:"true'
RawMaterialAvailable  int         'json:"RawMaterialAvailable" validate:"int,min=0"'
License               string      'json:"License" validate:"string,min=10"'
ExpiryDate            date.Date   'json:"ExpiryDate" validate:"date,before=2020-06-26"'
Active                bool	  'json:"Active" validate:"bool" default:"true"'
Metadata              interface{} 'json:"Metadata,omitempty"'
}

Validadores

Id
id:"true"
Este validador identifica la propiedad que define de forma única el activo subyacente. El activo se guarda según el valor de esta clave. Este validador se aplica automáticamente cuando se desplaza un nuevo proyecto Go.
En la siguiente captura de pantalla, "SupplierId" es la clave del activo de proveedor y tiene una propiedad de etiqueta id:"true" para la propiedad SupplierId.
type Supplier struct {
    Supplierld              string        'json:"Supplierld" validate:"string,mandatory" id:"true"' 
    RawMaterialAvailable    int           'json:"RawMaterialAvailable" validate:"int,min=0"'
    License                 string        'json:"License" validate:"string,min=10"'
    ExpiryDate              date.Date     'json:"ExpiryDate" validate:"date,before=2020-06-26"'
    Active                  bool          'json:"Active" validate:"bool" default :"true"'
    Metadata                interface{}   'json:"Metadata,omitempty"'   
}
Derivado
derived:"strategy,algorithm,format"
Este decorador se utiliza para definir el atributo derivado de otras propiedades. Este decorador tiene dos parámetros obligatorios:
  • strategy: toma los valores concat o hash. Necesita un parámetro adicional algorithm si se selecciona hash. El algoritmo por defecto es sha256; también se soporta md5.
  • format: toma una matriz de cadenas y valores de especificación que utilizará la estrategia.
type Supplier struct{
   AssetType string 'json:"AssetType" final:"chaincode1.Supplier"'
   SupplierId   string  'json:"SupplierId" validate:"string" id:"true" mandatory:"true" derived:"strategy=hash,algorith=sha256,format=IND%1%2,License,Name"'
   Name         string  'json:"Name" validate:"string,min=2,max=4"'
   License      string  'json:"License" validate:"string,min=2,max=4"'
}
Obligatorio
validate:"mandatory"
Esto marca la siguiente propiedad como obligatoria y no se puede omitir al guardar en el libro mayor. Si se omite, devuelve un error. En el siguiente ejemplo, "SupplierId" tiene una etiqueta validate:"mandatory".
Type Supplier struct {
    Supplierld              string      'json:"Supplierld" validate:"string,mandatory" id:"true"'
    RawMaterialAvailable    int         'json:"RawMaterialAvailable" validate:"int,min=0"'
    License                 string      'json:"License" validate:"string,min=10"'
    ExpiryDate              date.Date   'json:"ExpiryDate" validate:"date,before=2020-06-26"'
    Active                  bool        'json:"Active" validate:"bool" default :"true"'
    Metadata                interface{} 'json:"Metadata,omitempty"'
}
Valor por Defecto
default:"<param>"
Esto indica que la siguiente propiedad puede tener un valor por defecto. El valor por defecto de la etiqueta por defecto se utiliza cuando se omite la propiedad al guardar en el libro mayor. En la siguiente propiedad de ejemplo, Active tiene un valor por defecto de true, proporcionado como etiqueta default:"true"
Type Supplier struct {
    Supplierld            string       'json:"Supplierld" validate:"string,mandatory" id:"true"'
    RawMaterialAvailable  int          'json:"RawMaterialAvailable" validate:"int,min=0"'
    License               string       'json:"License" validate:"string,min=10"'
    ExpiryDate            date.Date    'json:"ExpiryDate" validate:"date,before=2020-06-26"'
    Active                bool         'json:"Active" validate:"bool" default :"true"'
    Metadata              interface{}  'json:"Metadata,omitempty"'
}
Tipos de validación
Los tipos básicos de Go se validan para una propiedad mediante la definición de una etiqueta de validación. Estas son las etiquetas de validación basadas en tipos:
  • cadena: validate: "string"
  • fecha: validate: "date"
  • número: validate: "int"
  • booleano: validate: "bool"
Validador mínimo
validate:"min=<param>"
Con el validador min, se puede establecer un valor mínimo para una propiedad de tipo número y cadena.
Para el tipo int: en el ejemplo, la propiedad RawMaterialAvailable tiene un valor mínimo de 0 y si se aplica un valor menor que 0 a RawMaterialAvailable se devolverá un error.
Para el tipo de cadena: para el tipo de cadena, el validador mínimo comprobará la longitud de la cadena con el valor proporcionado. Por lo tanto, en el siguiente ejemplo, la propiedad License debe tener una longitud mínima de 10 caracteres.
Por ejemplo:
Type Supplier struct {
    Supplierld             string       'json:"Supplierld" validate:"string,mandatory" id:"true"'
    RawMaterialAvailable   int          'json:"RawMaterialAvailable" validate:"int,min=0"'
    License                string       'json:"License" validate:"string,min=10"'
    ExpiryDate             date.Date    'json:"ExpiryDate" validate:"date,before=2020-06-26"'
    Active                 bool         'json:"Active" validate:"bool" default :"true"'
    Metadata               interface{}  'json:"Metadata,omitempty"'
}
Validador máximo
validate:"max=<param>"
Con el validador máximo, se puede definir el valor máximo para una propiedad de tipo número y cadena.
Para el tipo int: al igual que el validador mínimo, para el tipo int, si un valor proporcionado para structfield es mayor que el valor proporcionado en el validador, se devolverá un error.
Para la cadena de tipo: al igual que el validador mínimo, el validador máximo también comprobará la longitud de la cadena con el valor especificado. En el ejemplo, la propiedad Domain tiene un valor máximo de 50, por lo que si la propiedad Domain tiene una longitud de cadena superior a 50 caracteres, se devolverá un mensaje de error.
type Retailer struct {
    Retailerld         string        'json:"Retailerld" validate:"string,mandatory" id:"true"'   
    ProductsOrdered    int           'json:"ProductsOrdered" validate:"int,mandatory"'
    ProductsAvailable  int           'json:"ProductsAvailable" validate:"int" default:"1"' 
    ProductsSold       int           'json:"ProductsSold" validate:"int"'
    Remarks            string        'json:"Remarks" validate:"string" default :"open for business"'
    Items              []int         'json:"Items" validate:"array=int,range=l-5"'
    Domain             string        'json:"Domain" validate:"url,min=30,max=50"'
    Metadata           interface{}   'json:"Metadata,omitempty"'
}
Validadores de fecha
Antes del validador:
validate:"before=<param>"
El validador anterior valida una propiedad de tipo date para que tenga un valor menor que el especificado en el parámetro.
En este ejemplo, la propiedad ExpiryDate debe ser anterior a "2020-06-26" y, si no, devolverá un error.
Type Supplier struct {
    Supplierld            string       'json:"Supplierld" validate:"string,mandatory" id:"true"'
    RawMaterialAvailable  int          'json:"RawMaterialAvailable" validate:"int,min=0"'
    License               string       'json:"License" validate:"string,min=10"'
    ExpiryDate            date.Date    'json:"ExpiryDate" validate:"date,before=2020-06-26"'
    Active                bool         'json:"Active" validate:"bool" default :"true"'
    Metadata              interface{}  'json:"Metadata,omitempty"'
}
Después del validador:
validate:"after=<param>"
El validador anterior valida una propiedad de tipo date para que tenga un valor mayor que el especificado en el parámetro.
En este ejemplo, la propiedad CompletionDate debe ser posterior a "2020-06-26" y, si no, devolverá un error.
Type Supplier struct {
    Manufacturerld        string       'json:"Manufacturerld" validate:"string,mandatory" id:"true"'
    RawMaterialAvailable  int          'json:"RawMaterialAvailable" validate:"int,max=8"'
    ProductsAvailable     int          'json:"ProductsAvailable" validate:"int"'
    CompletionDate        date.Date    'json:"CompletionDate" validate:"date,after=2020-06-26"'
    Metadata              interface{}  'json:"Metadata,omitempty"'
}
Validador de URL
validate:"url"
El validador de URL validará una propiedad para las cadenas de URL.
En este ejemplo, la propiedad Domain debe ser una URL válida.
type Retailer struct {
    Retailerld         string        'json:"Retailerld" validate:"string,mandatory" id:"true"'   
    ProductsOrdered    int           'json:"ProductsOrdered" validate:"int,mandatory"'
    ProductsAvailable  int           'json:"ProductsAvailable" validate:"int" default:"1"' 
    ProductsSold       int           'json:"ProductsSold" validate:"int"'
    Remarks            string        'json:"Remarks" validate:"string" default :"open for business"'
    Items              []int         'json:"Items" validate:"array=int,range=l-5"'
    Domain             string        'json:"Domain" validate:"string,url,min=30,max=50"'
    Metadata           interface{}   'json:"Metadata,omitempty"'
}
Validador de expresiones regulares
validate:"regexp=<param>"
El validador de expresión regular validará la propiedad para la expresión regular de entrada.
En este ejemplo, la propiedad PhoneNumber se validará para un número móvil según la expresión regular.
type Customer struct {
Customerld      string       'json:"Customerld" validate:"string,mandatory" id:"true"'
Name            string       'json:"Name" validate:"string,mandatory"'
ProductsBought  int          'json:"ProductsBought" validate:"int"'
OfferApplied    int          'json:"OfferApplied" validate :"int,nax=0"'
PhoneNumber     string       'json:"PhoneNumber" validate:"string,regexp=A\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$"'
Received        bool         'json:"Received" validate:"bool"'
Metadata        interface{}  'json:"Metadata,omitempty"'
}
Varios validadores
Se pueden aplicar varios validadores a una propiedad.
En este ejemplo, la propiedad Domain tiene validación para una cadena, URL y longitud de cadena mínima y máxima.
type Retailer struct {
    Retailerld         string        'json:"Retailerld" validate:"string,mandatory" id:"true"'   
    ProductsOrdered    int           'json:"ProductsOrdered" validate:"int,mandatory"'
    ProductsAvailable  int           'json:"ProductsAvailable" validate:"int" default:"1"' 
    ProductsSold       int           'json:"ProductsSold" validate:"int"'
    Remarks            string        'json:"Remarks" validate:"string" default :"open for business"'
    Items              []int         'json:"Items" validate:"array=int,range=l-5"'
    Domain             string        'json:"Domain" validate:"string,url,min=30,max=50"'
    Metadata           interface{}   'json:"Metadata,omitempty"'
}

ORM

La capacidad de persistencia transparente o el ORM simplificado se capturan en la clase Model del objeto Context (Ctx). Si el modelo llama a cualquiera de los siguientes métodos de SDK, acceda a ellos mediante t.Ctx.Model.

Los métodos SDK que implantan ORM son los siguientes:
  • Save: esto llama al método PutState de Hyperledger Fabric
  • Get: esto llama al método GetState de Hyperledger Fabric
  • Update: esto llama al método PutState de Hyperledger Fabric
  • Delete: esto llama al método DeleteState de Hyperledger Fabric
  • History: esto llama al método GetHistoryForKey de Hyperledger Fabric
  • GetByRange: esto llama al método GetStateByRange de Hyperledger Fabric
  • GetByRangeWithPagination: esto llama al método GetStateByRangeWithPagination de Hyperledger Fabric

Métodos de SDK

Los códigos de cadenas de Go implantan la capacidad de persistencia transparente (ORM) con el paquete de modelos.

Note:

A partir de la versión 21.2.3, la forma de acceder a los métodos ORM ha cambiado. Ejecute el comando ochain --version para determinar la versión de Blockchain App Builder.

En versiones anteriores, los métodos ORM se exponían como métodos estáticos en el paquete de modelos. Los métodos ahora se definen en el receptor del modelo, que contiene el resguardo de la transacción. Para llamar a estos métodos, se utiliza el receptor de modelo retenido por el contexto de transacción en el controlador. Estos métodos se denominan t.Ctx.Model.<method_name> en lugar de model.<method_name>.

En el siguiente ejemplo, se muestran las llamadas al método Save y Get en versiones anteriores:

func (t *Controller) CreateSupplier(asset Supplier) (interface{}, error) {
  return model.Save(&asset)
}

func (t *Controller) GetSupplierById(id string) (Supplier, error) {
  var asset Supplier
  _, err := model.Get(id, &asset)
  return asset, err
}

En el siguiente ejemplo, se muestran las llamadas al método Save y Get de la versión 21.2.3 y posteriores:

func (t *Controller) CreateSupplier(asset Supplier) (interface{}, error) {
  return t.Ctx.Model.Save(&asset)
}

func (t *Controller) GetSupplierById(id string) (Supplier, error) {
  var asset Supplier
  _, err := t.Ctx.Model.Get(id, &asset)
  return asset, err
}

Después de actualizar a la versión 21.2.3, realice este cambio en todos los proyectos de código de cadenas que haya creado con una versión anterior de Blockchain App Builder. Si utiliza el comando sync para sincronizar los cambios entre el archivo de especificación y el código fuente, los cambios se llevan automáticamente al controlador para los métodos listos para usar. Aún debe resolver manualmente cualquier conflicto.

Los siguientes métodos ORM se exponen mediante el paquete de modelos:

Get
Consulta la contabilidad del activo almacenado en función del ID especificado.
func Get(Id string, result ...interface{}) (interface{}, error)
Parámetros:
  • Id: ID del activo que se necesita del libro mayor.
  • result (interface{}): objeto de activo vacío de un tipo concreto, que se transfiere por referencia. Este objeto contendrá el resultado de este método. Solo se utilizará si se requiere un resultado específico del tipo.
  • asset (interface): objeto de activo vacío, que se transfiere por referencia. Este objeto contendrá el resultado de este método. Solo se utilizará si se requiere un resultado específico del tipo.
Devuelve:
  • interface {}: la interfaz contiene el activo con el formato map[string]interface{}. Antes de operar en este mapa, es necesario afirmar la interfaz obtenida con el tipo map[string]interface{}. Para convertir esta asignación en un objeto de activo, puede utilizar la API de utilidad util.ConvertMaptoStruct (consulte: Paquete de utilidad).
  • error: contiene un error si se devuelve o es nulo.
Update
Actualiza el activo proporcionado en la contabilidad con los nuevos valores.
func Update(args ...interface{}) (interface{}, error)
Parámetros:
  • obj (interface): el objeto que se debe actualizar en la contabilidad se transfiere por referencia a esta API con los nuevos valores. El activo de entrada se valida y verifica según las etiquetas de estructura mencionadas en la especificación del modelo y, a continuación, se almacena en el libro mayor.
Devuelve:
  • interface{}: el activo guardado se devuelve como una interfaz.
  • error: contiene un error si se devuelve o es nulo.
Save
Guarda el activo en la contabilidad después de validar todas las etiquetas de estructura.
func Save(args ...interface{}) (interface{}, error)
Parámetros:
  • obj/args[0] (interface{}): el objeto que se debe almacenar en el libro mayor se transfiere por referencia en este método de utilidad.
  • metadata/args[1] (interface{}): este parámetro es opcional. Se ha proporcionado con el fin de facilitarle si necesita almacenar metadatos en el libro mayor junto con el activo en tiempo de ejecución. Este parámetro se puede omitir si no existe dicho requisito.
Devuelve:
  • interface {}: el activo se devuelve como una interfaz.
  • error: contiene un error si se devuelve o es nulo.
Delete
Suprime el activo del libro mayor.
func Delete(Id string) (interface{}, error)
Parámetros:
  • id (string): ID del activo que se debe suprimir del libro mayor.
Devuelve:
  • interface {}: contiene el activo que se va a suprimir con el formato map[string]interface{}.
GetByRange
Devuelve la lista de activos por rango de ID.
func GetByRange(startKey string, endKey string, asset ...interface{})
([]map[string]interface{}, error)
Parámetros:
  • startkey (string): ID de inicio para el rango de objetos necesarios.
  • endkey (string): fin del rango de objetos que son necesarios.
  • asset interface: matriz vacía de activos (opcional), que se transfiere por referencia. Esta matriz contendrá el resultado de este método. Se utilizará si se requiere un resultado específico del tipo.
Devuelve:
  • []map[string]interface{}: esta matriz contiene la lista de activos obtenidos del libro mayor. Puede acceder a los objetos que iteran en esta matriz y afirmar los objetos como map[string]interface{} y utilizar la utilidad para convertirlos en objeto de activo.
  • error: contiene un error si se devuelve o es nulo.
GetByRangeWithPagination
El método GetByRangeWithPagination es un método estático de la clase OchainModel que heredan las clases Model concretas de {chaincodeName}.model.ts.
De esta forma, se devuelve una lista de activos entre el rango startId y endId, filtrados por tamaño de página y marcador. Este método llama internamente al método GetStateByRangeWithPagination de Hyperledger Fabric.
Si no se proporciona el parámetro modelName, el método devuelve Promise<Object [ ] >. Si se proporciona el parámetro modelName, el método maneja la conversión en el tipo de emisor de llamada Model. En el siguiente ejemplo, la matriz de resultados es del tipo Supplier. Si el activo devuelto de la contabilidad no es del tipo Model, no se incluirá en la lista. Esta comprobación se realiza mediante la propiedad assetType de solo lectura en la clase Model.
Para devolver todos los activos entre el rango startId y endId, filtrados por tamaño de página y marcadores, utilice el método de controlador genérico getAssetsByRange.
func (m *Model) GetByRangeWithPagination(startKey string, endKey string, pageSize int32, bookmark string, asset ...interface{}) ([]map[string]interface{}, error) 
Parámetros:
  • startkey : string: clave de inicio del rango. Incluido en el rango.
  • endkey : string: clave de finalización del rango. Excluido del rango.
  • pageSize : number: tamaño de página de la consulta.
  • Bookmark : string: marcador de la consulta. La salida comienza desde este marcador.
  • asset interface: (opcional) matriz vacía de activos, transferida por referencia. Esta matriz contendrá el resultado de este método. Utilice este parámetro para obtener resultados específicos del tipo.
Devuelve:
  • []map[string]interface{}: matriz que contiene la lista de activos recuperados del libro mayor. Puede acceder a los objetos iterando en esta matriz y afirmando los objetos como map[string]interface{} y utilizando una utilidad para convertirlos en un objeto de activo.
  • error: contiene un error si se devuelve un error; de lo contrario, es nulo.
GetHistoryById
Devuelve el historial del activo con el ID especificado.
func GetHistoryByID(Id string) ([]interface{}, error)
Parámetros:
  • Id (string): ID del activo para el que se necesita el historial.
Devuelve:
  • []interface{}: esta porción contiene el historial del activo obtenido del libro mayor en forma de porción de map[string]interface{}. Puede acceder a cada elemento del historial iterando en este segmento y afirmando los objetos como map[string]interface{} y utilizando la utilidad para convertirlos en objeto de activo.
  • error: contiene el error si se observa.
Query
El método de consulta ejecutará una consulta de base de datos SQL/Couch a través del libro mayor. Este método solo está soportado para el despliegue remoto en Oracle Blockchain Platform. Se trata de un método genérico para ejecutar consultas SQL en la contabilidad.
func Query(queryString string) ([]interface{}, error)
Parámetros:
  • queryString (string): introduzca la cadena de consulta.
Devuelve:
  • []interface{}: contendrá la salida de la consulta. El resultado es una porción de interfaces. Debe iterar sobre la división y utilizar los elementos convirtiéndolos en tipos adecuados.
  • error: contiene el error si se observa.
QueryWithPagination
El método de consulta ejecutará una consulta de base de datos SQL/Couch sobre el libro mayor, filtrada por tamaño de página y marcador. Este método solo está soportado para el despliegue remoto en Oracle Blockchain Platform. Se trata de un método genérico para ejecutar consultas SQL en la contabilidad.
func (m *Model) QueryWithPagination(queryString string, pageSize int32, bookmark string) ([]interface{}, error)
Parámetros:
  • queryString (string): consulta de base de datos SQL/couch enriquecida.
  • pageSize : number: tamaño de página de la consulta.
  • bookmark : string: marcador de la consulta. La salida comienza desde este marcador.
Devuelve:
  • []interface{}: contendrá la salida de la consulta. El resultado es una porción de interfaces. Debe iterar sobre la división y utilizar los elementos convirtiéndolos en tipos adecuados.
  • error: contiene el error si se observa.
InvokeCrossChaincode
Este método se puede utilizar en un código de cadenas para llamar a una función en otro código de cadenas. Ambos códigos de cadena deben estar instalados en el mismo par.
func InvokeCrossChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
Parámetros:
  • chaincodeName: nombre del código de cadena que se va a llamar.
  • methodName: nombre del método al que llamar en el código de cadena.
  • arg: argumento del método de llamada.
  • channelName: canal en el que se encuentra el código de cadena al que llamar.
Devuelve:
  • interface{}: devuelve un objeto map[string]interface{} que contiene tres claves:
    • isValid: true si la llamada es válida.
    • payload: salida devuelta por la llamada de código de cadenas cruzadas, como un objeto JSON.
    • message: mensaje devuelto por la llamada de código de cadena cruzada, en formato UTF-8.
Ejemplo de valor devuelto:
{
      "isValid": true,
      "message": "Successfully invoked method [CreateAccount] on sub-chaincode [erc721_go_453]",
      "payload": {
                  "AccountId": "oaccount~6b83b8ab931f99442897dd04cd7a2a55f808686f49052a40334afe3753fda4c4",
                  "AssetType": "oaccount",
                  "BapAccountVersion": 0,
                  "NoOfNfts": 0,
                  "OrgId": "appdev",
                  "TokenType": "nonfungible",
                  "UserId": "user2"
      }
}
InvokeChaincode
Este método se puede utilizar en un código de cadenas para llamar a una función en otro código de cadenas. Ambos códigos de cadena deben estar instalados en el mismo par.
func InvokeChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
Parámetros:
  • chaincodeName: nombre del código de cadena que se va a llamar.
  • methodName: nombre del método al que llamar en el código de cadena.
  • arg: argumento del método de llamada.
  • channelName: canal en el que se encuentra el código de cadena al que llamar.
Devuelve:
  • interface{}: devuelve un objeto map[string]interface{} que contiene tres claves:
    • isValid: true si la llamada es válida.
    • payload: salida devuelta por la llamada de código de cadena cruzada, en formato UTF-8.
    • message: mensaje devuelto por la llamada de código de cadena cruzada, en formato UTF-8.
Ejemplo de valor devuelto:
{
    "isValid": true,
    "message": "Successfully invoked method [CreateAccount] on sub-chaincode [erc721_go_453]",
    "payload": "{\"AssetType\":\"oaccount\",\"AccountId\":\"oaccount~c6bd7f8dcc339bf7144ea2e1cf953f8c1df2f28482b87ad7895ac29e7613a58f\",\"UserId\":\"user1\",\"OrgId\":\"appdev\",\"TokenType\":\"nonfungible\",\"NoOfNfts\":0,\"BapAccountVersion\":0}"
} 

Métodos Clave Compuestos

GenerateCompositeKey
Este método genera y devuelve la clave compuesta basada en indexName y los atributos proporcionados en los argumentos.
func GenerateCompositeKey(indexName string, attributes []string)
            (string, error)
Parámetros:
  • indexName (string): tipo de objeto de la clave compuesta.
  • attrbutes ([]string): atributos del activo basados en los que se debe formar la clave compuesta.
Devuelve:
  • string: contiene el resultado de la clave compuesta.
  • error: contiene el error si se observa.
GetByCompositeKey
Este método devuelve el activo que coincide con la clave y la columna proporcionadas en los parámetros. El parámetro index indica el índice de la clave devuelta en la matriz del método stub SplitCompositeKey.
Internamente, este método llama a getStateByPartialCompositeKey, splitCompositeKey y getState de Hyperledger Fabric.
func GetByCompositeKey(key string, columns []string, index int)
                (interface{}, error)
Parámetros:
  • key (string): tipo de objeto proporcionado al crear la clave compuesta.
  • column ([]string): es la porción de atributos en la que se debe consultar la contabilidad mediante la clave compuesta.
  • index(int): índice del atributo.
Devuelve:
  • Interface{}: contiene la lista de activos que son resultado de este método.
  • error: contiene errores si están presentes.

Método de resguardo

GetNetworkStub
Este método devolverá Hyperledger Fabric chaincodeStub.
Puede acceder al stub shim llamando al método GetNetworkStub. Esto le ayudará a escribir su propia implantación trabajando directamente con los activos.
func GetNetworkStub() shim.ChaincodeStubInterface
Parámetros:
  • ninguno
Devuelve:
  • shim.ChaincodeStubInterface: es el stub de código de cadena de Hyperledger Fabric.

Otros métodos

  • GetTransactionId()
  • GetTransactionTimestamp()
  • GetChannelID()
  • GetCreator()
  • GetSignedProposal()
  • GetArgs()
  • GetStringArgs()
  • GetCreatorMspId()
  • GetId
GetTransactionId
Devuelve el ID de transacción para la solicitud de llamada de código de cadena actual. El ID de transacción identifica de manera única la transacción dentro del ámbito del canal.
func GetTransactionId() string
Parámetros:
  • ninguno
Devuelve:
  • string: contiene el ID de transacción necesario.
GetTransactionTimestamp
Devuelve el registro de hora cuando se creó la transacción. Esto se toma de la transacción ChannelHeader, por lo tanto, indicará el registro de hora del cliente y tendrá el mismo valor en todos los avalistas.
func GetTransactionTimestamp() (*timestamp.Timestamp, error)
Parámetros:
  • ninguno
Devuelve:
  • timestamp.Timestamp: contiene el registro de hora necesario.
  • error: contiene errores si están presentes.
GetChannelID
Devuelve el ID de canal de la propuesta para el código de cadena que se va a procesar.
func GetChannelID() string
Parámetros:
  • ninguno
Devuelve:
  • string: contiene el ID de canal necesario como cadena.
GetCreator
Devuelve el objeto de identidad del remitente de la llamada al código de cadena
func GetCreator() ([]byte, error)
Parámetros:
  • ninguno
Devuelve:
  • []byte: contiene el objeto de identidad necesario serializado.
  • error: contiene errores si están presentes.
GetSignedProposal
Devuelve un objeto totalmente descodificado de la propuesta de transacción firmada.
func GetSignedProposal() (*peer.SignedProposal, error)
Parámetros:
  • ninguno
Devuelve:
  • *peer.SignedProposal: contiene el objeto de propuesta firmado necesario.
  • error: contiene errores si están presentes.
GetArgs
Devuelve los argumentos como matriz de cadenas de la solicitud de llamada de código de cadena.
func GetArgs() [][]byte
Parámetros:
  • ninguno
Devuelve:
  • [][]byte: contiene los argumentos transferidos.
GetStringArgs
Devuelve los argumentos previstos para el código de cadena Init y Invoke como una matriz de cadena.
func GetStringArgs() []string
Parámetros:
  • ninguno
Devuelve:
  • []string: contiene los argumentos necesarios como una matriz de cadenas.
GetCreatorMspId
Devuelve el ID de MSP de la identidad de llamada.
func GetCreatorMspId() string
Parámetros:
  • ninguno
Devuelve:
  • string: devuelve el ID de MSP de la identidad de llamada.
GetId
Cuando el activo tiene una clave derivada como Id, puede utilizar este método para obtener un ID derivado. Este método devolverá un error si la clave derivada contiene %t (registro de hora).
Parámetros:
  • object: el objeto debe contener todas las propiedades de las que depende la clave derivada.
Devuelve:
  • Devuelve la clave derivada como una cadena.
Por ejemplo:
func (t *Controller) CustomGetterForSupplier(License string, Name string)(interface{}, error){
   var asset Supplier
   asset.License = License
   asset.Name = Name
   id,err := t.Ctx.Model.GetId(&asset)

   if err !=nil {
      return nil, fmt.Errorf("error in getting ID %v", err.Error())
   }
   return t.GetSupplierById(id)
}

Paquete de utilidades

Los siguientes métodos en el paquete de utilidades pueden ser útiles:

Util.CreateModel
Analiza la cadena JSON proporcionada y crea un objeto de activo del tipo proporcionado.
func CreateModel(obj interface{}, inputString string) error
Parámetros:
  • inputString (string): cadena JSON de entrada desde la que se va a crear el objeto.
  • obj (interface{}): referencia del objeto que se va a crear a partir de la cadena JSON. Este objeto almacenará el modelo creado, que también se valida según las etiquetas del validador.
Devuelve:
  • error: contiene los errores encontrados al crear o validar el activo.
util.ConvertMapToStruct
Convierta la asignación proporcionada en un objeto del tipo proporcionado.
func ConvertMapToStruct(inputMap map[string](interface{}), resultStruct
interface{}) error
Parámetros:
  • inputMap (map[string](interface{})): asignación que se debe convertir en el objeto de activo.
  • resultStruct (interface{}): referencia del objeto de activo necesario que se debe generar a partir del mapa. Contiene el objeto de activo de resultado necesario.
Devuelve:
  • error: contiene los errores encontrados al crear o validar el activo.

Para ver los métodos de SDK de token, consulte los temas de Soporte de tokenización mediante Blockchain App Builder.

Controlador

El archivo Controller.go implementa los métodos CRUD y personalizados para los activos.

Puede crear cualquier número de clases, funciones o archivos, pero solo los métodos definidos en la estructura del código de cadena se pueden invocar desde el exterior, el resto de ellos están ocultos.

Métodos generados automáticamente

Como se describe en Input Specification File (Archivo de especificación de entrada), puede especificar qué métodos CRUD desea generar en el archivo de especificación. Por ejemplo, si ha seleccionado generar todos los métodos, el resultado sería similar a:

//	
//Supplier
//	
func (t *ChainCode) CreateSupplier(inputString string) (interface{}, error) {
    var obj Supplier
    err := util.CreateModel(&obj, inputString)
    if err != nil {
        return nil, err   
    }
    return model.Save(&obj)
}

func (t *ChainCode) GetSupplierById(id string) (interface{}, error) {
    asset, err := model.Get(id) 
    return asset, err
}

func (t *ChainCode) UpdateSupplier(inputString string) (interface{}, error) {
    var obj Supplier
    err := util.CreateModel(&obj, inputstring)
    if err != nil {   
        return nil, err
    }
return model.Update(&obj)
}

func (t *ChainCode) DeleteSupplier(id string) (interface{}, error) { 
    return model.Delete(id)
}

func (t *ChainCode) GetSupplierHistoryById(id string) (interface{}, error) { 
    historyArray, err := model.GetHistoryByld(id) 
    return historyArray, err
}

func (t *ChainCode) GetSupplierByRange(startkey string, endKey string) (interface{}, error) { 
    assetArray, err := model.GetByRange(startkey, endKey) 
    return assetArray, err
}

Métodos personalizados

Los siguientes métodos personalizados se generaron a partir de nuestro archivo de especificación de ejemplo.

executeQuery muestra cómo se pueden llamar a las consultas enriquecidas SQL. Blockchain App Builder agrega automáticamente los validadores de los argumentos en función del tipo de argumento especificado en el archivo de especificación.

Puede implantar la funcionalidad de acuerdo con la lógica de negocio. Si agrega métodos personalizados, agréguelos al archivo del controlador. Si agrega métodos personalizados a la biblioteca en lugar del archivo del controlador, los cambios se perderán cuando el contenido de la carpeta de la biblioteca se actualice durante los procesos de sincronización o actualización del código de cadena.

//	
//Custom Methods
//			
/*
*	BDB sql rich queries can be executed in OBP CS/EE.
*	This method can be invoked only when connected to remote OBP CS/EE network.
*/
func (t *ChainCode) ExecuteQuery(inputQuery string) (interface{}, error) { 
    resultArray, err := model.Query(inputQuery) 
    return resultArray, err
}

func (t *ChainCode) FetchRawMaterial(supplierId string, rawMaterialSupply int) (interface{}, error) {
    return nil, nil
}

func (t *ChainCode) GetRawMaterialFromSupplier(manufacturerId string, supplierId string, rawMaterialSupply int) (interface{} error) { 
    return nil, nil
}

Func (t *ChainCode) CreateProducts(manufacturerId string, rawMaterialConsumed int, productsCreated int) (interface{}, error) { 
    return nil, nil
}

func (t *ChainCode) SendProductsToDistribution() (interface{}, error) { 
    return nil, nil
    }
Para los códigos de cadenas de Go, cada método personalizado debe devolver dos valores: interfaz vacía, error. Por ejemplo:
func (t *Controller) FetchRawMaterial(supplierId string, rawMaterialSupply int) (interface{}, error) { 
    return nil, nil
}

Método de inicialización

En el controlador se proporciona un método Init personalizado con una definición vacía. Si utiliza Blockchain App Builder para desplegar o actualizar, se llama automáticamente al método Init. Si despliega o actualiza desde la consola de Oracle Blockchain Platform, debe llamar al método Init manualmente. Puede utilizar una herramienta de terceros, como Postman, para llamar al método Init manualmente.

type Controller struct {
}
func (t *Controller) Init(args string) (interface{}, error) 
    { return nil, nil
}

Puede utilizar este método para inicializar cualquier estado de aplicación en este punto.