arrow-left

All pages
gitbookPowered by GitBook
1 of 23

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

GeoDID Collection Example

The Collection Specification of the GeoDID; includes the collection's fields for specification.

hashtag
The GeoDID Collection

As of right now, the Collection extends the default GeoDID Specification without any added fields. It is up to the user to add what they deem necessary,. However, the collection must function as a DID that will reference other DID documents or URL links. The metadata added to it must reflect that.

hashtag
Example of GeoDID Collection

GeoJSON

Under construction - stay tuned!

@AstralProtocolarrow-up-right
[
   '@context':'https://w3id.org/did/v1',
   id:'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre',
   publicKey: [
      {
         id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre#controller',
         type: 'Secp256k1VerificationKey2018',
         controller: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre',
         ethereumAddress: '0x4B11B9A1582E455c2C5368BEe0FF5d2F1dd4d28e'
      }
   ],
   did_metadata:{
      type:'collection',
      created:'2019-03-23T06:35:22Z',
      updated:'2019-03-23T06:37:45Z'
   },
   links:[
      {
         id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre',
         type: 'collection',
         rel: 'root'
      },
      {
         id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre',
         type: 'collection',
         rel: 'self'
      }
   ],
   service:[
      {
         id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre#collection-metadata'
         type: collection-metadata
         serviceEndpoint: <CID or URL>
      }
   ]
]

Cloud-optimized GeoTIFF

STAC

Under construction - stay tuned!

@AstralProtocolarrow-up-right
STAC Itemschevron-right
STAC Catalogschevron-right

GeoTIFF

Under construction - stay tuned!

@AstralProtocolarrow-up-right

IPLD-encoded GeoTIFF

STAC Items

STAC Catalogs

Types

Common Types used throughout the Project

hashtag
IDocumentInfo

interface IDocumentInfo {
    geodidid: string;
    documentVal: any;
    parentid?: string;
}

ILoadInfo

interface LoadInfo {
    documentInfo: IDocumentInfo;
    powergateInstance: Powergate 
}

IPinInfo

interface IPinInfo {
    geodidid: string;
    cid: string;
    pinDate: Date;
    token: string
} 

GeoDID Item Example

The Item Specification of the GeoDID; includes the item's fields for specification.

hashtag
The GeoDID Item

The Item extends the default GeoDID Specification. It can function as a standalone DID and does not rely on a GeoDID Collection to be referenced.

hashtag
Example of GeoDID Item

[
  {
    '@context': 'https://w3id.org/did/v1',
    id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre',
    publicKey: [
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre#controller',
        type: 'Secp256k1VerificationKey2018',
        controller: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre',
        ethereumAddress: '0x4B11B9A1582E455c2C5368BEe0FF5d2F1dd4d28e'
      }
    ],
    didmetadata: { type: 'item', created: '2021-03-12T15:56:10.937Z' },
    links: [
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre',
        type: 'item',
        rel: 'root'
      },
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre',
        type: 'item',
        rel: 'self'
      }
    ],
    service: [
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre#item-metadata-1'
        type: item-metadata
        serviceEndpoint: <CID or URL>
      },
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre#geojson-1'
        type: geojson
        serviceEndpoint: <CID or URL>
      },
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre#geojson-2'
        type: geojson
        serviceEndpoint: <CID or URL>
      },
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre#geotiff-1'
        type: geotiff
        serviceEndpoint: <CID or URL>
      },
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre#json-1'
        type: json
        serviceEndpoint: <CID or URL>
      },
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre#misc-1'
        type: misc
        serviceEndpoint: <CID or URL>
      }
    ]
  }
]

GeoDID Extensions

Spatial data assets identified by GeoDIDs will come in a particular format, likely with information about the spatial reference system, attribution and other metadata. GeoDID extensions will enable the GeoDID Core Spec to expand to support any type of spatial data asset - legacy, current, or future.

Under construction - stay tuned!

@AstralProtocolarrow-up-right

GeoDID Core Specification

The Core Specification of the GeoDID; includes default fields for specification.

Figure 1: GeoDID Document Hierarchy

hashtag
Types of GeoDIDs

There are two "types" of GeoDID Specifications under the Astral Protocol, that work together to enable structure between resources. At their core, they are both extensions of the DID and default GeoDID specification. However, they differ in their functionality and purpose, in order to enable a better user experience for all users.

The GeoDID Collection - A GeoDID Collection is a simple, flexible JSON file of service endpoints that provides a structure to organize and browse GeoDID Items. The collection is responsible for bundling a set of items or sub collections, by utilizing links to reference other child Collections or Items . The division of sub-collections is up to the implementor, but is generally done in order to make the end user's UX easier.

The GeoDID Item - A GeoDID Item is an extension of the Default GeoDID Structure. Unlike its counterpart, the GeoDID Item is responsible for identifying a particular resources and referencing relative assets, through the service endpoints. GeoDID Items can only act as the leaves of the tree and cannot link to other items or collections. It can only reference assets like raster imagery, videos, geojson and reference linked parent DID Documents.

hashtag
Default GeoDID Structure

hashtag
GeoDID Default Fields

Field
Type
Description

hashtag
Public Key Object Fields

The publicKey is used to specify how the is expected to be authenticated, for purposes such as performing CRUD operations on the DID Document. However, the PublicKey Object is OPTIONAL by default as stated by the .

Field
Description

Note: Do not worry about this field as it will automatically be populated with the user's Ethereum address.

hashtag
DID_Metadata Object Fields

Field
Type
Description

hashtag
Service Endpoint Object Fields

The Metadata Object array will contain an array of Metadata related to the assets or links within the GeoDID. (ex. List of Spatial Data Providers who provided the data, GeoJSON Feature)object list contains all the assets the GeoDID Item will need to reference.The Assets Object array will contain a list of references to assets relative to the GeoDID Item.

Field
Type
Description

hashtag
Link Object Field

This object list describes the one-to-many relationships with other GeoDIDs. These entities can be sub-collection or sub-item GeoDIDs. This object field will come in handy when a user needs to traverse or scrape a data collection.

