O Blockchain App Builder pega a entrada do seu arquivo de especificação e gera um projeto de chaincode andaime 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 capacidade de persistência transparente (ORM).
Se o projeto chaincode usa o idioma Go, o projeto scaffolded contém três arquivos principais:
main.go
<chaincodeName>.model.go
<chaincodeName>.controller.go
Todas as bibliotecas necessárias sã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 estruturas 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 scaffolded está localizado no diretório $GOPATH/src/example.com/<chaincodeName>
.
Modelo
Propriedade do Tipo de Ativo
Por padrão, cada struct tem uma propriedade adicional chamada
AssetType
. Você pode usar essa propriedade para extrair somente ativos desse tipo. Todas as alterações nesta propriedade são ignoradas quando os ativos são criados ou atualizados. O valor da propriedade por padrão é
<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 nesta chave. Este validador é aplicado automaticamente quando um novo projeto Go é scaffolded.
- No exemplo 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
. Se o parâmetro hash
for especificado, o parâmetro adicional algorithm
será obrigatório. O algoritmo padrão é sha256
; md5
também é suportado.
format
: Usa um array de strings e valores de especificação para 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"
- Este decorador marca a propriedade a seguir como obrigatória, de modo que não possa ser ignorada ao salvar no razão. Se ignorado, um erro é gerado. No exemplo a seguir, a propriedade
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>"
- Este decorador indica que a propriedade a seguir tem um valor padrão. O valor na etiqueta padrão é usado quando a propriedade é ignorada ao salvar no razão. No exemplo a seguir,
Active
tem um valor padrão true
, especificado como a 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 Go são validados para uma propriedade definindo uma tag de validação. As seguintes tags de validação são baseadas nos tipos básicos:
- string:
validate: "string"
- data:
validate: "date"
- número:
validate: "int"
- booliano:
validate: "bool"
-
Validador mínimo
validate:"min=<param>"
- Você pode usar o validador
min
para definir o valor mínimo de uma propriedade do tipo número ou string.
- Para o tipo int: No exemplo a seguir, a propriedade
RawMaterialAvailable
tem um valor mínimo de 0. Se um valor menor que 0 for aplicado à propriedade RawMaterialAvailable
, um erro será retornado.
- Para a string de tipo: O validador mínimo verifica o tamanho da string em relação ao valor especificado. No exemplo a seguir, a propriedade
License
deve ter pelo menos dez 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>"
- Você pode usar o validador máximo para definir o valor máximo para uma propriedade do tipo número e string.
- Para o tipo int: Semelhante ao validador min, se um valor especificado para um campo de estrutura for maior que o valor fornecido no validador, um erro será retornado.
- Para a string de tipo: Semelhante ao validador mínimo, o validador máximo verifica o tamanho da string em relação ao valor fornecido. No exemplo a seguir, a propriedade
Domain
tem um valor máximo de 50, portanto, se a propriedade Domain
tiver um comprimento de string superior a 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 de data
- Antes do validador:
validate:"before=<param>"
- O validador anterior valida uma propriedade do tipo
date
para ter um valor menor que o parâmetro especificado.
- No exemplo a seguir, a propriedade
ExpiryDate
deve ser anterior a "2020-06-26"
e, se não for, um erro será retornado.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"'
}
- Após o validador:
validate:"after=<param>"
- O validador posterior valida uma propriedade do tipo
date
para ter um valor maior que o parâmetro especificado.
- No exemplo a seguir, a propriedade
CompletionDate
deve ser posterior a "2020-06-26"
e, se não for, 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 valida uma propriedade para strings de URL.
- No exemplo a seguir, 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 valida uma propriedade com a expressão regular especificada.
- No exemplo a seguir, a propriedade
PhoneNumber
será validada para 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
- Vários validadores podem ser aplicados a uma propriedade.
- No exemplo a seguir, a propriedade
Domain
tem validação para uma string, um URL e o 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 de Contexto (Ctx
). Se seu modelo chamar qualquer um dos métodos SDK a seguir, acesse-os usando t.Ctx.Model
.
Os seguintes métodos SDK implementam o ORM:
- O
Save
chama o método PutState
do Hyperledger Fabric.
- O
Get
chama o método GetState
do Hyperledger Fabric.
- O
Update
chama o método PutState
do Hyperledger Fabric.
- O
Delete
chama o método DeleteState
do Hyperledger Fabric.
- O
History
chama o método GetHistoryForKey
do Hyperledger Fabric.
- O
GetByRange
chama o método GetStateByRange
do Hyperledger Fabric.
- O
GetByRangeWithPagination
chama o método GetStateByRangeWithPagination
do Hyperledger Fabric.
Métodos SDK
Go chaincodes implementar Transparent Persistence Capability (ORM) com o pacote de modelos.
Observação:
A partir da versão 21.2.3, a maneira de acessar os métodos ORM mudou. Execute o comando
ochain --version
para determinar a versão do Blockchain App Builder.
Em releases anteriores, os métodos ORM foram expostos como métodos estáticos no pacote de modelos. Os métodos agora são definidos no receptor de modelo, que contém o canhoto da transação. Para chamar esses métodos, você usa o modelo receptor mantido pelo contexto da 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 de 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 de 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 alterações entre o arquivo de especificação e o código-fonte, as alterações serão trazidas automaticamente ao controlador para os métodos prontos para uso. Você ainda deverá resolver manualmente quaisquer conflitos.
Os seguintes métodos ORM são expostos pelo pacote de modelos:
-
Get
- Consulta o razão para o ativo armazenado com base no ID fornecido.
-
func Get(Id string, result ...interface{}) (interface{}, error)
- Parâmetros:
Id
- O ID do ativo a ser recuperado do razão.
result (interface{})
- Um objeto de ativo vazio de um tipo específico, que é passado por referência. Este objeto conterá o resultado deste método. Use esse parâmetro somente se for necessário um resultado específico do tipo.
asset (interface)
- Um objeto de ativo vazio, que é passado por referência. Este objeto conterá o resultado deste método. Use esse parâmetro somente se for necessário um resultado específico do tipo.
- Retorna:
interface {}
- A interface contém o ativo no formato map[string]interface{}
. Antes de operar neste mapa, você deve afirmar a interface retornada 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 do Utilitário).
error
- Contém um erro se for retornado ou for nulo.
-
Update
- Atualiza o ativo especificado no razão com novos valores.
-
func Update(args ...interface{}) (interface{}, error)
- Parâmetros:
obj (interface)
- O objeto a ser atualizado no razão é informado por referência nessa API junto com os novos valores. O ativo de entrada é validado e verificado de acordo com as tags de estrutura 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 for retornado ou for 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 a ser armazenado no razão é passado por referência neste método de utilitário.
metadata/args[1] (interface{})
- (Opcional) Você pode usar esse parâmetro para armazenar metadados no razão junto com o ativo no runtime.
- Retorna:
interface {}
- O ativo é retornado como uma interface.
error
- Contém um erro se for retornado ou for nulo.
-
Delete
- Exclui o ativo do razão.
-
func Delete(Id string) (interface{}, error)
- Parâmetros:
id (string)
- O ID do ativo a ser excluído do razão.
- Retorna:
interface {}
- Contém o ativo que está sendo excluído no formulário map[string]interface{}
.
-
GetByRange
- Retorna uma lista de ativos especificados por um 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 a serem recuperados.
endkey (string)
- ID Final do intervalo de objetos a serem recuperados.
asset interface
- (Opcional) Um array vazio de ativos, informado por referência. Essa matriz conterá o resultado do método. Use esse parâmetro se for necessário um resultado específico do tipo.
- 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 um utilitário para converter em um objeto de ativo.
error
- Contém um erro se for retornado ou for nulo.
-
GetByRangeWithPagination
- O método
GetByRangeWithPagination
é um método estático da classe OchainModel
que é herdado pelas classes Model
concretas de {chaincodeName}.model.ts
.
- Esse método 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 no 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 a faixa
startId
e endId
, filtrados por tamanho de página e marcadores, use o método do 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, que é incluída no intervalo.
endkey : string
– Chave final do intervalo, que é excluída do intervalo.
pageSize : number
– O tamanho da página da consulta.
Bookmark : string
– O marcador da consulta. Esta saída começa neste marcador.
asset interface
– (Opcional) Um array vazio de ativos, transmitido por referência. Essa matriz conterá o resultado desse método. Use esse 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.
- 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 esse segmento e afirmando os objetos como map[string]interface{}
e usando um utilitário para converter em objeto de ativo.
error
- Contém o erro se um erro for retornado.
-
Query
- Este método executa uma consulta SQL/Couch DB no razão. Esse método só é suportado para implantações remotas 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)
- A string de consulta.
- Retorna:
[]interface{}
- A saída da consulta na forma de uma fatia de interfaces. Itere no intervalo e utilize os elementos convertendo-os em seus tipos apropriados.
error
- Contém o erro se um erro for retornado.
-
QueryWithPagination
- Este método executa uma consulta SQL/Couch DB no razão, filtrada por tamanho de página e marcador. Esse método só é suportado para implantações remotas 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 Rich SQL/Couch DB.
pageSize : number
- O tamanho da página da consulta.
bookmark : string
- O marcador da consulta. Esta saída começa neste marcador.
- Retorna:
[]interface{}
- A saída da consulta na forma de uma fatia de interfaces. Itere no intervalo e utilize os elementos convertendo-os em seus tipos apropriados.
error
- Contém o erro se um erro for retornado.
-
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 a ser chamado no chaincode.
arg
- O argumento do método de chamada.
channelName
- O canal onde 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 cross-chaincode, como um objeto JSON.
message
- A mensagem retornada pela chamada de código de cadeia cruzada, 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 a ser chamado no chaincode.
arg
- O argumento do método de chamada.
channelName
- O canal onde 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 código de cadeia cruzada, 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 no
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 no qual a chave composta será formada.
- Retorna:
string
- O resultado da chave composta.
error
- Contém o erro se um erro for retornado.
-
GetByCompositeKey
- Este método retorna o ativo que corresponde à chave e à coluna especificadas. O parâmetro
index
indica o índice da chave retornada no array do método stub SplitCompositeKey
.
- Internamente, esse método chama os métodos
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)
- A fatia de atributos na qual o razão será consultado usando a chave composta.
index(int)
- Índice do atributo.
- Retorna:
Interface{}
- A lista de ativos correspondentes.
error
- Contém o erro se um erro for retornado.
Método Stub
-
GetNetworkStub
- Este método retorna o valor
chaincodeStub
do Hyperledger Fabric.
- Você pode acessar o stub do shim chamando o método
GetNetworkStub
. Isso pode ajudá-lo a escrever sua própria implementação que funciona diretamente com ativos.
func GetNetworkStub() shim.ChaincodeStubInterface
- Parâmetros:
- Retorna:
shim.ChaincodeStubInterface
- Stub de chaincode do Hyperledger Fabric.
Outros métodos
GetTransactionId()
GetTransactionTimestamp()
GetChannelID()
GetCreator()
GetSignedProposal()
GetArgs()
GetStringArgs()
GetCreatorMspId()
GetId
-
GetTransactionId
- Este método 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 no escopo do canal.
func GetTransactionId() string
- Parâmetros:
- Retorna:
string
- O ID da transação.
-
GetTransactionTimestamp
- Retorna o timestamp quando a transação foi criada. Como o valor é obtido da transação
ChannelHeader
, ele indica o timestamp do cliente e tem o mesmo valor em todos os endossadores.
func GetTransactionTimestamp() (*timestamp.Timestamp, error)
- Parâmetros:
- Retorna:
timestamp.Timestamp
- O timestamp.
error
- Contém o erro se um erro for retornado.
-
GetChannelID
- Retorna o ID do canal da proposta para o chaincode a ser processado.
func GetChannelID() string
- Parâmetros:
- Retorna:
string
- O ID do canal solicitado no formato de string.
-
GetCreator
- Retorna o objeto de identidade do remetente da chamada de chaincode.
func GetCreator() ([]byte, error)
- Parâmetros:
- Retorna:
[]byte
- O objeto de identidade necessário em formato serializado.
error
- Contém o erro se um erro for retornado.
-
GetSignedProposal
- Retorna um objeto totalmente decodificado da proposta de transação assinada.
func GetSignedProposal() (*peer.SignedProposal, error)
- Parâmetros:
- Retorna:
*peer.SignedProposal
- O objeto de proposta assinado.
error
- Contém o erro se um erro for retornado.
-
GetArgs
- Retorna os argumentos como um array de strings da solicitação de chamada de chaincode.
func GetArgs() [][]byte
- Parâmetros:
- Retorna:
[][]byte
- Os argumentos informados.
-
GetStringArgs
- Retorna os argumentos destinados aos métodos chaincode
Init
e Invoke
como um array de string.
func GetStringArgs() []string
- Parâmetros:
- Retorna:
[]string
- Os argumentos como um array de string.
-
GetCreatorMspId
- Retorna o ID do MSP da identidade de chamada.
-
func GetCreatorMspId() string
- Parâmetros:
- Retorna:
string
- 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
(carimbo de data/hora).
- 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 métodos a seguir são fornecidos no pacote de utilitários.
-
Util.CreateModel
- Faz parse da string JSON especificada e cria um objeto de ativo do tipo especificado.
func CreateModel(obj interface{}, inputString string) error
- Parâmetros:
inputString (string)
- A string JSON de entrada a ser usada para criar o objeto.
obj (interface{})
- A referência do objeto a 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 o erro se um erro for retornado ao criar ou validar o ativo.
-
util.ConvertMapToStruct
- Converta o mapa especificado em um objeto do tipo especificado.
func ConvertMapToStruct(inputMap map[string](interface{}), resultStruct
interface{}) error
- Parâmetros:
inputMap (map[string](interface{}))
- O mapa a ser convertido em um objeto de ativo.
resultStruct (interface{})
- A referência do objeto do ativo a ser criado no mapa.
- Retorna:
error
- Contém o erro se um erro for retornado ao criar ou validar o ativo.
Para métodos de token SDK, consulte os tópicos em Suporte à 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 que são definidos na estrutura chaincode são invocáveis de fora; o resto deles estão ocultos.
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ê optar por gerar todos os métodos, o resultado será semelhante ao seguinte 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
Os métodos personalizados a seguir foram gerados a partir do arquivo de especificação de exemplo.
A função executeQuery
mostra como as consultas rich SQL podem ser chamadas. Os validadores contra os argumentos são adicionados automaticamente pelo Blockchain App Builder com base no tipo do argumento especificado no arquivo de especificação.
É possível implementar a funcionalidade de acordo com a lógica de negócio necessária. Se você adicionar métodos personalizados, adicione-os ao arquivo do controlador. Se você adicionar métodos personalizados à biblioteca em vez do arquivo controlador, suas alterações serão perdidas quando o conteúdo da pasta da biblioteca for atualizado durante os processos de sincronização ou atualização 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:
empty interface e
error, conforme mostrado no seguinte exemplo:
func (t *Controller) FetchRawMaterial(supplierId string, rawMaterialSupply int) (interface{}, error) {
return nil, nil
}
Método Init
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 da console do Oracle Blockchain Platform, 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
}
Em seguida, você pode usar esse método para inicializar qualquer estado do aplicativo.