@show-karma/karma-gap-sdk 0.4.16 → 0.4.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/core/abi/AirdropNFT.json +1 -1
  2. package/core/abi/Allo.json +860 -860
  3. package/core/abi/AlloRegistry.json +578 -578
  4. package/core/abi/CommunityResolverABI.json +506 -506
  5. package/core/abi/Donations.json +251 -251
  6. package/core/abi/EAS.json +1 -1
  7. package/core/abi/MultiAttester.json +746 -746
  8. package/core/abi/ProjectResolver.json +574 -574
  9. package/core/abi/SchemaRegistry.json +1 -1
  10. package/core/abi/index.d.ts +1114 -0
  11. package/core/abi/index.js +26 -0
  12. package/core/class/AllGapSchemas.d.ts +9 -0
  13. package/core/class/AllGapSchemas.js +19 -0
  14. package/core/class/Attestation.d.ts +173 -0
  15. package/core/class/Attestation.js +333 -0
  16. package/core/class/Fetcher.d.ts +175 -0
  17. package/core/class/Fetcher.js +13 -0
  18. package/core/class/GAP.d.ts +254 -0
  19. package/core/class/GAP.js +289 -0
  20. package/core/class/GapSchema.d.ts +34 -0
  21. package/core/class/GapSchema.js +62 -0
  22. package/core/class/Gelato/{Gelato.ts → Gelato.js} +0 -23
  23. package/core/class/GrantProgramRegistry/Allo.d.ts +17 -0
  24. package/core/class/GrantProgramRegistry/Allo.js +137 -0
  25. package/core/class/GrantProgramRegistry/AlloRegistry.d.ts +15 -0
  26. package/core/class/GrantProgramRegistry/AlloRegistry.js +70 -0
  27. package/core/class/GraphQL/AxiosGQL.d.ts +6 -0
  28. package/core/class/GraphQL/AxiosGQL.js +25 -0
  29. package/core/class/GraphQL/EASClient.d.ts +16 -0
  30. package/core/class/GraphQL/EASClient.js +26 -0
  31. package/core/class/GraphQL/GapEasClient.d.ts +71 -0
  32. package/core/class/GraphQL/GapEasClient.js +451 -0
  33. package/core/class/GraphQL/index.js +19 -0
  34. package/core/class/Schema.d.ts +233 -0
  35. package/core/class/Schema.js +488 -0
  36. package/core/class/SchemaError.d.ts +30 -0
  37. package/core/class/SchemaError.js +39 -0
  38. package/core/class/contract/GapContract.d.ts +102 -0
  39. package/core/class/contract/GapContract.js +285 -0
  40. package/core/class/entities/Community.d.ts +34 -0
  41. package/core/class/entities/Community.js +109 -0
  42. package/core/class/entities/ContributorProfile.d.ts +41 -0
  43. package/core/class/entities/ContributorProfile.js +69 -0
  44. package/core/class/entities/Grant.d.ts +54 -0
  45. package/core/class/entities/Grant.js +223 -0
  46. package/core/class/entities/GrantUpdate.d.ts +62 -0
  47. package/core/class/entities/GrantUpdate.js +114 -0
  48. package/core/class/entities/MemberOf.d.ts +11 -0
  49. package/core/class/entities/MemberOf.js +33 -0
  50. package/core/class/entities/Milestone.d.ts +168 -0
  51. package/core/class/entities/Milestone.js +657 -0
  52. package/core/class/entities/Project.d.ts +92 -0
  53. package/core/class/entities/Project.js +418 -0
  54. package/core/class/entities/ProjectImpact.d.ts +50 -0
  55. package/core/class/entities/ProjectImpact.js +112 -0
  56. package/core/class/entities/ProjectMilestone.d.ts +60 -0
  57. package/core/class/entities/ProjectMilestone.js +174 -0
  58. package/core/class/entities/ProjectPointer.d.ts +12 -0
  59. package/core/class/entities/ProjectPointer.js +22 -0
  60. package/core/class/entities/ProjectUpdate.d.ts +50 -0
  61. package/core/class/entities/ProjectUpdate.js +110 -0
  62. package/core/class/entities/Track.d.ts +16 -0
  63. package/core/class/entities/Track.js +21 -0
  64. package/core/class/entities/index.js +26 -0
  65. package/core/class/index.js +26 -0
  66. package/core/class/karma-indexer/GapIndexerClient.d.ts +66 -0
  67. package/core/class/karma-indexer/GapIndexerClient.js +207 -0
  68. package/core/class/karma-indexer/api/GapIndexerApi.d.ts +73 -0
  69. package/core/class/karma-indexer/api/GapIndexerApi.js +256 -0
  70. package/core/class/karma-indexer/api/types.d.ts +309 -0
  71. package/core/class/karma-indexer/api/types.js +2 -0
  72. package/core/class/remote-storage/IpfsStorage.d.ts +23 -0
  73. package/core/class/remote-storage/IpfsStorage.js +56 -0
  74. package/core/class/remote-storage/RemoteStorage.d.ts +41 -0
  75. package/core/class/remote-storage/RemoteStorage.js +38 -0
  76. package/core/class/types/allo.d.ts +78 -0
  77. package/core/class/types/allo.js +2 -0
  78. package/core/class/types/attestations.d.ts +173 -0
  79. package/core/class/types/attestations.js +66 -0
  80. package/core/consts.d.ts +48 -0
  81. package/core/consts.js +641 -0
  82. package/core/index.js +24 -0
  83. package/core/shared/types.d.ts +13 -0
  84. package/core/shared/types.js +2 -0
  85. package/core/types.d.ts +131 -0
  86. package/core/types.js +13 -0
  87. package/core/utils/gelato/index.js +19 -0
  88. package/core/utils/gelato/send-gelato-txn.d.ts +55 -0
  89. package/core/utils/gelato/send-gelato-txn.js +100 -0
  90. package/core/utils/gelato/sponsor-handler.d.ts +9 -0
  91. package/core/utils/gelato/sponsor-handler.js +59 -0
  92. package/core/utils/gelato/watch-gelato-txn.d.ts +7 -0
  93. package/core/utils/gelato/watch-gelato-txn.js +62 -0
  94. package/core/utils/get-date.d.ts +1 -0
  95. package/core/utils/get-date.js +6 -0
  96. package/core/utils/get-ipfs-data.d.ts +1 -0
  97. package/core/utils/get-ipfs-data.js +19 -0
  98. package/core/utils/get-web3-provider.d.ts +2 -0
  99. package/core/utils/get-web3-provider.js +18 -0
  100. package/core/utils/gql-queries.d.ts +12 -0
  101. package/core/utils/gql-queries.js +90 -0
  102. package/core/utils/index.js +23 -0
  103. package/core/utils/map-filter.d.ts +8 -0
  104. package/core/utils/map-filter.js +19 -0
  105. package/core/utils/serialize-bigint.d.ts +1 -0
  106. package/core/utils/serialize-bigint.js +7 -0
  107. package/core/utils/to-unix.d.ts +1 -0
  108. package/core/utils/to-unix.js +24 -0
  109. package/index.js +17 -0
  110. package/package.json +45 -45
  111. package/.cursorrules +0 -43
  112. package/core/abi/index.ts +0 -21
  113. package/core/class/AllGapSchemas.ts +0 -21
  114. package/core/class/Attestation.ts +0 -429
  115. package/core/class/Fetcher.ts +0 -224
  116. package/core/class/GAP.ts +0 -481
  117. package/core/class/GapSchema.ts +0 -93
  118. package/core/class/GrantProgramRegistry/Allo.ts +0 -188
  119. package/core/class/GrantProgramRegistry/AlloRegistry.ts +0 -101
  120. package/core/class/GraphQL/AxiosGQL.ts +0 -29
  121. package/core/class/GraphQL/EASClient.ts +0 -34
  122. package/core/class/GraphQL/GapEasClient.ts +0 -869
  123. package/core/class/Schema.ts +0 -659
  124. package/core/class/SchemaError.ts +0 -42
  125. package/core/class/contract/GapContract.ts +0 -457
  126. package/core/class/entities/Community.ts +0 -148
  127. package/core/class/entities/ContributorProfile.ts +0 -108
  128. package/core/class/entities/Grant.ts +0 -321
  129. package/core/class/entities/GrantUpdate.ts +0 -187
  130. package/core/class/entities/MemberOf.ts +0 -52
  131. package/core/class/entities/Milestone.ts +0 -898
  132. package/core/class/entities/Project.ts +0 -672
  133. package/core/class/entities/ProjectImpact.ts +0 -170
  134. package/core/class/entities/ProjectMilestone.ts +0 -254
  135. package/core/class/entities/ProjectPointer.ts +0 -39
  136. package/core/class/entities/ProjectUpdate.ts +0 -176
  137. package/core/class/entities/Track.ts +0 -32
  138. package/core/class/karma-indexer/GapIndexerClient.ts +0 -383
  139. package/core/class/karma-indexer/api/GapIndexerApi.ts +0 -446
  140. package/core/class/karma-indexer/api/types.ts +0 -313
  141. package/core/class/remote-storage/IpfsStorage.ts +0 -76
  142. package/core/class/remote-storage/RemoteStorage.ts +0 -65
  143. package/core/class/types/allo.ts +0 -93
  144. package/core/class/types/attestations.ts +0 -223
  145. package/core/consts.ts +0 -775
  146. package/core/scripts/create-grant.ts +0 -102
  147. package/core/scripts/create-program.ts +0 -43
  148. package/core/scripts/create-schemas.ts +0 -65
  149. package/core/scripts/deploy.ts +0 -65
  150. package/core/scripts/index.ts +0 -1
  151. package/core/scripts/milestone-multi-grants.ts +0 -125
  152. package/core/shared/types.ts +0 -13
  153. package/core/types.ts +0 -224
  154. package/core/utils/gelato/send-gelato-txn.ts +0 -114
  155. package/core/utils/gelato/sponsor-handler.ts +0 -77
  156. package/core/utils/gelato/watch-gelato-txn.ts +0 -67
  157. package/core/utils/get-date.ts +0 -3
  158. package/core/utils/get-ipfs-data.ts +0 -13
  159. package/core/utils/get-web3-provider.ts +0 -18
  160. package/core/utils/gql-queries.ts +0 -133
  161. package/core/utils/map-filter.ts +0 -21
  162. package/core/utils/serialize-bigint.ts +0 -7
  163. package/core/utils/to-unix.ts +0 -18
  164. package/create-community-example.ts +0 -119
  165. package/csv-upload/README.md +0 -74
  166. package/csv-upload/config.ts +0 -41
  167. package/csv-upload/example.csv +0 -2
  168. package/csv-upload/keys.example.json +0 -8
  169. package/csv-upload/scripts/run.ts +0 -417
  170. package/csv-upload/types.ts +0 -39
  171. package/docs/.gitkeep +0 -0
  172. package/docs/images/attestation-architecture.png +0 -0
  173. package/docs/images/dfd-get-projects.png +0 -0
  174. package/gap-schema.yaml +0 -155
  175. package/milestone-workflow-example.ts +0 -353
  176. package/readme.md +0 -872
  177. package/schemas/.gitkeep +0 -0
  178. package/schemas/GAP-schemas-1692135812877.json +0 -33
  179. package/test-file-indexer-api.ts +0 -25
  180. package/tsconfig.json +0 -26
  181. /package/{csv-upload/.gitkeep → core/class/Gelato/Gelato.d.ts} +0 -0
  182. /package/core/class/GraphQL/{index.ts → index.d.ts} +0 -0
  183. /package/core/class/entities/{index.ts → index.d.ts} +0 -0
  184. /package/core/class/{index.ts → index.d.ts} +0 -0
  185. /package/core/{index.ts → index.d.ts} +0 -0
  186. /package/core/utils/gelato/{index.ts → index.d.ts} +0 -0
  187. /package/core/utils/{index.ts → index.d.ts} +0 -0
  188. /package/{index.ts → index.d.ts} +0 -0
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mapFilter = mapFilter;
4
+ /**
5
+ * Filters an array by its condition then maps it to the desired format.
6
+ * @param arr
7
+ * @param condition
8
+ * @param mapTo
9
+ * @returns
10
+ */
11
+ function mapFilter(arr, condition, mapTo) {
12
+ const newArray = [];
13
+ for (const item of arr) {
14
+ if (condition(item)) {
15
+ newArray.push(mapTo(item));
16
+ }
17
+ }
18
+ return newArray;
19
+ }
@@ -0,0 +1 @@
1
+ export declare function serializeWithBigint(value: unknown): string;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.serializeWithBigint = serializeWithBigint;
4
+ function serializeWithBigint(value) {
5
+ return JSON.stringify(value, (this,
6
+ (key, value) => (typeof value === "bigint" ? value.toString() : value)));
7
+ }
@@ -0,0 +1 @@
1
+ export declare function toUnix(value: number | Date | string): number;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toUnix = toUnix;
4
+ function toUnix(value) {
5
+ switch (typeof value) {
6
+ case "number":
7
+ value = Math.round(value);
8
+ if (value.toString().length > 13)
9
+ throw new Error("Invalid timestamp length");
10
+ if (value.toString().length === 10)
11
+ return value;
12
+ return Math.floor(value / 1000);
13
+ case "string":
14
+ if (/\D/.test(value))
15
+ return null;
16
+ return toUnix(+value);
17
+ case "object":
18
+ if (value instanceof Date)
19
+ return toUnix(value.getTime());
20
+ return null;
21
+ default:
22
+ return null;
23
+ }
24
+ }
package/index.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./core"), exports);
package/package.json CHANGED
@@ -1,47 +1,47 @@
1
1
  {
2
- "name": "@show-karma/karma-gap-sdk",
3
- "publishConfig": {
4
- "access": "public"
5
- },
6
- "version": "0.4.16",
7
- "description": "Simple and easy interface between EAS and Karma GAP.",
8
- "main": "./index.js",
9
- "author": "KarmaHQ",
10
- "license": "MIT",
11
- "private": false,
12
- "repository": {
13
- "url": "git+https://github.com/show-karma/karma-gap-sdk.git",
14
- "type": "git"
15
- },
16
- "scripts": {
17
- "deploy": "npx ts-node ./core/scripts/deploy.ts",
18
- "csv-upload": "npx ts-node ./csv-upload/scripts/run.ts",
19
- "test-file": "npx ts-node ./test-file-indexer-api.ts",
20
- "test-milestone": "npx ts-node ./milestone-workflow-example.ts",
21
- "create-community": "npx ts-node ./create-community-example.ts",
22
- "publish-npm": "npm version patch && tsc && cd .dist && npm publish --scope=@show-karma/karma-gap-sdk --access public"
23
- },
24
- "dependencies": {
25
- "@allo-team/allo-v2-sdk": "^1.0.63",
26
- "@ethereum-attestation-service/eas-sdk": "1.4.2",
27
- "@gelatonetwork/relay-sdk": "^5.6.0",
28
- "@types/sha256": "^0.2.0",
29
- "axios": "^1.7.9",
30
- "dotenv": "^17.2.3",
31
- "ethers": "6.11.0",
32
- "sha256": "^0.2.0",
33
- "simple-ts-job-runner": "^1.0.12"
34
- },
35
- "overrides": {
36
- "ws": ">=8.17.1",
37
- "cookie": ">=0.7.0"
38
- },
39
- "devDependencies": {
40
- "@types/node": "^20.5.0",
41
- "eslint": "^8.47.0",
42
- "fast-csv": "^4.3.6",
43
- "husky": "^8.0.3",
44
- "prettier": "^3.0.1",
45
- "typescript": "^5.1.6"
46
- }
2
+ "name": "@show-karma/karma-gap-sdk",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "version": "0.4.17",
7
+ "description": "Simple and easy interface between EAS and Karma GAP.",
8
+ "main": "./index.js",
9
+ "author": "KarmaHQ",
10
+ "license": "MIT",
11
+ "private": false,
12
+ "repository": {
13
+ "url": "git+https://github.com/show-karma/karma-gap-sdk.git",
14
+ "type": "git"
15
+ },
16
+ "scripts": {
17
+ "deploy": "npx ts-node ./core/scripts/deploy.ts",
18
+ "csv-upload": "npx ts-node ./csv-upload/scripts/run.ts",
19
+ "test-file": "npx ts-node ./test-file-indexer-api.ts",
20
+ "test-milestone": "npx ts-node ./milestone-workflow-example.ts",
21
+ "create-community": "npx ts-node ./create-community-example.ts",
22
+ "publish-npm": "npm version patch && tsc && cd .dist && npm publish --scope=@show-karma/karma-gap-sdk --access public"
23
+ },
24
+ "dependencies": {
25
+ "@allo-team/allo-v2-sdk": "^1.0.63",
26
+ "@ethereum-attestation-service/eas-sdk": "1.4.2",
27
+ "@gelatonetwork/relay-sdk": "^5.6.0",
28
+ "@types/sha256": "^0.2.0",
29
+ "axios": "^1.7.9",
30
+ "dotenv": "^17.2.3",
31
+ "ethers": "6.11.0",
32
+ "sha256": "^0.2.0",
33
+ "simple-ts-job-runner": "^1.0.12"
34
+ },
35
+ "overrides": {
36
+ "ws": ">=8.17.1",
37
+ "cookie": ">=0.7.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^20.5.0",
41
+ "eslint": "^8.47.0",
42
+ "fast-csv": "^4.3.6",
43
+ "husky": "^8.0.3",
44
+ "prettier": "^3.0.1",
45
+ "typescript": "^5.1.6"
46
+ }
47
47
  }