circle-info

As of right now, , is persisting the relationships between the different DID Documents and their respective CIDs. We still need to figure out how to properly update the links within the GeoDID in a scalable way. For large trees of GeoDID Collection, updates to the relations might take too long, so as a work around we are maintaining all the relationships on The Graph. And the GeoDID will only contain a reference to itself, the root Document, and its' parent.

Field
Type
Description

Service Object

REQUIRED The service object contains several sub fields used to reference metadata, other GeoDIDs, and/or assets.

string

The Ethereum address of the controller.

string

REQUIRED UPON UPDATE The GeoDID package will automatically timestamp the GeoDID upon an update. If the GeoDID Document never updates then there will not be a

description

string

OPTIONAL A description describing the GeoDID Document. It can be anything but most likely the description will address the DID subject.

id

string

REQUIRED The identifier for the DID Document. It can be the root DID ID or it can be a DID URL with a specific path or fragment. The id must be of the following format: did:<method>:<specific identifier>. The path(.../path), query(...?query), and fragment(...#fragment) are optional but will be used later as identifiers for the children collections and items.

authentication

[Authentication Object]

OPTIONAL BY DEFAULT Authentication is a process (typically some type of protocol) by which an entity can prove it has a specific attribute or controls a specific secret using one or more verification methodsarrow-up-right. With DIDsarrow-up-right, a common example would be proving control of the private key associated with a public key published in a DID documentarrow-up-right.

did_metadata

did_metadata Object

REQUIRED The did_metadata object contains relative metadata pertaining to the particular GeoDID. For example, timestamps for the CRUD operations, the type of GeoDID, descriptions, etc.

id

string

The GeoDID ID + key fragment which will be used to reference the controllers public key.

type

string

The type of Verification method being used. (ex. Ed25519VerificationKey2018, Secp256k1VerificationKey2018)

controller

string

The GeoDID ID which will be used to reference the controllers.

type

string

REQUIRED The type can either be a Collection or Item. ****

subtype

string

REQUIRED The subtype can either be a GeoJSON or Raster.

created

string

REQUIRED UPON CREATION The GeoDID package will automatically timestamp the GeoDID upon creation.

id

string

REQUIRED The DID URL that dereferences to the entity's metadata. [#metadata]

type

string

REQUIRED The type of metadata (ex. collection-metadata, item-metadata), or the type of the asset. (ex. GeoTIFF, geoJSON, JSON, CSV)

serviceEndpoint

string

REQUIRED The actual link in the format of an URL or CID. Relative and absolute links are both allowed.

id

string

REQUIRED The DID URL that dereferences to the entity's GeoDID Document. This field is required if you want to create a hierarchy of GeoDID Documents (ex. GeoDID collection is parent to GeoDID Items or Collections).

type

string

REQUIRED See chapter "Endpoint types" for more information.

rel

string

REQUIRED Relationship between the current document and the linked document. See chapter "Relation types" for more information.

verification relationshiparrow-up-right
DID subjectarrow-up-right
W3C working groups' DID specificationarrow-up-right
The Grapharrow-up-right

service

ethereumAddress

updated

[
  {
    '@context': 'https://w3id.org/did/v1',
    id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre',
    publicKey: [
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre#controller',
        type: 'Secp256k1VerificationKey2018',
        controller: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre',
        ethereumAddress: '0x4B11B9A1582E455c2C5368BEe0FF5d2F1dd4d28e'
      }
    ],
    didmetadata: { type: 'collection', created: '2021-03-12T15:56:10.937Z' },
    links: [
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre',
        type: 'collection',
        rel: 'root'
      },
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre',
        type: 'collection',
        rel: 'self'
      }
    ],
    service: [
      {
        id: 'did:geo:QmdDEcQbiFEY5YWvKgk2exd6XLetgfVmswZvXRgNkpehre#' + `${<ServiceType>}` + `${index}`
        type: <ServiceType>
        serviceEndpoint: <CID or URL>
      }
    ]
  }
]

@astralprotocol/core

Documentation about the Astral Protocol Core Package.

hashtag
Description

The @astralprotocol/core package is a Typescript NPM package that is responsible for any CRUD operations performed on the DID Documents. This includes the creation of DID Documents, loading the DID Documents, as well as updating them. The package also has utilities that enable the creation of the collision resistant GeoDID IDs, a custom **** did-resolverarrow-up-right that enables DID Resolution, as well as pinning features for storing the Documents on IPFS or FFS. This package is meant to be used in conjunction with the @astralprotocol/contracts **** and @astralprotocol/subgraph **** packages. However, the package can also be used independently if the user does not want to rely on the Ethereum network.

circle-info

This package is not responsible for persistence of the documents (mappings, etc.), the created DID Documents are persisted through IPFS/FFS, and the metadata regarding the DID Documents are persisted through the subgraph and smart contracts.

hashtag
To add Astral Protocol Core to your application

hashtag
To develop or try the Astral Protocol Core locally

Set up a local Powergate Client

In order to store the GeoDIDs created by the core package, you will need to start up a local Powergate client or connect to an existing hosted client. Below will be a brief overview on how to setup a local Powergate client on your system. Further information is available at: .

In order to setup the Powergate Client locally on your system you must have , , and installed.

  • In your terminal, create a new directory and clone the Powergate repo into it:

git clone https://github.com/textileio/powergate.git

  • After you clone the repo, enter the following commands:

cd powergate/docker

make localnet

For moreinformation regarding Powergate's Localnet mode, please refer to their documentation:

Check an implementation of core package:

hashtag
Run the script

https://github.com/textileio/powergatearrow-up-right
Dockerarrow-up-right
Docker-Composearrow-up-right
Go 1.16arrow-up-right
https://github.com/textileio/powergate#localnet-modearrow-up-right
yarn add -D @astralprotocol/core
OR
npm install -D @astralprotocol/core

import AstralClient from '@astralprotocol/core';
OR
const AstralClient = require('@astralprotocol/core');
testScript.js
import AstralClient from '@astralprotocol/core';

