Issuer Quickstart

Claims rely on the claim_id field as the primary binding agent for use of their relevant methods.
They should not be mistaken for attributes even though they bare a lot of similarities.

Introduction

Fundamentally, a claim can be thought of as a package of fields which are stored on the blockchain.
We call these fields attestations. For the Moonlight and Vivid usecase, each attestation reflects an individual verified attribute on the platform making the relationship between attributes and claims many x many. The relationship between attributes and attestations is one x many because you may have multiple claims which are made against a single attribute. A good example of the one x many relationship is someone undergoing two different verification workflows where each one verifies the individual’s name. In this scenario, each workflow would submit a unique claim. Each claim would have an attestation for the verified name, which happens to be the same value.

Claims and Their Fields


{ 
  "attestations": [
    {
      "encryption":  //(enum) a number defining the encryption type of the value,
      "remark":     //(hexstring) an optional discription field for context,
      "value":      //(hexstring) a string formatted representation of the value,
    }
  ],
  "signed_by":        //(pubkey) the public key of the claim author,
  "signature":        //(hexstring) signature of the attestations by the claim issuer,
  "claim_id":         //(hexstring) a uniqueidentifier for the claim,
  "sub":              //(pubkey) the subject of the claim,
  "claim_topic":      //(hexstring) the claim topic,
  "expires":          //(unixtimestamp) a timestamp indicating the claim expiration date,
  "verification_uri": //(hexstring) an optional string for off-chain claim resources,
 }


Install Asteroid SDK

npm install @moonlight-io/asteroid-sdk-js
go get github.com/Moonlight-io/asteroid-sdk-go

Retrieving a Claim

Because of the storage approach of Vivid, there are multiple ways to retrieve a raw claim


    const neoCNS = "b434339f25b6f1bec68e99f620dfbf3ec27dacdc"
    const network = {
        name: "network",
        extra: {
            neoscan: "https://p1.neo.blockchain.moonlight.io:4001/api/main_net",
            rpcServer: "https://p1.neo.blockchain.moonlight.io:60333"
        }
    }
    
    //get the claims contract target
    const neoClaimsContract = await sdk.NeoContractNameService.getAddress(network, neoCNS, "moonlight", "claims")
    
    //get the claim by its ID
    let claim = await sdk.NeoContractClaims.getClaimByClaimID(network, neoClaimsContract, "NLBnCtGcA6Gx4NJ8")
    console.log("first res: ", claim)
    
    //get the claim by its pointer
    claim = await sdk.NeoContractClaims.getClaimByPointer(network, neoClaimsContract, 2)
    console.log("second res: ", claim)
    
    
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        
        
    first res:  {
    	"claim_id": "NLBnCtGcA6Gx4NJ8",
    	"attestations": [
    		{
    			"remark": "",
    			"value": "6f2eaf3c9deefbb3fa61bf71427f6d0cce1e7e699409fb55e25634d1bac3c946",
    			"encryption": "symmetric_aes256"
    		}
    	],
    	"signed_by": "02498c5c154df8a2b26047a9205d1329aa0d626a1ef9185a7e3ae4993290905afd",
    	"signature": "f2adae922a028e346825890afba09c1e88ee2f5ae5be3187d3d908ee907d94f79d9c2821ac6a06bddef1c3ef7c281f29ee9c3688d662c093fc17203a69dabfb7",
    	"sub": "02e8a8ecfaebe8b3fe19debfbb35939a9ba8e440e718977d3bc390d8d7aa4c6210",
    	"claim_topic": "email",
    	"expires": "undefined",
    	"verification_uri": "https://app.moonlight.io"
    }
    
    second res:  {
    	"claim_id": "NLBnCtGcA6Gx4NJ8",
    	"attestations": [
    		{
    			"remark": "",
    			"value": "6f2eaf3c9deefbb3fa61bf71427f6d0cce1e7e699409fb55e25634d1bac3c946",
    			"encryption": "symmetric_aes256"
    		}
    	],
    	"signed_by": "02498c5c154df8a2b26047a9205d1329aa0d626a1ef9185a7e3ae4993290905afd",
    	"signature": "f2adae922a028e346825890afba09c1e88ee2f5ae5be3187d3d908ee907d94f79d9c2821ac6a06bddef1c3ef7c281f29ee9c3688d662c093fc17203a69dabfb7",
    	"sub": "02e8a8ecfaebe8b3fe19debfbb35939a9ba8e440e718977d3bc390d8d7aa4c6210",
    	"claim_topic": "email",
    	"expires": "undefined",
    	"verification_uri": "https://app.moonlight.io"
    }
    
