Projet de code chaîne Go échafaudé

Blockchain App Builder prend l'entrée de votre fichier de spécification et génère un projet de code chaîne entièrement fonctionnel. Le projet contient des classes et des fonctions générées automatiquement, des méthodes CRUD, des méthodes SDK, la validation automatique des arguments, la sérialisation/désérialisation et la capacité de persistance transparente (ORM).

Si le projet de code chaîne est en langage Go, le projet échafaudé contient trois fichiers principaux :
  • main.go
  • <chaincodeName>.model.go
  • <chaincodeName>.controller.go
Toutes les bibliothèques nécessaires sont installées et packagées.

Le fichier <chaincodeName>.model.go du sous-répertoire model contient plusieurs définitions de ressource et le fichier <chaincodeName>.controller.go du sous-répertoire controller contient le comportement de la ressource et les méthodes CRUD. Les différentes balises et packages de structure Go dans model.go et controller.go prennent en charge des fonctionnalités telles que la validation automatique des arguments, la sérialisation/désérialisation des arguments, la capacité de persistance transparente (ORM) et l'appel de requêtes riches.

Le projet échafaudé peut être trouvé dans $GOPATH/src/example.com/<chaincodeName>

Modèle

Propriété de type d'immobilisation

Par défaut, chaque structure possède une propriété supplémentaire appelée AssetType. Cette propriété peut être utile pour extraire uniquement les ressources de ce type. Toute modification apportée à cette propriété est ignorée lors de la création et de la mise à jour de la ressource. Par défaut, la valeur de la propriété est <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"'
}

Valideurs

ID
id:"true"
Ce valideur identifie la propriété qui définit de manière unique l'actif sous-jacent. La ressource est sauvegardée par la valeur de cette clé. Ce validateur s'applique automatiquement lorsqu'un nouveau projet Go est échafaudé.
Dans la capture d'écran ci-dessous, "SupplierId" est la clé de la ressource fournisseur et possède une propriété de balise id:"true" pour la propriété 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"'   
}
Dérivé
derived:"strategy,algorithm,format"
Ce décorateur est utilisé pour définir l'attribut dérivé d'autres propriétés. Ce décorateur a deux paramètres obligatoires :
  • strategy : prend les valeurs concat ou hash. Nécessite un paramètre supplémentaire algorithm si hash est sélectionné. L'algorithme par défaut est sha256 ; md5 est également pris en charge.
  • format : prend un tableau de chaînes de spécification et de valeurs à utiliser par la stratégie.
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"'
}
Obligatoire
validate:"mandatory"
La propriété suivante est marquée comme obligatoire et ne peut pas être ignorée lors de l'enregistrement dans le livre. S'il est ignoré, une erreur est générée. Dans l'exemple ci-dessous, "SupplierId" comporte une balise 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"'
}
Par défaut
default:"<param>"
Cela indique que la propriété suivante peut avoir une valeur par défaut. La valeur par défaut de la balise par défaut est utilisée lorsque la propriété est ignorée lors de l'enregistrement dans le livre. Dans l'exemple de propriété ci-dessous, Active a la valeur par défaut true, fournie en tant que balise 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"'
}
Valider les types
Les types Go de base sont validés pour une propriété en définissant une balise de validation. Voici les balises de validation basées sur les types :
  • chaîne : validate: "string"
  • Date : validate: "date"
  • numéro : validate: "int"
  • boolean : validate: "bool"
