Blockchain App Builder 从您的规范文件中获取输入,并生成一个功能齐全的链码项目。该项目包含自动生成的类和函数,CRUD 方法,SDK 方法,参数自动验证,编组/非编组和透明持久性能力 (ORM)。
如果链代码项目使用 Go 语言,则支架项目包含三个主文件:
main.go
<chaincodeName>.model.go
<chaincodeName>.controller.go
安装并打包所有必需的磁带库。
model
子目录中的 <chaincodeName>.model.go
文件包含多个资产定义,controller
子目录中的 <chaincodeName>.controller.go
文件包含资产的行为和 CRUD 方法。model.go
和 controller.go
中的各种 Go 结构标记和程序包支持诸如参数自动验证、参数的编集/解编集、透明持久性功能 (Transparent Persistent Function,ORM) 以及调用富查询等功能。
支架式项目位于 $GOPATH/src/example.com/<chaincodeName>
目录中。
型号
资产类型属性
缺省情况下,每个结构都有一个名为
AssetType
的附加属性。您可以使用此属性仅提取此类型的资产。创建或更新资产时,将忽略对此属性所做的任何更改。缺省情况下,属性值为
<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"'
}
验证器
-
标识
id:"true"
- 此验证器标识唯一定义基础资产的属性。资产按此键中的值保存。当安装了新的 Go 项目时,将自动应用此验证器。
- 在以下示例中,
SupplierId
是供应商资产的关键字,并且 SupplierId
属性具有标记属性 id:"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"'
}
-
派生
derived:"strategy,algorithm,format"
- 此装饰器用于定义从其他属性派生的属性。此装饰器有两个必备参数:
strategy
:接受 concat
或 hash
的值。如果指定了 hash
,则需要附加参数 algorithm
。缺省算法为 sha256
;还支持 md5
。
format
:接受要由策略使用的规范字符串和值的数组。
-
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"'
}
-
必需
validate:"mandatory"
- 此装饰器将以下属性标记为必需属性,因此在保存到分类账时无法跳过该属性。如果跳过,则会引发错误。在以下示例中,
SupplierId
属性具有 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"'
}
-
默认值为
default:"<param>"
- 此装饰器指示以下属性具有默认值。在保存到分类账时跳过属性时,将使用默认标记中的值。在以下示例中,
Active
的默认值为 true
,指定为标记 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"'
}
-
验证类型为
- 通过定义验证标记来验证属性的基本 Go 类型。以下验证标记基于基本类型:
- 字符串:
validate: "string"
- 日期:
validate: "date"
- 编号:
validate: "int"
- 布尔值:
validate: "bool"
-
最小验证器
validate:"min=<param>"
- 可以使用
min
验证器为数字或字符串类型的属性设置最小值。
- 对于类型 int:在以下示例中,
RawMaterialAvailable
属性的最小值为 0。如果小于 0 的值应用于 RawMaterialAvailable
属性,将返回错误。
- 对于类型字符串:最小验证器根据指定值检查字符串的长度。在以下示例中,
License
属性的长度必须至少为十个字符。
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"'
}
-
最大验证器
validate:"max=<param>"
- 您可以使用最大验证器为数字和字符串类型的属性设置最大值。
- 对于类型 int:与最小验证器类似,如果为结构字段指定的值大于验证器中提供的值,将返回错误。
- 对于类型字符串:与最小验证器类似,最大验证器根据给定值检查字符串的长度。在以下示例中,
Domain
属性的最大值为 50,因此,如果 Domain
属性的字符串长度超过 50 个字符,则将返回错误消息。
-
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"'
}
-
日期验证器
- 验证器之前:
validate:"before=<param>"
- 之前的验证器验证
date
类型的属性的值小于指定的参数。
- 在以下示例中,
ExpiryDate
属性必须位于 "2020-06-26"
之前,否则将返回错误。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"'
}
- 验证器之后:
validate:"after=<param>"
- 后面的验证器将验证
date
类型的属性,使其具有大于指定参数的值。
- 在以下示例中,
CompletionDate
属性必须在 "2020-06-26"
之后,如果不是,将返回错误。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"'
}
-
URL 验证器
validate:"url"
- URL 验证器验证 URL 字符串的属性。
- 在以下示例中,
Domain
属性必须是有效的 URL。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"'
}
-
正则表达式验证器
validate:"regexp=<param>"
- 正则表达式验证器使用指定的正则表达式验证属性。
- 在以下示例中,将根据正则表达式对移动电话号码的
PhoneNumber
属性进行验证。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"'
}
-
多个验证器
- 一个属性可以应用多个验证器。
- 在以下示例中,
Domain
属性对字符串、URL 以及字符串的最小长度和最大长度进行了验证。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
在上下文 (Ctx
) 对象的 Model
类中捕获透明持久性功能或简化 ORM。如果您的模型调用了以下任一 SDK 方法,请使用 t.Ctx.Model
访问它们。
以下 SDK 方法实现 ORM:
Save
调用 Hyperledger Fabric PutState
方法。
Get
调用 Hyperledger Fabric GetState
方法。
Update
调用 Hyperledger Fabric PutState
方法。
Delete
调用 Hyperledger Fabric DeleteState
方法。
History
调用 Hyperledger Fabric GetHistoryForKey
方法。
GetByRange
调用 Hyperledger Fabric GetStateByRange
方法。
GetByRangeWithPagination
调用 Hyperledger Fabric GetStateByRangeWithPagination
方法。
SDK 方法
Go 链代码通过模型包实现透明持久性能力 (ORM)。
注意:
从版本 21.2.3 开始,访问 ORM 方法的方式已发生变化。运行
ochain --version
命令以确定 Blockchain App Builder 的版本。
在以前的发行版中,ORM 方法在模型程序包中作为静态方法公开。这些方法现在在保存事务处理存根的模型接收器上定义。要调用这些方法,请使用控制器中的事务处理上下文所持有的模型接收器。您可以将这些方法称为 t.Ctx.Model.<method_name>
而不是 model.<method_name>
。
以下示例显示了以前发行版中的 Save
和 Get
方法调用:
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
}
以下示例显示了版本 21.2.3 及更高版本的 Save
和 Get
方法调用:
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
}
升级到版本 21.2.3 后,请在使用早期版本的 Blockchain App Builder 创建的所有链代码项目中进行此更改。如果使用 sync
命令同步规范文件与源代码之间的更改,这些更改将自动带到控制器中,以便使用现成的方法。您仍必须手动解决任何冲突。
以下 ORM 方法由模型程序包公开:
-
Get
- 根据给定 ID 查询存储资产的分类账。
-
func Get(Id string, result ...interface{}) (interface{}, error)
- 参数:
Id
- 要从分类账中检索的资产的 ID。
result (interface{})
- 特定类型的空资产对象,通过引用传递。此对象将包含此方法的结果。仅当需要特定于类型的结果时才使用此参数。
asset (interface)
- 通过引用传递的空资产对象。此对象将包含此方法的结果。仅当需要特定于类型的结果时才使用此参数。
- 返回:
interface {}
- 接口包含 map[string]interface{}
格式的资产。在对此映射进行操作之前,必须使用 map[string]interface{}
类型声明返回的接口。要将此映射转换为资产对象,可以使用实用程序 API util.ConvertMaptoStruct
(请参阅:实用程序包)。
error
- 如果返回,则包含错误,或者为 nil。
-
Update
- 使用新值更新分类账中的指定资产。
-
func Update(args ...interface{}) (interface{}, error)
- 参数:
obj (interface)
- 在分类账中更新的对象通过引用传递到此 API 以及新值。输入资产将根据模型规范中的结构标记进行验证和验证,然后存储在分类账中。
- 返回:
interface{}
- 保存的资产将作为接口返回。
error
- 如果返回,则包含错误,或者为 nil。
-
Save
- 在验证所有结构标记后,将资产保存到分类账。
-
func Save(args ...interface{}) (interface{}, error)
- 参数:
obj/args[0] (interface{})
- 要存储在分类账中的对象通过引用在此实用程序方法中传递。
metadata/args[1] (interface{})
-(可选)您可以在运行时使用此参数将元数据与资产一起存储在分类账中。
- 返回:
interface {}
- 资产作为接口返回。
error
- 如果返回,则包含错误,或者为 nil。
-
Delete
- 从分类账中删除资产。
-
func Delete(Id string) (interface{}, error)
- 参数:
id (string)
- 要从分类账中删除的资产的 ID。
- 返回:
interface {}
- 包含以 map[string]interface{}
格式删除的资产。
-
GetByRange
- 返回由某个 ID 范围指定的资产列表。
-
func GetByRange(startKey string, endKey string, asset ...interface{})
([]map[string]interface{}, error)
- 参数:
startkey (string)
- 要检索的对象范围的起始 ID。
endkey (string)
- 要检索的对象范围的结束 ID。
asset interface
-(可选)通过引用传递的空资产数组。此数组将包含方法结果。如果需要特定于类型的结果,请使用此参数。
- 返回:
[]map[string]interface{}
- 此数组包含从分类账中获取的资产列表。您可以通过迭代此数组并将对象声明为 map[string]interface{}
并使用实用程序转换为资产对象来访问这些对象。
error
- 如果返回,则包含错误,或者为 nil。
-
GetByRangeWithPagination
GetByRangeWithPagination
方法是 OchainModel
类的静态方法,由 {chaincodeName}.model.ts
的具体 Model
类继承。
- 此方法返回
startId
和 endId
之间的资产列表,按页面大小和书签进行筛选。此方法在内部调用超级账本架构 GetStateByRangeWithPagination
方法。
- 如果未提供
modelName
参数,则该方法返回 Promise<Object [ ] >
。如果提供了 modelName
参数,则该方法将处理强制转换为调用方 Model
类型的操作。在以下示例中,结果数组的类型为 Supplier
。如果从分类账返回的资产不是 Model
类型,则该资产将不包括在列表中。此检查由 Model
类中的只读 assetType
属性完成。
- 要返回按页面大小和书签筛选的
startId
到 endId
范围之间的所有资产,请使用通用控制器方法 getAssetsByRange
。
-
func (m *Model) GetByRangeWithPagination(startKey string, endKey string, pageSize int32, bookmark string, asset ...interface{}) ([]map[string]interface{}, error)
- 参数:
startkey : string
- 范围的起始键,该键包含在范围中。
endkey : string
- 该范围的结束键,该键被排除在范围之外。
pageSize : number
- 查询的页面大小。
Bookmark : string
–查询的书签。输出从此书签开始。
asset interface
-(可选)通过引用传递的空资产数组。此数组将包含此方法的结果。使用此参数可获取特定于类型的结果。
- 返回:
[]map[string]interface{}
- 包含从分类账中检索到的资产列表的数组。您可以通过迭代通过此数组访问对象,并将对象声明为 map[string]interface{}
并使用实用程序转换为资产对象来访问这些对象。
error
- 如果返回错误,则包含错误,否则为 nil。
-
GetHistoryById
- 返回具有给定 ID 的资产的历史记录。
-
func GetHistoryByID(Id string) ([]interface{}, error)
- 参数:
- 返回:
[]interface{}
- 此切片包含从分类账中获取的资产的历史记录,格式为切片 map[string]interface{}
。您可以通过迭代此分片并将对象声明为 map[string]interface{}
并使用实用程序转换为资产对象来访问每个历史记录元素。
error
- 如果返回了错误,则包含错误。
-
Query
- 此方法对分类账运行 SQL/Couch 数据库查询。此方法仅适用于 Oracle Blockchain Platform 上的远程部署。这是对分类账运行 SQL 查询的通用方法。
-
func Query(queryString string) ([]interface{}, error)
- 参数:
queryString (string)
- 查询字符串。
- 返回:
[]interface{}
- 以接口分片形式输出的查询。对切片进行迭代,并通过将元素转换为其正确类型来使用元素。
error
- 如果返回了错误,则包含错误。
-
QueryWithPagination
- 此方法通过分类账运行 SQL/Couch 数据库查询,按页面大小和书签进行筛选。此方法仅适用于 Oracle Blockchain Platform 上的远程部署。这是对分类账运行 SQL 查询的通用方法。
-
func (m *Model) QueryWithPagination(queryString string, pageSize int32, bookmark string) ([]interface{}, error)
- 参数:
queryString (string)
- 丰富的 SQL/Couch 数据库查询。
pageSize : number
- 查询的页面大小。
bookmark : string
- 查询的书签。输出从此书签开始。
- 返回:
[]interface{}
- 以接口分片形式输出的查询。对切片进行迭代,并通过将元素转换为其正确类型来使用元素。
error
- 如果返回了错误,则包含错误。
-
InvokeCrossChaincode
- 您可以在链代码中使用此方法来调用另一个链代码中的函数。两个链代码必须安装在同一对等点上。
-
func InvokeCrossChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
- 参数:
chaincodeName
- 要调用的链代码的名称。
methodName
- 链代码中要调用的方法的名称。
arg
- 调用方法的参数。
channelName
- 要调用的链代码所在的渠道。
- 返回:
interface{}
- 返回包含三个键的 map[string]interface{}
对象:
isValid
- true
(如果调用有效)。
payload
- 跨链代码调用作为 JSON 对象返回的输出。
message
- 跨链代码调用返回的消息,采用 UTF-8 格式。
- 返回值示例:
{
"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
- 您可以在链代码中使用此方法来调用另一个链代码中的函数。两个链代码必须安装在同一对等点上。
-
func InvokeChaincode(chaincodeName string, method string, args []string, channelName string) (interface{}, error)
- 参数:
chaincodeName
- 要调用的链代码的名称。
methodName
- 链代码中要调用的方法的名称。
arg
- 调用方法的参数。
channelName
- 要调用的链代码所在的渠道。
- 返回:
interface{}
- 返回包含三个键的 map[string]interface{}
对象:
isValid
- true
(如果调用有效)。
payload
- 跨链代码调用以 UTF-8 格式返回的输出。
message
- 跨链代码调用返回的消息,采用 UTF-8 格式。
- 返回值示例:
{
"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}"
}
组合键方法
-
GenerateCompositeKey
- 此方法根据
indexName
和参数中提供的属性生成并返回组合键。
func GenerateCompositeKey(indexName string, attributes []string)
(string, error)
- 参数:
indexName (string)
- 组合键的对象类型。
attrbutes ([]string)
- 将基于其形成组合键的资产的属性。
- 返回:
string
- 组合键结果。
error
- 如果返回了错误,则包含错误。
-
GetByCompositeKey
- 此方法返回与指定键和列匹配的资产。
index
参数指示 stub 方法 SplitCompositeKey
数组中返回的键的索引。
- 在内部,此方法调用 Hyperledger Fabric 的
getStateByPartialCompositeKey
、splitCompositeKey
和 getState
方法。
func GetByCompositeKey(key string, columns []string, index int)
(interface{}, error)
- 参数:
key (string)
- 创建组合键时提供的对象类型。
column ([]string)
- 使用组合键查询分类账的属性分片。
index(int)
- 属性的索引。
- 返回:
Interface{}
- 匹配资产的列表。
error
- 如果返回了错误,则包含错误。
存根方法
-
GetNetworkStub
- 此方法返回 Hyperledger Fabric
chaincodeStub
值。
- 您可以通过调用
GetNetworkStub
方法来访问 shim stub。这可以帮助您编写自己的实施,直接与资产配合使用。
func GetNetworkStub() shim.ChaincodeStubInterface
- 参数:
- 返回:
shim.ChaincodeStubInterface
- 超级账本架构链代码存根。
其他方法
GetTransactionId()
GetTransactionTimestamp()
GetChannelID()
GetCreator()
GetSignedProposal()
GetArgs()
GetStringArgs()
GetCreatorMspId()
GetId
-
GetTransactionId
- 此方法返回当前链代码调用请求的事务处理 ID。事务处理 ID 在渠道范围内唯一标识事务处理。
func GetTransactionId() string
- 参数:
- 返回:
-
GetTransactionTimestamp
- 返回创建事务处理时的时间戳。因为该值取自事务
ChannelHeader
,所以它指示客户机的时间戳,并且在所有背书者中具有相同的值。
func GetTransactionTimestamp() (*timestamp.Timestamp, error)
- 参数:
- 返回:
timestamp.Timestamp
- 时间戳。
error
- 如果返回了错误,则包含错误。
-
GetChannelID
- 返回链代码要处理的建议的渠道 ID。
func GetChannelID() string
- 参数:
- 返回:
-
GetCreator
- 返回链代码调用的提交者的身份对象。
func GetCreator() ([]byte, error)
- 参数:
- 返回:
[]byte
- 采用序列化格式的所需标识对象。
error
- 如果返回了错误,则包含错误。
-
GetSignedProposal
- 返回已签名事务处理建议的完全解码的对象。
func GetSignedProposal() (*peer.SignedProposal, error)
- 参数:
- 返回:
*peer.SignedProposal
- 已签署的建议对象。
error
- 如果返回了错误,则包含错误。
-
GetArgs
- 从链代码调用请求中以字符串数组形式返回参数。
func GetArgs() [][]byte
- 参数:
- 返回:
-
GetStringArgs
- 以字符串数组形式返回链代码
Init
和 Invoke
方法的参数。
func GetStringArgs() []string
- 参数:
- 返回:
-
GetCreatorMspId
- 返回调用身份的 MSP ID。
-
func GetCreatorMspId() string
- 参数:
- 返回:
-
GetId
- 当资产的派生关键字为
Id
时,可以使用此方法获取派生 ID。如果派生关键字包含 %t
(时间戳),此方法将返回错误。
- 参数:
object
- 对象必须包含派生密钥所依赖的所有属性。
- 返回:
- 示例:
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)
}
实用程序包
实用程序包中提供了以下方法。
-
Util.CreateModel
- 解析指定的 JSON 字符串并创建指定类型的资产对象。
func CreateModel(obj interface{}, inputString string) error
- 参数:
inputString (string)
- 用于创建对象的输入 JSON 字符串。
obj (interface{})
- 要从 JSON 字符串创建的对象的引用。此对象将存储创建的模型,该模型也根据验证器标记进行验证。
- 返回:
error
- 如果在创建或验证资产时返回了错误,则包含错误。
-
util.ConvertMapToStruct
- 将指定的映射转换为指定类型的对象。
func ConvertMapToStruct(inputMap map[string](interface{}), resultStruct
interface{}) error
- 参数:
inputMap (map[string](interface{}))
- 要转换为资产对象的映射。
resultStruct (interface{})
- 要从映射创建的资产对象的引用。
- 返回:
error
- 如果在创建或验证资产时返回了错误,则包含错误。
有关令牌 SDK 方法,请参见 Tokenization Support Using Blockchain App Builder 下的主题。
控制器
Controller.go
文件为资产实施 CRUD 和定制方法。
您可以创建任意数量的类、函数或文件,但只能从外部调用链代码结构上定义的那些方法;其余的方法将被隐藏。
自动生成的方法
如 Input Specification File 中所述,您可以指定要在规范文件中生成的 CRUD 方法。例如,如果选择生成所有方法,则结果将类似于以下代码:
//
//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
}
自定义方法
以下定制方法是从示例规范文件生成的。
executeQuery
函数显示如何调用 SQL 富查询。根据规范文件中指定的参数类型,Blockchain App Builder 会自动添加针对这些参数的验证器。
您可以根据必要的业务逻辑实施功能。如果添加定制方法,请将其添加到控制器文件中。如果将定制方法添加到库而不是控制器文件,则在同步或链代码升级过程中更新库文件夹内容时,所做的更改将丢失。
//
//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
}
对于 Go 链代码,每个定制方法必须返回两个值:
empty interface 和
error,如以下示例所示:
func (t *Controller) FetchRawMaterial(supplierId string, rawMaterialSupply int) (interface{}, error) {
return nil, nil
}
初始化方法
控制器中提供了具有空定义的定制 Init
方法。如果您使用区块链应用构建器进行部署或升级,则会自动调用 Init
方法。如果您从 Oracle Blockchain Platform 控制台部署或升级,则必须手动调用 Init
方法。您可以使用第三方工具(如 Postman)手动调用 Init
方法。
type Controller struct {
}
func (t *Controller) Init(args string) (interface{}, error)
{ return nil, nil
}
然后,您可以使用此方法来初始化任何应用程序状态。