@show-karma/karma-gap-sdk 0.4.15 → 0.4.16
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/.cursorrules +43 -0
- 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.ts +21 -0
- package/core/class/AllGapSchemas.ts +21 -0
- package/core/class/Attestation.ts +429 -0
- package/core/class/Fetcher.ts +224 -0
- package/core/class/GAP.ts +481 -0
- package/core/class/GapSchema.ts +93 -0
- package/core/class/Gelato/{Gelato.js → Gelato.ts} +23 -0
- package/core/class/GrantProgramRegistry/Allo.ts +188 -0
- package/core/class/GrantProgramRegistry/AlloRegistry.ts +101 -0
- package/core/class/GraphQL/AxiosGQL.ts +29 -0
- package/core/class/GraphQL/EASClient.ts +34 -0
- package/core/class/GraphQL/GapEasClient.ts +869 -0
- package/core/class/Schema.ts +659 -0
- package/core/class/SchemaError.ts +42 -0
- package/core/class/contract/GapContract.ts +457 -0
- package/core/class/entities/Community.ts +148 -0
- package/core/class/entities/ContributorProfile.ts +108 -0
- package/core/class/entities/Grant.ts +321 -0
- package/core/class/entities/GrantUpdate.ts +187 -0
- package/core/class/entities/MemberOf.ts +52 -0
- package/core/class/entities/Milestone.ts +898 -0
- package/core/class/entities/Project.ts +672 -0
- package/core/class/entities/ProjectImpact.ts +170 -0
- package/core/class/entities/ProjectMilestone.ts +254 -0
- package/core/class/entities/ProjectPointer.ts +39 -0
- package/core/class/entities/ProjectUpdate.ts +176 -0
- package/core/class/entities/Track.ts +32 -0
- package/core/class/karma-indexer/GapIndexerClient.ts +383 -0
- package/core/class/karma-indexer/api/GapIndexerApi.ts +446 -0
- package/core/class/karma-indexer/api/types.ts +313 -0
- package/core/class/remote-storage/IpfsStorage.ts +76 -0
- package/core/class/remote-storage/RemoteStorage.ts +65 -0
- package/core/class/types/allo.ts +93 -0
- package/core/class/types/attestations.ts +223 -0
- package/core/consts.ts +775 -0
- package/core/scripts/create-grant.ts +102 -0
- package/core/scripts/create-program.ts +43 -0
- package/core/scripts/create-schemas.ts +65 -0
- package/core/scripts/deploy.ts +65 -0
- package/core/scripts/index.ts +1 -0
- package/core/scripts/milestone-multi-grants.ts +125 -0
- package/core/shared/types.ts +13 -0
- package/core/types.ts +224 -0
- package/core/utils/gelato/send-gelato-txn.ts +114 -0
- package/core/utils/gelato/sponsor-handler.ts +77 -0
- package/core/utils/gelato/watch-gelato-txn.ts +67 -0
- package/core/utils/get-date.ts +3 -0
- package/core/utils/get-ipfs-data.ts +13 -0
- package/core/utils/get-web3-provider.ts +18 -0
- package/core/utils/gql-queries.ts +133 -0
- package/core/utils/map-filter.ts +21 -0
- package/core/utils/serialize-bigint.ts +7 -0
- package/core/utils/to-unix.ts +18 -0
- package/create-community-example.ts +119 -0
- package/csv-upload/README.md +74 -0
- package/csv-upload/config.ts +41 -0
- package/csv-upload/example.csv +2 -0
- package/csv-upload/keys.example.json +8 -0
- package/csv-upload/scripts/run.ts +417 -0
- package/csv-upload/types.ts +39 -0
- 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 +155 -0
- package/milestone-workflow-example.ts +353 -0
- package/package.json +45 -39
- package/readme.md +872 -0
- package/schemas/.gitkeep +0 -0
- package/schemas/GAP-schemas-1692135812877.json +33 -0
- package/test-file-indexer-api.ts +25 -0
- package/tsconfig.json +26 -0
- package/core/abi/index.d.ts +0 -1114
- package/core/abi/index.js +0 -26
- package/core/class/AllGapSchemas.d.ts +0 -9
- package/core/class/AllGapSchemas.js +0 -19
- package/core/class/Attestation.d.ts +0 -173
- package/core/class/Attestation.js +0 -333
- package/core/class/Fetcher.d.ts +0 -175
- package/core/class/Fetcher.js +0 -13
- package/core/class/GAP.d.ts +0 -254
- package/core/class/GAP.js +0 -289
- package/core/class/GapSchema.d.ts +0 -34
- package/core/class/GapSchema.js +0 -62
- package/core/class/GrantProgramRegistry/Allo.d.ts +0 -17
- package/core/class/GrantProgramRegistry/Allo.js +0 -137
- package/core/class/GrantProgramRegistry/AlloRegistry.d.ts +0 -15
- package/core/class/GrantProgramRegistry/AlloRegistry.js +0 -70
- package/core/class/GraphQL/AxiosGQL.d.ts +0 -6
- package/core/class/GraphQL/AxiosGQL.js +0 -25
- package/core/class/GraphQL/EASClient.d.ts +0 -16
- package/core/class/GraphQL/EASClient.js +0 -26
- package/core/class/GraphQL/GapEasClient.d.ts +0 -71
- package/core/class/GraphQL/GapEasClient.js +0 -451
- package/core/class/GraphQL/index.js +0 -19
- package/core/class/Schema.d.ts +0 -233
- package/core/class/Schema.js +0 -488
- package/core/class/SchemaError.d.ts +0 -30
- package/core/class/SchemaError.js +0 -39
- package/core/class/contract/GapContract.d.ts +0 -102
- package/core/class/contract/GapContract.js +0 -285
- package/core/class/entities/Community.d.ts +0 -34
- package/core/class/entities/Community.js +0 -109
- package/core/class/entities/ContributorProfile.d.ts +0 -41
- package/core/class/entities/ContributorProfile.js +0 -69
- package/core/class/entities/Grant.d.ts +0 -54
- package/core/class/entities/Grant.js +0 -223
- package/core/class/entities/GrantUpdate.d.ts +0 -40
- package/core/class/entities/GrantUpdate.js +0 -114
- package/core/class/entities/MemberOf.d.ts +0 -11
- package/core/class/entities/MemberOf.js +0 -33
- package/core/class/entities/Milestone.d.ts +0 -168
- package/core/class/entities/Milestone.js +0 -657
- package/core/class/entities/Project.d.ts +0 -92
- package/core/class/entities/Project.js +0 -418
- package/core/class/entities/ProjectImpact.d.ts +0 -50
- package/core/class/entities/ProjectImpact.js +0 -112
- package/core/class/entities/ProjectMilestone.d.ts +0 -60
- package/core/class/entities/ProjectMilestone.js +0 -174
- package/core/class/entities/ProjectPointer.d.ts +0 -12
- package/core/class/entities/ProjectPointer.js +0 -22
- package/core/class/entities/ProjectUpdate.d.ts +0 -50
- package/core/class/entities/ProjectUpdate.js +0 -110
- package/core/class/entities/Track.d.ts +0 -16
- package/core/class/entities/Track.js +0 -21
- package/core/class/entities/index.js +0 -26
- package/core/class/index.js +0 -26
- package/core/class/karma-indexer/GapIndexerClient.d.ts +0 -66
- package/core/class/karma-indexer/GapIndexerClient.js +0 -207
- package/core/class/karma-indexer/api/GapIndexerApi.d.ts +0 -73
- package/core/class/karma-indexer/api/GapIndexerApi.js +0 -256
- package/core/class/karma-indexer/api/types.d.ts +0 -295
- package/core/class/karma-indexer/api/types.js +0 -2
- package/core/class/remote-storage/IpfsStorage.d.ts +0 -23
- package/core/class/remote-storage/IpfsStorage.js +0 -56
- package/core/class/remote-storage/RemoteStorage.d.ts +0 -41
- package/core/class/remote-storage/RemoteStorage.js +0 -38
- package/core/class/types/allo.d.ts +0 -78
- package/core/class/types/allo.js +0 -2
- package/core/class/types/attestations.d.ts +0 -168
- package/core/class/types/attestations.js +0 -66
- package/core/consts.d.ts +0 -48
- package/core/consts.js +0 -641
- package/core/index.js +0 -24
- package/core/shared/types.d.ts +0 -6
- package/core/shared/types.js +0 -2
- package/core/types.d.ts +0 -131
- package/core/types.js +0 -13
- package/core/utils/gelato/index.js +0 -19
- package/core/utils/gelato/send-gelato-txn.d.ts +0 -55
- package/core/utils/gelato/send-gelato-txn.js +0 -100
- package/core/utils/gelato/sponsor-handler.d.ts +0 -9
- package/core/utils/gelato/sponsor-handler.js +0 -60
- package/core/utils/gelato/watch-gelato-txn.d.ts +0 -7
- package/core/utils/gelato/watch-gelato-txn.js +0 -63
- package/core/utils/get-date.d.ts +0 -1
- package/core/utils/get-date.js +0 -7
- package/core/utils/get-ipfs-data.d.ts +0 -1
- package/core/utils/get-ipfs-data.js +0 -20
- package/core/utils/get-web3-provider.d.ts +0 -2
- package/core/utils/get-web3-provider.js +0 -18
- package/core/utils/gql-queries.d.ts +0 -12
- package/core/utils/gql-queries.js +0 -90
- package/core/utils/index.js +0 -23
- package/core/utils/map-filter.d.ts +0 -8
- package/core/utils/map-filter.js +0 -20
- package/core/utils/serialize-bigint.d.ts +0 -1
- package/core/utils/serialize-bigint.js +0 -8
- package/core/utils/to-unix.d.ts +0 -1
- package/core/utils/to-unix.js +0 -25
- package/index.js +0 -17
- /package/core/class/GraphQL/{index.d.ts → index.ts} +0 -0
- /package/core/class/entities/{index.d.ts → index.ts} +0 -0
- /package/core/class/{index.d.ts → index.ts} +0 -0
- /package/core/{index.d.ts → index.ts} +0 -0
- /package/core/utils/gelato/{index.d.ts → index.ts} +0 -0
- /package/core/utils/{index.d.ts → index.ts} +0 -0
- /package/{core/class/Gelato/Gelato.d.ts → csv-upload/.gitkeep} +0 -0
- /package/{index.d.ts → index.ts} +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ChainConfig } from "./types";
|
|
2
|
+
|
|
3
|
+
export const CHAIN_IDS: ChainConfig = {
|
|
4
|
+
optimism: 10,
|
|
5
|
+
"optimism-sepolia": 11155420,
|
|
6
|
+
sepolia: 11155111,
|
|
7
|
+
arbitrum: 42161,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const DEFAULT_CONFIG = {
|
|
11
|
+
DEFAULT_OWNER_ADDRESS: "0x23B7A53ecfd93803C63b97316D7362eae59C55B6",
|
|
12
|
+
DEFAULT_NETWORK: "optimism-sepolia" as const,
|
|
13
|
+
CSV_PROCESSING: {
|
|
14
|
+
DELAY_BETWEEN_ITEMS_MS: 2000,
|
|
15
|
+
ELLIPSIS_LIMIT: 100,
|
|
16
|
+
},
|
|
17
|
+
ENS_REGEX: /^\w+\.(eth)$/,
|
|
18
|
+
HEX_REGEX: /^0x[a-fA-F0-9]{64}$/,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const API_ENDPOINTS = {
|
|
22
|
+
ATTESTATIONS: "/attestations",
|
|
23
|
+
PROJECTS: {
|
|
24
|
+
CHECK: "/projects/check",
|
|
25
|
+
},
|
|
26
|
+
GRANTS: {
|
|
27
|
+
EXTERNAL_ID: {
|
|
28
|
+
BULK_UPDATE: "/grants/external-id/bulk-update",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const LINK_TYPES = {
|
|
34
|
+
WEBSITE: "website",
|
|
35
|
+
TWITTER: "twitter",
|
|
36
|
+
GITHUB: "github",
|
|
37
|
+
} as const;
|
|
38
|
+
|
|
39
|
+
export const GRANT_UPDATE_TYPES = {
|
|
40
|
+
GRANT_UPDATE: "grant-update",
|
|
41
|
+
} as const;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
URL,Owner,Twitter,Github,Website,Project,"Project Description","If you've participated in past grant rounds, please share any new updates or milestones from the prior months",How do you measure the impact of your project?
|
|
2
|
+
https://explorer.gitcoin.co/#/round/424/0x222ea76664ed77d18d4416d2b2e77937b76f0a35/0x222ea76664ed77d18d4416d2b2e77937b76f0a35-5,ethdotlimo.eth,https://eth.limo,https://github.com/ethlimo,https://eth.limo,test-skywalker,"eth.limo is a privacy-preserving ENS gateway, enabling users to access Ethereum-native dApps and content. LIMO represents a shift in dweb adoption by providing an alternative means of accessing ENS resolvable domains.","Support for .art ENS domain resolution, maintained 100% uptime, 1w3.eth content pinning - this ensures fast and reliable access to ENS domain data, with multiple storage locations and a streamlined gateway to IPFS for improved speed and availability. We're also working on some back-end improvements.",
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { ethers, isAddress } from "ethers";
|
|
3
|
+
import * as csv from "fast-csv";
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import {
|
|
6
|
+
GAP,
|
|
7
|
+
Grant,
|
|
8
|
+
Hex,
|
|
9
|
+
MemberOf,
|
|
10
|
+
Project,
|
|
11
|
+
TNetwork,
|
|
12
|
+
nullRef,
|
|
13
|
+
} from "../../core";
|
|
14
|
+
import { GrantUpdate, IGrantUpdate } from "../../core/class";
|
|
15
|
+
import {
|
|
16
|
+
GrantDetails,
|
|
17
|
+
ProjectDetails,
|
|
18
|
+
} from "../../core/class/types/attestations";
|
|
19
|
+
import {
|
|
20
|
+
API_ENDPOINTS,
|
|
21
|
+
CHAIN_IDS,
|
|
22
|
+
DEFAULT_CONFIG,
|
|
23
|
+
GRANT_UPDATE_TYPES,
|
|
24
|
+
LINK_TYPES,
|
|
25
|
+
} from "../config";
|
|
26
|
+
import { Link } from "../types";
|
|
27
|
+
|
|
28
|
+
const [, , fileName, communityUID] = process.argv;
|
|
29
|
+
|
|
30
|
+
interface Keys {
|
|
31
|
+
privateKey: string;
|
|
32
|
+
rpcURL: string;
|
|
33
|
+
gapAPI: string;
|
|
34
|
+
ipfsKey: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface Config {
|
|
38
|
+
[key: string]: Keys | string;
|
|
39
|
+
optimism: Keys;
|
|
40
|
+
"optimism-sepolia": Keys;
|
|
41
|
+
sepolia: Keys;
|
|
42
|
+
arbitrum: Keys;
|
|
43
|
+
"base-sepolia": Keys;
|
|
44
|
+
celo: Keys;
|
|
45
|
+
sei: Keys;
|
|
46
|
+
"sei-testnet": Keys;
|
|
47
|
+
lisk: Keys;
|
|
48
|
+
scroll: Keys;
|
|
49
|
+
gapAccessToken: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface NetworkConfig {
|
|
53
|
+
networkName: TNetwork;
|
|
54
|
+
rpcURL: string;
|
|
55
|
+
gapAPI: string;
|
|
56
|
+
ipfsURL: string;
|
|
57
|
+
privateKey: string;
|
|
58
|
+
ipfsKey: string;
|
|
59
|
+
gapAccessToken: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function loadConfig(): NetworkConfig {
|
|
63
|
+
const networkName = DEFAULT_CONFIG.DEFAULT_NETWORK as TNetwork;
|
|
64
|
+
const { [networkName]: keys, gapAccessToken } = require(__dirname +
|
|
65
|
+
"/../keys.json") as Config;
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
networkName,
|
|
69
|
+
rpcURL: keys.rpcURL,
|
|
70
|
+
gapAPI:
|
|
71
|
+
DEFAULT_CONFIG.DEFAULT_NETWORK === "optimism-sepolia"
|
|
72
|
+
? "https://gapstagapi.karmahq.xyz"
|
|
73
|
+
: "https://gapapi.karmahq.xyz",
|
|
74
|
+
ipfsURL: `${keys.gapAPI}/ipfs`,
|
|
75
|
+
privateKey: keys.privateKey,
|
|
76
|
+
ipfsKey: keys.ipfsKey,
|
|
77
|
+
gapAccessToken: gapAccessToken,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const config = loadConfig();
|
|
82
|
+
|
|
83
|
+
const web3 = new ethers.JsonRpcProvider(config.rpcURL);
|
|
84
|
+
const wallet = new ethers.Wallet(config.privateKey, web3);
|
|
85
|
+
|
|
86
|
+
const gap = GAP.getInstance({ network: config.networkName });
|
|
87
|
+
|
|
88
|
+
interface CSV {
|
|
89
|
+
Project: string;
|
|
90
|
+
ProposalURL: string;
|
|
91
|
+
Owner: string;
|
|
92
|
+
Twitter: string;
|
|
93
|
+
Github: string;
|
|
94
|
+
Website: string;
|
|
95
|
+
FundingMapID: string;
|
|
96
|
+
GrantTitle: string;
|
|
97
|
+
"Project Description": string;
|
|
98
|
+
"Grant Update": string;
|
|
99
|
+
"Grant Title": string;
|
|
100
|
+
GrantDescription: string;
|
|
101
|
+
externalId: string;
|
|
102
|
+
Amount: string;
|
|
103
|
+
"Grant Link": string;
|
|
104
|
+
"Grant Objective": string;
|
|
105
|
+
"Grant Size Justification": string;
|
|
106
|
+
Updates: string;
|
|
107
|
+
Problem: string;
|
|
108
|
+
Solution: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const duplicatedGrants: {
|
|
112
|
+
project: {
|
|
113
|
+
uid: string;
|
|
114
|
+
name?: string;
|
|
115
|
+
};
|
|
116
|
+
grant: {
|
|
117
|
+
uid: string;
|
|
118
|
+
title?: string;
|
|
119
|
+
};
|
|
120
|
+
currentExtId: string;
|
|
121
|
+
candidateExtId: string;
|
|
122
|
+
}[] = [];
|
|
123
|
+
|
|
124
|
+
export function parseCsv<T>(
|
|
125
|
+
path: string,
|
|
126
|
+
parserFn?: (row: unknown) => Promise<void> | void
|
|
127
|
+
): Promise<T[]> {
|
|
128
|
+
return new Promise((resolve, reject) => {
|
|
129
|
+
const res: T[] = [];
|
|
130
|
+
fs.createReadStream(path)
|
|
131
|
+
.pipe(csv.parse({ headers: true }))
|
|
132
|
+
.transform((row: unknown) => {
|
|
133
|
+
return row;
|
|
134
|
+
})
|
|
135
|
+
.on("data", (d) => res.push(parserFn ? parserFn(d) : d))
|
|
136
|
+
.on("error", reject)
|
|
137
|
+
.on("end", () => {
|
|
138
|
+
resolve(res);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const isEns = (str: string) => DEFAULT_CONFIG.ENS_REGEX.test(str);
|
|
144
|
+
const isHex = (str: string): str is Hex => DEFAULT_CONFIG.HEX_REGEX.test(str);
|
|
145
|
+
|
|
146
|
+
type DbAttestation = {
|
|
147
|
+
attester: string;
|
|
148
|
+
chainID: number;
|
|
149
|
+
createdAt: Date;
|
|
150
|
+
recipient: string;
|
|
151
|
+
revocationTime: number;
|
|
152
|
+
revoked: boolean;
|
|
153
|
+
schemaUID: string;
|
|
154
|
+
uid: string;
|
|
155
|
+
refUID: string;
|
|
156
|
+
data?: any;
|
|
157
|
+
type: string;
|
|
158
|
+
externalId?: string;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
async function checkProjectExists(projectDetails: DbAttestation) {
|
|
162
|
+
try {
|
|
163
|
+
const { data } = await axios.post(
|
|
164
|
+
`${config.gapAPI}${API_ENDPOINTS.PROJECTS.CHECK}`,
|
|
165
|
+
projectDetails
|
|
166
|
+
);
|
|
167
|
+
return data;
|
|
168
|
+
} catch (e) {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async function updateExternalIds(
|
|
174
|
+
projectUID: string,
|
|
175
|
+
communityUID: string,
|
|
176
|
+
externalId: string
|
|
177
|
+
) {
|
|
178
|
+
await axios.put(
|
|
179
|
+
`${config.gapAPI}${API_ENDPOINTS.GRANTS.EXTERNAL_ID.BULK_UPDATE}`,
|
|
180
|
+
{
|
|
181
|
+
projectUID,
|
|
182
|
+
communityUID,
|
|
183
|
+
externalId,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
headers: {
|
|
187
|
+
"x-access-token": config.gapAccessToken,
|
|
188
|
+
},
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async function validateInputs() {
|
|
194
|
+
if (!fileName || !fileName.endsWith(".csv")) {
|
|
195
|
+
throw new Error("Please provide a valid csv file name");
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (!communityUID || !isHex(communityUID)) {
|
|
199
|
+
throw new Error("Please provide a valid community UID");
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (!fs.existsSync(__dirname + `/../${fileName}`)) {
|
|
203
|
+
throw new Error(`File ${fileName} does not exist`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async function bootstrap() {
|
|
208
|
+
try {
|
|
209
|
+
await validateInputs();
|
|
210
|
+
|
|
211
|
+
let missedGrants: string[] = [];
|
|
212
|
+
let uids: Hex[] = [];
|
|
213
|
+
|
|
214
|
+
const file = __dirname + `/../${fileName}`;
|
|
215
|
+
const data = await parseCsv<CSV>(file);
|
|
216
|
+
const filtered = data.filter((d) => isAddress(d.Owner) || isEns(d.Owner));
|
|
217
|
+
|
|
218
|
+
let count = 0;
|
|
219
|
+
|
|
220
|
+
for (const item of data) {
|
|
221
|
+
try {
|
|
222
|
+
console.log(`${count} - ${item.Project.trim()}`);
|
|
223
|
+
count += 1;
|
|
224
|
+
await new Promise((f) =>
|
|
225
|
+
setTimeout(f, DEFAULT_CONFIG.CSV_PROCESSING.DELAY_BETWEEN_ITEMS_MS)
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
let address =
|
|
229
|
+
item?.Owner?.trim() || DEFAULT_CONFIG.DEFAULT_OWNER_ADDRESS;
|
|
230
|
+
|
|
231
|
+
const slug = await gap.generateSlug(item.Project.trim());
|
|
232
|
+
const project = new Project({
|
|
233
|
+
data: { project: true },
|
|
234
|
+
recipient: address as Hex,
|
|
235
|
+
schema: gap.findSchema("Project"),
|
|
236
|
+
uid: nullRef,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
const links: Link[] = [
|
|
240
|
+
{
|
|
241
|
+
type: LINK_TYPES.WEBSITE,
|
|
242
|
+
url: item.Website,
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
type: LINK_TYPES.TWITTER,
|
|
246
|
+
url: item.Twitter,
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
type: LINK_TYPES.GITHUB,
|
|
250
|
+
url: item.Github,
|
|
251
|
+
},
|
|
252
|
+
];
|
|
253
|
+
|
|
254
|
+
project.details = new ProjectDetails({
|
|
255
|
+
data: {
|
|
256
|
+
description: item["Project Description"],
|
|
257
|
+
imageURL: "",
|
|
258
|
+
title: item.Project.trim(),
|
|
259
|
+
links,
|
|
260
|
+
slug,
|
|
261
|
+
problem: item.Problem,
|
|
262
|
+
solution: item.Solution,
|
|
263
|
+
},
|
|
264
|
+
refUID: project.uid,
|
|
265
|
+
recipient: project.recipient,
|
|
266
|
+
schema: gap.findSchema("ProjectDetails"),
|
|
267
|
+
uid: nullRef,
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
const member = new MemberOf({
|
|
271
|
+
data: { memberOf: true },
|
|
272
|
+
recipient: project.recipient,
|
|
273
|
+
schema: gap.findSchema("MemberOf"),
|
|
274
|
+
refUID: project.uid,
|
|
275
|
+
uid: nullRef,
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
project.members.push(member);
|
|
279
|
+
|
|
280
|
+
const grant = new Grant({
|
|
281
|
+
data: { communityUID: communityUID as Hex },
|
|
282
|
+
recipient: project.recipient,
|
|
283
|
+
schema: gap.findSchema("Grant"),
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
grant.details = new GrantDetails({
|
|
287
|
+
data: {
|
|
288
|
+
proposalURL: item.ProposalURL,
|
|
289
|
+
title: item.GrantTitle,
|
|
290
|
+
description: item.GrantDescription,
|
|
291
|
+
...(item.Amount && { amount: item.Amount }),
|
|
292
|
+
payoutAddress: project.recipient,
|
|
293
|
+
programId: item.FundingMapID,
|
|
294
|
+
},
|
|
295
|
+
recipient: project.recipient,
|
|
296
|
+
schema: gap.findSchema("GrantDetails"),
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
grant.updates.push(
|
|
300
|
+
new GrantUpdate({
|
|
301
|
+
data: {
|
|
302
|
+
text: "Updates can be found here: " + item.ProposalURL,
|
|
303
|
+
type: GRANT_UPDATE_TYPES.GRANT_UPDATE,
|
|
304
|
+
title: "",
|
|
305
|
+
} as IGrantUpdate,
|
|
306
|
+
recipient: project.recipient,
|
|
307
|
+
schema: gap.findSchema("GrantDetails"),
|
|
308
|
+
})
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
project.grants.push(grant);
|
|
312
|
+
|
|
313
|
+
const defaultValues = {
|
|
314
|
+
recipient: project.recipient,
|
|
315
|
+
attester: project.recipient,
|
|
316
|
+
chainID: CHAIN_IDS[config.networkName],
|
|
317
|
+
createdAt: new Date(),
|
|
318
|
+
revocationTime: 0,
|
|
319
|
+
revoked: false,
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const projectDetails: DbAttestation = {
|
|
323
|
+
data: {
|
|
324
|
+
description: item["Project Description"],
|
|
325
|
+
imageURL: "",
|
|
326
|
+
title: item.Project.trim(),
|
|
327
|
+
slug: slug,
|
|
328
|
+
},
|
|
329
|
+
type: "ProjectDetails",
|
|
330
|
+
refUID: project.uid,
|
|
331
|
+
schemaUID: gap.findSchema("ProjectDetails").uid,
|
|
332
|
+
uid: nullRef,
|
|
333
|
+
...defaultValues,
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
// avoid duplicate projects
|
|
337
|
+
const hasProject = await checkProjectExists(projectDetails);
|
|
338
|
+
|
|
339
|
+
if (hasProject) {
|
|
340
|
+
const concurrentGrant = hasProject.grants.find(
|
|
341
|
+
(g) => g.details?.data?.title === item.GrantTitle
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
if (!concurrentGrant) {
|
|
345
|
+
console.log(`Didn't find grant for project ${item.Project}`);
|
|
346
|
+
Object.assign(grant, { refUID: hasProject.uid });
|
|
347
|
+
missedGrants.push(item.Project);
|
|
348
|
+
await grant.attest(wallet as any, hasProject.chainID);
|
|
349
|
+
} else {
|
|
350
|
+
console.log(`Found grant for project ${item.Project}`);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (
|
|
354
|
+
item.externalId &&
|
|
355
|
+
concurrentGrant &&
|
|
356
|
+
concurrentGrant.externalId &&
|
|
357
|
+
concurrentGrant.externalId !== item.externalId
|
|
358
|
+
) {
|
|
359
|
+
duplicatedGrants.push({
|
|
360
|
+
project: {
|
|
361
|
+
uid: hasProject.uid,
|
|
362
|
+
name: hasProject.details?.title,
|
|
363
|
+
},
|
|
364
|
+
grant: {
|
|
365
|
+
uid: concurrentGrant.uid,
|
|
366
|
+
title: concurrentGrant.details?.title,
|
|
367
|
+
},
|
|
368
|
+
currentExtId: concurrentGrant.externalId,
|
|
369
|
+
candidateExtId: item.externalId,
|
|
370
|
+
});
|
|
371
|
+
} else if (item.externalId) {
|
|
372
|
+
await updateExternalIds(
|
|
373
|
+
hasProject.uid,
|
|
374
|
+
communityUID,
|
|
375
|
+
item.externalId
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
try {
|
|
382
|
+
console.log(project.details.data);
|
|
383
|
+
console.log(project.grants?.[0]?.details?.data);
|
|
384
|
+
await project.attest(wallet as any);
|
|
385
|
+
uids.push(project.uid);
|
|
386
|
+
} catch (e) {
|
|
387
|
+
console.log(`Failed to save for ${item.Project}`);
|
|
388
|
+
}
|
|
389
|
+
} catch (error) {
|
|
390
|
+
console.error(`Error processing project ${item.Project}:`, error);
|
|
391
|
+
missedGrants.push(item.Project);
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
console.log("Attested projects: ", uids.length);
|
|
397
|
+
console.log(uids);
|
|
398
|
+
|
|
399
|
+
console.log("Found concurrent grants for external ids: ");
|
|
400
|
+
console.log(duplicatedGrants);
|
|
401
|
+
const concurrentGrantFile = `${__dirname}/${Date.now()}-concurrent-grants.json`;
|
|
402
|
+
fs.writeFileSync(
|
|
403
|
+
concurrentGrantFile,
|
|
404
|
+
JSON.stringify(duplicatedGrants, null, 2)
|
|
405
|
+
);
|
|
406
|
+
console.log(
|
|
407
|
+
`\x1b[36mConcurrent grants saved to ${concurrentGrantFile}\x1b[0m`
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
console.log("Missed grants:", missedGrants);
|
|
411
|
+
} catch (error) {
|
|
412
|
+
console.error("Fatal error:", error);
|
|
413
|
+
process.exit(1);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
bootstrap();
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface ChainConfig {
|
|
2
|
+
[key: string]: number;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export type LinkType = "website" | "twitter" | "github";
|
|
6
|
+
|
|
7
|
+
export interface Link {
|
|
8
|
+
type: LinkType;
|
|
9
|
+
url: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface Tag {
|
|
13
|
+
name: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ProjectData {
|
|
17
|
+
description: string;
|
|
18
|
+
imageURL: string;
|
|
19
|
+
title: string;
|
|
20
|
+
links: Link[];
|
|
21
|
+
tags?: Tag[];
|
|
22
|
+
slug?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface GrantData {
|
|
26
|
+
proposalURL: string;
|
|
27
|
+
title: string;
|
|
28
|
+
description: string;
|
|
29
|
+
amount: string;
|
|
30
|
+
payoutAddress: string;
|
|
31
|
+
cycle?: string;
|
|
32
|
+
season?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface GrantUpdateData {
|
|
36
|
+
text: string;
|
|
37
|
+
type: string;
|
|
38
|
+
title: string;
|
|
39
|
+
}
|
package/docs/.gitkeep
ADDED
|
File without changes
|
|
Binary file
|
|
Binary file
|
package/gap-schema.yaml
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
DatabaseEntities:
|
|
2
|
+
attestation: _id, uid, schemaUID, refUID, attester, recipient, revoked, revocationTime, createdAt, updatedAt, chainID, type, data, external, txid
|
|
3
|
+
category: _id, name, communityId, createdAt, updatedAt
|
|
4
|
+
project_category: _id, category, attestationId, createdAt, updatedAt
|
|
5
|
+
project_contact: _id, attestationId, name, email, telegram, createdAt, updatedAt
|
|
6
|
+
project_subscription: _id, name, email, subscriptionUids, createdAt, updatedAt
|
|
7
|
+
program_registry: _id, programId, profileId, chainID, name, isValid, createdAtBlock, createdByAddress, metadata, updatedAtBlock, projectNumber, projectType, registryAddress, anchorAddress, txHash, createdAt, updatedAt, approvedAt
|
|
8
|
+
embeddings: _id, entityId, entityType, embeddings, createdAt, updatedAt
|
|
9
|
+
offchain_program_registry: _id, profileID, name, chainID, metadata, isValid, createdAt, updatedAt
|
|
10
|
+
bulk_project_subscription: _id, email, publicAddress, createdAt, updatedAt
|
|
11
|
+
project_request_intro: _id, projectUID, chainID, email, telegram, message, status, createdAt, updatedAt
|
|
12
|
+
external_impact: _id, data, isOnchain, createdAt, updatedAt
|
|
13
|
+
milestone_evaluations: _id, projectUID, grantUID, chainID, milestoneUID, description, completionText, rating, reasoning, model, createdAt, updatedAt
|
|
14
|
+
project_member_invite_link: _id, attestationId, hash, revoked, createdAt, updatedAt
|
|
15
|
+
impact_indicators: _id, name, description, unitOfMeasure, communityUID, chainID, createdAt, updatedAt
|
|
16
|
+
impact_segments: _id, name, description, type, categoryId, createdAt, updatedAt, impact_indicators
|
|
17
|
+
impact_indicator_datapoints: _id, value, startDate, endDate, proof, projectUID, chainID, impactIndicatorId, createdAt, updatedAt
|
|
18
|
+
|
|
19
|
+
# This is how GAP stores its entities
|
|
20
|
+
Community:
|
|
21
|
+
type: attestation[]
|
|
22
|
+
reference: type("Community")
|
|
23
|
+
description: Used as the main entity for communities
|
|
24
|
+
relationships:
|
|
25
|
+
Details:
|
|
26
|
+
type: attestation
|
|
27
|
+
reference: refUID(Community.uid), type("CommunityDetails")
|
|
28
|
+
description: Details about the Community - always use the latest CommunityDetails by createdAt
|
|
29
|
+
|
|
30
|
+
Grant:
|
|
31
|
+
type: attestation
|
|
32
|
+
reference: refUID(Project.uid) data.communityUID(Community.uid), type("Grant")
|
|
33
|
+
description: Grants within a community recieved by a project
|
|
34
|
+
extras: external.gitcoin => contains gitcoin projectIds for the project, external.octant => contains octant projectIds for the project
|
|
35
|
+
relationships:
|
|
36
|
+
Details:
|
|
37
|
+
type: attestation
|
|
38
|
+
reference: refUID(Grant.uid), type("GrantDetails")
|
|
39
|
+
description: Details about the Grant - always use the latest GrantDetails by createdAt
|
|
40
|
+
|
|
41
|
+
Project:
|
|
42
|
+
type: attestation[]
|
|
43
|
+
reference: refUID(Project.uid), uid(Grant.uid), type("Project")
|
|
44
|
+
description: Used as the main entity for the projects
|
|
45
|
+
extras: external.oso[] => contains OSO(Open Source Obeservatory) slugs for the project, external.contractAddresses[] = ["0x123", "0x456"], contract addresses of the project
|
|
46
|
+
relationships:
|
|
47
|
+
Details:
|
|
48
|
+
type: attestation
|
|
49
|
+
reference: refUID(Project.uid), type("ProjectDetails")
|
|
50
|
+
description: Details about the Project - always use the latest ProjectDetails by createdAt
|
|
51
|
+
|
|
52
|
+
ProjectPointer:
|
|
53
|
+
type: attestation[]
|
|
54
|
+
reference: refUID(ProjectB.uid), type("ProjectPointer"), data.ogProjectUID(ProjectA.uid)
|
|
55
|
+
description: Pointer to the original project - used for merging projects
|
|
56
|
+
|
|
57
|
+
ProjectImpact:
|
|
58
|
+
type: attestation[]
|
|
59
|
+
reference: refUID(Project.uid), type("ProjectImpact")
|
|
60
|
+
description: Impacts of the project
|
|
61
|
+
relationship:
|
|
62
|
+
ProjectImpactVerified:
|
|
63
|
+
type: attestation[]
|
|
64
|
+
reference: refUID(ProjectImpact.uid), type("ProjectImpactVerified")
|
|
65
|
+
description: Used to show the show verifications of the Project Impact
|
|
66
|
+
|
|
67
|
+
ProjectMilestone:
|
|
68
|
+
type: attestation[]
|
|
69
|
+
reference: refUID(Project.uid), type("ProjectMilestone")
|
|
70
|
+
description: Milestones of the project
|
|
71
|
+
relationships:
|
|
72
|
+
ProjectMilestoneCompleted:
|
|
73
|
+
type: attestation[]
|
|
74
|
+
reference: refUID(ProjectMilestone.uid), type("ProjectMilestoneCompleted")
|
|
75
|
+
description: Entity to track if a milestone is completed
|
|
76
|
+
|
|
77
|
+
ProjectEndorsement:
|
|
78
|
+
type: attestation[]
|
|
79
|
+
reference: refUID(Project.uid), type("ProjectEndorsement")
|
|
80
|
+
description: Endorsements of the project
|
|
81
|
+
|
|
82
|
+
ProjectUpdate:
|
|
83
|
+
type: attestation[]
|
|
84
|
+
reference: refUID(Project.uid), type("ProjectUpdate")
|
|
85
|
+
description: Updates of the project
|
|
86
|
+
|
|
87
|
+
MemberOf:
|
|
88
|
+
type: attestation[]
|
|
89
|
+
reference: refUID(Project.uid), type("MemberOf")
|
|
90
|
+
description: Members of the project are represented in recipient(0x{string})
|
|
91
|
+
|
|
92
|
+
ProjectCategory:
|
|
93
|
+
type: project_category[]
|
|
94
|
+
references: attestationId(Project._id), categoryId(Category._id)
|
|
95
|
+
description: Mapping of categories to projects
|
|
96
|
+
|
|
97
|
+
GrantUpdate:
|
|
98
|
+
type: attestation[]
|
|
99
|
+
reference: refUID(Grant.uid), type("GrantUpdate")
|
|
100
|
+
description: Updates of a recieved Grant
|
|
101
|
+
relationships:
|
|
102
|
+
GrantUpdateStatus:
|
|
103
|
+
type: attestation
|
|
104
|
+
reference: refUID(GrantUpdate.uid), type("GrantUpdateStatus")
|
|
105
|
+
description: Used to describe the status of a GrantUpdate. data.type("grant-update-verified") is used to show verified
|
|
106
|
+
|
|
107
|
+
Milestone:
|
|
108
|
+
type: attestation[]
|
|
109
|
+
reference: refUID(Grant.uid), type("Milestone")
|
|
110
|
+
description: Milestones of a grant
|
|
111
|
+
relationships:
|
|
112
|
+
MilestoneStatus:
|
|
113
|
+
type: attestation
|
|
114
|
+
reference: refUID(Milestone.uid), type("MilestoneStatus")
|
|
115
|
+
description: Used to describe the status of a Milestone. data.type("verified") is used to show verified and data.type("completed") is for completed
|
|
116
|
+
|
|
117
|
+
Program:
|
|
118
|
+
type: program_registry
|
|
119
|
+
reference: data.programId(`${Program.programId}_${Program.chainID}`), type("GrantDetails")
|
|
120
|
+
description: Contains all the Grant programs in the funding map
|
|
121
|
+
relationships:
|
|
122
|
+
Community:
|
|
123
|
+
type: attestation[]
|
|
124
|
+
reference: metadata.communityRef[](Community.uid)
|
|
125
|
+
description: Communities linked to this program explicitly
|
|
126
|
+
|
|
127
|
+
ImpactIndicators:
|
|
128
|
+
type: impact_indicators[]
|
|
129
|
+
reference: communityUID(Community.uid)
|
|
130
|
+
description: Indicators within a Community
|
|
131
|
+
relationships:
|
|
132
|
+
ImpactIndicatorDatapoints:
|
|
133
|
+
type: impact_indicator_datapoints[]
|
|
134
|
+
reference: impactIndicatorId(ImpactIndicator._id), projectUID(Project.uid))
|
|
135
|
+
description: Data points stored for an Impact Indicator for a project
|
|
136
|
+
|
|
137
|
+
Category:
|
|
138
|
+
type: category
|
|
139
|
+
reference: communityId(Community._id)
|
|
140
|
+
description: Categories of projects in a community
|
|
141
|
+
relationships:
|
|
142
|
+
ProjectCategory:
|
|
143
|
+
type: project_category[]
|
|
144
|
+
reference: categoryId(Category._id) attestationId(Project._id)
|
|
145
|
+
description: Mapping of Categories to Projects
|
|
146
|
+
|
|
147
|
+
ImpactSegment:
|
|
148
|
+
type: impact_segments
|
|
149
|
+
reference: categoryId(Category._id)
|
|
150
|
+
description: Impact segments our output/outcome groups of indicators for a category of projects
|
|
151
|
+
relationships:
|
|
152
|
+
ImpactIndicator:
|
|
153
|
+
type: impact_indicators
|
|
154
|
+
reference: impact_indicators(impact_indicators._id)[]
|
|
155
|
+
description: List of impact indicators grouped under this impact segment
|