package/.cursorrules DELETED
@@ -1,43 +0,0 @@
1
- # Karma GAP SDK - Cursor Rules
2
-
3
- ## Project Overview
4
- The Karma GAP SDK is a library for easy integration with the Grantee Accountability Protocol. It provides tools to fetch and display Communities, Projects, Members, Grants, Milestones, and their dependencies, as well as create, update, and delete these entities. The SDK also supports gasless transactions with Gelato Relay and custom API endpoints for faster queries.
5
-
6
- ## Architecture Guidelines
7
- When working with this codebase, understand that it follows a modular architecture with these key components:
8
-
9
- 1. **GAP Facade** - Centralizes resources within the SDK, providing tools and methods to retrieve attestations and convert them into concrete objects.
10
- 2. **Attestations** - Base module for handling various types of attestations available at EAS. Can be inherited for specific attestation types.
11
- 3. **Schemas** - Abstract module that establishes connection with the EAS infrastructure. Contains parameters, methods, and interactions for blockchain communication.
12
- 4. **Entities** - Represents specific attestation types customized for specific requirements. Always extends the Attestation module.
13
- 5. **Fetcher** - Abstract module for interacting with EAS or custom API to retrieve attestations and transform them into Attestation instances.
14
- 6. **Contract** - Custom intermediary contract to add an abstraction layer to the original EAS contracts.
15
-
16
- ## Entity Types
17
- The SDK supports various entity types that represent different attestation types in the Grantee Accountability Protocol: Use the `gap-schema.yaml` file to understand the different types of attestations and their relationships.
18
-
19
- ## Code Style Guidelines
20
- - Use TypeScript for all new code
21
- - Follow the existing module pattern when adding new features
22
- - Maintain proper inheritance hierarchy for new entities (extend from Attestation)
23
- - Document all public methods and classes with JSDoc comments
24
- - Use async/await for asynchronous operations
25
- - Implement proper error handling with custom error classes
26
-
27
- ## Integration Features
28
- The SDK includes several integration features:
29
-
30
- - **Gelato Integration** - For gasless transactions
31
- - **GraphQL** - For data fetching
32
- - **Remote Storage** - For storing data remotely
33
- - **Karma Indexer** - For efficient data retrieval
34
-
35
- ## Testing Guidelines
36
- - Write unit tests for all new functionality
37
- - Ensure backward compatibility when modifying existing code
38
- - Test with both custom API and direct blockchain access
39
-
40
- ## Documentation
41
- - Update the README.md when adding new features
42
- - Include examples for new functionality
43
- - Document any breaking changes
package/core/abi/index.ts DELETED
@@ -1,21 +0,0 @@
1
- import AirdropNFT from "./AirdropNFT.json";
2
- import Allo from "./Allo.json";
3
- import AlloRegistry from "./AlloRegistry.json";
4
- import CommunityResolverABI from "./CommunityResolverABI.json";
5
- import Donations from "./Donations.json";
6
- import EAS from "./EAS.json";
7
- import MultiAttester from "./MultiAttester.json";
8
- import ProjectResolver from "./ProjectResolver.json";
9
- import SchemaRegistry from "./SchemaRegistry.json";
10
-
11
- export const abis = {
12
- AirdropNFT,
13
- Allo,
14
- AlloRegistry,
15
- CommunityResolverABI,
16
- Donations,
17
- EAS,
18
- MultiAttester,
19
- ProjectResolver,
20
- SchemaRegistry,
21
- };
@@ -1,21 +0,0 @@
1
- import { MountEntities, Networks } from "../../core/consts";
2
- import { SchemaInterface, TNetwork, TSchemaName } from "../types";
3
- import { GAP } from "./GAP";
4
- import { GapSchema } from "./GapSchema";
5
-
6
- export class AllGapSchemas {
7
- public allSchemas: { [network: string]: SchemaInterface<TSchemaName>[] } = {};
8
-
9
- constructor() {
10
- Object.keys(Networks).forEach((network) => {
11
- this.allSchemas[network] = Object.values(
12
- MountEntities(Networks[network])
13
- );
14
- });
15
- }
16
-
17
- findSchema(name: TSchemaName, network: TNetwork) {
18
- const schema = this.allSchemas[network].find((s) => s.name === name);
19
- return new GapSchema(schema, GAP.getInstance({ network }), false, false);
20
- }
21
- }
@@ -1,429 +0,0 @@
1
- import {
2
- Hex,
3
- IAttestation,
4
- JSONStr,
5
- MultiAttestData,
6
- MultiAttestPayload,
7
- SignerOrProvider,
8
- TNetwork,
9
- TSchemaName,
10
- } from "../types";
11
- import { Schema } from "./Schema";
12
- import { AttestationError, SchemaError } from "./SchemaError";
13
- import {
14
- SchemaDecodedItem,
15
- SchemaItem,
16
- SchemaValue,
17
- } from "@ethereum-attestation-service/eas-sdk";
18
- import { getDate } from "../utils/get-date";
19
- import { GAP } from "./GAP";
20
- import { GapSchema } from "./GapSchema";
21
- import { Networks, nullRef } from "../consts";
22
- import { GapContract } from "./contract/GapContract";
23
- import { IpfsStorage } from "./remote-storage/IpfsStorage";
24
- import { AttestationWithTx } from "./types/attestations";
25
-
26
- export interface AttestationArgs<T = unknown, S extends Schema = Schema> {
27
- data: T | string;
28
- schema: S;
29
- uid?: Hex;
30
- refUID?: Hex;
31
- attester?: Hex;
32
- recipient: Hex;
33
- revoked?: boolean;
34
- revocationTime?: Date | number;
35
- createdAt?: Date | number;
36
- chainID?: number;
37
- }
38
-
39
- /**
40
- * Represents the EAS Attestation and provides methods to manage attestations.
41
- * @example
42
- *
43
- * ```ts
44
- * const grantee = new Attestation({
45
- * schema: Schema.get("Grantee", "network-name"), // Use this.schema.gap.findSchema("SchemaName") if using default GAP schemas
46
- * data: { grantee: true },
47
- * uid: "0xabc123",
48
- * });
49
- *
50
- * const granteeDetails = new Attestation({
51
- * schema: Schema.get("GranteeDetails", "optimism"),
52
- * data: {
53
- * name: "John Doe",
54
- * description: "A description",
55
- * imageURL: "https://example.com/image.png",
56
- * },
57
- * uid: "0xab234"
58
- * );
59
- *
60
- * // Return the refferenced attestation
61
- * const ref = granteeDetails.reference<Grantee>();
62
- *
63
- * // Revoke attestation
64
- * granteeDetails.revoke();
65
- *
66
- * // Get attestation data from a decoded JSON string.
67
- * granteeDetails.fromDecodedSchema(granteeDetails.data);
68
- * ```
69
- */
70
- export class Attestation<T = unknown, S extends Schema = GapSchema>
71
- implements AttestationArgs<T, S>
72
- {
73
- readonly schema: S;
74
- private _data: T;
75
-
76
- protected _uid: Hex;
77
- readonly refUID?: Hex;
78
- readonly attester?: Hex;
79
- readonly recipient: Hex;
80
- readonly revoked?: boolean;
81
- readonly revocationTime?: Date;
82
- readonly createdAt: Date;
83
- private _chainID: number;
84
-
85
- private _reference?: Attestation;
86
-
87
- constructor(args: AttestationArgs<T, S>) {
88
- this.schema = args.schema;
89
-
90
- this._data = this.fromDecodedSchema(args.data);
91
-
92
- this.setValues(this._data);
93
- this._uid = args.uid || nullRef;
94
- this.refUID = args.refUID || nullRef;
95
- this.attester = args.attester;
96
- this.recipient = args.recipient;
97
- this.revoked = args.revoked;
98
- this.revocationTime = getDate(args.revocationTime);
99
- this.createdAt = getDate(args.createdAt || Date.now() / 1000);
100
- this._chainID = args.chainID || Networks[this.schema.gap.network].chainId;
101
- }
102
-
103
- /**
104
- * Encodes the schema.
105
- * @returns
106
- */
107
- encodeSchema(schema: SchemaItem[]) {
108
- return this.schema.encode(schema);
109
- }
110
-
111
- /**
112
- * Sets a field in the schema.
113
- */
114
- setValue<K extends keyof T>(key: K, value: SchemaValue) {
115
- this.schema.setValue(key as string, value);
116
- }
117
-
118
- /**
119
- * Set attestation values to be uploaded.
120
- * @param values
121
- */
122
- setValues(values: T) {
123
- const isJsonSchema = this.schema.isJsonSchema();
124
- if (isJsonSchema) this.schema.setValue("json", JSON.stringify(values));
125
- this._data = values;
126
-
127
- Object.entries(values).forEach(([key, value]) => {
128
- this[key] = value;
129
- if (!isJsonSchema) this.setValue(key as keyof T, value.value || value);
130
- });
131
- }
132
-
133
- /**
134
- * Returns the referenced attestation
135
- */
136
- reference<Ref = unknown, RefSchema extends Schema = Schema>() {
137
- return this._reference as Attestation<Ref, RefSchema>;
138
- }
139
-
140
- /**
141
- * Returns the attestation data as a JSON string.
142
- * @param data
143
- * @returns
144
- */
145
- fromDecodedSchema(data: T | JSONStr): T {
146
- return typeof data === "string"
147
- ? Attestation.fromDecodedSchema<T>(data)
148
- : data;
149
- }
150
-
151
- /**
152
- * Revokes this attestation.
153
- * @param eas
154
- * @param signer
155
- * @returns
156
- */
157
- async revoke(
158
- signer: SignerOrProvider,
159
- callback?: Function
160
- ): Promise<AttestationWithTx> {
161
- try {
162
- callback?.("preparing");
163
- const { tx } = await GapContract.multiRevoke(signer, [
164
- {
165
- data: [
166
- {
167
- uid: this.uid,
168
- value: 0n,
169
- },
170
- ],
171
- schema: this.schema.uid,
172
- },
173
- ]).then((res) => {
174
- callback?.("confirmed");
175
- return res;
176
- });
177
- return { tx, uids: [this.uid] };
178
- } catch (error) {
179
- console.error(error);
180
- throw new SchemaError(
181
- "REVOKE_ERROR",
182
- "Error revoking attestation.",
183
- error
184
- );
185
- }
186
- }
187
-
188
- /**
189
- * Attests the data using the specified signer and schema.
190
- * @param signer - The signer or provider to use for attestation.
191
- * @param args - Additional arguments to pass to the schema's `attest` method.
192
- * @returns A Promise that resolves to the UID of the attestation.
193
- * @throws An `AttestationError` if an error occurs during attestation.
194
- */
195
- async attest(
196
- signer: SignerOrProvider,
197
- ...args: unknown[]
198
- ): Promise<AttestationWithTx> {
199
- const callback =
200
- typeof args[args.length - 1] === "function"
201
- ? (args.pop() as (status: string) => void)
202
- : null;
203
- console.log(`Attesting ${this.schema.name}`);
204
- try {
205
- const { tx, uids } = await this.schema.attest<T>({
206
- data: this.data,
207
- to: this.recipient,
208
- refUID: this.refUID,
209
- signer,
210
- callback: callback,
211
- });
212
-
213
- this._uid = uids[0];
214
- console.log(`Attested ${this.schema.name} with UID ${this.uid}`);
215
- return { tx, uids };
216
- } catch (error) {
217
- console.error(error);
218
- throw new AttestationError(
219
- "ATTEST_ERROR",
220
- "Error during attestation.",
221
- error
222
- );
223
- }
224
- }
225
-
226
- /**
227
- * Validates the payload.
228
- *
229
- * If an attestation should have anything
230
- * specifically explicit, it should be implemented in
231
- * order to avoid errors.
232
- * @returns
233
- */
234
- protected assertPayload() {
235
- return true;
236
- }
237
-
238
- /**
239
- * Get the multi attestation payload for the referred index.
240
- *
241
- * The index should be the array position this payload wants
242
- * to reference.
243
- *
244
- * E.g:
245
- *
246
- * 1. Project is index 0;
247
- * 2. Project details is index 1;
248
- * 3. Grant is index 2;
249
- * 4. Grant details is index 3;
250
- * 5. Milestone is index 4;
251
- *
252
- * `[Project, projectDetails, grant, grantDetails, milestone]`
253
- *
254
- * -> Project.payloadFor(0); // refs itself (no effect)
255
- *
256
- * -> project.details.payloadFor(0); // ref project
257
- *
258
- * -> grant.payloadFor(0); // ref project
259
- *
260
- * -> grant.details.payloadFor(2); // ref grant
261
- *
262
- * -> milestone.payloadFor(2); // ref grant
263
- *
264
- *
265
- * @param refIdx
266
- * @returns [Encoded payload, Raw payload]
267
- */
268
- async payloadFor(refIdx: number): Promise<{
269
- payload: MultiAttestData;
270
- raw: MultiAttestData;
271
- }> {
272
- this.assertPayload();
273
-
274
- if (this.schema.isJsonSchema()) {
275
- if ((this as any).type) {
276
- (this._data as T & { type: string }).type = (this as any).type;
277
- this.schema.setValue("json", JSON.stringify(this._data));
278
- }
279
- }
280
-
281
- const payload = (encode = true): MultiAttestData => ({
282
- uid: nullRef,
283
- refIdx,
284
- multiRequest: {
285
- schema: this.schema.uid,
286
- data: [
287
- {
288
- refUID: this.refUID,
289
- expirationTime: 0n,
290
- revocable: this.schema.revocable || true,
291
- value: 0n,
292
- data: (encode ? this.schema.encode() : this.schema.schema) as any,
293
- recipient: this.recipient,
294
- },
295
- ],
296
- },
297
- });
298
- return {
299
- payload: payload(),
300
- raw: payload(false),
301
- };
302
- }
303
-
304
- /**
305
- * Returns an Attestation instance from a JSON decoded schema.
306
- * @param data
307
- * @returns
308
- */
309
- static fromDecodedSchema<T>(data: JSONStr): T {
310
- try {
311
- const parsed: SchemaDecodedItem[] = JSON.parse(data);
312
-
313
- if (data.length < 2 && !/\{.*\}/gim.test(data)) return {} as T;
314
- if (parsed.length === 1 && parsed[0].name === "json") {
315
- const { value } = parsed[0];
316
- return (
317
- typeof value.value === "string"
318
- ? JSON.parse(value.value)
319
- : value.value
320
- ) as T;
321
- }
322
-
323
- if (parsed && Array.isArray(parsed)) {
324
- return parsed.reduce((acc, curr) => {
325
- const { value } = curr.value;
326
- if (curr.type.includes("uint")) {
327
- acc[curr.name] = ["string", "bigint"].includes(typeof value)
328
- ? BigInt(value as any)
329
- : Number(value);
330
- } else acc[curr.name] = value;
331
- return acc;
332
- }, {}) as T;
333
- }
334
-
335
- throw new SchemaError(
336
- "INVALID_DATA",
337
- "Data must be a valid JSON array string."
338
- );
339
- } catch (error) {
340
- console.error(error);
341
- throw new SchemaError(
342
- "INVALID_DATA",
343
- "Data must be a valid JSON string.",
344
- error
345
- );
346
- }
347
- }
348
-
349
- /**
350
- * Transform attestation interface-based into class-based.
351
- */
352
- static fromInterface<T extends Attestation = Attestation>(
353
- attestations: IAttestation[],
354
- network: TNetwork
355
- ) {
356
- const result: T[] = [];
357
- attestations.forEach((attestation) => {
358
- try {
359
- const schema = Schema.get(attestation.schemaId, network);
360
- result.push(
361
- <T>new Attestation({
362
- ...attestation,
363
- schema,
364
- chainID: Networks[network].chainId,
365
- data: attestation.decodedDataJson,
366
- })
367
- );
368
- } catch (e) {
369
- console.log(e);
370
- }
371
- });
372
- return result;
373
- }
374
-
375
- /**
376
- * Asserts if schema is valid.
377
- * > Does not check refUID if `strict = false`. To check refUID use `Schema.validate()`
378
- * @param args
379
- */
380
- protected assert(args: AttestationArgs, strict = false) {
381
- const { schema, uid } = args;
382
-
383
- if (!schema || !(schema instanceof Schema)) {
384
- throw new SchemaError("MISSING_FIELD", "Schema must be an array.");
385
- }
386
-
387
- if (!uid) {
388
- throw new SchemaError("MISSING_FIELD", "Schema uid is required");
389
- }
390
-
391
- if (strict) Schema.validate(this.schema.gap.network);
392
- }
393
-
394
- get chainID() {
395
- return this._chainID;
396
- }
397
-
398
- get data(): T {
399
- return this._data;
400
- }
401
-
402
- get uid() {
403
- return this._uid;
404
- }
405
-
406
- set uid(uid: Hex) {
407
- this._uid = uid;
408
- }
409
-
410
- /**
411
- * Create attestation to serve as Attestation data.
412
- * @param data Data to attest
413
- * @param schema selected schema
414
- * @param from attester
415
- * @param to recipient
416
- * @returns
417
- */
418
- static factory<T = unknown>(data: T, schema: Schema, from: Hex, to: Hex) {
419
- return new Attestation({
420
- data: data,
421
- recipient: to,
422
- attester: from,
423
- schema,
424
- uid: "0x0",
425
- createdAt: new Date(),
426
- chainID: Networks[schema.gap.network].chainId,
427
- });
428
- }
429
- }