如何编写Flow交易向Inventory中的Grocery资源集合添加物品?
解决方案
首先需要修改你的Flow合约,给Inventory资源添加一个用于收纳Grocery物品的方法,再编写对应的交易来完成添加操作。
1. 修改后的合约代码
pub contract Crash{ pub resource Grocery{ pub var grocery: String pub var units: Int pub var price: UFix64 init(_grocery: String, _units: Int, _price: UFix64) { self.grocery = _grocery self.units = _units self.price = _price } } pub resource interface InventoryPublic{ pub var items: @{UInt64: Grocery} // 新增添加物品的接口声明 pub fun addGrocery(id: UInt64, item: @Grocery) } pub resource Inventory: InventoryPublic{ pub var items: @{UInt64: Grocery} init(){ self.items <- {} } // 实现添加物品的方法 pub fun addGrocery(id: UInt64, item: @Grocery) { // 可选:防止重复ID覆盖已有物品 if self.items[id] != nil { panic("Grocery with this ID already exists") } // 将Grocery资源移动到字典中 self.items[id] <-! item } destroy(){ destroy self.items } } pub fun createInventory(): @Inventory{ return <- create Inventory() } // 重命名函数使其语义更清晰:创建Grocery资源而非直接添加 pub fun createGrocery(name: String, nos: Int, price: UFix64): @Grocery{ return <- create Grocery(_grocery: name,_units : nos, _price: price) } }
2. 添加物品的交易代码
import Crash from 0xf8d6e0586b0a20c7 // 传入物品ID、名称、数量、价格作为交易参数 transaction(groceryId: UInt64, name: String, units: Int, price: UFix64) { prepare(acct: AuthAccount) { // 借取Inventory的引用(路径需与创建时一致) let inventoryRef = acct.borrow<&Crash.Inventory>(from: /storage/Inv1) ?? panic("Inventory not found at /storage/Inv1") // 1. 通过合约函数创建Grocery资源 let newGrocery <- Crash.createGrocery(name: name, nos: units, price: price) // 2. 调用Inventory的方法添加物品 inventoryRef.addGrocery(id: groceryId, item: <- newGrocery) } execute { log("Grocery item added successfully!") } }
关键说明
- 合约封装:通过在
Inventory中添加addGrocery方法,遵循Flow的资源封装原则,避免直接在交易中操作内部集合。 - 资源所有权:使用
<-!操作符将Grocery资源的所有权转移到Inventory的字典集合中,符合Flow的资源安全规则。 - 路径一致性:交易中借取Inventory的路径必须与创建时的存储路径(
/storage/Inv1)保持一致,否则会触发找不到资源的panic。
内容的提问来源于stack exchange,提问作者Allen Chrisso Dhas
相关产品推荐
相关产品推荐

