Imagine I have a move module that looks like this.
Move.toml
[package]
name = 'friends'
version = '1.0.0'
[dependencies.AptosFramework]
git = 'https://github.com/aptos-labs/aptos-core.git'
rev = 'testnet'
subdir = 'aptos-move/framework/aptos-framework'
[addresses]
friends = "81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e"
sources/nicknames.move
module friends::nicknames {
use std::error;
use std::signer;
use std::string::String;
use aptos_std::table::{Self, Table};
const ENOT_INITIALIZED: u64 = 0;
struct Nicknames has key {
// A map of friends' nicknames to wallet addresses.
nickname_to_addr: Table<String, address>
}
/// Initialize Inner to the caller's account.
public entry fun initialize(account: &signer) {
let nicknames = Nicknames {
nickname_to_addr: table::new(),
};
move_to(account, nicknames);
}
/// Initialize Inner to the caller's account.
public entry fun add(account: &signer, nickname: String, friend_addr: address) acquires Nicknames {
let signer_addr = signer::address_of(account);
assert!(exists<Nicknames>(signer_addr), error::not_found(ENOT_INITIALIZED));
let nickname_to_addr = &mut borrow_global_mut<Nicknames>(signer_addr).nickname_to_addr;
table::add(nickname_to_addr, nickname, friend_addr);
}
}
I then published the module (to testnet), initialized Nicknames
to my account, and then added an entry:
aptos move publish
aptos move run --function-id 81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e::nicknames::initialize
aptos move run --function-id 81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e::nicknames::add --args string:dport address:81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e
Now that my table is on-chain with some data, how would I go about reading the value of the dport
key. I think I can use the API for this?
You're right that you can use the API for this! First let's get some information about your table.
Let's look at the resource you've deployed to your account from the above Move module. First let's construct the struct tag (aka resource ID / handle), it looks like this:
<account_address>::<module>::<struct_name>
In your case:
0x81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e::nicknames::Nicknames
Because there can only be one of each resource in an account in the Aptos blockchain, we can use this to uniquely identify the resource in your account. Using this we can then get the table handle. A table handle is a globally unique ID (so, not just within the bounds of your account) that points to that specific table. We need that to make any further queries, so let's get that first:
$ curl https://fullnode.testnet.aptoslabs.com/v1/accounts/0x81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e/resource/0x81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e::nicknames::Nicknames | jq .
{
"type": "0x81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e::nicknames::Nicknames",
"data": {
"nickname_to_addr": {
"handle": "0x64fa842ed2c9da130f0419875e6c101aeea263882fadee3257b13f1bb4d7d41d"
}
}
}
Explaining the above:
https://fullnode.testnet.aptoslabs.com/v1/accounts/0x81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e/resource/<name>
lets us get a specific resource on an account.0x81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e::nicknames::Nicknames
. The two addresses happen to be the same here, but that's just because we're using the same account, another example could be 0x1::aptos_coin::AptosCoin
.0x64fa842ed2c9da130f0419875e6c101aeea263882fadee3257b13f1bb4d7d41d
.Using this handle, we can now query the API:
$ cat query.json
{
"key_type": "0x1::string::String",
"value_type": "address",
"key": "dport"
}
$ curl -H 'Content-Type: application/json' --data-binary "@query.json" https://fullnode.testnet.aptoslabs.com/v1/tables/0x64fa842ed2c9da130f0419875e6c101aeea263882fadee3257b13f1bb4d7d41d/item
"0x81e2e2499407693c81fe65c86405ca70df529438339d9da7a6fc2520142b591e"
Explaining the above:
query.json
file.key_type
is the type of the key in the table. You can see from the original declaration of nickname_to_addr
that this was 0x1::string::String
.value_type
is the type of the value. Its type was address
, a special type that isn't deployed at any particular module (hence the lack of <addr>::<module>::
.key
is the key that we're querying in the table.If hypothetically the key used in the table was more complex, like a struct instead of a single value like a string, you could represent that struct as JSON in the request, e.g.
{
"key_type": "0x1::string::String",
"value_type": "address",
"key": {
"first_name": "Ash",
"last_name": "Ketchum",
}
}
This is the extent of what you can do with the API right now. Namely, reading values given you know the key ahead of time. If you want to do the below things, you need to query an indexer:
I'll write an answer on how to do this later.