//To Be Defined

Querying for the claim topic will return contextual information about the attestation payloads. Note that in the case of the claim in the example, the encryption is “1” (encoded to a string value by the sdk).
In order to use the attestation payload, we need a key which can be recovered from the identity’s keychain. To recover a key, refer to the keychain documentation. A helper method is also available which can retrieve the claim and attempt to access the attestation payloads using the requestors key. It is used as follows:


   const neoCNS = "b434339f25b6f1bec68e99f620dfbf3ec27dacdc"
   const wif = "KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr"
   const network = {
       name: "network",
       extra: {
           neoscan: "https://p1.neo.blockchain.moonlight.io:4001/api/main_net",
           rpcServer: "https://p1.neo.blockchain.moonlight.io:60333"
       }
   }
   
   claim = await sdk.NeoVivid.getDecryptedClaimByClaimID(
       network,
       neoCNS,
       "NLBnCtGcA6Gx4NJ8",
       wif
   )
   console.log(claim)
   
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
       
    {
   	"claim_id": "NLBnCtGcA6Gx4NJ8",
   	"attestations": [
   		{
   			"remark": "",
   			"value": "6f2eaf3c9deefbb3fa61bf71427f6d0cce1e7e699409fb55e25634d1bac3c946",
   			"encryption": "symmetric_aes256",
   			"identifier": "email",
   			"decrypted_value": "[email protected]"
   		}
   	],
   	"signed_by": "02498c5c154df8a2b26047a9205d1329aa0d626a1ef9185a7e3ae4993290905afd",
   	"signature": "f2adae922a028e346825890afba09c1e88ee2f5ae5be3187d3d908ee907d94f79d9c2821ac6a06bddef1c3ef7c281f29ee9c3688d662c093fc17203a69dabfb7",
   	"sub": "02e8a8ecfaebe8b3fe19debfbb35939a9ba8e440e718977d3bc390d8d7aa4c6210",
   	"claim_topic": "email",
   	"expires": "undefined",
   	"verification_uri": "https://app.moonlight.io"
   }   
    
//To Be Defined

Issuing Claims

In order to issue a claim, the claim topic must already be issued to the claims contract. To create a claim topic, refer to the claim topic documentation. In the example below, we issue an email claim against an identity and also issue keys so the subject can access and share access to the attestations. In a typical workflow, we would also issue a key to the issuer so they can access the content they’ve generated.


const neoCNS = "b434339f25b6f1bec68e99f620dfbf3ec27dacdc"
const wif = "KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr"
const issuer = new neon.wallet.Account(wif);

const network = {
    name: "network",
    extra: {
        neoscan: "https://p1.neo.blockchain.moonlight.io:4001/api/main_net",
        rpcServer: "https://p1.neo.blockchain.moonlight.io:60333"
    }
}

const rawClaim = {
    sub: '029151b428cd17079bd1be8a1133874ecf4d323357b0372e5a467905a3fbb34e88',
    claim_id: 'e2ji2Jut76VKem19',
    claim_topic: 'email',
    verification_uri: 'http://localhost:8000',
    expires: 0,
    attestations:
        [ { identifier: 'EMAIL',
            remark: '',
            value: '[email protected]',
            encryption: 'symmetric_aes256' } ]
}

//get the claims and identity contract targets
const neoClaimsContract = await sdk.NeoContractNameService.getAddress(network, neoCNS, "moonlight", "claims")
const neoIdentityContract = await sdk.NeoContractNameService.getAddress(network, neoCNS, "moonlight", "identity")

//build the secure claim
const secureClaim = sdk.NeoContractClaims.buildClaim(rawclaim, issuer.WIF)

//issue the claim
await sdk.NeoContractClaims.createClaim(network, newClaimsContract, secureClaim, issuer.WIF)

//issue keys to the claim subject for each attestation in the claim
for ( let i = 0; i < secureClaim.keys.length; i++ ) {
      key = secureClaim.keys[i]
      keySub = rawClaim.claim_id + ":" + i
    
      await sdk.NeoContractIdentity.issueKey(
        network,
        neoIdentityContract,
        rawClaim.sub,
        issuer.publicKey,
        keySub,
        "proof",
        Buffer.from(JSON.stringify(key)),
        "holder_ecies",
        issuer.WIF
      )
    
//To Be Defined