async function run(){

    // Create a new Astral Client Instance with the user's ethAddress
    // and a subgraph endpoint (check the latest one @astralprotocol/subgraph)
    let astral = new AstralClient(
        '0xa3e1c2602f628112E591A18004bbD59BDC3cb512', 
        'https://api.thegraph.com/subgraphs/name/astralprotocol/spatialassetsv06'
    );
    
    try{
    
        // Creates a Genesis GeoDID 
        const genDocRes = await astral.createGenesisGeoDID('collection')
        console.log(genDocRes);

        // With the returned IDocumentInfo from the last function, we can pin it.
        // Since no token was specified the client will assign a new auth Token to the user.
        const results = await astral.pinDocument(genDocRes);
        console.log(results);

        const token = results.token;

        // With the Auth Token and the GeoDID ID we can load the document with the loadDocument function
        const loadResults = await astral.loadDocument(results.geodidid, token);
        console.log(loadResults);

        console.log('\n');
        console.log('\n');

        // Creates a Child GeoDID Item of the priviously created Genesis GeoDID
        const itemres = await astral.createChildGeoDID('item', results.geodidid, 'item1');
        console.log(itemres)

        console.log('\n');

        // With the returned IDocumentInfo from the last function, we can pin it.
        // This time we reuse the same token that was created earlier to pin the child document to the same instance.
        const itemresults = await astral.pinDocument(itemres, token);
        console.log(itemresults);

        console.log('\n');

        // With the Auth Token and the GeoDID ID we can load the document with the loadDocument function
        const loadItemResults = await astral.loadDocument(itemresults.geodidid, token);
        console.log(loadItemResults);

        console.log('\n');

        // Here we can display the string representation of the DID Document
        console.log(JSON.stringify(loadItemResults.documentInfo.documentVal));

    }catch(e){
        console.log(e);
    }
    
}
node testScript.js

API

API for the @astralprotocol/core package

hashtag
Constructor

Creates a new AstralClient Instance to utilize the following functions.

new AstralClient(_ethAddress, _endpoint?);

Name
Type
Attributes
Description

hashtag
Methods

hashtag
CreateGenesisGeoDID

Creates a GenesisGeoDID Document. This creates a new root node for the linked data structure.

async createGenesisGeoDID(_typeOfGeoDID: string): Promise<IDocumentInfo>{}

Type
Description

hashtag
CreateChildGeoDID

Creates a Child GeoDIDDocument. This creates a child node for an existing linked data structure.

async createChildGeoDID(_typeOfGeoDID: string, _parentID: string, _path: string): Promise<IDocumentInfo>{}

Name
Type
Attributes
Description

hashtag
PinDocument

Pins the Document to IPFS or FFS via Powergate.

async pinDocument(_documentInfo: IDocumentInfo, _token?: string): Promise<IPinInfo>{}

Name
Type
Attributes
Description

hashtag
LoadDocument

Loads the Document by the DocID and the Powergate Auth token associated with it.

async loadDocument(_docId: string, _token: string): Promise<ILoadInfo>{}

Name
Type
Attribute
Description

IDocumentInfo

Returns info regarding the Document Type, like the geodidid and the Document Itself.

string

REQUIRED

The path that will be appended to the Parent GeoDID ID

Type
Description

DocumentInfo

Returns information regarding the Document, like the GeoDID ID and the contents of the Document.

interface IDocumentInfo {
    geodidid: string;
    documentVal: any;
    parentid?: string;
}
Type
Description

IPinInfo

Returns information regarding the Pin, like the GeoDID ID, cid, Powergate Auth token, and the pinDate.

Type
Description

ILoadInfo

Returns information regarding the Load, like the DocumentInfo as well as the Powergate Instance that the Document was pinned on.

_ethAddress

string

REQUIRED

The Ethereum Address of the user.

_endpoint

string

OPTIONAL

The Graph Endpoint. Already has a default value that can be overloaded with another endpoint.

Name

Type

Attributes

Description

_typeOfGeoDID

GeoDidType

REQUIRED

The type of Genesis GeoDID you want to create. OfType GeoDidType.

_typeOfGeoDID

GeoDidType

REQUIRED

The type of Genesis GeoDID you want to create. OfType GeoDidType.

_parentID

string

REQUIRED

The Parent GeoDID ID of this new Child GeoDID

_documentInfo

IDocumentInfo

REQUIRED

The Info related to the Document that is required for pinning.

_token

string

OPTIONAL

The Auth Token of the Powergate Instance that you want to pin the document on. If you don't have one yet, the client will automatically create a new one for you and return it for you to save.

_docId

string

REQUIRED

The GeoDID id of the DID Document.

_token

string

REQUIRED

The Auth Token for the Powergate Instance that the Document in stored on.

_path

interface IDocumentInfo {
    geodidid: string;
    documentVal: any;
    parentid?: string;
}
interface IPinInfo {
    geodidid: string;
    cid: string;
    pinDate: Date;
    token: string
} 
interface LoadInfo {
    documentInfo: IDocumentInfo;
    powergateInstance: Powergate 
}

GeoDIDs

When sensor measurements are captured digitally, the information is formatted to be processed by some software. Spatial data comes in many different formats - GeoJSON, KML, shapefiles, GeoTIFFs, cryptospatial coordinates etc etc.

Astral endeavors to design an open and agnostic protocol that will gracefully develop and evolve with the state of spatial computing. We also expect full trustlessness, self sovereignty and independent verifiability of all protocols we design. This requires a versatile, Web3-native spatial data identification, encoding and storage scheme.

To achieve this, with support from the Filecoin Foundation and London Blockchain Labs, we have drafted a GeoDID Method Specificationarrow-up-right and prototype modules and smart contractsarrow-up-right to create, read, update and deactivate these geographic decentralized identifiers and the data assets they reference.

GeoDIDs will identify these files by wrapping the spatial data assets in DID documents, thereby providing a standard schema to grant the user verifiable control and enable trustless interoperability. Different spatial data formats will be supported through GeoDID Extensions - meaning GeoDIDs can support any current or future digital spatial data format. Required member variables will include relevant metadata to enable comprehensive indexing and use of the spatial data a GeoDID identifies.

