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 utiliza el lenguaje Go, el proyecto andamiaje contiene tres archivos principales:
main.go
<chaincodeName>.model.go
<chaincodeName>.controller.go
Todas las bibliotecas necesarias están instaladas y empaquetadas.
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 de andamios se encuentra en el directorio $GOPATH/src/example.com/<chaincodeName>
.
Modelo
Propiedad de tipo de activo
Por defecto, cada estructura tiene una propiedad adicional denominada
AssetType
. Puede utilizar esta propiedad para recuperar solo activos de este tipo. Los cambios realizados en esta propiedad se ignoran cuando se crean o actualizan activos. 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 el siguiente ejemplo,
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
. Si se especifica hash
, se necesita el parámetro adicional algorithm
. 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"
- Este decorador marca la siguiente propiedad como obligatoria, por lo que no se puede omitir al guardar en el libro mayor. Si se omite, se devuelve un error. En el siguiente ejemplo, la propiedad
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>"
- Este decorador indica que la siguiente propiedad tiene un valor por defecto. El valor de la etiqueta por defecto se utiliza cuando se omite la propiedad al guardar en el libro mayor. En el siguiente ejemplo,
Active
tiene un valor por defecto de true
, especificado 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. Las siguientes etiquetas de validación se basan en los tipos básicos:
- cadena:
validate: "string"
- fecha:
validate: "date"
- número:
validate: "int"
- booleano:
validate: "bool"
-
Validador mínimo
validate:"min=<param>"
- Puede utilizar el validador
min
para definir el valor mínimo para una propiedad de tipo número o cadena.
- Para el tipo int: en el siguiente ejemplo, la propiedad
RawMaterialAvailable
tiene un valor mínimo de 0. Si se aplica un valor menor que 0 a la propiedad RawMaterialAvailable
, se devolverá un error.
- Para la cadena de tipo: el validador mínimo comprueba la longitud de la cadena con respecto al valor especificado. En el siguiente ejemplo, la propiedad
License
debe tener al menos diez caracteres.
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>"
- Puede utilizar el validador máximo para definir el valor máximo para una propiedad de tipo número y cadena.
- Para el tipo int: similar al validador mínimo, si un valor especificado para un campo de estructura es mayor que el valor proporcionado en el validador, se devuelve un error.
- Para la cadena de tipo: de forma similar al validador mínimo, el validador máximo comprueba la longitud de la cadena con respecto al valor proporcionado. En el siguiente ejemplo, la propiedad
Domain
tiene un valor máximo de 50, por lo que si la propiedad Domain
tiene una longitud de cadena de más de 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 parámetro especificado.
- En el siguiente ejemplo, la propiedad
ExpiryDate
debe ser anterior a "2020-06-26"
y, si no lo es, se devuelve 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 after valida una propiedad de tipo
date
para que tenga un valor mayor que el parámetro especificado.
- En el siguiente 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 valida una propiedad para cadenas de URL.
- En el siguiente 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 regexp valida una propiedad con la expresión regular especificada.
- En el siguiente ejemplo, la propiedad
PhoneNumber
se validará para un número móvil de acuerdo con 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 el siguiente ejemplo, la propiedad
Domain
tiene validación para una cadena, una URL y una 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 siguientes métodos SDK implantan ORM:
Save
llama al método PutState
de Hyperledger Fabric.
Get
llama al método GetState
de Hyperledger Fabric.
Update
llama al método PutState
de Hyperledger Fabric.
Delete
llama al método DeleteState
de Hyperledger Fabric.
History
llama al método GetHistoryForKey
de Hyperledger Fabric.
GetByRange
llama al método GetStateByRange
de Hyperledger Fabric.
GetByRangeWithPagination
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 los conflictos.
Los siguientes métodos ORM se exponen en 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 va a recuperar 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. Utilice este parámetro solo si se necesita 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. Utilice este parámetro solo si se necesita un resultado específico del tipo.
- Devuelve:
interface {}
: la interfaz contiene el activo en formato map[string]interface{}
. Antes de operar en este mapa, debe confirmar la interfaz devuelta 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 especificado en la contabilidad con nuevos valores.
-
func Update(args ...interface{}) (interface{}, error)
- Parámetros:
obj (interface)
: el objeto que se va a actualizar en la contabilidad se transfiere por referencia a esta API junto con los nuevos valores. El activo de entrada se valida y verifica según las etiquetas de estructura de 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 va a almacenar en el libro mayor se transfiere por referencia en este método de utilidad.
metadata/args[1] (interface{})
: (opcional) puede utilizar este parámetro para almacenar metadatos en el libro mayor junto con el activo en tiempo de ejecución.
- 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 va a suprimir del libro mayor.
- Devuelve:
interface {}
: contiene el activo que se va a suprimir en el formulario map[string]interface{}
.
-
GetByRange
- Devuelve una lista de activos especificados por un rango de ID.
-
func GetByRange(startKey string, endKey string, asset ...interface{})
([]map[string]interface{}, error)
- Parámetros:
startkey (string)
: ID de inicio del rango de objetos que se va a recuperar.
endkey (string)
: ID final del rango de objetos que se recuperarán.
asset interface
: (opcional) matriz vacía de activos, transferida por referencia. Esta matriz contendrá el resultado del método. Utilice este parámetro si se necesita 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 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 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
.
- Este método 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, que se incluye en el rango.
endkey : string
: clave de finalización del rango, que se excluye 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.
- 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 una utilidad para convertirlos en objeto de activo.
error
: contiene el error si se devuelve un error.
-
Query
- Este método ejecuta una consulta SQL/Couch DB en el libro mayor. Este método solo está soportado para despliegues remotos 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)
: cadena de consulta.
- Devuelve:
[]interface{}
: salida de consulta en forma de un segmento de interfaces. Itere sobre la porción y utilice los elementos convirtiéndolos en sus tipos adecuados.
error
: contiene el error si se devuelve un error.
-
QueryWithPagination
- Este método ejecuta una consulta SQL/Couch DB en el libro mayor, filtrada por tamaño de página y marcador. Este método solo está soportado para despliegues remotos 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{}
: salida de consulta en forma de un segmento de interfaces. Itere sobre la porción y utilice los elementos convirtiéndolos en sus tipos adecuados.
error
: contiene el error si se devuelve un error.
-
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 en función del cual se formará la clave compuesta.
- Devuelve:
string
: resultado de la clave compuesta.
error
: contiene el error si se devuelve un error.
-
GetByCompositeKey
- Este método devuelve el activo que coincide con la clave y la columna especificadas. 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 los métodos
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)
: porción de atributos en la que se consultará el libro mayor mediante la clave compuesta.
index(int)
: índice del atributo.
- Devuelve:
Interface{}
: lista de activos coincidentes.
error
: contiene el error si se devuelve un error.
Método de resguardo
-
GetNetworkStub
- Este método devuelve el valor
chaincodeStub
de Hyperledger Fabric.
- Puede acceder al stub shim llamando al método
GetNetworkStub
. Esto puede ayudarle a escribir su propia implantación que funcione directamente con los activos.
func GetNetworkStub() shim.ChaincodeStubInterface
- Parámetros:
- Devuelve:
shim.ChaincodeStubInterface
: código de cadena de Hyperledger Fabric stub.
Otros métodos
GetTransactionId()
GetTransactionTimestamp()
GetChannelID()
GetCreator()
GetSignedProposal()
GetArgs()
GetStringArgs()
GetCreatorMspId()
GetId
-
GetTransactionId
- Este método 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 en el ámbito del canal.
func GetTransactionId() string
- Parámetros:
- Devuelve:
string
: ID de transacción.
-
GetTransactionTimestamp
- Devuelve el registro de hora cuando se creó la transacción. Puesto que el valor se toma de la transacción
ChannelHeader
, indica el registro de hora del cliente y tiene el mismo valor en todos los avalistas.
func GetTransactionTimestamp() (*timestamp.Timestamp, error)
- Parámetros:
- Devuelve:
timestamp.Timestamp
: registro de hora.
error
: contiene el error si se devuelve un error.
-
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:
- Devuelve:
string
: ID de canal solicitado en formato de cadena.
-
GetCreator
- Devuelve el objeto de identidad del remitente de la llamada al código de cadena.
func GetCreator() ([]byte, error)
- Parámetros:
- Devuelve:
[]byte
: objeto de identidad necesario en formato serializado.
error
: contiene el error si se devuelve un error.
-
GetSignedProposal
- Devuelve un objeto totalmente descodificado de la propuesta de transacción firmada.
func GetSignedProposal() (*peer.SignedProposal, error)
- Parámetros:
- Devuelve:
*peer.SignedProposal
: objeto de propuesta firmado.
error
: contiene el error si se devuelve un error.
-
GetArgs
- Devuelve los argumentos como una matriz de cadenas de la solicitud de llamada de código de cadena.
func GetArgs() [][]byte
- Parámetros:
- Devuelve:
[][]byte
: argumentos transferidos.
-
GetStringArgs
- Devuelve los argumentos destinados para los métodos de código de cadena
Init
y Invoke
como una matriz de cadenas.
func GetStringArgs() []string
- Parámetros:
- Devuelve:
[]string
: argumentos como matriz de cadenas.
-
GetCreatorMspId
- Devuelve el ID de MSP de la identidad de llamada.
-
func GetCreatorMspId() string
- Parámetros:
- Devuelve:
string
: 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 devuelve 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 se proporcionan en el paquete de utilidades.
-
Util.CreateModel
- Analiza la cadena JSON especificada y crea un objeto de activo del tipo especificado.
func CreateModel(obj interface{}, inputString string) error
- Parámetros:
inputString (string)
: cadena JSON de entrada que se utilizará para 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 de acuerdo con las etiquetas de validador.
- Devuelve:
error
: contiene el error si se devuelve un error al crear o validar el activo.
-
util.ConvertMapToStruct
- Convertir el mapa especificado en un objeto del tipo especificado.
func ConvertMapToStruct(inputMap map[string](interface{}), resultStruct
interface{}) error
- Parámetros:
inputMap (map[string](interface{}))
: asignación que se va a convertir en un objeto de activo.
resultStruct (interface{})
: referencia del objeto de activo que se va a crear a partir de la asignación.
- Devuelve:
error
: contiene el error si se devuelve un error 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 elige generar todos los métodos, el resultado sería similar al siguiente código:
//
//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 del archivo de especificación de ejemplo.
La función 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 necesaria. 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 Go, cada método personalizado debe devolver dos valores:
empty interface y
error, como se muestra en el siguiente 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
}
A continuación, puede utilizar este método para inicializar cualquier estado de aplicación.