# schema如何约束智能合约

## Schema的文件格式

一个完整的schema由三部分组成组成：前缀列表、class、predicate

#### 前缀列表

定义前缀，是为了更简短的描述一个资源。

如果没有前缀，那么需要采用完整的URI来描述资源，如描述Person\_001实体：

```
<http://relationlabs.ai/entity/Person_001>
```

定义了前缀之后，我们描述同样的实体，只需要使用简短字符：

```
:Person_001
```

完整的前缀列表:

```
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#>
```

{% hint style="info" %}
需要说明的是，`rdf:` 、`xsd:` 和 `rdfs:` 是W3C提供的标准前缀，`:`和 `p:` 是 Relation Protocol中定义的前缀，分别用于表示实体和属性。
{% endhint %}

#### Class

Class是对实体的抽象，实体是class的具体实例。比如，我们定义一组Soul实体，那么可以首先定义一个Soul的class，使用rdf描述为：

```
:Soul a rdfs:Class . 
```

#### Predicate

Predicate也叫做属性，用于描述主语和宾语的关系。Predicate通常需要定义`domain`和`range`，比如：

```
p:following a rdf:Property ;
    rdfs:domain :Soul ;
    rdfs:range :Soul .
```

这段Schema定义了：

* 谓词`p:following`是一个Property。
* `p:following`是`:Soul`的一个属性。
* `p:following`对应的属性值是`:Soul`。

## Schema示例

我们以Name Service的需求为例：

* 用户可以注册一个名称，即持有该域名
* 用户对持有的域名设置解析，将域名解析到自己的地址上

想要实现上面场景，我们需要有Soul实体表示用户的地址，Namen实体表示名称。 还需要谓词来描述两者的关系，这里有两个状态需要描述，分别为hold表示地址持有域名，resolved表示地址已被该域名解析。

因此，我们在schema里需要有下面的class和predicate

* Class
  * Soul
  * Name
* Predicate
  * hold
  * resolved
  * profileURI

基于上面定义的class和predicate，我们组装成一个完整的schema：

```
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." .

###################
# predicate
###################
p:hold a rdf:Property ;
    rdfs:label "hold" ;
    rdfs:comment "A Soul to own a name." ;
    rdfs:domain :Soul ;
    rdfs:range :Name .

p:resolved a rdf:Property ;
    rdfs:label "resolved" ;
    rdfs:comment "The resolved name of a soul." ;
    rdfs:domain :Soul ;
    rdfs:range :Name .

p:profileURI a rdf:Property ;
    rdfs:label "profileURI" ;
    rdfs:comment "The profileURI of a soul." ;
    rdfs:domain :Soul ;
    rdfs:range xsd:string .
```

一个完整的持有域名的rdf示例：

```
:Soul_0x0000000000000000000000000000000000000011 p:hold :Name_example.
```

一个完整的被域名解析的rdf示例：

```
:Soul_0000000000000000000000000000000000000011 p:resolved :Name_resolve.
```

## Schema对合约的约束

schema定义了RDF数据格式，作为合约数据模型的词汇表，需要合约内的数据模型定义跟schema保持一致（见图 4-2），这样合约生成的RDF数据才可以被Graph Indexer正确解析。

<figure><img src="/files/sI1zBOA0Vh2WmGpDDOSS" alt=""><figcaption><p>图 4-2 Schema如何约束RDF</p></figcaption></figure>

为此，我们在合约初始化时，需要传入参数schemaURI、className以及Predicate，将schema定义的内容转化成合约可读的代码结构。其中，schemaURI可以访问得到完整的schema内容；className为schema里定义的class名称；Predicate由schema里定义的predicate名称以及range类型组成。

下面是一个初始化合约传入的参数：

```javascript
const name = 'Relation Name Service V1';
const symbol = 'SBT';
const baseURI = 'https://api.example.com/v1/';
const schemaURI = 'ar://PsqAxxDYdxfk4iYa4UpPam5vm8XaEyKco3rzYwZJ_4E';
const className = ["Domain"];
const predicates = [["hold", 3], ["resolved", 3], ["profileURI", 1]];
await semanticSBT.initialize(
        owner.address,
        name,
        symbol,
        baseURI,
        schemaURI,
        className,
        predicates);
```

可以看到， schemaURI是[Arweave](https://www.arweave.org/)上的交易哈希，可以通过Arweave的网关直接访问[schema完整内容](https://arweave.net/PsqAxxDYdxfk4iYa4UpPam5vm8XaEyKco3rzYwZJ_4E)。className以及predicates与schema里定义的class和predicate是一致的。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://relationlabs.gitbook.io/protocol/protocol-zh/schema-standard/how-schema-limit-contract.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
