Replies: 1 comment 2 replies
-
This is a tricky one, because of the generics. I would note that, if you're already passing in the strategy address, you probably should already have the information about the generics (or you can make that information available on-chain for the off-chain reader on submission). I would definitely make a named object if you don't want to delete it and you want it to be idempotent / a singular instance. Here are a few options:
module 0x42::example {
#[resource_group_member(group = aptos_framework::object::ObjectGroup)]
struct Strategy<phantom X, phantom Y, phantom BinStep> has key { ... }
fun seed<X, Y, BinStep>() {
let seed = type_name<X>();
string::append(&mut seed, type_name<Y>());
string::append(&mut seed, type_name<BinStep>());
let seed_bytes = string::bytes(&seed);
}
fun create_strategy<X, Y, BinStep>(...) {
let seed_bytes = seed();
let strategy_constructor_ref = object::create_named_object(resource_signer, seed_bytes);
let strategy_object_signer = object::generate_signer(&strategy_constructor_ref);
let strategy_addr = signer::address_of(&strategy_object_signer);
}
public fun update_strategy<X, Y, BinStep>(sender: &signer, strategy_addr: address, some_setting: u128) acquires Strategy {
// If there's a limited number of strategies, you can check here e.g.:
if (exists<Strategy<A, B, C>) {
let strategy = borrow_global_mut<Strategy<A, B, C>>(strategy_addr);
strategy.some_setting = some_setting;
} else if (exists<Strategy<B, C, D>) {
let strategy = borrow_global_mut<Strategy<B, C, D>>(strategy_addr)
strategy.some_setting = some_setting;
} else if (...) {
} else {
abort 12345
}
}
} The second option here allows you to check the existence on-chain dynamically, but it's unsustainable for too many pairs.
module 0x42::example {
#[resource_group_member(group = aptos_framework::object::ObjectGroup)]
struct Strategy<phantom X, phantom Y, phantom BinStep> has key { ... }
fun create_strategy<X, Y, BinStep>(...) {
let seed = bcs::to_bytes(&vault_addr);
let strategy_constructor_ref = object::create_named_object(resource_signer, seed);
let strategy_object_signer = object::generate_signer(&strategy_constructor_ref);
let strategy_addr = signer::address_of(&strategy_object_signer);
}
public fun update_strategy(sender: &signer, strategy_addr: address, some_setting: u128) acquires Strategy {
// If there's a limited number of strategies, you can check here e.g.:
if (exists<Strategy<A, B, C>) {
let strategy = borrow_global_mut<Strategy<A, B, C>>(strategy_addr);
strategy.some_setting = some_setting;
} else if (exists<Strategy<B, C, D>) {
let strategy = borrow_global_mut<Strategy<B, C, D>>(strategy_addr)
strategy.some_setting = some_setting;
} else if (...) {
} else {
abort 12345
}
}
} The final one is similar to above, just some slight ergonomic changes at cost of slightly more storage.
module 0x42::example {
#[resource_group_member(group = aptos_framework::object::ObjectGroup)]
struct Strategy<phantom X, phantom Y, phantom BinStep> has key { ... }
#[resource_group_member(group = aptos_framework::object::ObjectGroup)]
struct StrategyType has key {
type: u16
}
fun create_strategy<X, Y, BinStep>(...) {
let seed = bcs::to_bytes(&vault_addr);
let strategy_constructor_ref = object::create_named_object(resource_signer, seed);
let strategy_object_signer = object::generate_signer(&strategy_constructor_ref);
let strategy_addr = signer::address_of(&strategy_object_signer);
if (type_name<X>() == "0x1::coin::Coin" && ...) {
move_to(&strategy_object_signer, StrategyType { type: 1 })
}
}
public fun update_strategy(sender: &signer, strategy_addr: address, some_setting: u128) acquires Strategy {
let strategy_type = borrow_global<StrategyType>(strategy_addr).type;
// If there's a limited number of strategies, you can check here e.g.:
if (strategy_type == 0) {
let strategy = borrow_global_mut<Strategy<A, B, C>>(strategy_addr)
strategy.some_setting = some_setting;
} else if (...) {
} else {
abort 12345
}
}
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Discord user ID
No response
Describe your question in detail.
I'm working on a Move module in Aptos that defines a generic resource struct:
Multiple instances of this
Strategy
struct are created and stored in global storage, each with different type parameters (<X, Y, BinStep>
).I'm facing a challenge in my functions(such as the
update_strategy
function) that need to operate on theseStrategy
instances. Currently, I have to explicitly pass the type arguments to these functions, which is cumbersome. I'd like to find a way to identify the correctStrategy
instance based on its address(i.e. the object address), and potentially infer its type arguments in a more dynamic way.My current approach involves:
object::create_named_object
to create the resourcestrategy_addr
from the object signer. A given strategy_addr is statically coupled to the type arguments<X, Y, BinStep>
Essentially something like:
I'm looking for guidance on best practices or recommended patterns for achieving this kind type inference with generic resources in Aptos Move.
Is it possible to directly infer the type arguments of a generic resource based on its address alone in Aptos Move, or are workarounds necessary?
Any code examples or insights from the community would be greatly appreciated!
What error, if any, are you getting?
No response
What have you tried or looked at? Or how can we reproduce the error?
N/A
Which operating system are you using?
N/A
Which SDK or tool are you using? (if any)
N/A
Describe your environment or tooling in detail
No response
Beta Was this translation helpful? Give feedback.
All reactions