abstract contract TextResolver is ITextResolver, ResolverBase {
  mapping(bytes32=>mapping(string=>string)) texts;

  /**
    * Sets the text data associated with an ENS node and key.
    * May only be called by the owner of that node in the ENS registry.
    * @param node The node to update.
    * @param key The key to set.
    * @param value The text data value to set.
    */
  function setText(bytes32 node, string calldata key, string calldata value) virtual external authorised(node) {
    texts[node][key] = value;
    emit TextChanged(node, key, key);
  }

  /**
    * Returns the text data associated with an ENS node and key.
    * @param node The ENS node to query.
    * @param key The text data key to query.
    * @return The associated text data.
    */
  function text(bytes32 node, string calldata key) virtual override external view returns (string memory) {
    return texts[node][key];
  }
}
function setText(bytes32 node, string calldata key, string calldata value) virtual external authorised(node) {
  texts[node][key] = value;
  emit TextChanged(node, key, key);
}

/**
 * Sets the text data associated with an ENS node and key.
 * May only be called by the owner of that node in the ENS registry.
 * @param node The node to update.
 * @param key The key to set.
 * @param value The text data value to set.
 */