Skip to content

Commit

Permalink
feat: As a user i want to get decoded attestation data via the subgra…
Browse files Browse the repository at this point in the history
…ph (#229)
  • Loading branch information
alainncls authored Sep 28, 2023
1 parent 5bac36d commit e475d26
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 4 deletions.
2 changes: 2 additions & 0 deletions subgraph/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ type Attestation @entity {
revoked: Boolean!
subject: Bytes!
attestationData: Bytes!
schemaString: String
decodedData:[String!]
}

type Module @entity {
Expand Down
94 changes: 90 additions & 4 deletions subgraph/src/attestation-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import {
AttestationRegistered as AttestationRegisteredEvent,
AttestationRegistry,
} from "../generated/AttestationRegistry/AttestationRegistry";
import { Attestation } from "../generated/schema";
import { BigInt } from "@graphprotocol/graph-ts";
import { Attestation, Schema } from "../generated/schema";
import { BigInt, ByteArray, Bytes, ethereum } from "@graphprotocol/graph-ts";

export function handleAttestationRegistered(event: AttestationRegisteredEvent): void {
const contract = AttestationRegistry.bind(event.address);
const attestationData = contract.getAttestation(event.params.attestationId);
const attestationRegistryContract = AttestationRegistry.bind(event.address);
const attestationData = attestationRegistryContract.getAttestation(event.params.attestationId);
const attestation = new Attestation(event.params.attestationId.toHex());

attestation.schemaId = attestationData.schemaId;
Expand All @@ -22,5 +22,91 @@ export function handleAttestationRegistered(event: AttestationRegisteredEvent):
attestation.subject = attestationData.subject;
attestation.attestationData = attestationData.attestationData;

// Get matching Schema
const schema = Schema.load(attestationData.schemaId.toHex());

if (schema) {
// Split Schema into a "type fieldName" array
const splitSchema = schema.schema.split(",");

// Keep only the Schema's types
const schemaTypes = splitSchema.map<string>((item) => item.trim().split(" ")[0]);

// Join the types in a single coma-separated string
const schemaString = schemaTypes.toString();

// Add this Schema string to the Attestation Entity
attestation.schemaString = schemaString;

const encodedData = attestationData.attestationData;

// Initiate the decoded data in case it's not decoded at all
attestation.decodedData = ["NOT DECODED"];

// Decode the encoded attestation data
let decoded = ethereum.decode("(" + schemaString + ")", Bytes.fromUint8Array(encodedData));

// If the decoding function didn't give anything, re-try with the encoded data as a tuple
if (!decoded) {
// Change attestation encoded data into an encoded Tuple
const tuplePrefix = ByteArray.fromHexString("0x0000000000000000000000000000000000000000000000000000000000000020");
const encodedDataAsTuple = new Uint8Array(tuplePrefix.length + encodedData.length);
encodedDataAsTuple.set(tuplePrefix, 0);
encodedDataAsTuple.set(encodedData, tuplePrefix.length);

// Decode the tuple
decoded = ethereum.decode("(" + schemaString + ")", Bytes.fromUint8Array(encodedDataAsTuple));
}

// If the decode function went through, save it as an Array of Strings
if (decoded) {
const tempStringArray: string[] = [];

// Make the decoded data into a Tuple
const tupleValue = decoded.toTuple();

// Convert every field of the Tuple into a String
for (let i = 0; i < tupleValue.length; i++) {
tempStringArray.push(valueToString(tupleValue[i]));
}

// Add this decoded Array to the Attestation Entity
attestation.decodedData = tempStringArray;
}
}

attestation.save();
}

function valueToString(value: ethereum.Value): string {
switch (value.kind) {
case ethereum.ValueKind.ADDRESS:
return value.toAddress().toHexString();
case ethereum.ValueKind.FIXED_BYTES:
return value.toBytes().toHex();
case ethereum.ValueKind.BYTES:
return value.toString();
case ethereum.ValueKind.INT:
return value.toBigInt().toHexString();
case ethereum.ValueKind.UINT:
return value.toBigInt().toHexString();
case ethereum.ValueKind.BOOL:
return value.toBoolean().toString();
case ethereum.ValueKind.STRING:
return value.toString();
case ethereum.ValueKind.FIXED_ARRAY:
return value
.toArray()
.map<string>((item) => valueToString(item))
.toString();
case ethereum.ValueKind.ARRAY:
return value
.toArray()
.map<string>((item) => valueToString(item))
.toString();
case ethereum.ValueKind.TUPLE:
return "TUPLE NOT SUPPORTED";
default:
return "UNKNOWN TYPE";
}
}

0 comments on commit e475d26

Please sign in to comment.