Update Token Socials
Writing the on-chain metadata record. One packed bytes32 per token, owned by the deployer and transferred automatically on a successful CTO.
Interface
const SOCIALS_ABI = [
"function set_socials(address token, bytes32 packed)",
"function transfer_owner(address token, address new_owner)",
"function get_socials(address token) view returns (bytes32)",
"function get_owner(address token) view returns (address)",
"function get_record(address token) view returns (bytes32 packed, address owner, uint256 updatedAt)",
"function is_registered(address token) view returns (bool)"
];
const socials = new ethers.Contract(TOKEN_SOCIALS, SOCIALS_ABI, signer);SOCIALS_ABI = json.load(open("TokenSocials.abi.json"))
socials = w3.eth.contract(address=TOKEN_SOCIALS, abi=SOCIALS_ABI)Reading a record
const [packed, owner, updatedAt] = await socials.get_record(token);
if (packed === ethers.ZeroHash) {
// Registered but never set — deployed with no socials
}packed, owner, updated_at = socials.functions.get_record(token).call()
if packed == bytes(32):
pass # Registered but never set — deployed with no socialsget_record returns everything in one call: owner and timestamp share a storage slot, so a full read is two SLOADs.
Writing
const me = await signer.getAddress();
if ((await socials.get_owner(token)) !== me) throw new Error("not owner");
await (await socials.set_socials(token, packed)).wait();me = acct.address
if socials.functions.get_owner(token).call() != me:
raise RuntimeError("not owner")
send(socials.functions.set_socials(token, packed))The write replaces the record wholesale and refreshes the timestamp. There is no partial update — build the full 32 bytes each time.
It stores 32 opaque bytes and takes no view on their meaning. There is no schema, no validation, and no canonical encoding — the layout is an application-layer convention between whoever writes and whoever reads. Consumers should tolerate records that do not decode under their expected scheme, including records written by a different tool.
A worked encoding
Thirty-two bytes is tight, so records generally store identifiers rather than URLs. One workable layout, offered as an example rather than a standard:
// [0] scheme version
// [1:12] platform handle A, ascii, null-padded
// [12:23] platform handle B, ascii, null-padded
// [23:32] reserved
function packSocials(version, handleA, handleB) {
const buf = new Uint8Array(32);
buf[0] = version;
const enc = new TextEncoder();
buf.set(enc.encode(handleA.slice(0, 11)), 1);
buf.set(enc.encode(handleB.slice(0, 11)), 12);
return ethers.hexlify(buf);
}# [0] scheme version
# [1:12] platform handle A, ascii, null-padded
# [12:23] platform handle B, ascii, null-padded
# [23:32] reserved
def pack_socials(version, handle_a, handle_b):
buf = bytearray(32)
buf[0] = version
a = handle_a[:11].encode("ascii")
b = handle_b[:11].encode("ascii")
buf[1:1 + len(a)] = a
buf[12:12 + len(b)] = b
return bytes(buf)For anything larger than a handle, store a content hash on-chain and resolve the payload off-chain.
Ownership
Socials ownership starts with the deployer and moves automatically when a CTO succeeds — the hook calls transfer_owner during finalization so metadata follows the deployer role. You can also transfer it manually:
await (await socials.transfer_owner(token, newOwner)).wait();send(socials.functions.transfer_owner(token, new_owner))Socials ownership and the fee-earning deployer role are tracked in different contracts. A CTO moves both. A manual transfer_owner moves only the metadata — the fee share stays where it was. Read PrimaryHook.getTokenInfo(token).deployer for the fee role and get_owner(token) for metadata; do not assume they match.
Setting socials at deployment
The fourth argument to deploy_pair is the initial packed record, saving a second transaction. Pass ethers.ZeroHash to skip it and set it later.
Common reverts
| Revert | Cause |
|---|---|
Not owner | Caller does not own the record |
Not registered | No record — the protocol token path does not register |
Unauthorized | register_token called by anything but the factory |