O Blockchain App Builder pega a entrada do seu arquivo de especificação e gera um projeto de chaincode com andaimes totalmente funcional. O projeto contém classes e funções geradas automaticamente, métodos CRUD, métodos SDK, validação automática de argumentos, marshalling/un-marshalling e recurso de persistência transparente (ORM).
Se o projeto chaincode estiver na linguagem Go, o projeto scaffolded contém três arquivos principais:
main.go
<chaincodeName>.model.go
<chaincodeName>.controller.go
Todas as bibliotecas necessárias estão instaladas e empacotadas.
O arquivo <chaincodeName>.model.go
no subdiretório model
contém várias definições de ativos e o arquivo <chaincodeName>.controller.go
no subdiretório controller
contém o comportamento do ativo e os métodos CRUD. As várias tags e pacotes de estrutura Go em model.go
e controller.go
fornecem suporte para recursos como validação automática de argumentos, marshalling/unmarshalling de argumentos, recurso de persistência transparente (ORM) e chamada de consultas avançadas.
O projeto de andaimes pode ser encontrado em $GOPATH/src/example.com/<chaincodeName>
Modelo
Propriedade do Tipo de Ativo
Por padrão, cada struct terá uma propriedade adicional chamada
AssetType
. Essa propriedade pode ser útil na extração apenas de ativos desse tipo. Todas as alterações nesta propriedade são ignoradas durante a criação e atualização do ativo. Por padrão, o valor da propriedade é
<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 a propriedade que define exclusivamente o ativo subjacente. O ativo é salvo pelo valor desta chave. Este validador se aplica automaticamente quando um novo projeto Go é montado.
- Na captura de tela a seguir,
"SupplierId"
é a chave do ativo do fornecedor e tem uma propriedade de tag id:"true"
para a propriedade 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 é usado para definir o atributo derivado de outras propriedades. Este decorador tem dois parâmetros obrigatórios:
strategy
: obtém valores de concat
ou hash
. Requer um parâmetro adicional algorithm
se hash
estiver selecionado. O algoritmo padrão é sha256
; md5
também é suportado.
format
: usa um array de strings de especificação e valores a serem usados pela estratégia.
-
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"'
}
-
Obrigatória
validate:"mandatory"
- Isso marca a seguinte propriedade como obrigatória e não pode ser ignorada ao salvar no razão. Se ignorado, ele gera um erro. No exemplo abaixo,
"SupplierId"
tem uma tag 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"'
}
-
Padrão
default:"<param>"
- Isso indica que a propriedade a seguir pode ter um valor padrão. O valor padrão na tag padrão é usado quando a propriedade é ignorada ao salvar no razão. Na propriedade de exemplo abaixo,
Active
tem um valor padrão de true
, fornecido como tag 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"'
}
-
Validar tipos
- Os tipos Básicos de Ir são validados para uma propriedade definindo uma tag de validação. Estas são as tags de validação com base nos tipos:
- string:
validate: "string"
- data:
validate: "date"
- número:
validate: "int"
- booleano:
validate: "bool"
-
Validador mínimo
validate:"min=<param>"
- Usando o validador mínimo, o valor mínimo pode ser definido para uma propriedade do tipo número e string.
- Para o tipo int: No exemplo, a propriedade
RawMaterialAvailable
tem um valor mínimo de 0 e, se um valor menor que 0 for aplicado a RawMaterialAvailable
, um erro será retornado.
- Para string de tipo: Para o validador mínimo de tipo de string, verifique o tamanho da string com o valor fornecido. Portanto, no exemplo abaixo, a propriedade
License
deve ter no mínimo 10 caracteres.
- Exemplo:
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>"
- Usando o validador máximo, o valor máximo pode ser definido para uma propriedade do tipo número e string.
- Para o tipo int: Como o validador min, para o tipo int, se um valor fornecido para
structfield
for maior que o valor fornecido no validador, um erro será retornado.
- Para string de tipo: Como o validador mínimo, o validador máximo também verificará o tamanho da string com o valor fornecido. No exemplo, a propriedade
Domain
tem um valor máximo de 50; portanto, se a propriedade Domain
tiver uma string com mais de 50 caracteres, uma mensagem de erro será retornada.
-
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 da data
- Antes do validador:
validate:"before=<param>"
- O validador anterior valida uma propriedade do tipo
date
para ter um valor menor que o especificado no parâmetro.
- Neste exemplo, a propriedade
ExpiryDate
deve ser anterior a "2020-06-26"
e, caso contrário, retornará um erro.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"'
}
- Depois do validador:
validate:"after=<param>"
- O validador anterior valida uma propriedade do tipo
date
para ter um valor maior que o especificado no parâmetro.
- Neste exemplo, a propriedade
CompletionDate
deve ser posterior a "2020-06-26"
e, caso contrário, retornará um erro.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"
- O validador de URL validará uma propriedade para strings de URL.
- Neste exemplo, a propriedade
Domain
deve ser um URL válido.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 Regexp
validate:"regexp=<param>"
- O validador Regexp validará a propriedade para a expressão regular de entrada.
- Neste exemplo, a propriedade
PhoneNumber
validará um número de celular de acordo com a expressão 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"'
}
-
Vários validadores
- É possível aplicar uma propriedade a vários validadores.
- Neste exemplo, a propriedade
Domain
tem validação para uma string, URL e tamanho mínimo e máximo da string.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
O Recurso de Persistência Transparente ou ORM simplificado é capturado na classe Model
do objeto Context (Ctx
). Se seu modelo chamar qualquer um dos métodos SDK a seguir, acesse-os usando t.Ctx.Model
.
Os métodos SDK que implementam o ORM são os seguintes:
Save
- chama o método PutState
do Hyperledger Fabric
Get
- chama o método GetState
do Hyperledger Fabric
Update
- chama o método PutState
do Hyperledger Fabric
Delete
- chama o método DeleteState
do Hyperledger Fabric
History
- chama o método GetHistoryForKey
do Hyperledger Fabric
GetByRange
- chama o método GetStateByRange
do Hyperledger Fabric
GetByRangeWithPagination
- chama o método GetStateByRangeWithPagination
do Hyperledger Fabric
Métodos SDK
Os chaincodes Go implementam o Recurso de Persistência Transparente (ORM) com o pacote de modelos.
Observação:
A partir da versão 21.2.3, a forma de acessar os métodos ORM foi alterada. Execute o comando
ochain --version
para determinar a versão do Blockchain App Builder.
Em versões anteriores, os métodos ORM eram expostos como métodos estáticos no pacote de modelos. Os métodos agora são definidos no receptor do modelo, que contém o stub da transação. Para chamar esses métodos, você usa o receptor de modelo mantido pelo contexto de transação no controlador. Você chama esses métodos como t.Ctx.Model.<method_name>
em vez de model.<method_name>
.
O exemplo a seguir mostra as chamadas do método Save
e Get
nas versões 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
}
O exemplo a seguir mostra as chamadas do método Save
e Get
da versão 21.2.3 e posterior:
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
}
Depois de fazer upgrade para a versão 21.2.3, faça essa alteração em todos os projetos de chaincode que você criou com uma versão anterior do Blockchain App Builder. Se você usar o comando sync
para sincronizar as alterações entre o arquivo de especificação e o código-fonte, as alterações serão trazidas automaticamente ao seu controlador para os métodos prontos para uso. Você ainda precisa resolver manualmente quaisquer conflitos.
Os seguintes métodos ORM são expostos por meio do pacote de modelos:
-
Get
- Consulta o razão do ativo armazenado com base no ID fornecido.
-
func Get(Id string, result ...interface{}) (interface{}, error)
- Parâmetros:
Id
- O ID do ativo que é necessário do razão.
result (interface{})
- Este é um objeto de ativo vazio de um tipo específico, que é passado por referência. Este objeto conterá o resultado deste método. A ser usado somente se o resultado específico do tipo for obrigatório.
asset (interface)
- Objeto de ativo vazio, que é passado por referência. Este objeto conterá o resultado deste método. A ser usado somente se o resultado específico do tipo for obrigatório.
- Retorna:
interface {}
- A interface contém o ativo na forma de map[string]interface{}
. Antes de operar neste mapa, é necessário afirmar a interface obtida com o tipo map[string]interface{}
. Para converter esse mapa em um objeto de ativo, você pode usar a API do utilitário util.ConvertMaptoStruct
(consulte: Pacote de Utilitários).
error
- Contém um erro, se retornado, ou nulo.
-
Update
- Atualiza o ativo fornecido no razão com os novos valores.
-
func Update(args ...interface{}) (interface{}, error)
- Parâmetros:
obj (interface)
- O objeto que precisa ser atualizado no razão é passado por referência a essa API com os novos valores. O ativo de entrada é validado e verificado de acordo com as tags de estrutura mencionadas na especificação do modelo e, em seguida, armazenado no razão.
- Retorna:
interface{}
- O ativo salvo é retornado como uma interface.
error
- Contém um erro, se retornado, ou nulo.
-
Save
- Salva o ativo no razão após a validação em todas as tags de estrutura.
-
func Save(args ...interface{}) (interface{}, error)
- Parâmetros:
obj/args[0] (interface{})
- O objeto que precisa ser armazenado no razão é passado por referência neste método do utilitário.
metadata/args[1] (interface{})
- Esse parâmetro é opcional. Ele foi fornecido para facilitar se você precisar armazenar quaisquer metadados no razão juntamente com o ativo no runtime. Este parâmetro poderá ser ignorado se não existir tal requisito.
- Retorna:
interface {}
- O ativo é retornado como uma interface.
error
- Contém um erro, se retornado, ou nulo.
-
Delete
- Deleta o ativo do razão.
-
func Delete(Id string) (interface{}, error)
- Parâmetros:
id (string)
- O ID do ativo que deve ser excluído do razão.
- Retorna:
interface {}
- Contém o ativo que está sendo excluído na forma de map[string]interface{}
.
-
GetByRange
- Retorna a lista de ativos por intervalo de IDs.
-
func GetByRange(startKey string, endKey string, asset ...interface{})
([]map[string]interface{}, error)
- Parâmetros:
startkey (string)
- ID Inicial do intervalo de objetos que são obrigatórios.
endkey (string)
- Fim da faixa de objetos que são obrigatórios.
asset interface
- (opcional) Array vazio de ativos, que é passado por referência. Essa matriz conterá o resultado desse método. A ser usado se o resultado específico do tipo for obrigatório.
- Retorna:
[]map[string]interface{}
- Esse array contém a lista de ativos obtidos do razão. Você pode acessar os objetos iterando sobre esse array e afirmando os objetos como map[string]interface{}
e usando o utilitário para converter em objeto de ativo.
error
- Contém um erro, se retornado, ou nulo.
-
GetByRangeWithPagination
- O método
GetByRangeWithPagination
é um método estático da classe OchainModel
que é herdado pelas classes Model
concretas de {chaincodeName}.model.ts
.
- Isso retorna uma lista de ativos entre o intervalo
startId
e endId
, filtrados por tamanho de página e marcador. Esse método chama o método GetStateByRangeWithPagination
do Hyperledger Fabric internamente.
- Se o parâmetro
modelName
não for fornecido, o método retornará Promise<Object [ ] >
. Se o parâmetro modelName
for fornecido, o método tratará a conversão para o tipo Model
do chamador. No exemplo a seguir, o array de resultados é do tipo Supplier
. Se o ativo retornado do razão não for do tipo Model
, ele não será incluído na lista. Essa verificação é feita pela propriedade assetType
somente para leitura na classe Model
.
- Para retornar todos os ativos entre o intervalo
startId
e endId
, filtrados por tamanho de página e marcadores, use o 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
- Chave inicial do intervalo. Incluído no intervalo.
endkey : string
- Chave final do intervalo. Excluído do intervalo.
pageSize : number
- O tamanho da página da consulta.
Bookmark : string
- O marcador da consulta. A saída começa com este marcador.
asset interface
- (Opcional) Um array vazio de ativos, passado por referência. Essa matriz conterá o resultado desse método. Use este parâmetro para obter resultados específicos do tipo.
- Retorna:
[]map[string]interface{}
- Um array que contém a lista de ativos recuperados do razão. Você pode acessar os objetos iterando sobre esse array e afirmando os objetos como map[string]interface{}
e usando um utilitário para conversão em um objeto de ativo.
error
- Contém um erro se um erro for retornado, caso contrário, é nulo.
-
GetHistoryById
- Retorna o histórico do ativo com o ID fornecido.
-
func GetHistoryByID(Id string) ([]interface{}, error)
- Parâmetros:
Id (string)
- ID do ativo para o qual o histórico é necessário.
- Retorna:
[]interface{}
- Esta fatia contém o histórico do ativo obtido do razão na forma de fatia de map[string]interface{}
. Você pode acessar cada elemento de histórico iterando sobre essa fatia e afirmando os objetos como map[string]interface{}
e usando o utilitário para converter em objeto de ativo.
error
- Contém o erro, se observado.
-
Query
- O método de consulta executará uma consulta SQL/Couch DB sobre o razão. Esse método só é suportado para implantação remota no Oracle Blockchain Platform. Este é um método genérico para executar consultas SQL no razão.
-
func Query(queryString string) ([]interface{}, error)
- Parâmetros:
queryString (string)
- Informe a string de consulta.
- Retorna:
[]interface{}
- conterá a saída da consulta. O resultado é na forma de segmento de interfaces. É necessário iterar sobre o intervalo e utilizar os elementos convertendo-os em tipos apropriados.
error
- Contém o erro, se observado.
-
QueryWithPagination
- O método de consulta executará uma consulta SQL/Couch DB sobre o razão, filtrada por tamanho de página e marcador. Esse método só é suportado para implantação remota no Oracle Blockchain Platform. Este é um método genérico para executar consultas SQL no razão.
-
func (m *Model) QueryWithPagination(queryString string, pageSize int32, bookmark string) ([]interface{}, error)
- Parâmetros:
queryString (string)
- Consulta avançada de SQL/Couch DB.
pageSize : number
- O tamanho da página da consulta.
bookmark : string
- O marcador da consulta. A saída começa com este marcador.
- Retorna:
[]interface{}
- conterá a saída da consulta. O resultado é na forma de segmento de interfaces. É necessário iterar sobre o intervalo e utilizar os elementos convertendo-os em tipos apropriados.
error
- Contém o erro, se observado.
-
InvokeCrossChaincode
- Você pode usar esse método em um chaincode para chamar uma função em outro chaincode. Ambos os chaincodes devem ser instalados no mesmo par.
-
func InvokeCrossChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
- Parâmetros:
chaincodeName
- O nome do chaincode a ser chamado.
methodName
- O nome do método para chamar no chaincode.
arg
- O argumento do método de chamada.
channelName
- O canal no qual o chaincode a ser chamado está localizado.
- Retorna:
interface{}
- Retorna um objeto map[string]interface{}
que contém três chaves:
isValid
- true
se a chamada for válida.
payload
- A saída retornada pela chamada de cross-chaincode, como um objeto JSON.
message
- A mensagem retornada pela chamada de cross-chaincode, no formato UTF-8.
- Exemplo de Valor de Retorno:
{
"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
- Você pode usar esse método em um chaincode para chamar uma função em outro chaincode. Ambos os chaincodes devem ser instalados no mesmo par.
-
func InvokeChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
- Parâmetros:
chaincodeName
- O nome do chaincode a ser chamado.
methodName
- O nome do método para chamar no chaincode.
arg
- O argumento do método de chamada.
channelName
- O canal no qual o chaincode a ser chamado está localizado.
- Retorna:
interface{}
- Retorna um objeto map[string]interface{}
que contém três chaves:
isValid
- true
se a chamada for válida.
payload
- A saída retornada pela chamada de código de cadeia cruzada, no formato UTF-8.
message
- A mensagem retornada pela chamada de cross-chaincode, no formato UTF-8.
- Exemplo de Valor de Retorno:
{
"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 de Chave Composta
-
GenerateCompositeKey
- Esse método gera e retorna a chave composta com base em
indexName
e nos atributos fornecidos nos argumentos.
func GenerateCompositeKey(indexName string, attributes []string)
(string, error)
- Parâmetros:
indexName (string)
- Tipo de objeto da chave composta.
attrbutes ([]string)
- Atributos do ativo com base nos quais a chave composta deve ser formada.
- Retorna:
string
- Contém o resultado da chave composta.
error
- Contém o erro, se observado.
-
GetByCompositeKey
- Este método retorna o ativo que corresponde à chave e à coluna fornecidas nos parâmetros. O parâmetro
index
indica o índice da chave retornada no array do método stub SplitCompositeKey
.
- Internamente, esse método chama
getStateByPartialCompositeKey
, splitCompositeKey
e getState
do Hyperledger Fabric.
func GetByCompositeKey(key string, columns []string, index int)
(interface{}, error)
- Parâmetros:
key (string)
- Tipo de objeto fornecido ao criar a chave composta.
column ([]string)
- Esta é a fatia de atributos na qual o razão deve ser consultado usando a chave composta.
index(int)
- Índice do atributo.
- Retorna:
Interface{}
- Contém a lista de ativos que são resultado desse método.
error
- Contém erros, se houver.
Método Stub
-
GetNetworkStub
- Este método retornará o Hyperledger Fabric
chaincodeStub
.
- Você pode obter acesso ao stub de shim chamando o método
GetNetworkStub
. Isso ajudará você a escrever sua própria implementação trabalhando diretamente com os ativos.
func GetNetworkStub() shim.ChaincodeStubInterface
- Parâmetros:
- Retorna:
shim.ChaincodeStubInterface
- Este é o stub de chaincode do Hyperledger Fabric.
Outros Métodos
GetTransactionId()
GetTransactionTimestamp()
GetChannelID()
GetCreator()
GetSignedProposal()
GetArgs()
GetStringArgs()
GetCreatorMspId()
GetId
-
GetTransactionId
- Retorna o ID da transação para a solicitação de chamada de chaincode atual. O ID da transação identifica exclusivamente a transação dentro do escopo do canal.
func GetTransactionId() string
- Parâmetros:
- Retorna:
string
- Contém o ID de transação necessário.
-
GetTransactionTimestamp
- Retorna o timestamp quando a transação foi criada. Isso é retirado da transação
ChannelHeader
, portanto, indicará o timestamp do cliente e terá o mesmo valor em todos os endossadores.
func GetTransactionTimestamp() (*timestamp.Timestamp, error)
- Parâmetros:
- Retorna:
timestamp.Timestamp
- Contém o timestamp necessário.
error
- Contém erros, se houver.
-
GetChannelID
- Retorna o ID do canal da proposta para o chaincode processar.
func GetChannelID() string
- Parâmetros:
- Retorna:
string
- Contém o ID de canal necessário como uma string.
-
GetCreator
- Retorna o objeto de identidade do remetente da chamada de chaincode.
func GetCreator() ([]byte, error)
- Parâmetros:
- Retorna:
[]byte
- Contém o objeto de identidade necessário serializado.
error
- Contém erros, se houver.
-
GetSignedProposal
- Retorna um objeto totalmente decodificado da proposta de transação assinada.
func GetSignedProposal() (*peer.SignedProposal, error)
- Parâmetros:
- Retorna:
*peer.SignedProposal
- Contém o objeto de proposta assinado necessário.
error
- Contém erros, se houver.
-
GetArgs
- Retorna os argumentos como array de strings da solicitação de chamada de chaincode.
func GetArgs() [][]byte
- Parâmetros:
- Retorna:
[][]byte
- Contém os argumentos informados.
-
GetStringArgs
- Retorna os argumentos destinados ao chaincode Init e Invoke como um array de string.
func GetStringArgs() []string
- Parâmetros:
- Retorna:
[]string
- Contém os argumentos necessários como um array de string.
-
GetCreatorMspId
- Retorna o ID do MSP da identidade de chamada.
-
func GetCreatorMspId() string
- Parâmetros:
- Retorna:
string
- Retorna o ID do MSP da identidade de chamada.
-
GetId
- Quando o ativo tiver uma chave derivada como
Id
, você poderá usar esse método para obter um ID derivado. Este método retornará um erro se a chave derivada contiver %t
(timestamp).
- Parâmetros:
object
- O objeto deve conter todas as propriedades das quais a chave derivada é dependente.
- Retorna:
- Retorna a chave derivada como uma string.
- Exemplo:
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)
}
Pacote de Utilitários
Os seguintes métodos no pacote do utilitário podem ser úteis:
-
Util.CreateModel
- Analisa a string JSON fornecida e cria um objeto de ativo do tipo fornecido.
func CreateModel(obj interface{}, inputString string) error
- Parâmetros:
inputString (string)
- A string JSON de entrada da qual o objeto deve ser criado.
obj (interface{})
- A referência do objeto que será criado com base na string JSON. Este objeto armazenará o modelo criado, que também é validado de acordo com as tags do validador.
- Retorna:
error
- Contém os erros encontrados durante a criação ou validação do ativo.
-
util.ConvertMapToStruct
- Converta o mapa fornecido em objeto do tipo fornecido.
func ConvertMapToStruct(inputMap map[string](interface{}), resultStruct
interface{}) error
- Parâmetros:
inputMap (map[string](interface{}))
- Mapa que precisa ser convertido no objeto do ativo.
resultStruct (interface{})
- A referência do objeto de ativo necessário que precisa ser gerado a partir do mapa. Contém o objeto do ativo de resultado necessário.
- Retorna:
error
- Contém os erros encontrados durante a criação ou validação do ativo.
Para métodos SDK de token, consulte os tópicos em Suporte a Tokenização Usando o Blockchain App Builder.
Controladora
O arquivo Controller.go
implementa o CRUD e os métodos personalizados para os ativos.
Você pode criar qualquer número de classes, funções ou arquivos, mas apenas os métodos definidos na estrutura do chaincode podem ser invocados de fora, o restante deles está oculto.
Métodos Gerados Automaticamente
Conforme descrito em Arquivo de Especificação de Entrada, você pode especificar quais métodos CRUD deseja gerar no arquivo de especificação. Por exemplo, se você selecionou gerar todos os métodos, o resultado seria semelhante 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
Os métodos personalizados a seguir foram gerados a partir de nosso arquivo de especificação de exemplo.
O executeQuery
mostra como as consultas ricas em SQL podem ser chamadas. Os validadores contra os argumentos são adicionados automaticamente pelo Blockchain App Builder com base no tipo de argumento especificado no arquivo de especificação.
É possível implementar a funcionalidade de acordo com a lógica de negócios. Se você adicionar métodos personalizados, adicione-os ao arquivo do controlador. Se você adicionar métodos personalizados à biblioteca em vez do arquivo do controlador, suas alterações serão perdidas quando o conteúdo da pasta da biblioteca for atualizado durante os processos de sincronização ou upgrade de chaincode.
//
//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 chaincodes Go, cada método personalizado deve retornar dois valores:
interface vazia,
erro. Por exemplo:
func (t *Controller) FetchRawMaterial(supplierId string, rawMaterialSupply int) (interface{}, error) {
return nil, nil
}
Método Inicial
Um método Init
personalizado é fornecido no controlador com uma definição vazia. Se você usar o Blockchain App Builder para implantar ou fazer upgrade, o método Init
será chamado automaticamente. Se você implantar ou fazer upgrade do console do Oracle Blockchain Platform na plataforma Hyperledger Fabric v1.4.7, o método Init
também será chamado automaticamente. Se você implantar ou fazer upgrade do console do Oracle Blockchain Platform na plataforma Hyperledger Fabric v2.x, deverá chamar o método Init
manualmente. Você pode usar uma ferramenta de terceiros, como Postman, para chamar o método Init
manualmente.
type Controller struct {
}
func (t *Controller) Init(args string) (interface{}, error)
{ return nil, nil
}
Se você quiser inicializar qualquer estado do aplicativo neste momento, poderá usar esse método para fazer isso.