# 短评第7期：再谈NFT预言机

By [ViewDAO](https://paragraph.com/@viewdao) · 2022-05-09

---

_Author：_[_ViewDAO.DaPangDun_](https://twitter.com/BxmZhao/) _&_ [_ViewDAO.askgo_](https://twitter.com/ctguxl)

1、NFTFi的发展
----------

自从《[关于NFT流动性的研究](https://viewdao.mirror.xyz/6CGlYphepRspxrFoTGcESaDvH7rVrz4pvGzONaHy4V8)》和《[NFT预言机赛道分析](https://viewdao.mirror.xyz/OPbOZHhZLaSaxfmeTbMBfkkeRa95FJDN3b6epuq0-KA)》之后，至今已有一月有余，NFTFi的相关项目也在不断发展中，其中BendDAO也引发了不少的关注，在这个过程当中，项目对于预言机的需求也变得越来越多。

`我个人目前也在深度参与一个NFTFi的相关项目，未来如果有起色会公布出来`

![NFTFi项目图谱（部分）](https://storage.googleapis.com/papyrus_images/474a8707effaee0d94e3225c22b3c8325278290a6cc292b678fb7b2c9db979a1.png)

NFTFi项目图谱（部分）

概括来说，NFT预言机主要可以用于以下几个方面：

1）NFT借贷：为借贷项目提供NFT价格，通常为floor price，用于NFT的清算环节；

2）NFT衍生品：如NFT合约，为NFT提供市场价格，可能为floor price，也可能是actual price，一般用于利润或亏损计算、衍生品清算环节；

3）NFT数据平台：提供NFT的实时价格、系列floor价格等数据，为数据分析和展示做支撑；

4）NFT租赁或其他NFTFi项目：提供NFT价格数据的参考，让用户在评估NFT价值时拥有一个大致的参考标准；

5）成为以上相关项目的其中一个数据源来提供价格数据。

2、NFT预言机的几种机制
-------------

NFT的定价机制有【手动定价】和【自动定价】两个大的方向，对于预言机而言，必然是走自动定价这个方向，这也是未来发展必然的趋势。

常见的NFT预言机原理有三种：

**2.1 博弈定价**

即Abacus Spot类型的定价方式，通过建立池子然后进行买卖博弈的形式来提供**实时的**、**实际的**价格；

**2.2 加权算法定价**

即Chainlink类型的定价形式，通过对于相关价格（主要是floor price）进行时间加权的形式然后来**提供实时的、平滑的、floor**价格；

**2.3 机器学习算法定价**

即类似于upshot或者banksea的方式，通过相关联的数据、特征值等来对每个NFT（通常必须要有一些交易数据）提供**实时的、预测的、偏实际的**价格。

从市场的角度来说：

1）floor price具有更加广泛的应用（比如当前的NFT借贷基本都是采用的floor price，一些NFT的衍生品也是采用的floor price）；

2）一个大的争论点就是在于NFT的稀有度不同造成的NFT的内在价值是不同的，如果用floor price来衡量相对来说是不够公平的；

3）NFT实际价值的定价需求是客观存在的，这也促使了相关定价项目的发展，其中预测、时间加权、实时博弈是目前几个主要的方向，预测会有超前性和不准确性、时间加权会有滞后性、实时博弈会有失衡的可能性；

4）由于NFT的交易频率和元数据的个数不同，floor price的计算或预测相对来说会更有保证，单个NFT的预测会因为元数据的问题而具有更高的不确定性。

3、两个项目的API测试情况
--------------

之前提到过两个我们看好的NFT预言机项目，即：upshot和banksea。我们的一个重要的理念是持续的追踪项目的情况，中间更新过这两个项目的一些信息，这次借本文更新一下对二者API的测试情况：

### 3.1 Upshot

upshot的API介绍文档：

[https://docs.upshot.xyz/upshot-api/](https://docs.upshot.xyz/upshot-api/)

我们测试总计9个接口，分述如下：

**3.1.1 GetCollections 获取收藏**

请求地址：

[https://api.upshot.io/v1/collections](https://api.upshot.io/v1/collections)

返回数据结构体：

    type Result struct {
        Status bool `json:"status"`  
        Message string `json:"message"` 
        Data struct {
            Count int `json:"count"`
            Collections []struct {
                ID int `json:"id"`  
                Name string `json:"name"`
                Description string `json:"description"`
                ImageURL string `json:"imageUrl"`
                Slug string `json:"slug"`
            } `json:"collections"`
        } `json:"data"`
    }
    

**3.1.2 GetCollectionsBySlug 通过slug获取收藏**

请求地址：

[https://api.upshot.io/v1/collections/slug/coquina-by-jacob-gold](https://api.upshot.io/v1/collections/slug/coquina-by-jacob-gold)

返回数据结构体：

    {
        "status": true,
        "message": "collection retrieved successfully",
        "data": {
            "id": 1520,
            "name": "Coquina",
            "description": "Organic....",
            "imageUrl": "https://api.artblocks.io/image/198000000",
            "slug": "coquina-by-jacob-gold"
        }
    }
    

**3.1.3 GetCollectionByContractAddress 通过合约地址获取收藏**

请求地址：[https://api.upshot.io/v1/collections/contractAddress/0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB](https://api.upshot.io/v1/collections/contractAddress/0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB)

返回数据结构体：

    {
        "status": true,
        "message": "collection retrieved successfully",
        "data": {
            "id": 1,
            "name": "CryptoPunks",
            "description": "CryptoPunks....",
            "imageUrl": "https://lh3.googleusercontent.com/BdxvLseXcfl57BiuQcQYdJ64v-aI8din7WPk0Pgo3qQFhAUH-B6i-dCqqc_mCkRIzULmwzwecnohLhrcH8A9mpWIZqA7ygc52Sr81hE=s120",
            "slug": "cryptopunks"
        }
    }
    

**3.1.4 GetAssetEvents 获取资产事件**

请求地址：

[https://api.upshot.io/v1/assets/events?assetId=0xe4605d46Fd0B3f8329d936a8b258D69276cBa264/439&type=SALE&marketType=SECONDARY](https://api.upshot.io/v1/assets/events?assetId=0xe4605d46Fd0B3f8329d936a8b258D69276cBa264/439&type=SALE&marketType=SECONDARY)

返回数据结构体：

    {
        "status": true,
        "message": "Asset Events gotten successfully",
        "data": []
    }
    

**3.1.5 GetAsset 获取资产**

请求地址：

[https://api.upshot.io/v1/assets?assetId=0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB/0](https://api.upshot.io/v1/assets?assetId=0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB/0)

返回数据结构体：

    type Result struct {
        Status bool `json:"status"`
        Message string `json:"message"`
        Data struct {
            Count int `json:"count"`
            Assets []struct {
                AssetID string `json:"assetId"`
                TokenID string `json:"tokenId"`
                Name string `json:"name"`
                Description string `json:"description"`
                CreatorAddress string `json:"creatorAddress"`
                MediaURL string `json:"mediaUrl"`
                TokenURI interface{} `json:"tokenUri"`
                ContractAddress string `json:"contractAddress"`
                PreviewImageURL string `json:"previewImageUrl"`
                MediaType string `json:"mediaType"`
                SourceType string `json:"sourceType"`
                TxBlockNumber string `json:"txBlockNumber"`
                TxHash string `json:"txHash"`
                TxAt int `json:"txAt"`
                Contract struct {
                    Address string `json:"address"`
                    Name string `json:"name"`
                    ImageURL string `json:"imageUrl"`
                    Description string `json:"description"`
                    TotalSupply interface{} `json:"totalSupply"`
                    SchemaType string `json:"schemaType"`
                    Symbol interface{} `json:"symbol"`
                    ChainID int `json:"chainId"`
                } `json:"contract"`
                Traits []struct {
                    TraitID int `json:"traitId"`
                    Trait struct {
                        TraitType string `json:"traitType"`
                        DisplayType string `json:"displayType"`
                        Value string `json:"value"`
                    } `json:"trait"`
                } `json:"traits"`
            } `json:"assets"`
        } `json:"data"`
    }
    

**3.1.6 GetAllPricesPerAsset 获取每项资产的所有价格**

请求地址：

[https://api.upshot.io/v1/prices?assetId=0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB/11](https://api.upshot.io/v1/prices?assetId=0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB/11)

返回数据结构体：

      type Result  struct {
        Status bool `json:"status"`
        Message string `json:"message"`
        Data struct {
            Count int `json:"count"`
            Pricings []struct {
                AssetID string `json:"assetId"`
                EstimatedPrice string `json:"estimatedPrice"`
                Low string `json:"low"`
                High string `json:"high"`
                Confidence float64 `json:"confidence"`
                Source string `json:"source"`
                Timestamp int `json:"timestamp"`
                ResolutionID interface{} `json:"resolutionId"`
                CollectionID int `json:"collectionId"`
                Agreement interface{} `json:"agreement"`
                CertificationTimestamp interface{} `json:"certificationTimestamp"`
                EthSalePrice string `json:"ethSalePrice"`
                UsdSalePrice string `json:"usdSalePrice"`
                MedianRelativeError float64 `json:"medianRelativeError"`
                Currency struct {
                    ID int `json:"id"`
                    Symbol string `json:"symbol"`
                    Name string `json:"name"`
                    Decimals int `json:"decimals"`
                    ContractAddress string `json:"contractAddress"`
                    Description interface{} `json:"description"`
                    ImageURL string `json:"imageUrl"`
                    CoinGeckoID string `json:"coinGeckoId"`
                    ChainID int `json:"chainId"`
                } `json:"currency"`
                Asset struct {
                    ID string `json:"id"`
                    TokenID string `json:"tokenId"`
                    Name string `json:"name"`
                    Description string `json:"description"`
                    CreatorAddress string `json:"creatorAddress"`
                    MediaURL string `json:"mediaUrl"`
                    TokenURI interface{} `json:"tokenUri"`
                    ContractAddress string `json:"contractAddress"`
                    MediaType string `json:"mediaType"`
                    SourceType string `json:"sourceType"`
                    TxBlockNumber string `json:"txBlockNumber"`
                    TxHash string `json:"txHash"`
                    TxAt int `json:"txAt"`
                    PreviewVideoURL interface{} `json:"previewVideoUrl"`
                    Rarity float64 `json:"rarity"`
                    RarityProcessed bool `json:"rarityProcessed"`
                    Allowed bool `json:"allowed"`
                    Popular bool `json:"popular"`
                    Priority string `json:"priority"`
                    LastSaleAt interface{} `json:"lastSaleAt"`
                    LastSaleWeiPrice interface{} `json:"lastSaleWeiPrice"`
                    LastAppraisalAt int `json:"lastAppraisalAt"`
                    LastAppraisalWeiPrice string `json:"lastAppraisalWeiPrice"`
                    TotalOwners int `json:"totalOwners"`
                    LastSaleUsdPrice interface{} `json:"lastSaleUsdPrice"`
                    LastAppraisalUsdPrice string `json:"lastAppraisalUsdPrice"`
                    PreviewImageWidth int `json:"previewImageWidth"`
                    PreviewImageHeight int `json:"previewImageHeight"`
                    WarningBanner bool `json:"warningBanner"`
                    CollectionID int `json:"collectionId"`
                    CreatedAt time.Time `json:"createdAt"`
                    UpdatedAt time.Time `json:"updatedAt"`
                    DeletedAt interface{} `json:"deletedAt"`
                } `json:"asset"`
            } `json:"pricings"`
        } `json:"data"`
    }
    

**3.1.7 GetCurrentPricesForAnAsset 获取资产的当前价格**

请求地址：

[https://api.upshot.io/v1/prices/latest?assetId=0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB/11](https://api.upshot.io/v1/prices/latest?assetId=0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB/11)

返回数据结构体：

    type Result struct {
        Status bool `json:"status"`
        Message string `json:"message"`
        Data []struct {
            AssetID string `json:"assetId"`
            CurrentPricing struct {
                AssetID string `json:"assetId"`
                EstimatedPrice string `json:"estimatedPrice"`
                Low string `json:"low"`
                High string `json:"high"`
                Confidence float64 `json:"confidence"`
                Source string `json:"source"`
                Timestamp int `json:"timestamp"`
                ResolutionID interface{} `json:"resolutionId"`
                CollectionID int `json:"collectionId"`
                Agreement interface{} `json:"agreement"`
                CertificationTimestamp interface{} `json:"certificationTimestamp"`
                EthSalePrice string `json:"ethSalePrice"`
                UsdSalePrice string `json:"usdSalePrice"`
                MedianRelativeError float64 `json:"medianRelativeError"`
                Currency struct {
                    ID int `json:"id"`
                    Symbol string `json:"symbol"`
                    Name string `json:"name"`
                    Decimals int `json:"decimals"`
                    ContractAddress string `json:"contractAddress"`
                    Description interface{} `json:"description"`
                    ImageURL string `json:"imageUrl"`
                    CoinGeckoID string `json:"coinGeckoId"`
                    ChainID int `json:"chainId"`
                } `json:"currency"`
                Asset struct {
                    ID string `json:"id"`
                    TokenID string `json:"tokenId"`
                    Name string `json:"name"`
                    Description string `json:"description"`
                    CreatorAddress string `json:"creatorAddress"`
                    MediaURL string `json:"mediaUrl"`
                    TokenURI interface{} `json:"tokenUri"`
                    ContractAddress string `json:"contractAddress"`
                    MediaType string `json:"mediaType"`
                    SourceType string `json:"sourceType"`
                    TxBlockNumber string `json:"txBlockNumber"`
                    TxHash string `json:"txHash"`
                    TxAt int `json:"txAt"`
                    PreviewVideoURL interface{} `json:"previewVideoUrl"`
                    Rarity float64 `json:"rarity"`
                    RarityProcessed bool `json:"rarityProcessed"`
                    Allowed bool `json:"allowed"`
                    Popular bool `json:"popular"`
                    Priority string `json:"priority"`
                    LastSaleAt interface{} `json:"lastSaleAt"`
                    LastSaleWeiPrice interface{} `json:"lastSaleWeiPrice"`
                    LastAppraisalAt int `json:"lastAppraisalAt"`
                    LastAppraisalWeiPrice string `json:"lastAppraisalWeiPrice"`
                    TotalOwners int `json:"totalOwners"`
                    LastSaleUsdPrice interface{} `json:"lastSaleUsdPrice"`
                    LastAppraisalUsdPrice string `json:"lastAppraisalUsdPrice"`
                    PreviewImageWidth int `json:"previewImageWidth"`
                    PreviewImageHeight int `json:"previewImageHeight"`
                    WarningBanner bool `json:"warningBanner"`
                    CollectionID int `json:"collectionId"`
                    CreatedAt time.Time `json:"createdAt"`
                    UpdatedAt time.Time `json:"updatedAt"`
                    DeletedAt interface{} `json:"deletedAt"`
                } `json:"asset"`
            } `json:"currentPricing"`
        } `json:"data"`
    }
    

**3.1.8 GetUser 获取用户**

请求地址 ：

[https://api.upshot.io/v1/users/0xc896866e927e6f8a416ba209976115e79fa0a66f](https://api.upshot.io/v1/users/0xc896866e927e6f8a416ba209976115e79fa0a66f)

返回数据结构体：

    type Result struct {
        Status bool `json:"status"`
        Message string `json:"message"`
        Data struct {
            UserAddress string `json:"userAddress"`
            Ens interface{} `json:"ens"`
            AppraisedWeiSum string `json:"appraisedWeiSum"`
            AppraisedUSDSum string `json:"appraisedUSDSum"`
            AssetOwned []struct {
                AssetID string `json:"assetId"`
                TotalEditions string `json:"totalEditions"`
                AcquiredTimestamp int `json:"acquiredTimestamp"`
                SentTimestamp interface{} `json:"sentTimestamp"`
                Asset struct {
                    ID string `json:"id"`
                    TokenID string `json:"tokenId"`
                    Name string `json:"name"`
                    Description string `json:"description"`
                    CreatorAddress string `json:"creatorAddress"`
                    MediaURL string `json:"mediaUrl"`
                    TokenURI string `json:"tokenUri"`
                    ContractAddress string `json:"contractAddress"`
                    PreviewImageURL string `json:"previewImageUrl"`
                    MediaType string `json:"mediaType"`
                    SourceType string `json:"sourceType"`
                    TxBlockNumber string `json:"txBlockNumber"`
                    TxHash string `json:"txHash"`
                    TxAt int `json:"txAt"`
                    LastSaleAt interface{} `json:"lastSaleAt"`
                    LastSaleWeiPrice interface{} `json:"lastSaleWeiPrice"`
                    LastAppraisalAt int `json:"lastAppraisalAt"`
                    LastAppraisalWeiPrice string `json:"lastAppraisalWeiPrice"`
                    TotalOwners int `json:"totalOwners"`
                    LastSaleUsdPrice interface{} `json:"lastSaleUsdPrice"`
                    LastAppraisalUsdPrice string `json:"lastAppraisalUsdPrice"`
                } `json:"asset"`
            } `json:"assetOwned"`
        } `json:"data"`
    }
    

**3.1.9 GetMultipleUsers 获取多个用户**

请求地址：

[https://api.upshot.io/v1/users?addressOrENS=](https://api.upshot.io/v1/users?addressOrENS=)\["0xB4460Bdf3Fe5Ba4e25f96135A76BDCb9E45AB010", "don-luv.eth"\]

返回数据结构体：

    type Result struct {
        Status bool `json:"status"`
        Message string `json:"message"`
        Data []struct {
            UserAddress string `json:"userAddress"`
            Ens interface{} `json:"ens"`
            AppraisedWeiSum string `json:"appraisedWeiSum"`
            AppraisedUSDSum string `json:"appraisedUSDSum"`
            AssetOwned []struct {
                AssetID string `json:"assetId"`
                TotalEditions string `json:"totalEditions"`
                AcquiredTimestamp int `json:"acquiredTimestamp"`
                SentTimestamp interface{} `json:"sentTimestamp"`
                Asset struct {
                    ID string `json:"id"`
                    TokenID string `json:"tokenId"`
                    Name string `json:"name"`
                    Description string `json:"description"`
                    CreatorAddress string `json:"creatorAddress"`
                    MediaURL string `json:"mediaUrl"`
                    TokenURI string `json:"tokenUri"`
                    ContractAddress string `json:"contractAddress"`
                    PreviewImageURL string `json:"previewImageUrl"`
                    MediaType string `json:"mediaType"`
                    SourceType string `json:"sourceType"`
                    TxBlockNumber string `json:"txBlockNumber"`
                    TxHash string `json:"txHash"`
                    TxAt int `json:"txAt"`
                    LastSaleAt interface{} `json:"lastSaleAt"`
                    LastSaleWeiPrice interface{} `json:"lastSaleWeiPrice"`
                    LastAppraisalAt interface{} `json:"lastAppraisalAt"`
                    LastAppraisalWeiPrice interface{} `json:"lastAppraisalWeiPrice"`
                    TotalOwners int `json:"totalOwners"`
                    LastSaleUsdPrice interface{} `json:"lastSaleUsdPrice"`
                    LastAppraisalUsdPrice interface{} `json:"lastAppraisalUsdPrice"`
                } `json:"asset"`
            } `json:"assetOwned"`
        } `json:"data"`
    }
    

目前API是开放的，我们测试了没有调用频率的限制（未来应该会加上限制）

### 3.2 Banksea

目前只提供了一个接口 用来取价格 Fetch price

**3.2.1 测试 Ethereum 上数据**

测试 Ethereum 上面的数据，测试NFT集为 BoredApeYachtClub BAYC #3421

Eethereum提供合约ID和TokenID

    const report1 = await fetchTokenReport(program, {
      contractAddress: 0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d
      tokenId: 3421
    })
    

请求之后 成功返回：

    {
      assetAddr: 'CzhLY2c312v8tRCTc4rfcaU6GYN9tVKQL6wZBdZqpyc1',
      decimal: '6',
      price: '19457051',
      priceType: 'ETH',
      risk: '9442',
      time: '1651201855',
      name: 'BAYC #3421'
    }
    

**3.2.2 测试Solana链上数据**

测试 Solana 上面的数据，测试NFT集为 Degen Ape #110 项目市场位于 [https://solanart.io/](https://solanart.io/)

Solana 上面 只需提供NFT的合约地址

    const report2 = await fetchTokenReport(program, '7xZxwzmYVTfzvHR21fwp81PNy8dzMvN2DAmEi12WfRqA')
    

请求之后 成功返回：

    {
      assetAddr: 'YZj65Lhtni37ZM8tqtxEUZLpD8Uzu1rouJcseLCtA6w',
      decimal: '6',
      price: '34656747',
      priceType: 'SOL',
      risk: '7604',
      time: '1651209074',
      name: 'Degen Ape #110'
    }
    

测试 Solana 上面的数据，测试NFT集为 SolPunk\_#3596 (SolPunks)项目市场位于 [https://solanart.io/](https://solanart.io/)

报错信息为：

    Account does not exist ${address.toString()}

---

*Originally published on [ViewDAO](https://paragraph.com/@viewdao/7-nft)*
