Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: change cached profile id to cidv0 to account for updated profiles #4

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Binary file added .cache/cache.db
Binary file not shown.
13 changes: 6 additions & 7 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ contracts:
- name: HubV2
handler: src/EventHandlers.ts
events:
- event: RegisterHuman(address indexed avatar)
- event: InviteHuman(address indexed inviter, address indexed invited)
- event: RegisterHuman(address indexed avatar, address indexed inviter)
- event: RegisterOrganization(address indexed organization, string name)
- event: RegisterGroup(address indexed group, address indexed mint, address indexed treasury, string name, string symbol)
- event: Trust(address indexed truster, address indexed trustee, uint256 expiryTime)
Expand Down Expand Up @@ -86,20 +85,20 @@ networks:
# - name: WrapperERC20Personal
- id: 100
# start_block: 12529458
start_block: 35732788
start_block: 36486014
contracts:
- name: HubV2
address:
- 0xa5c7ADAE2fd3844f12D52266Cb7926f8649869Da
- 0xc12C1E50ABB450d6205Ea2C3Fa861b3B834d13e8
- name: ERC20Lift
address:
- 0xB6B79BeEfd58cf33b298A456934554cf440354aD
- 0x5F99a795dD2743C36D63511f0D4bc667e6d3cDB5
- name: StandardTreasury
address:
- 0xbb76CF35ec106c5c7a447246257dcfCB7244cA04
- 0x08F90aB73A515308f03A718257ff9887ED330C6e
- name: NameRegistry
address:
- 0x738fFee24770d0DE1f912adf2B48b0194780E9AD
- 0xA27566fD89162cC3D40Cb59c87AAaA49B85F3474
- name: WrapperERC20Personal
- name: SafeAccount

Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
},
"dependencies": {
"envio": "2.4.3",
"viem": "2.21.0"
"viem": "2.21.0",
"multihashes": "^4.0.3",
"sqlite3": "^5.1.7"
},
"optionalDependencies": {
"generated": "./generated"
Expand Down
878 changes: 864 additions & 14 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

20 changes: 15 additions & 5 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ type TrustRelation {
transactionIndex: Int!
logIndex: Int!
version: Int!
trustee: String!
truster: String!
trustee: Avatar!
truster: Avatar!
# v2 only or always UInt256.MAX in case of v1
expiryTime: BigInt!
# v1 only or always '100' in case of v2
Expand All @@ -60,7 +60,7 @@ enum AvatarType {
Signup
OrganizationSignup
RegisterHuman
InviteHuman
Invite
RegisterGroup
RegisterOrganization
}
Expand Down Expand Up @@ -96,12 +96,22 @@ type Avatar {
# groups only
name: String
# IPFS CID of the avatar's profile
cidV0Digest: String
cidV0: String
# balances of all tokens
balances: [AvatarBalance!]! @derivedFrom(field: "avatar")
# balance of all tokens aggregated
balance: BigInt!
lastMint: BigInt!
trustedByN: Int!
profile: Profile
}

type Profile {
id: ID!
name: String!
description: String
previewImageUrl: String
imageUrl: String
}

enum TokenType {
Expand All @@ -123,4 +133,4 @@ type Token {
version: Int!
tokenType: TokenType!
tokenOwner: String!
}
}
112 changes: 78 additions & 34 deletions src/EventHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ import {
zeroAddress,
maxUint256,
parseEther,
Address,
} from "viem";
import { incrementStats } from "./incrementStats";
import { TransferType_t } from "generated/src/db/Enums.gen";
import { getProfileMetadataFromIpfs, uint8ArrayToCidV0 } from "./utils";

function makeAvatarBalanceEntityId(avatarId: string, tokenId: string) {
return `${avatarId}-${tokenId}`;
Expand Down Expand Up @@ -84,12 +86,14 @@ Hub.OrganizationSignup.handler(async ({ event, context }) => {
version: 1,
logIndex: event.logIndex,
tokenId: undefined,
cidV0Digest: undefined,
cidV0: undefined,
name: undefined,
transactionIndex: event.transaction.transactionIndex,
wrappedTokenId: undefined,
balance: 0n,
lastMint: 0n,
trustedByN: 0,
profile_id: event.params.organization,
};

context.Avatar.set(avatarEntity);
Expand All @@ -113,12 +117,14 @@ Hub.Signup.handler(async ({ event, context }) => {
version: 1,
logIndex: event.logIndex,
tokenId: event.params.token,
cidV0Digest: undefined,
cidV0: undefined,
name: undefined,
transactionIndex: event.transaction.transactionIndex,
wrappedTokenId: undefined,
balance: avatarBalance?.balance || 0n,
lastMint: 0n,
trustedByN: 0,
profile_id: event.params.user,
};

context.Avatar.set(avatarEntity);
Expand Down Expand Up @@ -160,12 +166,14 @@ HubV2.RegisterHuman.handler(async ({ event, context }) => {
version: 2,
logIndex: event.logIndex,
tokenId: bytesToBigInt(toBytes(event.params.avatar)).toString(),
cidV0Digest: undefined,
cidV0: undefined,
name: undefined,
transactionIndex: event.transaction.transactionIndex,
wrappedTokenId: undefined,
balance: 0n,
lastMint: 0n,
trustedByN: 0,
profile_id: event.params.avatar,
};

context.Avatar.set(avatarEntity);
Expand Down Expand Up @@ -197,29 +205,6 @@ SafeAccount.ExecutionSuccess.handlerWithLoader({
},
});

HubV2.InviteHuman.handler(async ({ event, context }) => {
const avatarEntity: Avatar = {
id: event.params.invited,
avatarType: "InviteHuman",
blockNumber: event.block.number,
timestamp: event.block.timestamp,
transactionHash: event.transaction.hash,
invitedBy: event.params.inviter,
version: 2,
logIndex: event.logIndex,
tokenId: bytesToBigInt(toBytes(event.params.invited)).toString(),
cidV0Digest: undefined,
name: undefined,
transactionIndex: event.transaction.transactionIndex,
wrappedTokenId: undefined,
balance: 0n,
lastMint: 0n,
};

context.Avatar.set(avatarEntity);
await incrementStats(context, "signups");
});

HubV2.RegisterOrganization.handler(async ({ event, context }) => {
const avatarEntity: Avatar = {
id: event.params.organization,
Expand All @@ -231,12 +216,14 @@ HubV2.RegisterOrganization.handler(async ({ event, context }) => {
version: 2,
logIndex: event.logIndex,
tokenId: bytesToBigInt(toBytes(event.params.organization)).toString(),
cidV0Digest: undefined,
cidV0: undefined,
name: event.params.name,
transactionIndex: event.transaction.transactionIndex,
wrappedTokenId: undefined,
balance: 0n,
lastMint: 0n,
trustedByN: 0,
profile_id: event.params.organization,
};

context.Avatar.set(avatarEntity);
Expand All @@ -254,12 +241,14 @@ HubV2.RegisterGroup.handler(async ({ event, context }) => {
version: 2,
logIndex: event.logIndex,
tokenId: bytesToBigInt(toBytes(event.params.group)).toString(),
cidV0Digest: undefined,
cidV0: undefined,
name: event.params.name,
transactionIndex: event.transaction.transactionIndex,
wrappedTokenId: undefined,
balance: 0n,
lastMint: 0n,
trustedByN: 0,
profile_id: event.params.group,
};

context.Avatar.set(avatarEntity);
Expand Down Expand Up @@ -350,9 +339,31 @@ StandardTreasury.GroupRedeemCollateralReturn.handler(
NameRegistry.UpdateMetadataDigest.handler(async ({ event, context }) => {
const avatar = await context.Avatar.get(event.params.avatar);
if (avatar) {
const cidV0Formatted = uint8ArrayToCidV0(
Uint8Array.from(
Buffer.from(
event.params.metadataDigest.slice(
2,
event.params.metadataDigest.length
),
"hex"
)
)
);

const profileMetadata = await getProfileMetadataFromIpfs(cidV0Formatted);

context.Profile.set({
id: avatar.id,
name: profileMetadata?.name || "name not found",
description: profileMetadata?.description || "",
previewImageUrl: profileMetadata?.previewImageUrl || "",
imageUrl: profileMetadata?.imageUrl || "",
});

context.Avatar.set({
...avatar,
cidV0Digest: event.params.metadataDigest,
cidV0: cidV0Formatted,
});
}
});
Expand Down Expand Up @@ -663,8 +674,8 @@ Hub.Trust.handler(async ({ event, context }) => {
transactionIndex: event.transaction.transactionIndex,
logIndex: event.logIndex,
version: 1,
trustee: event.params.canSendTo,
truster: event.params.user,
trustee_id: event.params.canSendTo,
truster_id: event.params.user,
expiryTime: maxUint256,
limit: event.params.limit,
isMutual,
Expand All @@ -682,7 +693,40 @@ HubV2.Trust.handler(async ({ event, context }) => {
);
const timeDifference =
event.params.expiryTime - BigInt(event.block.timestamp);
if (timeDifference < 3600n) {
const isUntrust = timeDifference < 3600n;

// invite
const avatarTrustee = await context.Avatar.get(event.params.trustee);
if (!avatarTrustee) {
context.Avatar.set({
id: event.params.trustee,
avatarType: "Invite",
blockNumber: event.block.number,
timestamp: event.block.timestamp,
transactionHash: event.transaction.hash,
invitedBy: event.params.truster,
version: 2,
logIndex: event.logIndex,
tokenId: undefined,
cidV0: undefined,
name: undefined,
transactionIndex: event.transaction.transactionIndex,
wrappedTokenId: undefined,
balance: 0n,
lastMint: 0n,
trustedByN: 1,
profile_id: event.params.trustee,
});
} else {
context.Avatar.set({
...avatarTrustee,
trustedByN: isUntrust
? avatarTrustee.trustedByN - 1
: avatarTrustee.trustedByN + 1,
});
}

if (isUntrust) {
// this is untrust
const trustRelation = await context.TrustRelation.get(trustId);
if (trustRelation) {
Expand Down Expand Up @@ -714,8 +758,8 @@ HubV2.Trust.handler(async ({ event, context }) => {
transactionIndex: event.transaction.transactionIndex,
logIndex: event.logIndex,
version: 2,
trustee: event.params.trustee,
truster: event.params.truster,
trustee_id: event.params.trustee,
truster_id: event.params.truster,
expiryTime: event.params.expiryTime,
limit: parseEther("100"),
isMutual,
Expand Down
68 changes: 68 additions & 0 deletions src/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import sqlite3 from "sqlite3";
import { Profile as Metadata } from "./types";

// SQLite database initialization
const db = new sqlite3.Database(".cache/cache.db");

export class ProfileCache {
static async init() {
const cache = new ProfileCache("cache");
await cache.createTableIfNotExists();
return cache;
}

private readonly key: string;

private constructor(key: string) {
this.key = key;
}

private async createTableIfNotExists() {
const query = `
CREATE TABLE IF NOT EXISTS ${this.key} (
id TEXT PRIMARY KEY,
data TEXT
)
`;
await new Promise<void>((resolve, reject) => {
db.run(query, (err) => {
if (err) {
console.error("Error creating table:", err);
reject(err);
} else {
resolve();
}
});
});
}

public read(id: string): Promise<Metadata | null> {
return new Promise((resolve, reject) => {
const query = `SELECT data FROM ${this.key} WHERE id = ?`;
db.get(query, [id], (err, row: any) => {
if (err) {
console.error("Error executing query:", err);
reject(err);
} else {
resolve(row ? JSON.parse(row.data) : null);
}
});
});
}

public async add(id: string, metadata: Metadata) {
const query = `INSERT INTO ${this.key} (id, data) VALUES (?, ?)`;
const data = JSON.stringify(metadata);

return new Promise<void>((resolve, reject) => {
db.run(query, [id, data], (err) => {
if (err) {
console.error("Error executing query:", err);
reject(err);
} else {
resolve();
}
});
});
}
}
6 changes: 6 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface Profile {
name: string;
description?: string;
previewImageUrl?: string;
imageUrl?: string;
}
Loading