Valideur minimal
validate:"min=<param>"
A l'aide du valideur min, une valeur minimale peut être définie pour une propriété de type numérique et chaîne.
Pour le type int : dans l'exemple, la propriété RawMaterialAvailable a une valeur minimale de 0 et si une valeur inférieure à 0 est appliquée à RawMaterialAvailable, une erreur est renvoyée.
Pour le type string : Pour le type string, le validateur minimum vérifiera la longueur de la chaîne avec la valeur fournie. Par conséquent, dans l'exemple ci-dessous, la propriété License doit comporter au moins 10 caractères.
Par exemple :
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"'
}
Valideur maximal
validate:"max=<param>"
A l'aide du valideur max, la valeur maximale peut être définie pour une propriété de type numérique et chaîne.
Pour le type int : comme pour le validateur min, pour le type int, si une valeur fournie pour structfield est supérieure à la valeur fournie dans le validateur, une erreur est renvoyée.
Pour le type string : Comme le validateur min, max validator vérifiera également la longueur de la chaîne avec une valeur donnée. Dans l'exemple, la propriété Domain a une valeur maximale de 50. Par conséquent, si la propriété Domain a une longueur de chaîne supérieure à 50 caractères, un message d'erreur est renvoyé.
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"'
}
Valideurs de date
avant le validateur :
validate:"before=<param>"
Le valideur before valide une propriété de type date pour qu'elle ait une valeur inférieure à celle indiquée dans le paramètre.
Dans cet exemple, la propriété ExpiryDate doit être antérieure à "2020-06-26" et, dans le cas contraire, elle renverra une erreur.
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"'
}
Après validateur :
validate:"after=<param>"
Le valideur before valide une propriété de type date pour qu'elle ait une valeur supérieure à celle indiquée dans le paramètre.
Dans cet exemple, la propriété CompletionDate doit être postérieure à "2020-06-26" et, dans le cas contraire, elle renverra une erreur.
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"'
}
Valideur d'URL
validate:"url"
Le valideur d'URL validera une propriété pour les chaînes d'URL.
Dans cet exemple, la propriété Domain doit être une URL valide.
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"'
}
Valideur d'expression régulière
validate:"regexp=<param>"
Le valideur d'expression régulière validera la propriété de l'expression régulière d'entrée.
Dans cet exemple, la propriété PhoneNumber effectue la validation pour un numéro de portable conformément à l'expression régulière.
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"'
}
Valideurs multiples
Plusieurs valideurs peuvent être appliqués à une propriété.
Dans cet exemple, la propriété Domain dispose d'une validation pour une chaîne, une URL et les longueurs de chaîne minimale et maximale.
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 fonctionnalité de persistance transparente ou ORM simplifié est capturée dans la classe Model de l'objet Contexte (Ctx). Si votre modèle appelle l'une des méthodes SDK suivantes, accédez-y à l'aide de t.Ctx.Model.

Les méthodes SDK qui implémentent ORM sont les méthodes suivantes :
  • Save : appelle la méthode PutState d'Hyperledger Fabric
  • Get : appelle la méthode GetState d'Hyperledger Fabric
  • Update : appelle la méthode PutState d'Hyperledger Fabric
  • Delete : appelle la méthode DeleteState d'Hyperledger Fabric
  • History : appelle la méthode GetHistoryForKey d'Hyperledger Fabric
  • GetByRange : appelle la méthode GetStateByRange d'Hyperledger Fabric
  • GetByRangeWithPagination : appelle la méthode GetStateByRangeWithPagination d'Hyperledger Fabric

Méthodes SDK

Les codes chaîne d'accès implémentent la fonctionnalité de persistance transparente (ORM) avec le package de modèle.

Remarques :

Depuis la version 21.2.3, le mode d'accès aux méthodes ORM a changé. Exécutez la commande ochain --version pour déterminer la version de Blockchain App Builder.

Dans les versions précédentes, les méthodes ORM étaient exposées en tant que méthodes statiques dans le package de modèle. Les méthodes sont maintenant définies sur le récepteur du modèle, qui contient le stub de transaction. Pour appeler ces méthodes, vous utilisez le récepteur de modèle détenu par le contexte de transaction dans le contrôleur. Vous appelez ces méthodes en tant que t.Ctx.Model.<method_name> au lieu de model.<method_name>.

L'exemple suivant présente les appels de méthode Save et Get dans les versions précédentes :

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'exemple suivant présente les appels de méthode Save et Get à partir de la version 21.2.3 et des versions ultérieures :

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
}

Après la mise à niveau vers la version 21.2.3, apportez cette modification à tous les projets de code chaîne que vous avez créés avec une version antérieure de Blockchain App Builder. Si vous utilisez la commande sync pour synchroniser les modifications entre le fichier de spécification et votre code source, les modifications sont automatiquement apportées au contrôleur pour les méthodes prêtes à l'emploi. Vous devez toujours résoudre manuellement les conflits.

Les méthodes ORM suivantes sont exposées via le package de modèle :

Get
Interroge le livre de l'immobilisation stockée en fonction de l'ID donné.
func Get(Id string, result ...interface{}) (interface{}, error)
Paramètres :
  • Id : ID de l'immobilisation requis dans le livre.
  • result (interface{}) : objet de ressource vide d'un type particulier, transmis par référence. Cet objet contiendra le résultat de cette méthode. À utiliser uniquement si un résultat spécifique au type est requis.
  • asset (interface) : objet de ressource vide transmis par référence. Cet objet contiendra le résultat de cette méthode. À utiliser uniquement si un résultat spécifique au type est requis.