We have designed the initial draft of the spec and would be curious for feedback from you or anyone interested when we release the spec to the community for review.

GeoDIDs are agnostic to the spatial data assets being identified. However, we are designing the alpha implementation of the GeoDID modules to rely on IPFS by default, so we can cryptographically verify the integrity of the data assets referenced.

The GeoDID Method Specification can be found , and writing on the extensions . A repository containing our prototype implementation of a GeoDID system is .

here
here
herearrow-up-right

Build with GeoDIDs

As part of our exploration process we build a system for storing geospatial data on IPFS for a Filecoin Development Grantarrow-up-right in Q1 2021. This work has informed our thinking abourn building tools for Web3-native satellite imagery, which we're carrying forward.

triangle-exclamation

This project was experimental, and code is not stable. If you'd like to build with Astral tools, reach out on Discord: https://discord.gg/4WPyYvRtzQarrow-up-right.

hashtag
Data

We're developing Geographic Decentralized Identifiers (GeoDIDs) to provide a Web3-native format for identifying spatial data assets.

hashtag
Oracles

To date our oracle systems are quite simple, and we're looking for developers who are interested in implementing those to pull spatial data from GeoDIDs into smart contracts.

hashtag
Spatial Contracts

We have been developing patterns and libraries to work with spatial data in smart contracts for a few years now, and are looking for additional support. Specifically, we are working on:

  • A Solidity library of geometric and topological functions, much like .

  • A verifiable spatial data registry for GeoDIDs:

    • A zone registry, where users can control polygons representing areas of space on, beneath or above the Earth's surface.

Front-end packages and dApp interfaces to connect with spatial contracts.

Turf.jsarrow-up-right

Getting Started

Follow these simple steps to register GeoDIDs quickly

hashtag
Setting up local Powergate Client

In order to store the GeoDIDs created by the core package, you will need to start up a local Powergate client or connect to an existing hosted client. Below will be a brief overview on how to setup a local Powergate client on your system. Further information is available at: https://github.com/textileio/powergatearrow-up-right.

circle-info

In order to setup the Powergate Client locally on your system you must have , , and installed.

In your terminal, create a new directory and clone the Powergate repo into it:

git clone https://github.com/textileio/powergate.git

After you clone the repo, enter the following commands:

cd powergate/docker

make localnet

More information regarding Powergate's Localnet mode, please refer to their documentation:

hashtag
Install the packages

hashtag
Configure truffle-config.js

hashtag
Create a script for interacting with the Astral Client and Contracts

hashtag
And execute with

circle-info

The steps executed in this page have been reproduced in a public github that you can consult: ****

@astralprotocol/subgraph

Documentation about the Astral Protocol Subgraph Package.

hashtag
Description

The @astralprotocol/subgraph serves as the indexing engine of the protocol, capturing the registration and modification events of GeoDIDs in the @astralprotocol/contracts. It acts like a decentralized querying database where it is substantially easier to make complex queries to the Spatial Assets registry. It is used to create the tree of GeoDID nodes that represents their relationships and groupings.

The current version of the subgraph (spatialassetsfinalv1) is indexing the Ethereum Roptsten network at the following GraphQL endpoints:

You can connect to these with your GraphQL client of choice or try them at .

hashtag
To add Astral Protocol Subgraph to your application

hashtag
To develop or try the Astral Protocol Subgraph locally

hashtag
Prerequisites

  • Clone the astralprotocol repository and go to packages/subgraph

  • Run sudo apt-get install libsecret-1-dev

hashtag
Deployment

  1. Ensure you have ganache running with the contracts deployed from packages/contracts

  2. Update the SpatialAssets contract address that you got from the previous step in the subgraph.yaml (if needed and ensure the correct file is named according to the network of deployment - for ganache it should read as mainnet: backup the current subgraph.yamlfile and rename it to subgraphRopsten.yaml).

hashtag
Testing

The following query can be provided to the graphql endpoint to view the GeoDIDs tree (after doing the deployment steps above):

Dockerarrow-up-right
Docker-Composearrow-up-right
Go 1.16arrow-up-right
https://github.com/textileio/powergate#localnet-modearrow-up-right
https://github.com/AstralProtocol/wrapperTestarrow-up-right
yarn add @astralprotocol/core @astralprotocol/contracts dotenv bs58 truffle @truffle/hdwallet-provider
const HDWalletProvider = require("@truffle/hdwallet-provider");
require('dotenv').config();

// Create a .env file with your MNEMONIC and a ROPSTEN API key from INFURA
// Must have the following format:
// MNEMONIC="words here "
// ROPSTEN_API_KEY=https://ropsten.infura.io/v3/key

let mnemonic = process.env.MNEMONIC
let ropstenURL = process.env.ROPSTEN_API_KEY


let provider = new HDWalletProvider({
  mnemonic: {
    phrase: mnemonic,
  },
  providerOrUrl: ropstenURL,
});

module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",
      port: 8545,
      network_id: "*",
    },
    ropsten: {
      provider: provider,
      network_id: "3",
    },
  },
  compilers: {
    solc: {
      version: "0.6.12",
    },
  },
};
scripts/deployGeoDIDs.js
const { AstralClient } = require('@astralprotocol/core');
const SpatialAssets = require("@astralprotocol/contracts/build/contracts/SpatialAssets.json")
const bs58 = require('bs58')

