Name Service

In Web3 systems, an address is used as a user's identity. However, addresses are difficult to recognize and remember. Take an address on the Ethereum blockchain for example, it is a heximal string with a length of 40 characters. It is not easy to recognize that in a social setting.

Therefore, we devised a Relation Name Service contract parsing readable names (eg. "relation.soul") as computer-readable identifiers.

Meanwhile, we also use arweave, a decentralized storage system, to expand properties of an identity to build a comprehensive profile. Users can store other information in arweave and save the arweave transaction hash in the Name Service contract.

Relation Name Service, or RNS, is an important part of the Relation Protocol. RNS is a SBT itself, allowing users to control their own social identity data in the Relation network.

Name Service SBTs are owned by individual addresses. They have two status:

  • hold: Under this status, a Name Service SBT can be transferred. But no one can search for it with its name or query its address.

  • resolved: When an address undertakes a "resolve" action to bind the token with Soul, the Name Service SBT 's name will be bound to an address. It can not be transferred under this status.

To ensure a unique result for recommendation and searching by the social graph, an address can hold multiple Name Service SBTs, but it can only "Bound" one at the same time.

Schema

The schema corresponding to the Relation Name Service contract is saved to Arweave in the form of a ttl file, with the transaction hash as the schemaURI to be passed to the contract during its initialization stage. For example:

ar://PsqAxxDYdxfk4iYa4UpPam5vm8XaEyKco3rzYwZJ_4E
  • The list of prefixes.

PREFIX : <http://relationlabs.ai/entity/>
PREFIX p: <http://relationlabs.ai/property/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
  • Class

:Soul a rdfs:Class ;
    rdfs:label "soul" ;
    rdfs:comment "A soul" .

:Name a rdfs:Class ;
    rdfs:label "name" ;
    rdfs:comment "A name." .

":Soul" represents the address accepting and bounding names. ":Domain" represents a domain name.

  • Predicate

p:hold a rdfs:Class ;
    rdfs:label "connectionAddress" ;
    rdfs:comment "A Soul to own a name." ;
    rdfs:range :Name .

p:resolved a rdfs:Class ;
    rdfs:label "connectionAddress" ;
    rdfs:comment "The resolved name of a soul." ;
    rdfs:range :Name .
    
p:profileURI a rdfs:Class ;
    rdfs:label "profileURI" ;
    rdfs:comment "The profileURI of a soul." ;
    rdfs:domain :Soul ;
    rdfs:range xsd:string .

"p:hold" means the address holds an address but has not yet resolved it. "p:resolved" means the address has linked with a domain name, thus one can resolve the address via the domain name."p:profileURI" means the profileURI of an address.

Contract

The interface of the contract

The interface of the Name Service contract is as follows:

interface INameService is ISemanticSBT {

    /**
     * To register a domain name
     * @param owner : The owner of a domain name
     * @param name : The domain name to be registered.
     * @param reverseRecord : Whether to set a record for resolving the domain name.
     * @returns tokenId
     */
    function register(address owner, string calldata name, bool reverseRecord) external returns (uint);

    /**
     * To set a record for resolving the domain name, linking the name to an address.
     * @param addr : The owner of the domain name. If the address is "0", then the link is canceled.
     * @param name : The domain name.
     */
    function setNameForAddr(address addr, string calldata name) external;

    /**
     * A profileURI set for the caller
     * @param profileURI : The transaction hash from arweave.
     */
    function setProfileURI(string memory profileURI) external;

    /**
     * To resolve a domain name.
     * @param name : The domain name.
     * @return addr : The address.
     */
    function addr(string calldata name) virtual external view returns (address);

    /**
     * Reverse mapping
     * @param addr : The address.
     * @return name : The domain name.
     */
    function nameOf(address addr) external view returns (string memory);

    /**
     * To query the profileURI of an address.
     * @param addr : The address.
     * @return profileURI : The transaction hash from arweave.
     */
    function profileURI(address addr) external view returns (string memory);
}

Full source code:

Contract implementation note:

We set a few rules for the Name Service:

  • The shortest length for a domain name is 3 characters.

  • A domain name can only be resolved properly by the contract after setting a resolve record. This can be done in two ways:

    • To set the record during "register".

    • To call the "setNameForAddr" method after "register"

  • If the current domain name has set a resolve record, you need to unbound it from the previous address before you can resolve it to a new one.

  • The contract disables "transfer" by default, effectively banning all token transfers. To turn on this option, you can call the "setTransferable" method.

  • Only tokens without a current resolve record can be transferred.

Last updated