Renvoie :
  • interface {} : l'interface contient la ressource sous la forme map[string]interface{}. Avant de travailler sur cette carte, il est nécessaire d'affirmer l'interface obtenue avec le type map[string]interface{}. Pour convertir cette correspondance en objet de ressource, vous pouvez utiliser l'API d'utilitaire util.ConvertMaptoStruct (reportez-vous à Package d'utilitaire).
  • error : contient une erreur si elle est renvoyée ou est nulle.
Update
Met à jour l'immobilisation fournie dans le livre avec les nouvelles valeurs.
func Update(args ...interface{}) (interface{}, error)
Paramètres :
  • obj (interface) : l'objet devant être mis à jour dans le livre est transmis par référence à cette API avec les nouvelles valeurs. L'actif d'entrée est validé et vérifié selon les balises struct mentionnées dans la spécification du modèle, puis stocké dans le livre.
Renvoie :
  • interface{} : la ressource enregistrée est renvoyée en tant qu'interface.
  • error : contient une erreur si elle est renvoyée ou est nulle.
Save
Enregistre l'immobilisation dans le livre après validation sur toutes les balises de structure.
func Save(args ...interface{}) (interface{}, error)
Paramètres :
  • obj/args[0] (interface{}) : l'objet qui doit être stocké dans le livre est transmis par référence dans cette méthode utilitaire.
  • metadata/args[1] (interface{}) : ce paramètre est facultatif. Il a été fourni afin de vous faciliter si vous devez stocker des métadonnées dans le livre avec la ressource lors de l'exécution. Ce paramètre peut être ignoré s'il n'existe aucune exigence de ce type.
Renvoie :
  • interface {} : la ressource est renvoyée en tant qu'interface.
  • error : contient une erreur si elle est renvoyée ou est nulle.
Delete
Permet de supprimer l'immobilisation du livre.
func Delete(Id string) (interface{}, error)
Paramètres :
  • id (string) : ID de l'immobilisation devant être supprimée du livre.
Renvoie :
  • interface {} : contient la ressource en cours de suppression sous la forme map[string]interface{}.
GetByRange
Renvoie la liste des immobilisations par plage d'ID.
func GetByRange(startKey string, endKey string, asset ...interface{})
([]map[string]interface{}, error)
Paramètres :
  • startkey (string) : ID de début de la plage d'objets requis.
  • endkey (string) : fin de la plage d'objets requis.
  • asset interface : (facultatif) tableau vide de ressources, transmis par référence. Ce tableau contiendra le résultat de cette méthode. A utiliser si un résultat spécifique au type est requis.
Renvoie :
  • []map[string]interface{} : ce tableau contient la liste des ressources obtenues à partir du livre. Vous pouvez accéder aux objets itérant sur ce tableau, en indiquant les objets comme map[string]interface{} et en utilisant l'utilitaire pour les convertir en objet de ressource.
  • error : contient une erreur si elle est renvoyée ou est nulle.
GetByRangeWithPagination
La méthode GetByRangeWithPagination est une méthode statique de la classe OchainModel héritée par les classes Model concrètes de {chaincodeName}.model.ts.
Cela renvoie la liste des ressources comprises entre la plage startId et endId, filtrées par taille de page et signet. Cette méthode appelle la méthode GetStateByRangeWithPagination d'Hyperledger Fabric en interne.
Si le paramètre modelName n'est pas fourni, la méthode renvoie Promise<Object [ ] >. Si le paramètre modelName est fourni, la méthode gère la conversion dans le type Model de l'appelant. Dans l'exemple suivant, le tableau de résultats est de type Supplier. Si la ressource renvoyée par le livre n'est pas de type Model, elle ne sera pas incluse dans la liste. Cette vérification est effectuée par la propriété assetType en lecture seule dans la classe Model.
Pour renvoyer toutes les ressources comprises entre la plage startId et endId, filtrées par taille de page et signets, utilisez la méthode de contrôleur générique getAssetsByRange.
func (m *Model) GetByRangeWithPagination(startKey string, endKey string, pageSize int32, bookmark string, asset ...interface{}) ([]map[string]interface{}, error) 
Paramètres :
  • startkey : string : clé de début de la plage. Inclus dans la gamme.
  • endkey : string : clé de fin de la plage. Exclu de la plage.
  • pageSize : number : taille de page de la requête.
  • Bookmark : string : signet de la requête. La sortie commence à partir de ce signet.
  • asset interface : (facultatif) tableau vide de ressources, transmis par référence. Ce tableau contiendra le résultat de cette méthode. Utilisez ce paramètre pour obtenir des résultats spécifiques au type.