module.exports = async function (callback) {
  const stringToBytes = (string) => web3.utils.asciiToHex(string)

    // based on https://ethereum.stackexchange.com/questions/17094/how-to-store-ipfs-hash-using-bytes32
  // Return bytes32 hex string from base58 encoded ipfs hash,
  // stripping leading 2 bytes from 34 byte IPFS hash
  // Assume IPFS defaults: function:0x12=sha2, size:0x20=256 bits
  // E.g. "QmNSUYVKDSvPUnRLKmuxk9diJ6yS96r1TrAXzjTiBcCLAL" -->
  // "0x017dfd85d4f6cb4dcd715a88101f7b1f06cd1e009b2327a0809d01eb9c91f231"
  function getBytes32FromIpfsHash(ipfsListing) {
    return "0x"+bs58.decode(ipfsListing).slice(2).toString('hex')
  }

  try {

    const accounts = await web3.eth.getAccounts()
    const userAccount = accounts[0]

    // find contract in network 3 (Ropsten)
    const SpatialAssetsContract = new web3.eth.Contract(SpatialAssets.abi, SpatialAssets.networks['3'].address, {
      from: userAccount,
      data: SpatialAssets.deployedBytecode,
    });

    // update the endpoint to the latest
    const subgraphEndpoint = "https://api.thegraph.com/subgraphs/name/astralprotocol/spatialassetsfinalv1"

    const astral = await AstralClient.build(userAccount, subgraphEndpoint, "https://astralinstance.tk");
  
    const storage = stringToBytes('FILECOIN');

    // Creates a Genesis GeoDID 
    
    const genDocRes = await astral.createGenesisGeoDID('collection')
    console.log(genDocRes);
  
    // With the returned IDocumentInfo from the last function, we can pin it.
    // Since no token was specified the client will assign a new auth Token to the user.
    const results = await astral.pinDocument(genDocRes);
    console.log(results);
              
    // register the geodid id and cid obtained. Type 0 because it is a collection

    console.log(results.geodidid)
    console.log(results.cid)

    const bytes32GeoDID= getBytes32FromIpfsHash(results.geodidid.substring(8));
    const bytes32Cid = getBytes32FromIpfsHash(results.cid);
  
    try {
      await SpatialAssetsContract.methods.registerSpatialAsset(userAccount, bytes32GeoDID, stringToBytes(''),[], bytes32Cid, storage,0).send()    
      .on('receipt', function(receipt){
      // receipt example
      console.log(receipt);

      })
      .on('error', function(error) { // If the transaction was rejected by the network with a receipt, the second parameter will be the receipt.
        console.log(error);
      });
    } 
    catch (err) {
      // Will throw an error if tx reverts
      console.log(err)
    }

    
    // With the Auth Token and the GeoDID ID we can load the document with the loadDocument function
    const loadResults = await astral.loadDocument(results.geodidid);
    console.log(loadResults);

  }
  catch(error) {
    console.log(error)
  }

    callback()
};
"deployGeoDIDs": "truffle exec scripts/deployGeoDIDs.js --network ropsten",
yarn deployGeoDIDs

