Blockchain App Builder prende l'input dal file delle specifiche e genera un progetto di codice concatenato impalcato completamente funzionale. Il progetto contiene classi e funzioni generate automaticamente, metodi CRUD, metodi SDK, convalida automatica degli argomenti, marshalling/un-marshalling e capacità di persistenza trasparente (ORM).
Se il progetto con codice concatenato è in lingua Go, il progetto impalcato contiene tre file principali:
main.go
<chaincodeName>.model.go
<chaincodeName>.controller.go
Tutte le librerie necessarie vengono installate e inserite in un package.
Il file <chaincodeName>.model.go nella sottodirectory model contiene più definizioni di asset e il file <chaincodeName>.controller.go nella sottodirectory controller contiene il comportamento dell'asset e i metodi CRUD. I vari tag e pacchetti di struttura Go in model.go e controller.go forniscono supporto per funzioni come la convalida automatica degli argomenti, il marshalling/unmarshalling degli argomenti, la capacità di persistenza trasparente (ORM) e la chiamata di query avanzate.
Il progetto impalcato può essere trovato in $GOPATH/src/example.com/<chaincodeName>
Modello
Proprietà tipo di asset
Per impostazione predefinita, ogni struttura avrà una proprietà aggiuntiva denominata
AssetType. Questa proprietà può essere utile per recuperare solo gli asset di questo tipo. Qualsiasi modifica apportata a questa proprietà viene ignorata durante la creazione e l'aggiornamento dell'asset. Il valore predefinito della proprietà è
<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"'
}
Validator
-
ID
id:"true"
- Questo programma di convalida identifica la proprietà che definisce in modo univoco l'asset sottostante. Il cespite viene salvato dal valore in questa chiave. Questo validatore si applica automaticamente quando un nuovo progetto Go è impalcato.
- Nello screenshot seguente
"SupplierId" è la chiave per l'asset fornitore e dispone di una proprietà tag id:"true" per la proprietà 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"'
}
-
Derivato
derived:"strategy,algorithm,format"
- Questo decoratore viene utilizzato per definire l'attributo derivato da altre proprietà. Questo decoratore ha due parametri obbligatori:
strategy: accetta i valori concat o hash. Richiede un parametro aggiuntivo algorithm se è selezionato hash. L'algoritmo predefinito è sha256; è supportato anche md5.
format: accetta un array di stringhe e valori di specifica da utilizzare dalla strategia.
-
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"'
}
-
Obbligatorio
validate:"mandatory"
- Questa opzione contrassegna la proprietà seguente come obbligatoria e non può essere saltata durante il salvataggio nel libro contabile. Se saltato, genera un errore. Nell'esempio seguente,
"SupplierId" dispone di un 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"'
}
-
Predefinito
default:"<param>"
- Indica che la proprietà seguente può avere un valore predefinito. Il valore predefinito nel tag predefinito viene utilizzato quando la proprietà viene saltata durante il salvataggio nel libro contabile. Nella proprietà di esempio riportata di seguito,
Active ha il valore predefinito true, fornito come 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"'
}
-
Tipi di convalida
- I tipi di accesso di base vengono convalidati per una proprietà mediante la definizione di una tag di convalida. Di seguito sono riportati i tag di convalida in base ai tipi.
- stringa:
validate: "string"
- data:
validate: "date"
- numero:
validate: "int"
- booleano:
validate: "bool"
-
Convalidatore minimo
validate:"min=<param>"
- Utilizzando il validator min, è possibile impostare un valore minimo per una proprietà di tipo numero e stringa.
- Per int tipo: nell'esempio, la proprietà
RawMaterialAvailable ha un valore minimo pari a 0 e se a RawMaterialAvailable viene applicato un valore minore di 0 viene restituito un errore.
- Per la stringa di tipo: per il tipo di stringa, il validatore minimo controllerà la lunghezza della stringa con il valore fornito. Pertanto, nell'esempio seguente la proprietà
License deve avere una lunghezza minima di 10 caratteri.
- Esempio:
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"'
}
-
Numero massimo di validator
validate:"max=<param>"
- Utilizzando il validator max, è possibile impostare il valore massimo per una proprietà di tipo numero e stringa.
- Per int. tipo: come il validator min, per int. tipo, se un valore fornito per
structfield è maggiore del valore fornito nel validator, verrà restituito un errore.
- Per la stringa di tipo: come il validatore min, il validatore max controllerà anche la lunghezza della stringa con il valore specificato. Nell'esempio, la proprietà
Domain ha un valore massimo di 50, quindi se la proprietà Domain ha una lunghezza di stringa superiore a 50 caratteri, verrà restituito un messaggio di errore.
-
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"'
}
-
Convalida della data
- Prima del validatore:
validate:"before=<param>"
- Il programma di convalida precedente convalida una proprietà di tipo
date con un valore inferiore a quello specificato nel parametro.
- In questo esempio, la proprietà
ExpiryDate deve essere precedente a "2020-06-26" e, in caso contrario, restituirà un errore.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"'
}
- Dopo il validatore:
validate:"after=<param>"
- Il programma di convalida precedente convalida una proprietà di tipo
date per avere un valore maggiore di quello specificato nel parametro.
- In questo esempio, la proprietà
CompletionDate deve essere successiva a "2020-06-26" e, in caso contrario, restituirà un errore.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"'
}
-
Convalida URL
validate:"url"
- Il programma di convalida URL convaliderà una proprietà per le stringhe URL.
- In questo esempio, la proprietà
Domain deve essere un URL valido.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"'
}
-
Convalidatore Regexp
validate:"regexp=<param>"
- Il programma di convalida Regexp convaliderà la proprietà per l'espressione regolare di input.
- In questo esempio, la proprietà
PhoneNumber verrà convalidata per un numero di cellulare in base all'espressione regolare.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"'
}
-
Più convalidatori
- È possibile applicare più programmi di convalida a una struttura.
- In questo esempio, la proprietà
Domain dispone della convalida per una stringa, un URL e una lunghezza di stringa minima e massima.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 funzionalità di persistenza trasparente o ORM semplificato viene acquisita nella classe Model dell'oggetto Contesto (Ctx). Se il modello chiama uno qualsiasi dei seguenti metodi SDK, accedervi utilizzando t.Ctx.Model.
I metodi SDK che implementano ORM sono i seguenti:
Save: chiama il metodo Hyperledger Fabric PutState
Get: chiama il metodo Hyperledger Fabric GetState
Update: chiama il metodo Hyperledger Fabric PutState
Delete: chiama il metodo Hyperledger Fabric DeleteState
History: chiama il metodo Hyperledger Fabric GetHistoryForKey
GetByRange: chiama il metodo Hyperledger Fabric GetStateByRange
GetByRangeWithPagination: chiama il metodo Hyperledger Fabric GetStateByRangeWithPagination
Metodi SDK
Go chaincodes implementa Transparent Persistence Capability (ORM) con il package del modello.
Nota
A partire dalla versione 21.2.3, la modalità di accesso ai metodi ORM è cambiata. Eseguire il comando
ochain --version per determinare la versione di Blockchain App Builder.
Nelle release precedenti, i metodi ORM erano esposti come metodi statici nel package del modello. I metodi sono ora definiti sul ricevente modello, che contiene lo stub della transazione. Per chiamare questi metodi, si utilizza il ricevitore modello tenuto dal contesto della transazione nel controller. Questi metodi vengono chiamati t.Ctx.Model.<method_name> anziché model.<method_name>.
L'esempio seguente mostra le chiamate ai metodi Save e Get nelle release precedenti:
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
}
L'esempio seguente mostra le chiamate ai metodi Save e Get dalla versione 21.2.3 e successive:
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
}
Dopo l'aggiornamento alla versione 21.2.3, apportare questa modifica in tutti i progetti di codice concatenato creati con una versione precedente di Blockchain App Builder. Se si utilizza il comando sync per sincronizzare le modifiche tra il file di specifica e il codice sorgente, le modifiche vengono automaticamente apportate al controller per i metodi pronti all'uso. È comunque necessario risolvere manualmente eventuali conflitti.
I seguenti metodi ORM sono esposti tramite il package di modelli:
-
Get
- Esegue una query sul libro contabile per il cespite memorizzato in base all'ID specificato.
-
func Get(Id string, result ...interface{}) (interface{}, error)
- Parametri:
Id: l'ID del cespite richiesto dal libro contabile.
result (interface{}): oggetto asset vuoto di un tipo specifico passato per riferimento. Questo oggetto conterrà il risultato di questo metodo. Da utilizzare solo se è richiesto un risultato specifico del tipo.
asset (interface) - Oggetto asset vuoto, passato per riferimento. Questo oggetto conterrà il risultato di questo metodo. Da utilizzare solo se è richiesto un risultato specifico del tipo.
- Restituisce:
interface {} - L'interfaccia contiene l'asset sotto forma di map[string]interface{}. Prima di operare su questa mappa, è necessario affermare l'interfaccia ottenuta con il tipo map[string]interface{}. Per convertire questa mappa in un oggetto asset, è possibile utilizzare la utility API util.ConvertMaptoStruct (vedere: Utility Package).
error: contiene un errore se restituito o è nullo.
-
Update
- Aggiorna il cespite fornito nel libro contabile con i nuovi valori.
-
func Update(args ...interface{}) (interface{}, error)
- Parametri:
obj (interface) - L'oggetto da aggiornare nel libro contabile viene passato per riferimento a questa API con i nuovi valori. L'asset di input viene convalidato e verificato in base ai tag di struttura menzionati nella specifica del modello e quindi archiviato nel libro contabile.
- Restituisce:
interface{} - L'asset salvato viene restituito come interfaccia.
error: contiene un errore se restituito o è nullo.
-
Save
- Salva l'asset nel libro contabile dopo la convalida su tutti i tag di struttura.
-
func Save(args ...interface{}) (interface{}, error)
- Parametri:
obj/args[0] (interface{}) - L'oggetto che deve essere memorizzato nel libro contabile viene passato per riferimento in questo metodo di utility.
metadata/args[1] (interface{}): questo parametro è facoltativo. È stato dato al fine di agevolare l'utente se è necessario memorizzare i metadati nel libro contabile insieme all'asset in fase di esecuzione. Questo parametro può essere ignorato se non esiste alcun requisito di questo tipo.
- Restituisce:
interface {}: l'asset viene restituito come interfaccia.
error: contiene un errore se restituito o è nullo.
-
Delete
- Elimina l'asset dal libro contabile.
-
func Delete(Id string) (interface{}, error)
- Parametri:
id (string) - L'ID del cespite che deve essere eliminato dal libro contabile.
- Restituisce:
interface {} - Contiene l'asset da eliminare nel formato map[string]interface{}.
-
GetByRange
- Restituisce l'elenco di asset in base all'intervallo di ID.
-
func GetByRange(startKey string, endKey string, asset ...interface{})
([]map[string]interface{}, error)
- Parametri:
startkey (string) - ID iniziale per l'intervallo di oggetti richiesti.
endkey (string) - Fine dell'intervallo di oggetti richiesti.
asset interface - (facoltativo) Array vuoto di asset, passato per riferimento. Questo array conterrà il risultato di questo metodo. Da utilizzare se è richiesto un risultato specifico del tipo.
- Restituisce:
[]map[string]interface{} - Questo array contiene l'elenco degli asset ottenuti dal libro contabile. È possibile accedere agli oggetti iteranti su questo array e asserire gli oggetti come map[string]interface{} e utilizzare la utility per eseguire la conversione in oggetto asset.
error: contiene un errore se restituito o è nullo.
-
GetByRangeWithPagination
- Il metodo
GetByRangeWithPagination è un metodo statico della classe OchainModel ereditato dalle classi Model concrete di {chaincodeName}.model.ts.
- Restituisce un elenco di asset compreso tra l'intervallo
startId e endId, filtrato in base alla dimensione della pagina e al segnalibro. Questo metodo chiama internamente il metodo Hyperledger Fabric GetStateByRangeWithPagination.
- Se il parametro
modelName non viene fornito, il metodo restituisce Promise<Object [ ] >. Se viene fornito il parametro modelName, il metodo gestisce il casting nel tipo Model del chiamante. Nell'esempio seguente, l'array dei risultati è di tipo Supplier. Se il cespite restituito dal libro contabile non è di tipo Model, non verrà incluso nell'elenco. Questo controllo viene eseguito dalla proprietà assetType di sola lettura nella classe Model.
- Per restituire tutti gli asset compresi tra l'intervallo
startId e endId, filtrati in base alle dimensioni della pagina e ai segnalibri, utilizzare il metodo controller generico getAssetsByRange.
-
func (m *Model) GetByRangeWithPagination(startKey string, endKey string, pageSize int32, bookmark string, asset ...interface{}) ([]map[string]interface{}, error)
- Parametri:
startkey : string: chiave iniziale dell'intervallo. Incluso nell'intervallo.
endkey : string: chiave finale dell'intervallo. Escluso dall'intervallo.
pageSize : number: la dimensione della pagina della query.
Bookmark : string: il segnalibro della query. L'output inizia da questo segnalibro.
asset interface: (facoltativo) array di asset vuoto, passato per riferimento. Questo array conterrà il risultato di questo metodo. Utilizzare questo parametro per ottenere risultati specifici del tipo.
- Restituisce:
[]map[string]interface{}: array che contiene l'elenco di asset recuperati dal libro contabile. È possibile accedere agli oggetti iterando su questo array e affermando gli oggetti come map[string]interface{} e utilizzando una utility per la conversione in un oggetto asset.
error: contiene un errore se viene restituito un errore, altrimenti è nullo.
-
GetHistoryById
- Restituisce la cronologia del cespite con l'ID specificato.
-
func GetHistoryByID(Id string) ([]interface{}, error)
- Parametri:
Id (string) - ID dell'asset per il quale è necessaria la cronologia.
- Restituisce:
[]interface{} - Questa sezione contiene la cronologia dell'asset ottenuto dal libro contabile sotto forma di sezione di map[string]interface{}. È possibile accedere a ogni elemento della cronologia iterando su questa sezione e affermando gli oggetti come map[string]interface{} e utilizzando la utility per la conversione in oggetto asset.
error: contiene l'errore se osservato.
-
Query
- Il metodo di query eseguirà una query DB SQL/Couch sul libro contabile. Questo metodo è supportato solo per la distribuzione remota su Oracle Blockchain Platform. Metodo generico per l'esecuzione di query SQL nel libro contabile.
-
func Query(queryString string) ([]interface{}, error)
- Parametri:
queryString (string): immettere la stringa di query.
- Restituisce:
[]interface{}: conterrà l'output della query. Il risultato è sotto forma di slice di interfacce. È necessario iterare la slice e utilizzare gli elementi convertendoli in tipi appropriati.
error: contiene l'errore se osservato.
-
QueryWithPagination
- Il metodo di query eseguirà una query SQL/Couch DB sul libro contabile, filtrata in base alla dimensione della pagina e al segnalibro. Questo metodo è supportato solo per la distribuzione remota su Oracle Blockchain Platform. Metodo generico per l'esecuzione di query SQL nel libro contabile.
-
func (m *Model) QueryWithPagination(queryString string, pageSize int32, bookmark string) ([]interface{}, error)
- Parametri:
queryString (string) - Query Rich SQL/Couch DB.
pageSize : number: la dimensione della pagina della query.
bookmark : string: il segnalibro della query. L'output inizia da questo segnalibro.
- Restituisce:
[]interface{}: conterrà l'output della query. Il risultato è sotto forma di slice di interfacce. È necessario iterare la slice e utilizzare gli elementi convertendoli in tipi appropriati.
error: contiene l'errore se osservato.
-
InvokeCrossChaincode
- È possibile utilizzare questo metodo in un codice concatenato per chiamare una funzione in un altro codice concatenato. Entrambi i codici concatenati devono essere installati sullo stesso peer.
-
func InvokeCrossChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
- Parametri:
chaincodeName – Il nome del codice concatenato da chiamare.
methodName - Il nome del metodo da chiamare nel codice concatenato.
arg: l'argomento del metodo chiamante.
channelName - Il canale in cui si trova il codice concatenato da chiamare.
- Restituisce:
interface{}: restituisce un oggetto map[string]interface{} che contiene tre chiavi:
isValid - true se la chiamata è valida.
payload: l'output restituito dalla chiamata cross-chaincode come oggetto JSON.
message - Il messaggio restituito dalla chiamata cross-chaincode, in formato UTF-8.
- Esempio di valore restituito:
{
"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
- È possibile utilizzare questo metodo in un codice concatenato per chiamare una funzione in un altro codice concatenato. Entrambi i codici concatenati devono essere installati sullo stesso peer.
-
func InvokeChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
- Parametri:
chaincodeName – Il nome del codice concatenato da chiamare.
methodName - Il nome del metodo da chiamare nel codice concatenato.
arg: l'argomento del metodo chiamante.
channelName - Il canale in cui si trova il codice concatenato da chiamare.
- Restituisce:
interface{}: restituisce un oggetto map[string]interface{} che contiene tre chiavi:
isValid - true se la chiamata è valida.
payload - L'output restituito dalla chiamata cross-chaincode, in formato UTF-8.
message - Il messaggio restituito dalla chiamata cross-chaincode, in formato UTF-8.
- Esempio di valore restituito:
{
"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}"
}
Metodi chiave composita
-
GenerateCompositeKey
- Questo metodo genera e restituisce la chiave composta in base al valore
indexName e agli attributi specificati negli argomenti.
func GenerateCompositeKey(indexName string, attributes []string)
(string, error)
- Parametri:
indexName (string): tipo di oggetto della chiave composta.
attrbutes ([]string) - Attributi dell'asset in base ai quali deve essere formata la chiave composta.
- Restituisce:
string: contiene il risultato della chiave composta.
error: contiene l'errore se osservato.
-
GetByCompositeKey
- Questo metodo restituisce l'asset che corrisponde alla chiave e alla colonna specificate nei parametri. Il parametro
index indica l'indice della chiave restituita nell'array del metodo stub SplitCompositeKey.
- Internamente questo metodo chiama
getStateByPartialCompositeKey, splitCompositeKey e getState di Hyperledger Fabric.
func GetByCompositeKey(key string, columns []string, index int)
(interface{}, error)
- Parametri:
key (string): tipo di oggetto fornito durante la creazione della chiave composta.
column ([]string) - Questa è la porzione di attributi su cui deve essere eseguita una query sul libro contabile utilizzando la chiave composta.
index(int) - Indice dell'attributo.
- Restituisce:
Interface{} - Contiene l'elenco degli asset risultanti da questo metodo.
error: contiene eventuali errori.
Metodo stub
-
GetNetworkStub
- Questo metodo restituirà Hyperledger Fabric
chaincodeStub.
- È possibile accedere allo shim stub chiamando il metodo
GetNetworkStub. Ciò ti aiuterà a scrivere la tua implementazione lavorando direttamente con gli asset.
func GetNetworkStub() shim.ChaincodeStubInterface
- Parametri:
- Restituisce:
shim.ChaincodeStubInterface: stub del codice concatenato Hyperledger Fabric.
Altri metodi
GetTransactionId()
GetTransactionTimestamp()
GetChannelID()
GetCreator()
GetSignedProposal()
GetArgs()
GetStringArgs()
GetCreatorMspId()
GetId
-
GetTransactionId
- Restituisce l'ID transazione per la richiesta di richiamo del codice concatenato corrente. L'ID transazione identifica in modo univoco la transazione nell'ambito del canale.
func GetTransactionId() string
- Parametri:
- Restituisce:
string: contiene l'ID transazione richiesto.
-
GetTransactionTimestamp
- Restituisce l'indicatore orario al momento della creazione della transazione. Questo è preso dalla transazione
ChannelHeader, quindi indicherà la data e l'ora del cliente e avrà lo stesso valore in tutti gli sponsor.
func GetTransactionTimestamp() (*timestamp.Timestamp, error)
- Parametri:
- Restituisce:
timestamp.Timestamp: contiene l'indicatore orario richiesto.
error: contiene eventuali errori.
-
GetChannelID
- Restituisce l'ID canale per la proposta per il codice concatenato da elaborare.
func GetChannelID() string
- Parametri:
- Restituisce:
string: contiene l'ID canale richiesto come stringa.
-
GetCreator
- Restituisce l'oggetto di identità dell'autore sottomissione del richiamo del codice concatenato
func GetCreator() ([]byte, error)
- Parametri:
- Restituisce:
[]byte: contiene l'oggetto identità richiesto serializzato.
error: contiene eventuali errori.
-
GetSignedProposal
- Restituisce un oggetto completamente decodificato della proposta di transazione firmata.
func GetSignedProposal() (*peer.SignedProposal, error)
- Parametri:
- Restituisce:
*peer.SignedProposal - Contiene l'oggetto proposta firmato richiesto.
error: contiene eventuali errori.
-
GetArgs
- Restituisce gli argomenti come array di stringhe dalla richiesta di richiamo del codice concatenato.
func GetArgs() [][]byte
- Parametri:
- Restituisce:
[][]byte - Contiene gli argomenti passati.
-
GetStringArgs
- Restituisce gli argomenti destinati al codice concatenato Init e Invoke come array di stringhe.
func GetStringArgs() []string
- Parametri:
- Restituisce:
[]string: contiene gli argomenti richiesti come array di stringhe.
-
GetCreatorMspId
- Restituisce l'ID MSP dell'identità di richiamo.
-
func GetCreatorMspId() string
- Parametri:
- Restituisce:
string: restituisce l'ID MSP dell'identità di richiamo.
-
GetId
- Quando il cespite ha una chiave derivata come
Id, è possibile utilizzare questo metodo per ottenere un ID derivato. Questo metodo restituirà un errore se la chiave derivata contiene %t (indicatore orario).
- Parametri:
object: l'oggetto deve contenere tutte le proprietà da cui dipende la chiave derivata.
- Restituisce:
- Restituisce la chiave derivata come stringa.
- Esempio:
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)
}
Pacchetto utility
I seguenti metodi nel pacchetto di utilità possono essere utili:
-
Util.CreateModel
- Analizza la stringa JSON fornita e crea un oggetto asset del tipo specificato.
func CreateModel(obj interface{}, inputString string) error
- Parametri:
inputString (string): la stringa JSON di input da cui deve essere creato l'oggetto.
obj (interface{}): il riferimento dell'oggetto da creare dalla stringa JSON. Questo oggetto memorizzerà il modello creato che viene convalidato anche in base alle tag del validator.
- Restituisce:
error: contiene eventuali errori rilevati durante la creazione o la convalida dell'asset.
-
util.ConvertMapToStruct
- Converte la mappa fornita in oggetto di tipo specificato.
func ConvertMapToStruct(inputMap map[string](interface{}), resultStruct
interface{}) error
- Parametri:
inputMap (map[string](interface{})) - Mappa che deve essere convertita nell'oggetto asset.
resultStruct (interface{}): il riferimento dell'oggetto asset richiesto che deve essere generato dalla mappa. Contiene l'oggetto asset risultato richiesto.
- Restituisce:
error: contiene eventuali errori rilevati durante la creazione o la convalida dell'asset.
Per i metodi SDK del token, vedere gli argomenti in Supporto della tokenizzazione mediante Blockchain App Builder.
Controller
Il file Controller.go implementa il CRUD e i metodi personalizzati per gli asset.
È possibile creare un numero qualsiasi di classi, funzioni o file, ma solo i metodi definiti nella struttura del codice concatenato sono richiamabili dall'esterno, il resto sono nascosti.
Metodi generati automaticamente
Come descritto in File di specifica di input, è possibile specificare i metodi CRUD da generare nel file di specifica. Ad esempio, se si è scelto di generare tutti i metodi, il risultato sarà simile 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
}
Metodi personalizzati
I seguenti metodi personalizzati sono stati generati dal nostro file di specifica di esempio.
executeQuery mostra come è possibile chiamare le query avanzate SQL. I validator rispetto agli argomenti vengono aggiunti automaticamente da Blockchain App Builder in base al tipo di argomento specificato nel file di specifica.
È possibile implementare la funzionalità in base alla logica aziendale. Se si aggiungono metodi personalizzati, aggiungerli al file del controller. Se si aggiungono metodi personalizzati alla libreria anziché al file del controller, le modifiche andranno perse quando il contenuto della cartella della libreria viene aggiornato durante i processi di sincronizzazione o aggiornamento del codice concatenato.
//
//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
}
Per i codici concatenati Go, ogni metodo personalizzato deve restituire due valori:
interfaccia vuota,
errore. Ad esempio:
func (t *Controller) FetchRawMaterial(supplierId string, rawMaterialSupply int) (interface{}, error) {
return nil, nil
}
Metodo inizializzazione
Nel controller viene fornito un metodo Init personalizzato con una definizione vuota. Se si utilizza Blockchain App Builder per la distribuzione o l'aggiornamento, il metodo Init viene richiamato automaticamente. Se si esegue la distribuzione o l'upgrade dalla console di Oracle Blockchain Platform, è necessario chiamare il metodo Init manualmente. È possibile utilizzare uno strumento di terze parti come Postman per chiamare manualmente il metodo Init.
type Controller struct {
}
func (t *Controller) Init(args string) (interface{}, error)
{ return nil, nil
}
È possibile utilizzare questo metodo per inizializzare qualsiasi stato dell'applicazione a questo punto.