Renvoie :
  • []map[string]interface{} : tableau contenant la liste des ressources extraites du livre. Vous pouvez accéder aux objets en itérant sur ce tableau, en affirmant les objets en tant que map[string]interface{} et en utilisant un utilitaire pour la conversion en objet de ressource.
  • error : contient une erreur si une erreur est renvoyée. Sinon, elle est nulle.
GetHistoryById
Renvoie l'historique de l'immobilisation avec l'ID donné.
func GetHistoryByID(Id string) ([]interface{}, error)
Paramètres :
  • Id (string) : ID de la ressource pour laquelle l'historique est nécessaire.
Renvoie :
  • []interface{} : cette tranche contient l'historique de la ressource obtenue à partir du livre sous forme de tranche de map[string]interface{}. Vous pouvez accéder à chaque élément d'historique en itérant sur cette tranche, en affirmant les objets en tant que map[string]interface{} et en utilisant l'utilitaire pour les convertir en objet de ressource.
  • error : contient l'erreur si elle est observée.
Query
La méthode de requête exécutera une requête de base de données SQL/Couch sur le livre. Cette méthode est uniquement prise en charge pour le déploiement à distance sur Oracle Blockchain Platform. Il s'agit d'une méthode générique pour exécuter des requêtes SQL sur le livre.
func Query(queryString string) ([]interface{}, error)
Paramètres :
  • queryString (string) : entrez la chaîne de requête.
Renvoie :
  • []interface{} : contient la sortie de la requête. Le résultat se présente sous la forme d'une tranche d'interfaces. Vous devez effectuer des itérations sur la tranche et utiliser les éléments en les convertissant en types appropriés.
  • error : contient l'erreur si elle est observée.
QueryWithPagination
La méthode de requête exécutera une requête de base de données SQL/Couch sur le livre, filtrée par taille de page et signet. Cette méthode est uniquement prise en charge pour le déploiement à distance sur Oracle Blockchain Platform. Il s'agit d'une méthode générique pour exécuter des requêtes SQL sur le livre.
func (m *Model) QueryWithPagination(queryString string, pageSize int32, bookmark string) ([]interface{}, error)
Paramètres :
  • queryString (string) : requête de base de données SQL/Couch enrichie.
  • pageSize : number : taille de page de la requête.
  • bookmark : string : signet de la requête. La sortie commence à partir de ce signet.
Renvoie :
  • []interface{} : contient la sortie de la requête. Le résultat se présente sous la forme d'une tranche d'interfaces. Vous devez effectuer des itérations sur la tranche et utiliser les éléments en les convertissant en types appropriés.
  • error : contient l'erreur si elle est observée.
InvokeCrossChaincode
Vous pouvez utiliser cette méthode dans un code chaîne pour appeler une fonction dans un autre code chaîne. Les deux codes chaîne doivent être installés sur le même pair.
func InvokeCrossChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
Paramètres :
  • chaincodeName : nom du code chaîne à appeler.
  • methodName : nom de la méthode à appeler dans le code chaîne.
  • arg : argument de la méthode appelante.
  • channelName : canal sur lequel se trouve le code chaîne à appeler.
Renvoie :
  • interface{} : renvoie un objet map[string]interface{} contenant trois clés :
    • isValid : true si l'appel est valide.
    • payload : sortie renvoyée par l'appel de code chaîne croisé, en tant qu'objet JSON.
    • message : message renvoyé par l'appel inter-code de chaîne, au format UTF-8.