Run git clone https://github.com/graphprotocol/graph-node/ (check setup instructions for docker version on )

  • Have the development steps of @astralprotocol/contracts done previously (with Ganache)

  • In another terminal, inside the graph-node folder, run cd docker && docker-compose up. If using Docker for WSL, Docker must be running on Windows. If graph-node throws an error try clearing the data/postgres folder, within the docker directory of graph-node, with sudo rm -rf data/postgres. Restart docker if needed.

  • Generate subgraph typescript files with yarn codegen, then create and deploy the subgraph to the graph-node with yarn create-local && yarn deploy-local

  • You can query the subgraph and view the GeoDID tree in the local provided endpoint.

  • The Graph's playgroundarrow-up-right
    Docker Instalationarrow-up-right
    https://api.thegraph.com/subgraphs/name/astralprotocol/spatialassetsfinalv1
    wss://api.thegraph.com/subgraphs/name/astralprotocol/spatialassetsfinalv1
    yarn add @astralprotocol/subgraph
    {
      geoDIDs {
        id
        owner
        cid
        storage
        root
        parent
        edges {
          id
          childGeoDID {
            id
          }
        }
        active
        type
      }
    }
    https://thegraph.com/docs/arrow-up-right

    @astralprotocol/contracts

    Documentation about the Astral Protocol Contracts Package.

    arrow-up-right arrow-up-right

    hashtag
    Description

    These contracts serve as the Registry for the Astral Protocol GeoDIDs. It allows binding of a GeoDID to an ethereum address and CID name resolving.

    By registering a spatial asset Smart Contract events are triggered, which are picked up by the subgraph indexer to build the tree of relationships for easy querying.

    hashtag
    To add Astral Protocol Contracts to your application

    hashtag
    To develop or try the Astral Protocol Contracts locally

    • Clone the and go to packages/contracts:

    • Run ganache yarn ganache

    • In a new terminal, deploy contracts with yarn truffle

    • Run tests with yarn truffle-test

    hashtag
    To deploy your own contracts in the Ropsten testnet

    • Create a .env file in /packages/contracts with a MNEMONIC and ROPSTEN_API_KEY

  • You can deploy an instance by running yarn new-instance. It builds a GeoDID tree with hardcoded GeoDID ids and CIDs.

  • You can test the removal of some links by running yarn remove-links.

  • Watch the changes in a locally deployed subgraph.

  • Do coverage check up by killing the ganache process in the first terminal and running yarn coverage

  • astralprotocol repositoryarrow-up-right
    yarn add @astralprotocol/contracts
    git clone git@github.com:AstralProtocol/astralprotocol.git
    cd astralprotocol/packages/contracts
    .env
    MNEMONIC="mnemonic phrase goes here with testnet ether in address[0] on ropsten cool"
    ROPSTEN_API_KEY=https://ropsten.infura.io/v3/<PROJECT ID HERE>
    Build Status
    Coverage Status

    GeoDID Core

    We are early in developing the GeoDID spec. For now, we are focused on storing geojson vector spatial data structures, and geotiff raster data. The GeoDID specification is designed to be flexible and identify any spatial dataset in any format - even ones that haven't been developed yet.

    hashtag
    Abstract

    Geographic decentralized identifiers, or GeoDIDs, are DIDs designed to identify spatial data assets and to be compatible with any distributed ledger or network. Spatial data has unique properties that require special treatment - the GeoDID Method Specification defines an approach in creating, reading, updating and deleting identifiers for these assets using DIDs. In creating a GeoDID, data controllers permissionlessly create irrevocable, cryptographically-verifiable identities for spatial data assets that can be useful in decentralized applications

    The objective of the GeoDID is to encourage contribution to the DID specification and Linked Data Signatures to identify and ensure trustable spatial data. This will allow rapid development of extensions to these without requiring the usage of trustless infrastructures such as blockchains or other distributed systems.

    The GeoDID is inspired by the and utilizes a similar linked data structure. The structure alleviates a handful of problems associated with traversing large datasets, and allows for ease of use for the end user. Spatial data assets are identified in the service endpoints of the GeoDID document. These service endpoints can be classed as either Collections or Items. Each "Collection" contains a number of child Collections or Items; and each "Item" will contain several service endpoints that dereference to geospatial data assets. This hierarchy of encapsulating linked data within the GeoDIDs will allow for user's to find or create the data/datasets that they need easily.

    circle-info

    This data model is based on the STAC specification, which was designed for cataloging spatiotemporal data assets including satellite images, UAV imagery, LIDAR scans etc.

    For the alpha version of the specification we did not consider the OGC API - Features specification, which is better optimized for representing vector spatial data. Future versions of the GeoDID Method Specification should evolve so that vector and raster data assets are identified according to the most appropriate specification - work to be done.

    hashtag
    1. GeoDID Method

    The namestring that shall identify this DID method is: geo.

    A DID that uses this method MUST begin with the following prefix: did:geo. Per the DID specification, this string MUST be in lowercase. The remainder of the DID after the prefix, is specified below.

    hashtag
    2. Namespace Specific Identifier:

    did:geo:<geo-specific-identifier>

    All GeoDIDs are base58 encoded using the Bitcoin / IPFS alphabets of a 16-byte UUID.

    geo-did = "did:geo:" + geo-specific-identifier geo-specific-identifier = new CID(0, 'dag-pb', hash, 'base58btc') hash = multihash(byte, sha2-256) byte = new TextEncoder().encode(ethereum address + UNIX Time)

    hashtag
    Namestring Generation Method

    For the draft version of this specification, <geo-specific-identifier> referenced above is created by computing a sha2-256 multihash on the byte representation of the DID controller's ethereum address + Unix time: multihash(ethAddress + time, sha2-256). Then we create a new CID Block by encoding the multihash with a base58 encoding. This will return a cid that will act as the identifier for the GeoDID.

    circle-info

    This <geo-specific-identifier> generation procedure achieves our design goals of enabling one Ethereum address to control multiple GeoDIDs. However, in future versions of the specification we intend to investigate the potential of encoding more information into the identifier, including a hash or checksum of the spatial data assets identified, similar to the .

    We also could encode some segment of the identifier to indicate which blockchain the GeoDID is registered on, a possible approach to achieve our design goal of platform agnosticism.

    Fundamentally, the GeoDID identifier should not change even if GeoDID Document contents are subsequently updated by the GeoDID controller.

    hashtag
    Identifying the correct GeoDID

    The service array in the GeoDID will contain several references to other GeoDIDs and/or assets. The idea is that if the GeoDID is the root DID in the hierarchy, regardless of its type, then it has the base DID identifier. If the GeoDID is a sub-collection or sub-item then it is referenced via path, and if it is an asset within the sub-item's service array, then it is referenced via fragment.

    Standalone or Root GeoDIDs using the Base DID Identifier:

    did:geo:9H8WRbfd4K3kQ2NTxT6L2wTNyMj1ARCaVVsT5GJ87Jw2

    Paths reference other GeoDID sub-Collections or sub-Items:

    did:geo:9H8WRbfd4K3kQ2NTxT6L2wTNyMj1ARCaVVsT5GJ87Jw2/sub-collection-A/sub-item-1

    Fragments reference assets within the GeoDID sub-Items:

    did:geo:9H8WRbfd4K3kQ2NTxT6L2wTNyMj1ARCaVVsT5GJ87Jw2/sub-collection-A/sub-item-1#raster-image-1

    did:geo:9H8WRbfd4K3kQ2NTxT6L2wTNyMj1ARCaVVsT5GJ87Jw2/sub-collection-A/sub-item-1#thumbnail

    circle-info

    In future versions of the specification we hope to incorporate spatial, temporal and other query parameter capabilities in the GeoDID fragment, so we could retrieve matching features. By incorporating this querying, filtering and masking capability many advanced spatial decentralized applications would be enabled - though technical feasibility has not be assessed.

    hashtag
    3. CRUD Operation Definitions

    hashtag
    Create (Register)

    In order to create a GeoDID, a method specific identifier must be created, which will be used to build the document. After the method specific identifier is created, the user will need to select the type of Document they would like to create, Collection or Item.

    hashtag
    Required Assets

    • ECDSA keypair. (for the alpha version of the specification - future versions may be agnostic to which digital signature algorithm is used).

    • Spatial data asset(s), or URI(s) resolving to spatial data asset(s), along with relevant metadata / attribution.

    • If GeoDID Collection, some information about the relationships between the spatial data assets being identified.

    hashtag
    Proof of Concept Process

    1. Create Method Specific Identifier described in (2), above.

    2. User chooses which type of GeoDID they want to create (Collection or standalone Item).

    3. If the user decides to create a standalone Item then they just upload the assets, did-metadata information, and item-metadata they want in the DID. The GeoDID will be built, pinned on IPFS, and anchored on the Ropsten Testnet.

    In the near future, we will also create automation features to create trees, by uploading folders with files in it. We hope this will kill two birds with one stone, so the user will only need to prepare the data once, and upload it in bulk.

    hashtag
    Read (Resolve)

    In the alpha implementation of the specification a GeoDID document can be resolved by invoking the resolve(<GeoDID ID>) method at contract address <0x___TBD___> on Ethereum's Ropsten testnet. This contract method will first verify that the user has access to this GeoDID by checking to make sure that his address registered the GeoDID via the create method. The contract will store a mapping from the user's address to GeoDID IDs.

    Once the user has been authenticated, the contract will trigger an event that the astral-protocol-core package will be listening for. From there the geo-did-resolver will handle the rest, and dereference to the proper GeoDID Document.

    The GeoDID Document can then be parsed and analyzed by the client, or spatial data assets can be fetched from their respective service endpoints. Do note that sometimes data assets will be identified by CIDs and stored on the IPFS network, while other service endpoints may be HTTP URLs - appropriate resolution methods will be required.

    Controller Address

    Each identity always has a controller address. To check the read only contract function identityOwner(address identity) on the deployed version of the ERC1056 contract.

    The identity controller will always have a publicKey with the id set as the DID with the fragment #key appended.

    An entry is also added to the authentication array of the DID document with type Secp256k1SignatureAuthentication2018.

    hashtag
    Service Endpoints

    Service Endpoints are relevant in both GeoDID Controllers **<Collections?>**¸ and Items. It exists to list relevant relationships to and from itself. <?Each object in the> service array will contain a required link field and several that contain the GeoDID ID, its relationship to the DID ID, and a reference link if the controller needs to dereference it. The purpose of the link field is to enables browsers and crawlers to access the sets of Items, in an organized and straightforward way. These service endpoints can also contain references to assets that are related to a specific item.

    The GeoDID Document identified by the CID can the be resolved using a browser with native IPFS support (ipfs://<CID>), or by resolving via a gateway, like ipfs.io/ipfs/<GeoDID Document CID>

    hashtag
    Update

    The DID Document may be updated by invoking the update(<GeoDID ID>) method at contract address <0x_____> on the Ropsten testnet.

    Once the address has been verified as the DID controller, an oracle function will be invoked and will trigger an off chain event to open the GeoDID Document for the user to update. When user is done updating, they can submit the update, which will compute the CID of the GeoDID Document and compare the block to the previous CID version.

    If the CIDs differ, the client will append the timestamp of the update within the GeoDID Document, recalculate the finalized CID, and will append a new Record in the astral-core-package. The updated CID will be returned via the oracle, and appends to the end of the array of GeoDID Document CIDs, meaning users can fetchVersionHistory(<GeoDID fragment>) and retrieve all the CIDs of historical GeoDID documents.

    hashtag
    Deactivate (Revoke)

    A GeoDID Controller can revoke access to a GeoDID by invoking the deactivate(<GeoDID fragment>) method. This simply sets that GeoDID's GeoDIDActive record to false - it does not remove information from the smart contract about the historical versions of the GeoDID. It does, however, mean that future attempts to resolve that GeoDID will not succeed.

    hashtag
    Reference Implementations

    Once we develop it, we will store code at as a reference implementation of this DID method.\

    If the user decides to create a Collection then the client will build a collection GeoDID and return the GeoDID ID. The GeoDID will be built, pinned on IPFS, and anchored on the Ropsten Testnet.

  • The user will save this GeoDID ID to append children sub-collections or sub-items as children.

  • If the user decides to add children to the sub-collection, they repeat step 4, and use the returned GeoDID ID + Collection path to append more leaf nodes.

  • If the user decides to add items to the collection, they repeat step 3, until they finish adding all items.

  • SpatioTemporal Asset Catalog (STAC) specificationarrow-up-right
    Ocean Protocol DID Methodarrow-up-right
    https://github.com/AstralProtocolarrow-up-right

    API

    API for the @astralprotocol/contracts package

    hashtag
    State modifying methods

    constructor

    Initiates the smart contract with an hardcoded uri type representing the did method (did:geo). Also initiates the msg.sender as the default admin and as a data supplier role.

    registerRole

    Registers a new user with the ability to register a spatial asset. Contract creator is hardcoded as default admin and data supplier roles.

    enableStorage

    Registers a new storage that can accept GeoDID document creation.

    disableStorage

    Disables an existing storage.

    registerSpatialAsset

    Registers on-chain one Spatial Asset.

    addChildrenGeoDIDs

    Adds children GeoDIDs to an existing GeoDID. GeoDIDId must correspond to a GeoDID type that can be a parent (Collection or type 0).

    addParentGeoDID

    Adds a GeoDID as a parent to an already existing GeoDID.

    removeChildrenGeoDIDs

    Removes children GeoDIDs from a specified GeoDID.

    removeParentGeoDID

    Removes a specified parent GeoDID from a GeoDID.

    deactivateSpatialAsset

    De-registers a spatial asset.

    constructor(string memory uri) public

    bytes32

    OPTIONAL

    GeoDID Id of the parent. Must be set to 0 if no parent is to be added.

    childrenGeoDIDIDs

    bytes32[]

    OPTIONAL

    GeoDID IDs of the children. Must be set to [] if no children are to be added.

    cid

    bytes32

    REQUIRED

    CID of the GeoDID Document generated with its creation (check @astralprotocol/core)

    offChainStorage

    bytes32

    REQUIRED

    Bytes32 representation of the off-chain storage signature (must be pre-approved)

    geoDIDtype

    uint256

    REQUIRED

    0 for Collection type GeoDIDs, 1 for Item type GeoDIDs. emit SpatialAssetRegistered(owner, geoDIDId, cid, offChainStorage, geoDIDId, _canBeParent[geoDIDId]);

    Event
    Arguments
    Condition

    SpatialAssetRegistered

    address indexed to, bytes32 indexed geoDIDId, bytes32 indexed cid, bytes32 offChainStorage, bytes32 root, bool canBeParent

    Successful registration of a GeoDID

    ParentAdded

    bytes32 indexed geoDIDId, bytes32 indexed parentGeoDIDId

    If parentGeoDIDId is different than 0

    ChildrenAdded

    bytes32 indexed geoDIDId, bytes32 indexed childrenGeoDIDId

    If the childrenGeoDIDIds array is not empty and the GeoDIDs exist

    Event
    Arguments
    Condition

    ChildrenAdded

    bytes32 indexed geoDIDId, bytes32 indexed childrenGeoDIDId

    If the childrenGeoDIDIds array is not empty and the GeoDIDs exist

    Event
    Arguments
    Condition

    ParentAdded

    bytes32 indexed geoDIDId, bytes32 indexed parentGeoDIDId

    If parentGeoDIDId exists

    Event
    Arguments
    Condition

    ChildrenRemoved

    bytes32 indexed geoDIDId, bytes32 indexed childrenGeoDIDId

    If the childrenGeoDIDIds array is not empty and the GeoDIDs exist.

    Event
    Arguments
    Condition

    ParentRemoved

    bytes32 indexed geoDIDId, bytes32 indexed parentGeoDIDId

    If parentGeoDIDId exists

    Event
    Arguments
    Condition

    SpatialAssetDeactivated

    bytes32 indexed geoDIDId, bytes32[] **** childrenToRemove

    If geoDIDId exists

    Name

    Type

    Attributes

    Description

    offChainStorage

    bytes32

    REQUIRED

    Bytes32 representation of the off-chain storage signature to be enabled

    Name

    Type

    Attributes

    Description

    offChainStorage

    bytes32

    REQUIRED

    Bytes32 representation of the off-chain storage signature to be disabled

    Name

    Type

    Attributes

    Description

    owner

    address

    REQUIRED

    To be designated the owner of the GeoDID. Currently must be msg.sender.

    geoDIDId

    bytes32

    REQUIRED

    GeoDID Id generated with the GeoDID creation (check @astralprotocol/core)

    Name

    Type

    Attributes

    Description

    geoDIDId

    bytes32

    REQUIRED

    GeoDID Id generated with the GeoDID creation and registered in the smart contract

    childrenGeoDIDIDs

    bytes32[]

    OPTIONAL

    GeoDID IDs of the children. Must be set to [] if no children are to be added (nothing is executed in the function)

    Name

    Type

    Attributes

    Description

    geoDIDId

    bytes32

    REQUIRED

    GeoDID Id generated with the GeoDID creation (check @astralprotocol/core)

    parentGeoDIDId

    bytes32

    REQUIRED

    GeoDID Id of the parent. It must exist.

    Name

    Type

    Attributes

    Description

    geoDIDId

    bytes32

    REQUIRED

    GeoDID Id generated with the GeoDID creation (check @astralprotocol/core)

    childrenGeoDIDIds

    bytes32[]

    OPTIONAL

    GeoDID IDs of the children. Must be set to [] if no children are to be removed.

    Name

    Type

    Attributes

    Description

    geoDIDId

    bytes32

    REQUIRED

    GeoDID Id generated with the GeoDID creation (check @astralprotocol/core)

    parentGeoDIDId

    bytes32

    REQUIRED

    GeoDID Id of the parent to remove. It must exist.

    Name

    Type

    Attributes

    Description

    geoDIDId

    bytes32

    REQUIRED

    GeoDID Id generated with the GeoDID creation (check @astralprotocol/core)

    childrenGeoDIDIds

    bytes32[]

    OPTIONAL

    GeoDID IDs of the children. Must be set to [] if no children are to be removed.

    parentGeoDIDId

    function registerRole() public
    function enableStorage(bytes32 offChainStorage) public
    function disableStorage(bytes32 offChainStorage) public
    function registerSpatialAsset (
        address owner, 
        bytes32 geoDIDId, 
        bytes32 parentGeoDIDId , 
        bytes32[] memory childrenGeoDIDIds, 
        bytes32 cid, 
        bytes32 offChainStorage, 
        uint256 geoDIDtype
    ) public
    function addChildrenGeoDIDs(
        bytes32 geoDIDId, 
        bytes32[] memory childrenGeoDIDIds
    ) public
    function addParentGeoDID(
    	  bytes32 geoDIDId, 
        bytes32 parentGeoDIDId
    ) public
    function removeChildrenGeoDIDs(
        bytes32 geoDIDId, 
        bytes32[] memory childrenGeoDIDIds
    ) public
    function removeParentGeoDID(
        bytes32 geoDIDId, 
        bytes32 parentGeoDIDId
    ) public
    function deactivateSpatialAsset(
        bytes32 geoDIDId, 
        bytes32[] memory childrenToRemove
    ) public

    GeoDIDs v0.2

    Planned upgrades to the GeoDID Method Specification

    GeoDIDs identify spatial data assets. DIDs support selectors, paths, query parameters and fragments. These additional details that can be included in a GeoDID offer a powerful way to efficiently represent and store large spatial datasets in a much more resource-constrained manner that is still persistent, cryptographically verifiable and optionally private.

    The next phase of research and development will be for GeoDIDs that support spatial querying and clipping.

    For example, consider GeoDID representing a collection of satellite imagery. We should be able to specify a sub-collection, or even item, that defines a spatial and temporal query in the GeoDID itself. That way, a user could store a single GeoDID that specifies a single image, clipped to a particular area, extracted from the GeoDID Collection. The user would not need to store that clipped image, but only the GeoDID with query parameters - they would still have the confidence that the GeoDID would resolve to the same clipped image permanently.

    This would be crucial for the auditability of spatial finance applications. A satellite image might prove that a particular green infrastructure project was completed by a certain date, or that some insured natural capital warranted a payout. For both traditional and decentralized spatial finance, this verifiability will likely bring a lot of value to

    See by Dr Phil Windley for more details on selectors, paths, query parameters and fragments.

    Decentralized Identifiersarrow-up-right

    DID Primer

    A primer on DIDs before we go into the Core Specification of GeoDIDs

    hashtag
    What is a DID?

    Decentralized identifiersarrow-up-right (DIDs) are a new type of identifier that enables verifiable, decentralized digital identities. A DIDarrow-up-right identifies any subject (e.g., a person, organization, thing, data model, abstract entity, etc.) that the controller of the DIDarrow-up-right decides that it identifies. DIDsarrow-up-right are URIs that associate a DID subjectarrow-up-right with a DID documentarrow-up-right allowing trustable interactions associated with that subject.

    Each DID documentarrow-up-right can express cryptographic material, verification methods, or , which provide a set of mechanisms enabling a to prove control of the .

    To learn more about DIDs and why they're useful:

    service endpointsarrow-up-right
    DID controllerarrow-up-right
    DIDarrow-up-right
    W3C DID Corearrow-up-right
    Ceramic Networkarrow-up-right
    Decentralized identifiers fundamentals and deep divearrow-up-right
    Figure 1: The basic architecture of the DID