问题描述
我有一个NEAR智能合约,该合约保留Veggie记录的HashMap.我最基本的访问器方法get_veggie(vid)查找并返回一条Veggie记录,通过了单元测试,但是在部署的合同中失败.当我发送另一个访问器方法get_veggie_keys()返回的键之一时,它会因蔬菜不存在"而感到恐慌.
I have a NEAR smart contract that keeps a HashMap of Veggie records. My most basic accessor method get_veggie(vid), which looks up and returns one Veggie record, passes unit tests but fails in the deployed contract. It panics with 'veggie does not exist' when I send one of the keys returned by another accessor method, get_veggie_keys().
// this method returns an array of u64 keys:
pub fn get_veggie_keys(&self) -> Vec<TokenId> {
self.veggies.keys().cloned().collect()
}
// but this method panics when I give it one of those keys:
pub fn get_veggie(&self, vid: TokenId) -> Veggie {
let veggie = match self.veggies.get(&vid) {
Some(c) => {
c
},
None => {
env::panic(b"Veggie does not exist.")
}
};
veggie.clone()
}
当我从NEAR CLI调用这些方法时,我看到了这种现象:
I see this behavior when I call these methods from the NEAR CLI:
% near call --accountId $ACCOUNTID $CONTRACT_NAME get_veggie_keys
Scheduling a call: dev-1602786511653-5521463.get_veggie_keys()
Transaction Id FdWjevTsMD73eFPno41THrvrChfB9HDoLAozuiXsBwru
To see the transaction in the transaction explorer, please open this url in your browser
https://explorer.testnet.near.org/transactions/FdWjevTsMD73eFPno41THrvrChfB9HDoLAozuiXsBwru
[ 3469591985938534000, [length]: 1 ]
%
% near call --accountId $ACCOUNTID $CONTRACT_NAME get_veggie '{"vid":3469591985938534000}'
Scheduling a call: dev-1602786511653-5521463.get_veggie({"vid":3469591985938534000})
Receipt: 68ahRQyNN7tzAQMbguCEy83ofL6S5mv3iLVmmN2NH8gh
Failure [dev-1602786511653-5521463]: Error: Smart contract panicked: Veggie does not exist.
An error occured [...]
合同中的这种行为与单元测试中的行为有何不同?我称方法错误吗?我不了解HashMaps吗?感谢您的任何建议.也许我犯了一个Rust noob错误,但是我对此深感困惑...
How is this behavior different in the contract than in unit tests? Am I calling the method wrong? Do I not understand HashMaps? Thanks for any advice. Maybe I'm making a Rust noob error, but I'm deeply puzzled here ...
推荐答案
您正在靠近那里.您将要使用 U64
或 U128
,它们是特殊的JSON类型.另外,您也不想使用 HashMap
,因为它无法缩放.我在这里创建了一个示例存储库供您查看: https://github.com/mikedotexe/near-stackoverflow-64378144/blob/master/src/lib.rs
You're getting close there. You'll want to use U64
or U128
which are special JSON types. Also, you'll not want to use a HashMap
as that doesn't scale.I have created an example repository here for you to see:https://github.com/mikedotexe/near-stackoverflow-64378144/blob/master/src/lib.rs
如果参数要使用需要超过53位的数字,则需要这样做:
If a parameter is going to take a number that requires more than 53 bits you'll need to do it like this:
use near_sdk::json_types::U128;
…
pub fn add_veggie_taste(&mut self, upc: U128, taste: String) {
…
}
如前所述,您将要使用NEAR集合而不是HashMap.请查看此链接以了解各种选项: https://docs.rs/near-sdk/2.0.0/near_sdk/collections/index.html
As mentioned, you'll want to use a NEAR Collection instead of HashMap. Please see this link for the various options:https://docs.rs/near-sdk/2.0.0/near_sdk/collections/index.html
此外,我相信您可能没有像下面那样在结构上方添加宏.对于单元测试而不是链上测试,这将是有意义的.
Also, I believe you may not have added the macros above your struct as we have below. This would make sense for it working with unit tests but not on-chain.
#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct Produce {
pub veggies_taste: TreeMap<UPC, String>,
pub veggies_taste2: TreeMap<UPC, String>
}
#[near_bindgen]
impl Produce {
…
pub fn add_veggie_taste(&mut self, upc: U128, taste: String) {
let existing_veggie: Option<String> = self.veggies_taste.get(&upc.into());
if existing_veggie.is_some() {
env::panic(b"Sorry, already added this UPC!")
}
// Note that "into" turns the U128 (as a string, basically) into u128
self.veggies_taste.insert(&upc.into(), &taste);
}
…
}
我受到这篇文章的启发,并决定在此处制作视频: https://youtu.be/d68_hw_zjT4
I was inspired by this post and decided to make a video here, as well:https://youtu.be/d68_hw_zjT4
这篇关于为什么我不能在NEAR合同中阅读此HashMap?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!