Originally asked on Discord.
The short answer to this is “no” – address-owned, shared and immutable objects all need to be specified as inputs to entry functions, so it is not possible to load them dynamically by ID in the middle of a move call transaction.
However, Dynamic Fields can be loaded dynamically, so if you find yourself needing to load an object by its ID during a move call, a useful pattern is to add those objects as dynamic fields to an over-arching parent, which is passed in as entry function for access. The Bag collection type is an example of this pattern:
module example::dynamic_loading {
use std::string::{Self, String};
use sui::object_bag::{Self as obag, ObjectBag};
use sui::object::{Self, ID, UID};
use sui::tx_context::{Self, TxContext};
struct Item has key, store {
id: UID,
label: String,
};
struct Holder has key {
id: UID,
items: ObjectBag<Id, Item>,
}
public entry fun add_item(holder: &mut Holder, item: Item) {
obag::add<ID, Item>(
&mut hold.items,
object::id(&item),
item,
);
}
public entry fun use_item(holder: &Holder, i: ID, j: ID, choice: bool) {
let item = obag::borrow<ID, Item>(
&holder.items,
if (choice) { i } else { j },
);
// use item: &Item
}
}