# Web3应用程序商店协议——为Web3应用程序的注册和分发提供标准

By [W3.Hitchhiker](https://paragraph.com/@w3hitchhiker) · 2021-12-28

---

原文：

[https://github.com/RabbyHub/Web3AppStoreProtocol#web3-app-store-protocol---standardizes-registration-and-distribution-for-web3-app](https://github.com/RabbyHub/Web3AppStoreProtocol#web3-app-store-protocol---standardizes-registration-and-distribution-for-web3-app)

译者：Evelyn ｜ W3.Hitchhiker

Background（背景）
--------------

目前，开发者可以通过区块链上的一套智能合约向用户提供无信任协议层服务。但是，典型的日常用户不具有可以直接理解和使用这些智能合约的能力——因此，他们需要一个无信任、安全和易于使用的应用层。

应用层开发人员部署了易于使用的用户界面，以帮助用户与协议和代币直接互动。这些应用程序大多会尝试连接到用户的Web3钱包，并直接请求签名。

我们将这些应用程序称为 "Web3 App"。例如，Uniswap的官方网络应用，托管在[https://app.uniswap.org](https://app.uniswap.org/)，是一个典型的Web3应用，它将帮助用户在区块链上与自己的协议进行互动。以下是Uniswap的应用程序和协议的技术结构：

![](https://storage.googleapis.com/papyrus_images/00765815ea24f7686f546cc8fd9536748d48e0842366eb411ee149bb71f76fa6.png)

### Motivation（激励）

随着协议层上的智能合约与相应的Web3应用程序一起激增，但我们仍然能看到目前行业实践中有两个关键的问题，即围绕可访问性和安全性。

### Accessibility（可访问性）

首先，如今大多数Web3应用程序都将其代码存储在项目所有者所控制的云服务中。如果所有者将网站下线，或者网站被DDos关闭，或者为了响应国家政策要求，等等，一个典型的用户将不再能够轻松地管理他们的资产（除非他们足够聪明，能够直接与协议层互动）。访问的不确定性可以是很可怕的，因为这会减少用户之间的信任。

### Security（安全性）

其次，目前大多数用户通过Web浏览器和Web3插件的组合来访问Web3应用程序，这个过程充满了安全问题。这就使项目组和黑客都有机会在Web3应用程序中嵌入新的恶意代码，从而窃取用户的资产。

无论是插件还是浏览器，都无法对用户发出警报或保证其安全。这种缺乏保护的情况基本上意味着Web3的用户需要精通技术和安全，否则很容易被黑客咬死，并永远离开加密世界。

Specification（规格）
-----------------

### Web3应用程序商店协议

我们提出了一个**Web3应用商店协议**来解决上述的可访问性和安全性问题。这些应用商店应该包含一个基于智能合约的**Web3应用注册中心（Web3 App Registry）**，一个基于围绕权限、版本描述、规格等存储在链外的元数据的**Web3应用程序包**，以及一个安装在用户本地设备上的**Web3应用商店客户端**。之后，我们还需要**Web3审核员（auditors**）来帮助用户审核Web3应用程序的源代码。这些组件之间的关系如下所示。

![](https://storage.googleapis.com/papyrus_images/a997975dd761627159d6bfc5cf9428bae60853fcd8f01d7d6cf2639a46f17048.png)

**Web3应用注册中心（Web3 App Registry）是一套基于Web3 App注册标准（Web3 App Registration Standard）的智能合约**。团体（Orgs）和个人可以无权限地建立他们自己的Web3应用程序注册中心。Web3开发者可以使用他们的链上账户在该注册中心中注册他们的Web3应用程序，并对安装包的发行版和校验和（checksum）进行版本管理。审核员可以无权限地使用他们的链上账户来审核所有这些应用程序，并在注册表中公布结果。

\*\*Web3应用程序包（Web3 App Packages）**是指由开发商发布的软件，供用户在其本地设备上安装Web3应用程序。这些软件包可以存储在任何中心化或去中心化的存储服务中，软件包的网址和校验和应记录在注册表上。同时，在基于**Web3应用配置标准（Web3 Application Configuration Standard）\*\*上，在软件包的根部应该有一个包含Web3应用的权限声明和版本描述的配置文件。源代码的存储路径应被指定在配置文件中，以便审计人员能够轻松获取源代码进行审计。

\*\*Web3应用商店客户端（Web3 App Store Client）**是安装在用户本地设备上的软件。团体和个人可以在**Web3应用商店客户端标准（App Store Client Standard）\*\*的基础上自由地建立自己的应用商店客户端。客户端可以同时连接到一个或多个注册中心。它需要从注册表中获取Web3应用程序列表、版本信息和审计信息。当用户安装或更新一个Web3应用程序时，需要自动获取安装包。然后验证软件包的校验和（checksum）是否与注册中心中的校验和（checksum）相等。最后，它应该告诉用户这个Web3应用需要多少权限。而在用户确认权限后，Web3 App将被安装在本地设备上。

这种设计框架确保了Web3应用程序的可访问性，是因为用户可以继续使用旧的本地版本——并有权根据新的注册中心和新的应用程序包进行升级。

同时，客户端会将本地软件包的校验和与注册中心中的校验和（checksum）进行验证，从而避免了黑客或项目组的更改机会，并确保用户使用的应用程序与链上注册中心中公布的应用程序一致。而软件包中的配置文件也指向了当前版本的源代码，审核员就可以通过校验和（checksum）来验证该软件包是由这些源代码打包而成的。它将确保源代码和安装包之间的一致性，然后确保用户使用的是经审计师审计过的安全包。

当用户使用Web3应用程序时，客户端也会根据用户之前确认的应用程序的权限声明来限制这些应用程序的权限。然后完全保证用户在访问本地Web3服务时的安全。

### **Web3 App Registration Standard（Web3应用注册标准）**

    pragma solidity ^0.8.0;
    
    /**
     * @title AppRegistration interface
     */
    
    interface IAppRegistration {
    
        struct auditorVote {
            address auditor;
            uint8 level;
        }
    
        function createApp() external returns (uint256);
    
        function addVersion(uint256 appId, string memory versionId, string memory fileUrl) external;
    
        function getAppIds() external returns (uint256[] memory);
    
        function getVersions(uint256 appId) external returns (string[] memory);
    
        function getVersionFileUrl(uint256 appId, string memory versionId) external view returns (string memory);
    
        function voteApp(uint256 appId, uint8 level) external;
    
        function voteAppVersion(uint256 appId, string memory versionId, uint8 level) external;
    
        function getVotes(uint256 appId, string memory versionId) external returns (auditorVote[] memory);
    }
    

### **Web3 App Configration Standard（Web3应用配置标准）**

    {
      "properties": {
        "name": {
          "title": "Name of the App",
          "type": "string"
        },
        "logoUrl": {
          "title": "Logo of the App",
          "type": "string"
        },
        "description": {
          "title": "Description of the App",
          "type": "string"
        },
        "origin": {
          "title": "Online dapp origin",
          "type": "string",
          "pattern": "^((https|http)?:\/\/)[^\\s]+"
        },
        "permissions": {
          "properties": {
            "web3Provider": {
              "requestAccount": {
                "title": "If App need permission to connect with wallet",
                "type": "boolean"
              },
              "personalSign": {
                "properties": {
                  "request": {
                    "type": "boolean",
                    "title": "If App need permission to request sign text message"
                  },
                  "patterns": {
                    "type": "array",
                    "title": "Patterns of text message" 
                  }
                },
                "title": "Declaration for sign text message",
                "type": "object"
              },
              "transaction": {
                "properties": {
                  "request": {
                    "type": "boolean",
                    "title": "If App need permission to request transaction"
                  },
                  "contractCalls": {
                    "type": "array",
                    "title": "Declaration for contrat transaction"
                  },
                  "tokenApproves": {
                    "type": "array",
                    "title": "Declaration for token approval"
                  },
                  "ERC20TokenTransfer": {
                    "type": "array",
                    "title": "Declaration for ERC20 token transfer transaction"
                  }
                },
                "type": "object",
                "title": "Declaration for transaction"
              },
              "network": {
                "urlPatterns": {
                  "type": "array",
                  "title": "Patterns of whitelist network request URL"
                },
                "title": "Declaration for APP network request",
                "type": "object"
              },
              "title": "Declaration for Web3Provider permissions",
              "type": "object"
            }
          },
          "title": "Declaration for App permissions",
          "type": "object"
        },
        "app": {
          "properties": {
            "id": {
              "title": "AppId allocated by App Store",
              "type": "string"
            },
            "chainId": {
              "title": "The chainId which App Store deployed",
              "type": "string"
            },
            "contract": {
              "title": "The contract address of App Store",
              "type": "string" 
            }
          },
          "type": "object",
          "title": "App information on App Store"
        },
        "source": {
          "properties": {
            "repository": {
              "type": "string",
              "title": "The URL that can access App source code",
              "pattern": "^(https:\/\/|git@)[^\\s]+"
            },
            "buildScript": {
              "type": "string",
              "title": "The script that can complie source code to bundles"
            },
            "systemEnvironment": {
              "type": "string",
              "title": "The system environment that can make sure auditor can build bundle which has the same SHA256"
            }
          },
          "type": "object",
          "title": "Information of source code for auditor use"
        }
      },
      "title": "Web3 App json config file",
      "type": "object"
    }
    

**Web3 App Store Client Standard（Web3 应用商店客户端标准）**

    interface App {
      app: {
        id: string
        chainId: string
        contract: string
      }
      permissions: {
        network: {
          urlPatterns: string[]
        },
        web3Provider: {
          requestAccount: boolean
          personalSign: {
            request: boolean
            patterns: string[]
          },
          transaction: {
            request: boolean
            contractCalls: ContractCallItem[]
            tokenApproves: TokenApproveItem[]
            ERC20TokenTransfer: ERC20TokenTransferItem[]
          }
        }
      }
      source: {
        repository: string
        buildScript: string
        systemEnvironment: string
      }
      appId: number
      domain: string
      versionId: string
      files: string[]
      name: string
      description?: string
      logoUrl: string
    }
    
    enum VoteLevel {
      DANGER = -1
      UNKNOW = 0
      SAFE = 1
    }
    
    class Web3AppStore {
      chainId: string; // The chainId which App Store deployed
      
      contract: string; // The contract address of App Store
      
      getApps(): Promise<App[]>
      
      getApp(appId: number, version?: string): Promise<App>
      
      getAppVersions(appId: number): Promise<App[]>
     
      createApp(): Promise<number>
      
      addVersion(appId: number, fileUrls: string[]): Promise<void>
      
      voteApp(appId: number, level: VoteLevel): Promise<void>
      
      voteAppVersion(appId: number, versionId: string, level: VoteLevel): Promise<void>
      
      // Validate the SHA256 of App file is same as versionId of not
      validateAppVersion(app: App): Promise<Boolean>
      
      // Validate if the domain which declared in domain property has the same web3.json file of current App
      validateAppDomain(app: App): Promise<Boolean>
    }
    

[**Releases**](https://github.com/RabbyHub/Web3AppStoreProtocol/releases)

No releases published

[**Packages**](https://github.com/orgs/RabbyHub/packages?repo_name=Web3AppStoreProtocol)

No packages published

---

*Originally published on [W3.Hitchhiker](https://paragraph.com/@w3hitchhiker/web3-web3)*
