我有一个模块方法,将固定费用关联到来自各种托盘的调用。因此,我试图匹配通过托盘,调用名称和调用参数传递给我的方法作为参数的调用。
类似如下:
impl<T: Config> Module<T>
{
fn compute_call_fee_(call: &<T as Config>::Call) -> Result<u64, &'static str> {
let fee = match *call {
Call::PalletA(palletA::Call::name_of_palletA_call(x,y)) => 50u64, // here this is not real syntax, this is what I need to figure out
_ => 100u64
};
Ok(fee)
}
}
对于上面的情况,Config trait将从匹配的不同托盘中实现Config trait:
pub trait Config: system::Config + palletA::Config + palletB::Config {
type Call: Parameter + Dispatchable<Origin = Self::Origin> + GetDispatchInfo;
}
我如何匹配call
的原点托盘,函数名和函数参数?
我试过:
使用类似的语法,没有成功
使
Config::Call
实现GetCallMetadata
:这只给我原点托盘和功能名称,而不是参数使调用实现
IsSubType
,并遵循这个答案:如何解码和匹配调用时,作为衬底的参数传递。如果我做对了,这与来自其他托盘的呼叫无关。对于使用
IsSubType
,我已经将其添加为绑定到impl块的trait,而不是在Config
trait中:impl<T: Config> Module<T> where <T as Config>::Call: IsSubType<Call<T>>, { fn compute_call_fee_(call: &<T as Config>::Call) -> Result<u64, &'static str> { if let Some(local_call) = call.is_sub_type() { return match local_call { palletA::Call::name_of_palletA_call(x,y) => Ok(42u64), _ => Ok(0u64), } } Ok(21u64) } }
很难说,直到您粘贴完整的代码(特别是type Call = xxx
部分),但我可以猜测您错过的是:type Call: IsSubType<pallet_balances::Call<Self>>;
。你提到的另一个问题也有同样的建议,但我猜你用错了。
请注意,总体而言,外部Call
(通过type Call
传递到托盘中的那个)实现了两件事:
From<pallet_call>
为每个单独的托盘调用。这将允许您始终将内部Call
转换为外部Call
。IsSubType<pallet_call>
为每个单独的托盘调用。这将允许你有条件地转换外部调用为内部调用,如果它存在的话。
也许这里的命名可以更好一点。我将考虑至少将外部Call
重命名为..OuterCall
.
最后,绝对建议在节点模板上运行cargo expand
,并寻找enum Call
。
TLDR;如果你把它应用在node-template上,这个困难也会起作用,应该也能回答你的问题。
diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml
index 12b810de1..6f91e8c9a 100644
--- a/bin/node-template/pallets/template/Cargo.toml
+++ b/bin/node-template/pallets/template/Cargo.toml
@@ -25,6 +25,11 @@ default-features = false
version = "2.0.0"
path = "../../../../frame/system"
+[dependencies.pallet-balances]
+default-features = false
+version = "2.0.0"
+path = "../../../../frame/balances"
+
[dev-dependencies.sp-core]
default-features = false
version = "2.0.0"
@@ -46,5 +51,6 @@ default = ['std']
std = [
'codec/std',
'frame-support/std',
- 'frame-system/std'
+ 'frame-system/std',
+ 'pallet-balances/std'
]
diff --git a/bin/node-template/pallets/template/src/lib.rs b/bin/node-template/pallets/template/src/lib.rs
index 24de4f2f5..562675a0b 100644
--- a/bin/node-template/pallets/template/src/lib.rs
+++ b/bin/node-template/pallets/template/src/lib.rs
@@ -14,9 +14,11 @@ mod mock;
mod tests;
/// Configure the pallet by specifying the parameters and types on which it depends.
-pub trait Config: frame_system::Config {
+use frame_support::traits::IsSubType;
+pub trait Config: frame_system::Config + pallet_balances::Config {
/// Because this pallet emits events, it depends on the runtime's definition of an event.
type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;
+ type Call: IsSubType<pallet_balances::Call<Self>>;
}
// The pallet's runtime storage items.
diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs
index 51df3dd5a..4ca2ab613 100644
--- a/bin/node-template/runtime/src/lib.rs
+++ b/bin/node-template/runtime/src/lib.rs
@@ -258,6 +258,7 @@ impl pallet_sudo::Config for Runtime {
/// Configure the pallet template in pallets/template.
impl template::Config for Runtime {
type Event = Event;
+ type Call = Call;
}
// Create the runtime by composing the FRAME pallets that were previously configured.
最后,使用IsSubType
确实是解决方案。
我需要将其添加到与Config
性状相关的type Call
中,如@kiaenigma所示:
pub trait Config pub trait Config: system::Config + palletA::Config + palletB::Config {
type Call: Parameter + Dispatchable<Origin = Self::Origin> + GetDispatchInfo + IsSubType<palletA::Call<Self>> + IsSubType<palletB::Call<Self>>;
}
然后在模块的方法,稍微改变我的代码如下:
impl<T: Config> Module<T>
{
fn compute_call_fee_(call: &<T as Config>::Call) -> Result<u64, DispatchError> {
match call.is_sub_type() {
Some(palletA::Call::palletA_method1(_arg1,_arg2)) => return Ok(60_u64),
Some(palletA::Call::palletA_method2(_arg1,_arg2,_arg3)) => return Ok(60_u64),
_ => {}
};
match call.is_sub_type() {
Some(palletB::Call::palletB_method1(_arg1)) => return Ok(40_u64),
_ => {}
};
return 80_u64;
}
}