You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从嵌套资源中获取值而非UUID?能否更新值?

问题描述

现有合约代码

pub resource interface InventoryPublic{
    pub var items: @{UInt64: Grocery}
}

pub resource Inventory: InventoryPublic{
    pub var items: @{UInt64: Grocery}

    pub fun addItem(item: @Grocery) {
        var olditem <- self.items[item.uuid] <- item
        //self.items[item.uuid] <-! item
        destroy olditem
    }
    init(){
            self.items <- {}
    }

    destroy(){
        destroy self.items
    }
}

pub fun createInventory(): @Inventory{
        return <- create Inventory()
}

pub fun addItems(name: String, nos: Int, price: UFix64): @Grocery{
        return <- create Grocery(_grocery: name,_units : nos, _price: price)
}

当前查询脚本

import AgroLink from 0xf8d6e0586b0a20c7

pub fun main(acct: Address){
    let myitems = getAccount(acct).getCapability(/public/InventoryPublic)
                        .borrow<&AgroLink.Inventory>()
                        ?? panic("Can't get public link!")
    log(myitems.items.keys)
}

疑问

  1. 如何从嵌套资源中获取UUID对应的具体值而非仅键?
  2. 如果能获取值,是否可以对其进行更新?若可以,具体实现方法是什么?

解决方案

一、获取UUID对应的具体值

核心逻辑

当前脚本仅能拿到键,是因为直接访问了字典的keys属性。要获取对应值,需满足两个前提:

  • Grocery的字段(如name/units/price)需设为公开可访问(假设Grocery已定义这些字段);
  • 通过遍历字典键值对,或指定UUID直接取值。

实现脚本

方式1:遍历所有键值对

import AgroLink from 0xf8d6e0586b0a20c7

pub fun main(acct: Address){
    let inventory = getAccount(acct).getCapability(/public/InventoryPublic)
                        .borrow<&AgroLink.Inventory>()
                        ?? panic("无法获取公开库存能力!")
    
    // 遍历所有UUID与对应商品信息
    for uuid, item in inventory.items {
        log("UUID: \(uuid), 商品名: \(item.name), 数量: \(item.units), 价格: \(item.price)")
    }
}

方式2:指定UUID直接取值

import AgroLink from 0xf8d6e0586b0a20c7

pub fun main(acct: Address, targetUUID: UInt64){
    let inventory = getAccount(acct).getCapability(/public/InventoryPublic)
                        .borrow<&AgroLink.Inventory>()
                        ?? panic("无法获取公开库存能力!")
    
    if let item = inventory.items[targetUUID] {
        log("找到商品: 名称\(item.name), 数量\(item.units), 价格\(item.price)")
    } else {
        log("未找到UUID为\(targetUUID)的商品")
    }
}

二、更新商品值的实现方法

限制说明

Cadence不允许外部直接修改合约内的资源/字典值,必须通过合约内部暴露的函数操作。需先修改合约添加更新逻辑,再编写脚本调用。

具体步骤

1. 修改合约:添加更新函数

在InventoryPublic接口中声明更新函数,再在Inventory资源中实现:

pub resource interface InventoryPublic{
    pub var items: @{UInt64: Grocery}
    // 新增:声明更新商品的函数
    pub fun updateItem(uuid: UInt64, newUnits: Int, newPrice: UFix64)
}

pub resource Inventory: InventoryPublic{
    pub var items: @{UInt64: Grocery}

    pub fun addItem(item: @Grocery) {
        var olditem <- self.items[item.uuid] <- item
        destroy olditem
    }

    // 新增:实现更新逻辑
    pub fun updateItem(uuid: UInt64, newUnits: Int, newPrice: UFix64) {
        // 取出商品资源,修改后放回字典
        var item <- self.items[uuid] ?? panic("未找到对应UUID的商品")
        item.units = newUnits
        item.price = newPrice
        self.items[uuid] <- item
    }

    init(){
            self.items <- {}
    }

    destroy(){
        destroy self.items
    }
}

// 其余代码保持不变

若Grocery是结构体而非资源,可简化为直接借读修改(无需资源转移操作)。

2. 编写调用更新的脚本

import AgroLink from 0xf8d6e0586b0a20c7

pub fun main(acct: Address, targetUUID: UInt64, newUnits: Int, newPrice: UFix64){
    let inventory = getAccount(acct).getCapability(/public/InventoryPublic)
                        .borrow<&AgroLink.Inventory>()
                        ?? panic("无法获取公开库存能力!")
    
    inventory.updateItem(uuid: targetUUID, newUnits: newUnits, newPrice: newPrice)
    log("商品已更新")
}

额外注意事项

  • 确保Grocery的字段为pub var(需修改)或pub let(只读),否则外部无法访问;
  • 原合约addItem函数写法正确,若无需保留旧资源,可改用self.items[item.uuid] <-! item(强制替换并自动销毁旧值)简化代码。

内容的提问来源于stack exchange,提问作者Allen Chrisso Dhas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 21:37:40