Exemple de valeur renvoyée :
{
      "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
Vous pouvez utiliser cette méthode dans un code chaîne pour appeler une fonction dans un autre code chaîne. Les deux codes chaîne doivent être installés sur le même pair.
func InvokeChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
Paramètres :
  • chaincodeName : nom du code chaîne à appeler.
  • methodName : nom de la méthode à appeler dans le code chaîne.
  • arg : argument de la méthode appelante.
  • channelName : canal sur lequel se trouve le code chaîne à appeler.
Renvoie :
  • interface{} : renvoie un objet map[string]interface{} contenant trois clés :
    • isValid : true si l'appel est valide.
    • payload : sortie renvoyée par l'appel de code chaîne croisé, au format UTF-8.
    • message : message renvoyé par l'appel inter-code de chaîne, au format UTF-8.
Exemple de valeur renvoyée :
{
    "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éthodes à clé composite

GenerateCompositeKey
Cette méthode génère et renvoie la clé composite en fonction de indexName et des attributs indiqués dans les arguments.
func GenerateCompositeKey(indexName string, attributes []string)
(string, error)
Paramètres :
  • indexName (string) : type d'objet de la clé composite.
  • attrbutes ([]string) : attributs de la ressource en fonction desquels la clé composite doit être formée.
Renvoie :
  • string : contient le résultat de la clé composite.
  • error : contient l'erreur si elle est observée.
GetByCompositeKey
Cette méthode renvoie la ressource qui correspond à la clé et à la colonne indiquées dans les paramètres. Le paramètre index indique l'index de la clé renvoyée dans le tableau de la méthode stub SplitCompositeKey.
En interne, cette méthode appelle getStateByPartialCompositeKey, splitCompositeKey et getState d'Hyperledger Fabric.
func GetByCompositeKey(key string, columns []string, index int)
(interface{}, error)
Paramètres :
  • key (string) : type d'objet fourni lors de la création de la clé composite.
  • column ([]string) : tranche d'attributs sur laquelle le livre doit être interrogé à l'aide de la clé composite.
  • index(int) : index de l'attribut.
Renvoie :
  • Interface{} : contient la liste des ressources résultant de cette méthode.
  • error : contient des erreurs, le cas échéant.

Méthode stub

GetNetworkStub
Cette méthode renvoie Hyperledger Fabric chaincodeStub.
Vous pouvez accéder au stub shim en appelant la méthode GetNetworkStub. Cela vous aidera à écrire votre propre implémentation en travaillant directement avec les ressources.
func GetNetworkStub() shim.ChaincodeStubInterface
Paramètres :
  • Aucun élément
Renvoie :
  • shim.ChaincodeStubInterface : stub de code chaîne Hyperledger Fabric.

Autres méthodes

  • GetTransactionId()
  • GetTransactionTimestamp()
  • GetChannelID()
  • GetCreator()
  • GetSignedProposal()
  • GetArgs()
  • GetStringArgs()
  • GetCreatorMspId()
  • GetId
GetTransactionId
Renvoie l'ID de transaction pour la demande d'appel de code chaîne en cours. L'ID transaction identifie de manière unique la transaction dans la portée du canal.
func GetTransactionId() string
Paramètres :
  • Aucun élément
Renvoie :
  • string : contient l'ID de transaction requis.
GetTransactionTimestamp
Renvoie l'horodatage de la création de la transaction. Cette valeur provient de la transaction ChannelHeader. Elle indique donc l'horodatage du client et a la même valeur pour tous les approbateurs.
func GetTransactionTimestamp() (*timestamp.Timestamp, error)
Paramètres :
  • Aucun élément
Renvoie :
  • timestamp.Timestamp : contient l'horodatage requis.
  • error : contient des erreurs, le cas échéant.
GetChannelID
Renvoie l'ID de canal pour la proposition de code chaîne à traiter.
func GetChannelID() string
Paramètres :
  • Aucun élément
Renvoie :
  • string : contient l'ID de canal requis sous forme de chaîne.
GetCreator
Renvoie l'objet d'identité de l'émetteur de l'appel de code chaîne
func GetCreator() ([]byte, error)
Paramètres :
  • Aucun élément
Renvoie :
  • []byte : contient l'objet d'identité requis sérialisé.
  • error : contient des erreurs, le cas échéant.
GetSignedProposal
Renvoie un objet entièrement décodé de la proposition de transaction signée.
func GetSignedProposal() (*peer.SignedProposal, error)
Paramètres :
  • Aucun élément
Renvoie :
  • *peer.SignedProposal : contient l'objet de proposition signée requis.
  • error : contient des erreurs, le cas échéant.
GetArgs
Renvoie les arguments sous forme de tableau de chaînes à partir de la demande d'appel de code chaîne.
func GetArgs() [][]byte
Paramètres :
  • Aucun élément
Renvoie :
  • [][]byte : contient les arguments transmis.
GetStringArgs
Renvoie les arguments destinés au code chaîne Init et Invoke en tant que tableau de chaînes.
func GetStringArgs() []string
Paramètres :
  • Aucun élément
Renvoie :
  • []string : contient les arguments requis sous forme de tableau de chaînes.
GetCreatorMspId
Renvoie l'ID MSP de l'identité appelante.
func GetCreatorMspId() string
Paramètres :
  • Aucun élément
Renvoie :
  • string : renvoie l'ID MSP de l'identité appelante.
GetId
Lorsque la ressource a une clé dérivée en tant que Id, vous pouvez utiliser cette méthode pour obtenir un ID dérivé. Cette méthode renvoie une erreur si la clé dérivée contient %t (horodatage).
Paramètres :
  • object : l'objet doit contenir toutes les propriétés dont dépend la clé dérivée.
Renvoie :
  • Renvoie la clé dérivée sous forme de chaîne.
Par exemple :
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)
}

