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 utilizza la 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 di Go in model.go
e controller.go
forniscono supporto per funzioni quali 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 si trova nella directory $GOPATH/src/example.com/<chaincodeName>
.
Modello
Proprietà tipo di asset
Per impostazione predefinita, ogni struttura dispone di una proprietà aggiuntiva denominata
AssetType
. È possibile utilizzare questa proprietà per recuperare solo gli asset di questo tipo. Eventuali modifiche a questa proprietà vengono ignorate quando gli asset vengono creati o aggiornati. 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 validator viene applicato automaticamente quando un nuovo progetto Go viene impalcato.
- Nell'esempio seguente,
SupplierId
è la chiave per l'asset fornitore e ha 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
. Se si specifica hash
, il parametro aggiuntivo algorithm
è obbligatorio. L'algoritmo predefinito è sha256
; è supportato anche md5
.
format
: consente di utilizzare un array di stringhe e valori di specifica per la 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"
- Questo decoratore contrassegna la proprietà seguente come obbligatoria, in modo che non possa essere saltata durante il salvataggio nel libro contabile. Se saltato, viene restituito un errore. Nell'esempio seguente, la proprietà
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>"
- Questo decorator indica che la proprietà seguente ha un valore predefinito. Il valore nel tag predefinito viene utilizzato quando la proprietà viene saltata durante il salvataggio nel libro contabile. Nell'esempio seguente,
Active
ha il valore predefinito true
, specificato 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. Le tag di convalida riportate di seguito si basano sui tipi di base.
- stringa:
validate: "string"
- data:
validate: "date"
- numero:
validate: "int"
- booleano:
validate: "bool"
-
Convalidatore minimo
validate:"min=<param>"
- È possibile utilizzare il programma di convalida
min
per impostare il valore minimo per una proprietà di tipo numero o stringa.
- Per type int: nell'esempio seguente, la proprietà
RawMaterialAvailable
ha un valore minimo di 0. Se alla proprietà RawMaterialAvailable
viene applicato un valore inferiore a 0, verrà restituito un errore.
- Per la stringa di tipo: il validatore minimo controlla la lunghezza della stringa rispetto al valore specificato. Nell'esempio seguente, la proprietà
License
deve avere una lunghezza minima di dieci caratteri.
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>"
- È possibile utilizzare il programma di convalida massimo per impostare il valore massimo per una proprietà di tipo numero e stringa.
- Per int. tipo: simile al validatore min, se un valore specificato per un campo struttt è maggiore del valore fornito nel validator, viene restituito un errore.
- Per la stringa di tipo: simile al validatore min, il validatore max controlla la lunghezza della stringa rispetto al valore specificato. Nell'esempio seguente, 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 al parametro specificato.
- Nell'esempio seguente, la proprietà
ExpiryDate
deve essere precedente a "2020-06-26"
e, in caso contrario, viene restituito 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 successivo convalida una proprietà di tipo
date
per avere un valore maggiore del parametro specificato.
- Nell'esempio seguente, 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 convalida una proprietà per le stringhe URL.
- Nell'esempio seguente, 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 convalida una proprietà con l'espressione regolare specificata.
- Nell'esempio riportato di seguito, 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.
- Nell'esempio seguente, 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 seguenti metodi SDK implementano ORM:
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.
Il package di modelli espone i seguenti metodi ORM:
-
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 da recuperare dal libro contabile.
result (interface{})
: oggetto asset vuoto di un tipo specifico passato per riferimento. Questo oggetto conterrà il risultato di questo metodo. Utilizzare questo parametro solo se è richiesto un risultato specifico del tipo.
asset (interface)
: un oggetto asset vuoto passato per riferimento. Questo oggetto conterrà il risultato di questo metodo. Utilizzare questo parametro solo se è richiesto un risultato specifico del tipo.
- Restituisce:
interface {}
- L'interfaccia contiene l'asset in formato map[string]interface{}
. Prima di operare su questa mappa, è necessario affermare l'interfaccia restituita 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 specificato nel libro contabile con 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 insieme ai nuovi valori. L'asset di input viene convalidato e verificato in base ai tag di struttura nella specifica del modello e quindi memorizzato 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 da memorizzare nel libro contabile viene passato per riferimento in questo metodo di utility.
metadata/args[1] (interface{})
- (Facoltativo) È possibile utilizzare questo parametro per memorizzare i metadati nel libro contabile insieme all'asset in fase di runtime.
- 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 da eliminare dal libro contabile.
- Restituisce:
interface {}
- Contiene l'asset da eliminare nel modulo map[string]interface{}
.
-
GetByRange
- Restituisce un elenco di asset specificato da un intervallo di ID.
-
func GetByRange(startKey string, endKey string, asset ...interface{})
([]map[string]interface{}, error)
- Parametri:
startkey (string)
- ID iniziale dell'intervallo di oggetti da recuperare.
endkey (string)
- ID finale per l'intervallo di oggetti da recuperare.
asset interface
- (Facoltativo) Array vuoto di asset passato per riferimento. Questo array conterrà il risultato del metodo. Utilizzare questo parametro 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 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 restituito o è nullo.
-
GetByRangeWithPagination
- Il metodo
GetByRangeWithPagination
è un metodo statico della classe OchainModel
ereditato dalle classi Model
concrete di {chaincodeName}.model.ts
.
- Questo metodo restituisce un elenco di asset compresi tra l'intervallo
startId
e endId
, filtrati 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, inclusa nell'intervallo.
endkey : string
: chiave finale dell'intervallo, esclusa 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.
- 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 una utility per la conversione in oggetto asset.
error
- Contiene l'errore se viene restituito un errore.
-
Query
- Questo metodo esegue una query DB SQL/Couch sul libro contabile. Questo metodo è supportato solo per le distribuzioni remote su Oracle Blockchain Platform. Metodo generico per l'esecuzione di query SQL nel libro contabile.
-
func Query(queryString string) ([]interface{}, error)
- Parametri:
queryString (string)
: la stringa di query.
- Restituisce:
[]interface{}
: l'output della query sotto forma di una slice di interfacce. Iterare sulla slice e utilizzare gli elementi convertendoli nei tipi appropriati.
error
- Contiene l'errore se viene restituito un errore.
-
QueryWithPagination
- Questo metodo esegue una query SQL/Couch DB sul libro contabile, filtrata in base alla dimensione della pagina e al segnalibro. Questo metodo è supportato solo per le distribuzioni remote 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{}
: l'output della query sotto forma di una slice di interfacce. Iterare sulla slice e utilizzare gli elementi convertendoli nei tipi appropriati.
error
- Contiene l'errore se viene restituito un errore.
-
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 verrà formata la chiave composta.
- Restituisce:
string
: il risultato della chiave composta.
error
- Contiene l'errore se viene restituito un errore.
-
GetByCompositeKey
- Questo metodo restituisce l'asset che corrisponde alla chiave e alla colonna specificate. Il parametro
index
indica l'indice della chiave restituita nell'array del metodo stub SplitCompositeKey
.
- Internamente questo metodo chiama i metodi
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)
: la porzione di attributi su cui verrà eseguita una query sul libro contabile utilizzando la chiave composta.
index(int)
- Indice dell'attributo.
- Restituisce:
Interface{}
: la lista degli asset corrispondenti.
error
- Contiene l'errore se viene restituito un errore.
Metodo stub
-
GetNetworkStub
- Questo metodo restituisce il valore
chaincodeStub
di Hyperledger Fabric.
- È possibile accedere allo stub shim chiamando il metodo
GetNetworkStub
. Ciò può aiutarti a scrivere la tua implementazione che funziona direttamente con gli asset.
func GetNetworkStub() shim.ChaincodeStubInterface
- Parametri:
- Restituisce:
shim.ChaincodeStubInterface
- Lo stub del codice concatenato Hyperledger Fabric.
Altri metodi
GetTransactionId()
GetTransactionTimestamp()
GetChannelID()
GetCreator()
GetSignedProposal()
GetArgs()
GetStringArgs()
GetCreatorMspId()
GetId
-
GetTransactionId
- Questo metodo 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:
-
GetTransactionTimestamp
- Restituisce l'indicatore orario durante la creazione della transazione. Poiché il valore deriva dalla transazione
ChannelHeader
, indica l'indicatore orario del cliente e ha lo stesso valore in tutti gli approvatori.
func GetTransactionTimestamp() (*timestamp.Timestamp, error)
- Parametri:
- Restituisce:
timestamp.Timestamp
: l'indicatore orario.
error
- Contiene l'errore se viene restituito un errore.
-
GetChannelID
- Restituisce l'ID canale per la proposta per il codice concatenato da elaborare.
func GetChannelID() string
- Parametri:
- Restituisce:
string
: l'ID canale richiesto in formato stringa.
-
GetCreator
- Restituisce l'oggetto di identità dell'autore sottomissione del richiamo del codice concatenato.
func GetCreator() ([]byte, error)
- Parametri:
- Restituisce:
[]byte
: l'oggetto identità richiesto in formato serializzato.
error
- Contiene l'errore se viene restituito un errore.
-
GetSignedProposal
- Restituisce un oggetto completamente decodificato della proposta di transazione firmata.
func GetSignedProposal() (*peer.SignedProposal, error)
- Parametri:
- Restituisce:
*peer.SignedProposal
- L'oggetto della proposta firmato.
error
- Contiene l'errore se viene restituito un errore.
-
GetArgs
- Restituisce gli argomenti come array di stringhe della richiesta di richiamo del codice concatenato.
func GetArgs() [][]byte
- Parametri:
- Restituisce:
[][]byte
: gli argomenti passati.
-
GetStringArgs
- Restituisce gli argomenti destinati ai metodi
Init
e Invoke
del codice concatenato come array di stringhe.
func GetStringArgs() []string
- Parametri:
- Restituisce:
[]string
: gli argomenti come array di stringhe.
-
GetCreatorMspId
- Restituisce l'ID MSP dell'identità di richiamo.
-
func GetCreatorMspId() string
- Parametri:
- Restituisce:
string
: 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 restituisce 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
Nel pacchetto di utility sono disponibili i metodi riportati di seguito.
-
Util.CreateModel
- Analizza la stringa JSON specificata e crea un oggetto asset del tipo specificato.
func CreateModel(obj interface{}, inputString string) error
- Parametri:
inputString (string)
: la stringa JSON di input da utilizzare per creare 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 ai tag validator.
- Restituisce:
error
: contiene l'errore se viene restituito un errore durante la creazione o la convalida dell'asset.
-
util.ConvertMapToStruct
- Converte la mappa specificata in un oggetto del tipo specificato.
func ConvertMapToStruct(inputMap map[string](interface{}), resultStruct
interface{}) error
- Parametri:
inputMap (map[string](interface{}))
: la mappa da convertire in un oggetto asset.
resultStruct (interface{})
: il riferimento dell'oggetto asset da creare dalla mappa.
- Restituisce:
error
: contiene l'errore se viene restituito un errore 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 possono essere richiamati 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 sceglie di generare tutti i metodi, il risultato sarà simile al codice seguente:
//
//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 file di specifica di esempio.
La funzione executeQuery
mostra come è possibile chiamare le query RTF 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 le funzionalità in base alla logica aziendale necessaria. 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:
empty interface e
error, come mostrato nell'esempio riportato di seguito.
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
}
È quindi possibile utilizzare questo metodo per inizializzare qualsiasi stato dell'applicazione.