@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.
- package/core/abi/AirdropNFT.json +1 -1
- package/core/abi/Allo.json +860 -860
- package/core/abi/AlloRegistry.json +578 -578
- package/core/abi/CommunityResolverABI.json +506 -506
- package/core/abi/Donations.json +251 -251
- package/core/abi/EAS.json +1 -1
- package/core/abi/MultiAttester.json +746 -746
- package/core/abi/ProjectResolver.json +574 -574
- package/core/abi/SchemaRegistry.json +1 -1
- package/core/abi/index.d.ts +1114 -0
- package/core/abi/index.js +26 -0
- package/core/class/AllGapSchemas.d.ts +9 -0
- package/core/class/AllGapSchemas.js +19 -0
- package/core/class/Attestation.d.ts +173 -0
- package/core/class/Attestation.js +333 -0
- package/core/class/Fetcher.d.ts +175 -0
- package/core/class/Fetcher.js +13 -0
- package/core/class/GAP.d.ts +254 -0
- package/core/class/GAP.js +289 -0
- package/core/class/GapSchema.d.ts +34 -0
- package/core/class/GapSchema.js +62 -0
- package/core/class/Gelato/{Gelato.ts → Gelato.js} +0 -23
- package/core/class/GrantProgramRegistry/Allo.d.ts +17 -0
- package/core/class/GrantProgramRegistry/Allo.js +137 -0
- package/core/class/GrantProgramRegistry/AlloRegistry.d.ts +15 -0
- package/core/class/GrantProgramRegistry/AlloRegistry.js +70 -0
- package/core/class/GraphQL/AxiosGQL.d.ts +6 -0
- package/core/class/GraphQL/AxiosGQL.js +25 -0
- package/core/class/GraphQL/EASClient.d.ts +16 -0
- package/core/class/GraphQL/EASClient.js +26 -0
- package/core/class/GraphQL/GapEasClient.d.ts +71 -0
- package/core/class/GraphQL/GapEasClient.js +451 -0
- package/core/class/GraphQL/index.js +19 -0
- package/core/class/Schema.d.ts +233 -0
- package/core/class/Schema.js +488 -0
- package/core/class/SchemaError.d.ts +30 -0
- package/core/class/SchemaError.js +39 -0
- package/core/class/contract/GapContract.d.ts +102 -0
- package/core/class/contract/GapContract.js +285 -0
- package/core/class/entities/Community.d.ts +34 -0
- package/core/class/entities/Community.js +109 -0
- package/core/class/entities/ContributorProfile.d.ts +41 -0
- package/core/class/entities/ContributorProfile.js +69 -0
- package/core/class/entities/Grant.d.ts +54 -0
- package/core/class/entities/Grant.js +223 -0
- package/core/class/entities/GrantUpdate.d.ts +62 -0
- package/core/class/entities/GrantUpdate.js +114 -0
- package/core/class/entities/MemberOf.d.ts +11 -0
- package/core/class/entities/MemberOf.js +33 -0
- package/core/class/entities/Milestone.d.ts +168 -0
- package/core/class/entities/Milestone.js +657 -0
- package/core/class/entities/Project.d.ts +92 -0
- package/core/class/entities/Project.js +418 -0
- package/core/class/entities/ProjectImpact.d.ts +50 -0
- package/core/class/entities/ProjectImpact.js +112 -0
- package/core/class/entities/ProjectMilestone.d.ts +60 -0
- package/core/class/entities/ProjectMilestone.js +174 -0
- package/core/class/entities/ProjectPointer.d.ts +12 -0
- package/core/class/entities/ProjectPointer.js +22 -0
- package/core/class/entities/ProjectUpdate.d.ts +50 -0
- package/core/class/entities/ProjectUpdate.js +110 -0
- package/core/class/entities/Track.d.ts +16 -0
- package/core/class/entities/Track.js +21 -0
- package/core/class/entities/index.js +26 -0
- package/core/class/index.js +26 -0
- package/core/class/karma-indexer/GapIndexerClient.d.ts +66 -0
- package/core/class/karma-indexer/GapIndexerClient.js +207 -0
- package/core/class/karma-indexer/api/GapIndexerApi.d.ts +73 -0
- package/core/class/karma-indexer/api/GapIndexerApi.js +256 -0
- package/core/class/karma-indexer/api/types.d.ts +309 -0
- package/core/class/karma-indexer/api/types.js +2 -0
- package/core/class/remote-storage/IpfsStorage.d.ts +23 -0
- package/core/class/remote-storage/IpfsStorage.js +56 -0
- package/core/class/remote-storage/RemoteStorage.d.ts +41 -0
- package/core/class/remote-storage/RemoteStorage.js +38 -0
- package/core/class/types/allo.d.ts +78 -0
- package/core/class/types/allo.js +2 -0
- package/core/class/types/attestations.d.ts +173 -0
- package/core/class/types/attestations.js +66 -0
- package/core/consts.d.ts +48 -0
- package/core/consts.js +641 -0
- package/core/index.js +24 -0
- package/core/shared/types.d.ts +13 -0
- package/core/shared/types.js +2 -0
- package/core/types.d.ts +131 -0
- package/core/types.js +13 -0
- package/core/utils/gelato/index.js +19 -0
- package/core/utils/gelato/send-gelato-txn.d.ts +55 -0
- package/core/utils/gelato/send-gelato-txn.js +100 -0
- package/core/utils/gelato/sponsor-handler.d.ts +9 -0
- package/core/utils/gelato/sponsor-handler.js +59 -0
- package/core/utils/gelato/watch-gelato-txn.d.ts +7 -0
- package/core/utils/gelato/watch-gelato-txn.js +62 -0
- package/core/utils/get-date.d.ts +1 -0
- package/core/utils/get-date.js +6 -0
- package/core/utils/get-ipfs-data.d.ts +1 -0
- package/core/utils/get-ipfs-data.js +19 -0
- package/core/utils/get-web3-provider.d.ts +2 -0
- package/core/utils/get-web3-provider.js +18 -0
- package/core/utils/gql-queries.d.ts +12 -0
- package/core/utils/gql-queries.js +90 -0
- package/core/utils/index.js +23 -0
- package/core/utils/map-filter.d.ts +8 -0
- package/core/utils/map-filter.js +19 -0
- package/core/utils/serialize-bigint.d.ts +1 -0
- package/core/utils/serialize-bigint.js +7 -0
- package/core/utils/to-unix.d.ts +1 -0
- package/core/utils/to-unix.js +24 -0
- package/index.js +17 -0
- package/package.json +45 -45
- package/.cursorrules +0 -43
- package/core/abi/index.ts +0 -21
- package/core/class/AllGapSchemas.ts +0 -21
- package/core/class/Attestation.ts +0 -429
- package/core/class/Fetcher.ts +0 -224
- package/core/class/GAP.ts +0 -481
- package/core/class/GapSchema.ts +0 -93
- package/core/class/GrantProgramRegistry/Allo.ts +0 -188
- package/core/class/GrantProgramRegistry/AlloRegistry.ts +0 -101
- package/core/class/GraphQL/AxiosGQL.ts +0 -29
- package/core/class/GraphQL/EASClient.ts +0 -34
- package/core/class/GraphQL/GapEasClient.ts +0 -869
- package/core/class/Schema.ts +0 -659
- package/core/class/SchemaError.ts +0 -42
- package/core/class/contract/GapContract.ts +0 -457
- package/core/class/entities/Community.ts +0 -148
- package/core/class/entities/ContributorProfile.ts +0 -108
- package/core/class/entities/Grant.ts +0 -321
- package/core/class/entities/GrantUpdate.ts +0 -187
- package/core/class/entities/MemberOf.ts +0 -52
- package/core/class/entities/Milestone.ts +0 -898
- package/core/class/entities/Project.ts +0 -672
- package/core/class/entities/ProjectImpact.ts +0 -170
- package/core/class/entities/ProjectMilestone.ts +0 -254
- package/core/class/entities/ProjectPointer.ts +0 -39
- package/core/class/entities/ProjectUpdate.ts +0 -176
- package/core/class/entities/Track.ts +0 -32
- package/core/class/karma-indexer/GapIndexerClient.ts +0 -383
- package/core/class/karma-indexer/api/GapIndexerApi.ts +0 -446
- package/core/class/karma-indexer/api/types.ts +0 -313
- package/core/class/remote-storage/IpfsStorage.ts +0 -76
- package/core/class/remote-storage/RemoteStorage.ts +0 -65
- package/core/class/types/allo.ts +0 -93
- package/core/class/types/attestations.ts +0 -223
- package/core/consts.ts +0 -775
- package/core/scripts/create-grant.ts +0 -102
- package/core/scripts/create-program.ts +0 -43
- package/core/scripts/create-schemas.ts +0 -65
- package/core/scripts/deploy.ts +0 -65
- package/core/scripts/index.ts +0 -1
- package/core/scripts/milestone-multi-grants.ts +0 -125
- package/core/shared/types.ts +0 -13
- package/core/types.ts +0 -224
- package/core/utils/gelato/send-gelato-txn.ts +0 -114
- package/core/utils/gelato/sponsor-handler.ts +0 -77
- package/core/utils/gelato/watch-gelato-txn.ts +0 -67
- package/core/utils/get-date.ts +0 -3
- package/core/utils/get-ipfs-data.ts +0 -13
- package/core/utils/get-web3-provider.ts +0 -18
- package/core/utils/gql-queries.ts +0 -133
- package/core/utils/map-filter.ts +0 -21
- package/core/utils/serialize-bigint.ts +0 -7
- package/core/utils/to-unix.ts +0 -18
- package/create-community-example.ts +0 -119
- package/csv-upload/README.md +0 -74
- package/csv-upload/config.ts +0 -41
- package/csv-upload/example.csv +0 -2
- package/csv-upload/keys.example.json +0 -8
- package/csv-upload/scripts/run.ts +0 -417
- package/csv-upload/types.ts +0 -39
- package/docs/.gitkeep +0 -0
- package/docs/images/attestation-architecture.png +0 -0
- package/docs/images/dfd-get-projects.png +0 -0
- package/gap-schema.yaml +0 -155
- package/milestone-workflow-example.ts +0 -353
- package/readme.md +0 -872
- package/schemas/.gitkeep +0 -0
- package/schemas/GAP-schemas-1692135812877.json +0 -33
- package/test-file-indexer-api.ts +0 -25
- package/tsconfig.json +0 -26
- /package/{csv-upload/.gitkeep → core/class/Gelato/Gelato.d.ts} +0 -0
- /package/core/class/GraphQL/{index.ts → index.d.ts} +0 -0
- /package/core/class/entities/{index.ts → index.d.ts} +0 -0
- /package/core/class/{index.ts → index.d.ts} +0 -0
- /package/core/{index.ts → index.d.ts} +0 -0
- /package/core/utils/gelato/{index.ts → index.d.ts} +0 -0
- /package/core/utils/{index.ts → index.d.ts} +0 -0
- /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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
}
|