Package d'utilitaires

Les méthodes suivantes du package de l'utilitaire peuvent être utiles :

Util.CreateModel
Analyse la chaîne JSON fournie et crée un objet de ressource du type fourni.
func CreateModel(obj interface{}, inputString string) error
Paramètres :
  • inputString (string) : chaîne JSON d'entrée à partir de laquelle l'objet doit être créé.
  • obj (interface{}) : référence de l'objet à créer à partir de la chaîne JSON. Cet objet stocke le modèle créé qui est également validé selon les balises de validateur.
Renvoie :
  • error : contient les erreurs détectées lors de la création ou de la validation de la ressource.
util.ConvertMapToStruct
Convertir la carte fournie en objet du type fourni.
func ConvertMapToStruct(inputMap map[string](interface{}), resultStruct
interface{}) error
Paramètres :
  • inputMap (map[string](interface{})) : correspondance à convertir en objet de ressource.
  • resultStruct (interface{}) : référence de l'objet de ressource requis qui doit être généré à partir de la correspondance. Contient l'objet d'immobilisation de résultat requis.
Renvoie :
  • error : contient les erreurs détectées lors de la création ou de la validation de la ressource.

Pour les méthodes SDK de jeton, reportez-vous aux rubriques sous Prise en charge de la création de jetons à l'aide de Blockchain App Builder.

Contrôleur

Le fichier Controller.go implémente le CRUD et les méthodes personnalisées pour les ressources.

Vous pouvez créer autant de classes, de fonctions ou de fichiers que vous le souhaitez, mais seules les méthodes définies sur la structure de code chaîne peuvent être appelées de l'extérieur, le reste étant masqué.

Méthodes générées automatiquement

Comme décrit dans la section Fichier de spécification d'entrée, vous pouvez spécifier les méthodes CRUD à générer dans le fichier de spécification. Par exemple, si vous avez choisi de générer toutes les méthodes, le résultat sera le suivant :

//	
//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éthodes personnalisées

Les méthodes personnalisées suivantes ont été générées à partir de notre exemple de fichier de spécification.

executeQuery indique comment les requêtes enrichies SQL peuvent être appelées. Les validateurs par rapport aux arguments sont automatiquement ajoutés par Blockchain App Builder en fonction du type de l'argument spécifié dans le fichier de spécification.

Vous pouvez implémenter la fonctionnalité en fonction de la logique métier. Si vous ajoutez des méthodes personnalisées, ajoutez-les au fichier de contrôleur. Si vous ajoutez des méthodes personnalisées à la bibliothèque au lieu du fichier de contrôleur, vos modifications seront perdues lorsque le contenu du dossier de bibliothèque sera mis à jour lors des processus de synchronisation ou de mise à niveau du code chaîne.

//	
//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
}
Pour les codes chaîne Go, chaque méthode personnalisée doit renvoyer deux valeurs : interface vide, erreur. Exemple :
func (t *Controller) FetchRawMaterial(supplierId string, rawMaterialSupply int) (interface{}, error) { 
    return nil, nil
}

Méthode d'initialisation

Une méthode Init personnalisée est fournie dans le contrôleur avec une définition vide. Si vous utilisez Blockchain App Builder pour le déploiement ou la mise à niveau, la méthode Init est appelée automatiquement. Si vous effectuez un déploiement ou une mise à niveau à partir de la console Oracle Blockchain Platform sur la plate-forme Hyperledger Fabric v1.4.7, la méthode Init est également appelée automatiquement. Si vous effectuez un déploiement ou une mise à niveau à partir de la console Oracle Blockchain Platform sur la plate-forme Hyperledger Fabric v2.x, vous devez appeler la méthode Init manuellement. Vous pouvez utiliser un outil tiers tel que Postman pour appeler manuellement la méthode Init.

type Controller struct {
}
func (t *Controller) Init(args string) (interface{}, error) 
    { return nil, nil
}

Si vous souhaitez initialiser un état d'application à ce stade, vous pouvez utiliser cette méthode pour ce faire.