@show-karma/karma-gap-sdk 0.4.19 → 0.4.21

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 (32) hide show
  1. package/core/__tests__/received-date.types.test.d.ts +1 -0
  2. package/core/__tests__/received-date.types.test.js +39 -0
  3. package/core/class/GAP.d.ts +52 -17
  4. package/core/class/GAP.js +35 -18
  5. package/core/class/GrantProgramRegistry/Allo.d.ts +5 -7
  6. package/core/class/GrantProgramRegistry/Allo.js +4 -28
  7. package/core/class/GrantProgramRegistry/AlloRegistry.d.ts +3 -8
  8. package/core/class/GrantProgramRegistry/AlloRegistry.js +5 -26
  9. package/core/class/Schema.d.ts +3 -8
  10. package/core/class/Schema.js +3 -8
  11. package/core/class/SchemaError.d.ts +0 -3
  12. package/core/class/SchemaError.js +1 -5
  13. package/core/class/contract/GapContract.d.ts +15 -13
  14. package/core/class/contract/GapContract.js +16 -14
  15. package/core/class/index.d.ts +0 -2
  16. package/core/class/index.js +0 -2
  17. package/core/class/karma-indexer/api/GapIndexerApi.d.ts +34 -34
  18. package/core/class/karma-indexer/api/types.d.ts +2 -1
  19. package/core/class/types/attestations.d.ts +2 -0
  20. package/core/consts.js +0 -12
  21. package/core/types.d.ts +18 -14
  22. package/core/utils/get-web3-provider.d.ts +16 -1
  23. package/core/utils/get-web3-provider.js +50 -10
  24. package/core/utils/index.d.ts +1 -1
  25. package/core/utils/index.js +5 -1
  26. package/package.json +3 -1
  27. package/core/class/remote-storage/IpfsStorage.d.ts +0 -23
  28. package/core/class/remote-storage/IpfsStorage.js +0 -56
  29. package/core/class/remote-storage/RemoteStorage.d.ts +0 -41
  30. package/core/class/remote-storage/RemoteStorage.js +0 -38
  31. package/core/utils/get-ipfs-data.d.ts +0 -1
  32. package/core/utils/get-ipfs-data.js +0 -19
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const attestationGrantDetails = {
4
+ title: "Grant",
5
+ proposalURL: "https://example.com",
6
+ type: "grant-details",
7
+ receivedDate: 1704844800
8
+ };
9
+ const indexerGrantDetails = {
10
+ id: "attestation-id",
11
+ uid: "0x1111111111111111111111111111111111111111111111111111111111111111",
12
+ schemaUID: "0x2222222222222222222222222222222222222222222222222222222222222222",
13
+ refUID: "0x0000000000000000000000000000000000000000000000000000000000000000",
14
+ attester: "0x3333333333333333333333333333333333333333333333333333333333333333",
15
+ recipient: "0x4444444444444444444444444444444444444444444444444444444444444444",
16
+ revoked: false,
17
+ createdAt: new Date().toISOString(),
18
+ updatedAt: new Date().toISOString(),
19
+ chainID: 10,
20
+ type: "GrantDetails",
21
+ decodedDataJson: "{}",
22
+ isOffchain: false,
23
+ revocable: true,
24
+ schemaId: "0x5555555555555555555555555555555555555555555555555555555555555555",
25
+ data: {
26
+ title: "Grant",
27
+ amount: "1000",
28
+ description: "Description",
29
+ proposalURL: "https://example.com",
30
+ payoutAddress: "0x6666666666666666666666666666666666666666666666666666666666666666",
31
+ questions: [],
32
+ type: "grant-details",
33
+ receivedDate: 1704844800
34
+ }
35
+ };
36
+ const attestationReceivedDate = attestationGrantDetails.receivedDate;
37
+ const indexerReceivedDate = indexerGrantDetails.data.receivedDate;
38
+ void attestationReceivedDate;
39
+ void indexerReceivedDate;
@@ -1,8 +1,7 @@
1
1
  import { ethers } from "ethers";
2
- import { AttestArgs, Facade, SchemaInterface, SignerOrProvider, TNetwork, TSchemaName } from "../types";
2
+ import { AttestArgs, Facade, GAPRpcConfig, SchemaInterface, SignerOrProvider, TNetwork, TSchemaName } from "../types";
3
3
  import { Fetcher } from "./Fetcher";
4
4
  import { GapSchema } from "./GapSchema";
5
- import { RemoteStorage } from "./remote-storage/RemoteStorage";
6
5
  interface GAPArgs {
7
6
  network: TNetwork;
8
7
  globalSchemas?: boolean;
@@ -12,6 +11,37 @@ interface GAPArgs {
12
11
  */
13
12
  apiClient?: Fetcher;
14
13
  schemas?: SchemaInterface<TSchemaName>[];
14
+ /**
15
+ * RPC URL configuration for the networks you need to use.
16
+ * Maps chain IDs to RPC endpoint URLs.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * // Using literal strings
21
+ * const gap = new GAP({
22
+ * network: "optimism",
23
+ * rpcUrls: {
24
+ * 10: "https://opt-mainnet.g.alchemy.com/v2/YOUR_KEY",
25
+ * 42161: "https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY",
26
+ * },
27
+ * });
28
+ *
29
+ * // Using environment variables (with validation)
30
+ * const requireEnv = (key: string): string => {
31
+ * const value = process.env[key];
32
+ * if (!value) throw new Error(`Missing: ${key}`);
33
+ * return value;
34
+ * };
35
+ *
36
+ * const gap = new GAP({
37
+ * network: "optimism",
38
+ * rpcUrls: {
39
+ * 10: requireEnv("OPTIMISM_RPC_URL"),
40
+ * },
41
+ * });
42
+ * ```
43
+ */
44
+ rpcUrls?: GAPRpcConfig;
15
45
  /**
16
46
  * Defined if the transactions will be gasless or not.
17
47
  *
@@ -89,12 +119,6 @@ interface GAPArgs {
89
119
  */
90
120
  useGasless?: boolean;
91
121
  };
92
- /**
93
- * Defines a remote storage client to be used to store data.
94
- * If defined, all the details data from an attestation will
95
- * be stored in the remote storage, e.g. IPFS.
96
- */
97
- remoteStorage?: RemoteStorage;
98
122
  }
99
123
  /**
100
124
  * GAP SDK Facade.
@@ -156,10 +180,10 @@ interface GAPArgs {
156
180
  * ```
157
181
  */
158
182
  export declare class GAP extends Facade {
159
- private static remoteStorage?;
160
183
  private static instances;
161
184
  readonly fetch: Fetcher;
162
185
  readonly network: TNetwork;
186
+ readonly rpcConfig: GAPRpcConfig;
163
187
  private _schemas;
164
188
  private static _gelatoOpts;
165
189
  /**
@@ -168,7 +192,7 @@ export declare class GAP extends Facade {
168
192
  * @param args Optional initialization arguments
169
193
  * @returns The singleton instance of GAP for the specified network
170
194
  */
171
- static getInstance(args?: GAPArgs): GAP;
195
+ static getInstance(args: GAPArgs): GAP;
172
196
  /**
173
197
  * Creates a new instance of GAP.
174
198
  * You can either use this constructor directly or use the singleton pattern via getInstance().
@@ -214,25 +238,37 @@ export declare class GAP extends Facade {
214
238
  * @returns
215
239
  */
216
240
  findManySchemas(names: TSchemaName[]): GapSchema[];
241
+ /**
242
+ * Get a Web3 provider for a specific chain ID using this instance's RPC configuration.
243
+ *
244
+ * @param chainId - The chain ID to get a provider for
245
+ * @returns An ethers JsonRpcProvider for the specified chain
246
+ * @throws Error if no RPC URL is configured for the chain ID
247
+ */
248
+ getProvider(chainId: number): ethers.JsonRpcProvider;
217
249
  /**
218
250
  * Get the multicall contract
219
251
  * @param signer
220
252
  */
221
253
  static getMulticall(signer: SignerOrProvider): Promise<ethers.Contract>;
222
254
  /**
223
- * Get the multicall contract
224
- * @param signer
255
+ * Get the project resolver contract
256
+ * @param signer - The signer or provider to use
257
+ * @param rpcConfig - RPC URL configuration (required when chainId is provided)
258
+ * @param chainId - Optional chain ID to use a different chain than the signer's
225
259
  */
226
260
  static getProjectResolver(signer: SignerOrProvider & {
227
261
  getChainId?: () => Promise<number>;
228
- }, chainId?: number): Promise<ethers.Contract>;
262
+ }, rpcConfig?: GAPRpcConfig, chainId?: number): Promise<ethers.Contract>;
229
263
  /**
230
- * Get the multicall contract
231
- * @param signer
264
+ * Get the community resolver contract
265
+ * @param signer - The signer or provider to use
266
+ * @param rpcConfig - RPC URL configuration (required when chainId is provided)
267
+ * @param chainId - Optional chain ID to use a different chain than the signer's
232
268
  */
233
269
  static getCommunityResolver(signer: SignerOrProvider & {
234
270
  getChainId?: () => Promise<number>;
235
- }, chainId?: number): Promise<ethers.Contract>;
271
+ }, rpcConfig?: GAPRpcConfig, chainId?: number): Promise<ethers.Contract>;
236
272
  get schemas(): GapSchema[];
237
273
  /**
238
274
  * Defined if the transactions will be gasless or not.
@@ -249,6 +285,5 @@ export declare class GAP extends Facade {
249
285
  */
250
286
  static get gelatoOpts(): GAPArgs["gelatoOpts"];
251
287
  static set useGasLess(useGasLess: boolean);
252
- static get remoteClient(): RemoteStorage<unknown>;
253
288
  }
254
289
  export {};
package/core/class/GAP.js CHANGED
@@ -83,16 +83,10 @@ class GAP extends types_1.Facade {
83
83
  * @returns The singleton instance of GAP for the specified network
84
84
  */
85
85
  static getInstance(args) {
86
- if (!args) {
87
- throw new Error("Network must be specified when getting GAP instance");
88
- }
89
86
  const existingInstance = GAP.instances.get(args.network);
90
87
  if (existingInstance) {
91
88
  return existingInstance;
92
89
  }
93
- if (!args) {
94
- throw new Error("Initialization arguments required for first instance");
95
- }
96
90
  const newInstance = new GAP(args);
97
91
  GAP.instances.set(args.network, newInstance);
98
92
  return newInstance;
@@ -132,6 +126,7 @@ class GAP extends types_1.Facade {
132
126
  };
133
127
  const schemas = args.schemas || Object.values((0, consts_1.MountEntities)(consts_1.Networks[args.network]));
134
128
  this.network = args.network;
129
+ this.rpcConfig = args.rpcUrls ?? {};
135
130
  this._eas = new eas_sdk_1.EAS(consts_1.Networks[args.network].contracts.eas);
136
131
  this.fetch =
137
132
  args.apiClient ||
@@ -141,7 +136,6 @@ class GAP extends types_1.Facade {
141
136
  this.fetch.gapInstance = this;
142
137
  this.assertGelatoOpts(args);
143
138
  GAP._gelatoOpts = args.gelatoOpts;
144
- GAP.remoteStorage = args.remoteStorage;
145
139
  this._schemas = schemas.map((schema) => new GapSchema_1.GapSchema(schema, this, false, args.globalSchemas ? !args.globalSchemas : false));
146
140
  Schema_1.Schema.validate(this.network);
147
141
  console.info(`Loaded GAP SDK v${package_json_1.version} for network ${this.network}`);
@@ -207,6 +201,16 @@ class GAP extends types_1.Facade {
207
201
  const schemas = Schema_1.Schema.getMany(names, this.network);
208
202
  return schemas.map((s) => GapSchema_1.GapSchema.clone(s));
209
203
  }
204
+ /**
205
+ * Get a Web3 provider for a specific chain ID using this instance's RPC configuration.
206
+ *
207
+ * @param chainId - The chain ID to get a provider for
208
+ * @returns An ethers JsonRpcProvider for the specified chain
209
+ * @throws Error if no RPC URL is configured for the chain ID
210
+ */
211
+ getProvider(chainId) {
212
+ return (0, get_web3_provider_1.getWeb3Provider)(chainId, this.rpcConfig);
213
+ }
210
214
  /**
211
215
  * Get the multicall contract
212
216
  * @param signer
@@ -220,28 +224,44 @@ class GAP extends types_1.Facade {
220
224
  return new ethers_1.ethers.Contract(address, MultiAttester_json_1.default, signer);
221
225
  }
222
226
  /**
223
- * Get the multicall contract
224
- * @param signer
227
+ * Get the project resolver contract
228
+ * @param signer - The signer or provider to use
229
+ * @param rpcConfig - RPC URL configuration (required when chainId is provided)
230
+ * @param chainId - Optional chain ID to use a different chain than the signer's
225
231
  */
226
- static async getProjectResolver(signer, chainId) {
232
+ static async getProjectResolver(signer, rpcConfig, chainId) {
227
233
  const currentChainId = chainId ||
228
234
  Number((await signer.provider.getNetwork())?.chainId ||
229
235
  (await signer.getChainId()));
230
- const provider = chainId ? (0, get_web3_provider_1.getWeb3Provider)(chainId) : signer;
236
+ const provider = chainId && rpcConfig
237
+ ? (0, get_web3_provider_1.getWeb3Provider)(chainId, rpcConfig)
238
+ : signer;
231
239
  const network = Object.values(consts_1.Networks).find((n) => +n.chainId === Number(currentChainId));
240
+ if (!network) {
241
+ throw new Error(`Network with chain ID ${currentChainId} is not supported. ` +
242
+ `Supported networks: ${Object.keys(consts_1.Networks).join(", ")}`);
243
+ }
232
244
  const address = network.contracts.projectResolver;
233
245
  return new ethers_1.ethers.Contract(address, ProjectResolver_json_1.default, provider);
234
246
  }
235
247
  /**
236
- * Get the multicall contract
237
- * @param signer
248
+ * Get the community resolver contract
249
+ * @param signer - The signer or provider to use
250
+ * @param rpcConfig - RPC URL configuration (required when chainId is provided)
251
+ * @param chainId - Optional chain ID to use a different chain than the signer's
238
252
  */
239
- static async getCommunityResolver(signer, chainId) {
253
+ static async getCommunityResolver(signer, rpcConfig, chainId) {
240
254
  const currentChainId = chainId ||
241
255
  Number((await signer.provider.getNetwork())?.chainId ||
242
256
  (await signer.getChainId()));
243
- const provider = chainId ? (0, get_web3_provider_1.getWeb3Provider)(chainId) : signer;
257
+ const provider = chainId && rpcConfig
258
+ ? (0, get_web3_provider_1.getWeb3Provider)(chainId, rpcConfig)
259
+ : signer;
244
260
  const network = Object.values(consts_1.Networks).find((n) => +n.chainId === Number(currentChainId));
261
+ if (!network) {
262
+ throw new Error(`Network with chain ID ${currentChainId} is not supported. ` +
263
+ `Supported networks: ${Object.keys(consts_1.Networks).join(", ")}`);
264
+ }
245
265
  const address = network.contracts.communityResolver;
246
266
  return new ethers_1.ethers.Contract(address, CommunityResolverABI_json_1.default, provider);
247
267
  }
@@ -280,9 +300,6 @@ class GAP extends types_1.Facade {
280
300
  }
281
301
  this._gelatoOpts.useGasless = useGasLess;
282
302
  }
283
- static get remoteClient() {
284
- return this.remoteStorage;
285
- }
286
303
  }
287
304
  exports.GAP = GAP;
288
305
  GAP.instances = new Map();
@@ -3,15 +3,13 @@ export declare class AlloBase {
3
3
  private signer;
4
4
  private contract;
5
5
  private allo;
6
- private pinataJWTToken;
7
- constructor(signer: ethers.Signer, pinataJWTToken: string, chainId: number);
8
- saveAndGetCID(data: any, pinataMetadata?: {
9
- name: string;
10
- }): Promise<any>;
6
+ constructor(signer: ethers.Signer, chainId: number);
11
7
  encodeStrategyInitData(applicationStart: number, applicationEnd: number, roundStart: number, roundEnd: number, payoutToken: string): Promise<string>;
12
- createGrant(args: any, callback?: Function): Promise<{
8
+ createGrant(args: any & {
9
+ metadataCid: string;
10
+ }, callback?: Function): Promise<{
13
11
  poolId: string;
14
12
  txHash: string;
15
13
  }>;
16
- updatePoolMetadata(poolId: string, poolMetadata: any, callback?: Function): Promise<any>;
14
+ updatePoolMetadata(poolId: string, metadataCid: string, callback?: Function): Promise<any>;
17
15
  }
@@ -9,32 +9,13 @@ const Allo_json_1 = __importDefault(require("../../abi/Allo.json"));
9
9
  const consts_1 = require("../../consts");
10
10
  const ethers_2 = require("ethers");
11
11
  const allo_v2_sdk_1 = require("@allo-team/allo-v2-sdk/");
12
- const axios_1 = __importDefault(require("axios"));
13
12
  // ABI fragment for the Initialized event
14
13
  const INITIALIZED_EVENT = ["event Initialized(uint256 poolId, bytes data)"];
15
14
  class AlloBase {
16
- constructor(signer, pinataJWTToken, chainId) {
15
+ constructor(signer, chainId) {
17
16
  this.signer = signer;
18
17
  this.contract = new ethers_1.ethers.Contract(consts_1.AlloContracts.alloProxy, Allo_json_1.default, signer);
19
18
  this.allo = new allo_v2_sdk_1.Allo({ chain: chainId });
20
- this.pinataJWTToken = pinataJWTToken;
21
- }
22
- async saveAndGetCID(data, pinataMetadata = { name: "via karma-gap-sdk" }) {
23
- try {
24
- const res = await axios_1.default.post("https://api.pinata.cloud/pinning/pinJSONToIPFS", {
25
- pinataContent: data,
26
- pinataMetadata: pinataMetadata,
27
- }, {
28
- headers: {
29
- "Content-Type": "application/json",
30
- Authorization: `Bearer ${this.pinataJWTToken}`,
31
- },
32
- });
33
- return res.data.IpfsHash;
34
- }
35
- catch (error) {
36
- console.log(error);
37
- }
38
19
  }
39
20
  async encodeStrategyInitData(applicationStart, applicationEnd, roundStart, roundEnd, payoutToken) {
40
21
  const encoder = new ethers_2.AbiCoder();
@@ -54,13 +35,9 @@ class AlloBase {
54
35
  const walletBalance = await this.signer.provider.getBalance(await this.signer.getAddress());
55
36
  console.log("Wallet balance:", (0, ethers_1.formatEther)(walletBalance.toString()), " ETH");
56
37
  try {
57
- const metadata_cid = await this.saveAndGetCID({
58
- round: args.roundMetadata,
59
- application: args.applicationMetadata,
60
- });
61
38
  const metadata = {
62
39
  protocol: BigInt(1),
63
- pointer: metadata_cid,
40
+ pointer: args.metadataCid,
64
41
  };
65
42
  const initStrategyData = (await this.encodeStrategyInitData(args.applicationStart, args.applicationEnd, args.roundStart, args.roundEnd, args.payoutToken));
66
43
  const createPoolArgs = {
@@ -114,13 +91,12 @@ class AlloBase {
114
91
  throw new Error(`Failed to create pool metadata: ${error}`);
115
92
  }
116
93
  }
117
- async updatePoolMetadata(poolId, poolMetadata, callback) {
94
+ async updatePoolMetadata(poolId, metadataCid, callback) {
118
95
  try {
119
96
  callback?.("preparing");
120
- const metadata_cid = await this.saveAndGetCID(poolMetadata);
121
97
  const metadata = {
122
98
  protocol: 1,
123
- pointer: metadata_cid,
99
+ pointer: metadataCid,
124
100
  };
125
101
  const tx = await this.contract.updatePoolMetadata(poolId, metadata);
126
102
  callback?.("pending");
@@ -1,15 +1,10 @@
1
1
  import { ethers } from "ethers";
2
- import { ProfileMetadata } from "../types/allo";
3
2
  export declare class AlloRegistry {
4
3
  private contract;
5
- private pinataJWTToken;
6
- constructor(signer: ethers.Signer, pinataJWTToken: string);
7
- saveAndGetCID(data: any, pinataMetadata?: {
8
- name: string;
9
- }): Promise<any>;
10
- createProgram(nonce: number, name: string, profileMetadata: ProfileMetadata, owner: string, members: string[]): Promise<{
4
+ constructor(signer: ethers.Signer);
5
+ createProgram(nonce: number, name: string, metadataCid: string, owner: string, members: string[]): Promise<{
11
6
  profileId: any;
12
7
  txHash: any;
13
8
  }>;
14
- updateProgramMetadata(profileId: string, profileMetadata: ProfileMetadata): Promise<any>;
9
+ updateProgramMetadata(profileId: string, metadataCid: string): Promise<any>;
15
10
  }
@@ -7,36 +7,16 @@ exports.AlloRegistry = void 0;
7
7
  const ethers_1 = require("ethers");
8
8
  const AlloRegistry_json_1 = __importDefault(require("../../abi/AlloRegistry.json"));
9
9
  const consts_1 = require("../../consts");
10
- const axios_1 = __importDefault(require("axios"));
11
10
  class AlloRegistry {
12
- constructor(signer, pinataJWTToken) {
11
+ constructor(signer) {
13
12
  this.contract = new ethers_1.ethers.Contract(consts_1.AlloContracts.registry, AlloRegistry_json_1.default, signer);
14
- this.pinataJWTToken = pinataJWTToken;
15
13
  }
16
- async saveAndGetCID(data, pinataMetadata = { name: "via karma-gap-sdk" }) {
17
- try {
18
- const res = await axios_1.default.post("https://api.pinata.cloud/pinning/pinJSONToIPFS", {
19
- pinataContent: data,
20
- pinataMetadata: pinataMetadata,
21
- }, {
22
- headers: {
23
- "Content-Type": "application/json",
24
- Authorization: `Bearer ${this.pinataJWTToken}`,
25
- },
26
- });
27
- return res.data.IpfsHash;
28
- }
29
- catch (error) {
30
- console.log(error);
31
- }
32
- }
33
- async createProgram(nonce, name, profileMetadata, owner, members) {
14
+ async createProgram(nonce, name, metadataCid, owner, members) {
34
15
  console.log("Creating program...");
35
16
  try {
36
- const metadata_cid = await this.saveAndGetCID(profileMetadata);
37
17
  const metadata = {
38
18
  protocol: 1,
39
- pointer: metadata_cid,
19
+ pointer: metadataCid,
40
20
  };
41
21
  const tx = await this.contract.createProfile(nonce, name, metadata, owner, members);
42
22
  const receipt = await tx.wait();
@@ -51,12 +31,11 @@ class AlloRegistry {
51
31
  console.error(`Failed to register program: ${error}`);
52
32
  }
53
33
  }
54
- async updateProgramMetadata(profileId, profileMetadata) {
34
+ async updateProgramMetadata(profileId, metadataCid) {
55
35
  try {
56
- const metadata_cid = await this.saveAndGetCID(profileMetadata);
57
36
  const metadata = {
58
37
  protocol: 1,
59
- pointer: metadata_cid,
38
+ pointer: metadataCid,
60
39
  };
61
40
  const tx = await this.contract.updateProfileMetadata(profileId, metadata);
62
41
  const receipt = await tx.wait();
@@ -135,16 +135,11 @@ export declare abstract class Schema<T extends string = string> implements Schem
135
135
  /**
136
136
  * Validates and attests a given schema.
137
137
  *
138
- * This function checks a schema against predefined standards or rules. If the 'ipfsKey' parameter is enabled,
139
- * it uploads the data to the IPFS (InterPlanetary File System). Upon successful upload, the function
140
- * returns the CID (Content Identifier) within the Attestation Body, providing a reference to the data on IPFS.
141
- *
142
- * Usage:
143
- * - Ensure that the schema to be attested conforms to the required format.
144
- * - Enable 'ipfsKey' if you wish to store the data on IPFS and retrieve its CID.
138
+ * This function checks a schema against predefined standards or rules and creates
139
+ * an attestation on-chain.
145
140
  *
146
141
  * @param {Object} param0 - An object containing the schema and other optional settings.
147
- * @returns {Object} An object containing the attestation results, including the CID if 'ipfsKey' is enabled.
142
+ * @returns {Object} An object containing the attestation results.
148
143
  */
149
144
  attest<T>({ data, to, signer, refUID, callback, }: AttestArgs<T>): Promise<AttestationWithTx>;
150
145
  /**
@@ -208,16 +208,11 @@ class Schema {
208
208
  /**
209
209
  * Validates and attests a given schema.
210
210
  *
211
- * This function checks a schema against predefined standards or rules. If the 'ipfsKey' parameter is enabled,
212
- * it uploads the data to the IPFS (InterPlanetary File System). Upon successful upload, the function
213
- * returns the CID (Content Identifier) within the Attestation Body, providing a reference to the data on IPFS.
214
- *
215
- * Usage:
216
- * - Ensure that the schema to be attested conforms to the required format.
217
- * - Enable 'ipfsKey' if you wish to store the data on IPFS and retrieve its CID.
211
+ * This function checks a schema against predefined standards or rules and creates
212
+ * an attestation on-chain.
218
213
  *
219
214
  * @param {Object} param0 - An object containing the schema and other optional settings.
220
- * @returns {Object} An object containing the attestation results, including the CID if 'ipfsKey' is enabled.
215
+ * @returns {Object} An object containing the attestation results.
221
216
  */
222
217
  async attest({ data, to, signer, refUID, callback, }) {
223
218
  const eas = this.gap.eas.connect(signer);
@@ -14,7 +14,6 @@ declare const SchemaErrorCodes: {
14
14
  INVALID_REF_UID: number;
15
15
  REVOKATION_ERROR: number;
16
16
  NOT_REVOCABLE: number;
17
- REMOTE_STORAGE_UPLOAD: number;
18
17
  };
19
18
  export declare class SchemaError extends Error {
20
19
  readonly code: number;
@@ -25,6 +24,4 @@ export declare class SchemaError extends Error {
25
24
  }
26
25
  export declare class AttestationError extends SchemaError {
27
26
  }
28
- export declare class RemoteStorageError extends SchemaError {
29
- }
30
27
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RemoteStorageError = exports.AttestationError = exports.SchemaError = void 0;
3
+ exports.AttestationError = exports.SchemaError = void 0;
4
4
  const SchemaErrorCodes = {
5
5
  INVALID_SCHEMA: 50001,
6
6
  INVALID_SCHEMA_NAME: 50002,
@@ -17,7 +17,6 @@ const SchemaErrorCodes = {
17
17
  INVALID_REF_UID: 50013,
18
18
  REVOKATION_ERROR: 50014,
19
19
  NOT_REVOCABLE: 50015,
20
- REMOTE_STORAGE_UPLOAD: 50016,
21
20
  };
22
21
  class SchemaError extends Error {
23
22
  constructor(code, append, originalError) {
@@ -34,6 +33,3 @@ exports.SchemaError = SchemaError;
34
33
  class AttestationError extends SchemaError {
35
34
  }
36
35
  exports.AttestationError = AttestationError;
37
- class RemoteStorageError extends SchemaError {
38
- }
39
- exports.RemoteStorageError = RemoteStorageError;
@@ -1,5 +1,5 @@
1
1
  import { MultiRevocationRequest } from "@ethereum-attestation-service/eas-sdk";
2
- import { CallbackStatus, Hex, RawAttestationPayload, RawMultiAttestPayload, SignerOrProvider } from "core/types";
2
+ import { CallbackStatus, GAPRpcConfig, Hex, RawAttestationPayload, RawMultiAttestPayload, SignerOrProvider } from "core/types";
3
3
  import { Transaction } from "ethers";
4
4
  import { AttestationWithTx } from "../types/attestations";
5
5
  export declare class GapContract {
@@ -66,22 +66,24 @@ export declare class GapContract {
66
66
  static transferProjectOwnership(signer: SignerOrProvider, projectUID: Hex, newOwner: Hex): Promise<any>;
67
67
  /**
68
68
  * Check if the signer is the owner of the project
69
- * @param signer
70
- * @param projectUID
71
- * @param projectChainId
72
- * @param publicAddress
73
- * @returns
69
+ * @param signer - Signer or provider
70
+ * @param projectUID - The project UID
71
+ * @param projectChainId - The chain ID where the project exists
72
+ * @param publicAddress - Optional public address to check (uses signer address if not provided)
73
+ * @param rpcConfig - Optional RPC config for cross-chain operations. If not provided, uses the signer's chain.
74
+ * @returns Whether the address is a project owner
74
75
  */
75
- static isProjectOwner(signer: SignerOrProvider, projectUID: Hex, projectChainId: number, publicAddress?: string): Promise<boolean>;
76
+ static isProjectOwner(signer: SignerOrProvider, projectUID: Hex, projectChainId: number, publicAddress?: string, rpcConfig?: GAPRpcConfig): Promise<boolean>;
76
77
  /**
77
78
  * Check if the signer is admin of the project
78
- * @param signer
79
- * @param projectUID
80
- * @param projectChainId
81
- * @param publicAddress
82
- * @returns
79
+ * @param signer - Signer or provider
80
+ * @param projectUID - The project UID
81
+ * @param projectChainId - The chain ID where the project exists
82
+ * @param publicAddress - Optional public address to check (uses signer address if not provided)
83
+ * @param rpcConfig - Optional RPC config for cross-chain operations. If not provided, uses the signer's chain.
84
+ * @returns Whether the address is a project admin
83
85
  */
84
- static isProjectAdmin(signer: SignerOrProvider, projectUID: Hex, projectChainId: number, publicAddress?: string): Promise<boolean>;
86
+ static isProjectAdmin(signer: SignerOrProvider, projectUID: Hex, projectChainId: number, publicAddress?: string, rpcConfig?: GAPRpcConfig): Promise<boolean>;
85
87
  private static getTransactionLogs;
86
88
  /**
87
89
  * Add Project Admin
@@ -222,28 +222,30 @@ class GapContract {
222
222
  }
223
223
  /**
224
224
  * Check if the signer is the owner of the project
225
- * @param signer
226
- * @param projectUID
227
- * @param projectChainId
228
- * @param publicAddress
229
- * @returns
225
+ * @param signer - Signer or provider
226
+ * @param projectUID - The project UID
227
+ * @param projectChainId - The chain ID where the project exists
228
+ * @param publicAddress - Optional public address to check (uses signer address if not provided)
229
+ * @param rpcConfig - Optional RPC config for cross-chain operations. If not provided, uses the signer's chain.
230
+ * @returns Whether the address is a project owner
230
231
  */
231
- static async isProjectOwner(signer, projectUID, projectChainId, publicAddress) {
232
- const contract = await GAP_1.GAP.getProjectResolver(signer, projectChainId);
232
+ static async isProjectOwner(signer, projectUID, projectChainId, publicAddress, rpcConfig) {
233
+ const contract = await GAP_1.GAP.getProjectResolver(signer, rpcConfig, projectChainId);
233
234
  const address = publicAddress || (await this.getSignerAddress(signer));
234
235
  const isOwner = await contract.isOwner(projectUID, address);
235
236
  return isOwner;
236
237
  }
237
238
  /**
238
239
  * Check if the signer is admin of the project
239
- * @param signer
240
- * @param projectUID
241
- * @param projectChainId
242
- * @param publicAddress
243
- * @returns
240
+ * @param signer - Signer or provider
241
+ * @param projectUID - The project UID
242
+ * @param projectChainId - The chain ID where the project exists
243
+ * @param publicAddress - Optional public address to check (uses signer address if not provided)
244
+ * @param rpcConfig - Optional RPC config for cross-chain operations. If not provided, uses the signer's chain.
245
+ * @returns Whether the address is a project admin
244
246
  */
245
- static async isProjectAdmin(signer, projectUID, projectChainId, publicAddress) {
246
- const contract = await GAP_1.GAP.getProjectResolver(signer, projectChainId);
247
+ static async isProjectAdmin(signer, projectUID, projectChainId, publicAddress, rpcConfig) {
248
+ const contract = await GAP_1.GAP.getProjectResolver(signer, rpcConfig, projectChainId);
247
249
  const address = publicAddress || (await this.getSignerAddress(signer));
248
250
  const isAdmin = await contract.isAdmin(projectUID, address);
249
251
  return isAdmin;
@@ -6,5 +6,3 @@ export * from './SchemaError';
6
6
  export * from './entities';
7
7
  export * from './Fetcher';
8
8
  export * from './karma-indexer/GapIndexerClient';
9
- export * from './remote-storage/IpfsStorage';
10
- export * from './remote-storage/RemoteStorage';
@@ -22,5 +22,3 @@ __exportStar(require("./SchemaError"), exports);
22
22
  __exportStar(require("./entities"), exports);
23
23
  __exportStar(require("./Fetcher"), exports);
24
24
  __exportStar(require("./karma-indexer/GapIndexerClient"), exports);
25
- __exportStar(require("./remote-storage/IpfsStorage"), exports);
26
- __exportStar(require("./remote-storage/RemoteStorage"), exports);
@@ -2,72 +2,72 @@ import { AxiosGQL } from "../../GraphQL/AxiosGQL";
2
2
  import { Hex, IAttestationResponse, ICommunityResponse, ICommunityAdminsResponse, IGrantResponse, IProjectResponse, ISearchResponse, IProjectMilestoneResponse, ITrackResponse, ITrackAssignmentResponse, IProjectTrackResponse } from "./types";
3
3
  export declare class GapIndexerApi extends AxiosGQL {
4
4
  constructor(url: string);
5
- attestation(uid: Hex): Promise<import("axios").AxiosResponse<IAttestationResponse, any>>;
6
- attestations(schemaUID: string, search?: string): Promise<import("axios").AxiosResponse<IAttestationResponse[], any>>;
7
- attestationsOf(schemaUID: string, attester: Hex): Promise<import("axios").AxiosResponse<IAttestationResponse[], any>>;
5
+ attestation(uid: Hex): Promise<import("axios").AxiosResponse<IAttestationResponse, any, {}>>;
6
+ attestations(schemaUID: string, search?: string): Promise<import("axios").AxiosResponse<IAttestationResponse[], any, {}>>;
7
+ attestationsOf(schemaUID: string, attester: Hex): Promise<import("axios").AxiosResponse<IAttestationResponse[], any, {}>>;
8
8
  /**
9
9
  * Community
10
10
  */
11
- communities(search?: string): Promise<import("axios").AxiosResponse<ICommunityResponse[], any>>;
12
- communitiesOf(address: Hex, withGrants: boolean): Promise<import("axios").AxiosResponse<ICommunityResponse[], any>>;
13
- adminOf(address: Hex): Promise<import("axios").AxiosResponse<ICommunityResponse[], any>>;
14
- communityBySlug(slug: string): Promise<import("axios").AxiosResponse<ICommunityResponse, any>>;
15
- communityAdmins(uid: Hex): Promise<import("axios").AxiosResponse<ICommunityAdminsResponse, any>>;
11
+ communities(search?: string): Promise<import("axios").AxiosResponse<ICommunityResponse[], any, {}>>;
12
+ communitiesOf(address: Hex, withGrants: boolean): Promise<import("axios").AxiosResponse<ICommunityResponse[], any, {}>>;
13
+ adminOf(address: Hex): Promise<import("axios").AxiosResponse<ICommunityResponse[], any, {}>>;
14
+ communityBySlug(slug: string): Promise<import("axios").AxiosResponse<ICommunityResponse, any, {}>>;
15
+ communityAdmins(uid: Hex): Promise<import("axios").AxiosResponse<ICommunityAdminsResponse, any, {}>>;
16
16
  /**
17
17
  * Project
18
18
  */
19
- projectBySlug(slug: string): Promise<import("axios").AxiosResponse<IProjectResponse, any>>;
20
- search(query: string): Promise<import("axios").AxiosResponse<ISearchResponse, any>>;
21
- searchProjects(query: string): Promise<import("axios").AxiosResponse<IProjectResponse[], any>>;
22
- projects(name?: string): Promise<import("axios").AxiosResponse<IProjectResponse[], any>>;
23
- projectsOf(grantee: Hex): Promise<import("axios").AxiosResponse<IProjectResponse[], any>>;
24
- projectMilestones(uidOrSlug: string): Promise<import("axios").AxiosResponse<IProjectMilestoneResponse[], any>>;
19
+ projectBySlug(slug: string): Promise<import("axios").AxiosResponse<IProjectResponse, any, {}>>;
20
+ search(query: string): Promise<import("axios").AxiosResponse<ISearchResponse, any, {}>>;
21
+ searchProjects(query: string): Promise<import("axios").AxiosResponse<IProjectResponse[], any, {}>>;
22
+ projects(name?: string): Promise<import("axios").AxiosResponse<IProjectResponse[], any, {}>>;
23
+ projectsOf(grantee: Hex): Promise<import("axios").AxiosResponse<IProjectResponse[], any, {}>>;
24
+ projectMilestones(uidOrSlug: string): Promise<import("axios").AxiosResponse<IProjectMilestoneResponse[], any, {}>>;
25
25
  /**
26
26
  * Grantee
27
27
  */
28
- grantee(address: Hex): Promise<import("axios").AxiosResponse<any, any>>;
28
+ grantee(address: Hex): Promise<import("axios").AxiosResponse<any, any, {}>>;
29
29
  grantees(): Promise<import("axios").AxiosResponse<{
30
30
  [key: `0x${string}`]: {
31
31
  grants: number;
32
32
  projects: number;
33
33
  };
34
- }, any>>;
34
+ }, any, {}>>;
35
35
  /**
36
36
  * Grant
37
37
  */
38
- grantsOf(grantee: Hex, withCommunity?: boolean): Promise<import("axios").AxiosResponse<IGrantResponse[], any>>;
39
- grantsFor(uid: string, withCommunity?: boolean): Promise<import("axios").AxiosResponse<IGrantResponse[], any>>;
40
- grantsForExtProject(projectExtId: string): Promise<import("axios").AxiosResponse<IGrantResponse[], any>>;
41
- grantBySlug(slug: Hex): Promise<import("axios").AxiosResponse<IGrantResponse, any>>;
38
+ grantsOf(grantee: Hex, withCommunity?: boolean): Promise<import("axios").AxiosResponse<IGrantResponse[], any, {}>>;
39
+ grantsFor(uid: string, withCommunity?: boolean): Promise<import("axios").AxiosResponse<IGrantResponse[], any, {}>>;
40
+ grantsForExtProject(projectExtId: string): Promise<import("axios").AxiosResponse<IGrantResponse[], any, {}>>;
41
+ grantBySlug(slug: Hex): Promise<import("axios").AxiosResponse<IGrantResponse, any, {}>>;
42
42
  grantsByCommunity(uid: Hex, page?: number, pageLimit?: number): Promise<import("axios").AxiosResponse<{
43
43
  data: IGrantResponse[];
44
- }, any>>;
44
+ }, any, {}>>;
45
45
  /**
46
46
  * Milestone
47
47
  */
48
- milestonesOf(uid: Hex): Promise<import("axios").AxiosResponse<any, any>>;
48
+ milestonesOf(uid: Hex): Promise<import("axios").AxiosResponse<any, any, {}>>;
49
49
  slugExists(slug: string): Promise<boolean>;
50
50
  /**
51
51
  * Tracks
52
52
  */
53
- getTracks(communityUID: string, includeArchived?: boolean): Promise<import("axios").AxiosResponse<ITrackResponse[], any>>;
54
- getTrackById(id: string): Promise<import("axios").AxiosResponse<ITrackResponse, any>>;
53
+ getTracks(communityUID: string, includeArchived?: boolean): Promise<import("axios").AxiosResponse<ITrackResponse[], any, {}>>;
54
+ getTrackById(id: string): Promise<import("axios").AxiosResponse<ITrackResponse, any, {}>>;
55
55
  createTrack(data: {
56
56
  name: string;
57
57
  description?: string;
58
58
  communityUID: string;
59
- }): Promise<import("axios").AxiosResponse<ITrackResponse, any>>;
59
+ }): Promise<import("axios").AxiosResponse<ITrackResponse, any, {}>>;
60
60
  updateTrack(id: string, data: {
61
61
  name?: string;
62
62
  description?: string;
63
63
  communityUID?: string;
64
- }): Promise<import("axios").AxiosResponse<ITrackResponse, any>>;
65
- archiveTrack(id: string): Promise<import("axios").AxiosResponse<ITrackResponse, any>>;
66
- assignTracksToProgram(programId: string, trackIds: string[]): Promise<import("axios").AxiosResponse<ITrackAssignmentResponse[], any>>;
67
- unassignTrackFromProgram(programId: string, trackId: string): Promise<import("axios").AxiosResponse<ITrackAssignmentResponse, any>>;
68
- getTracksForProgram(programId: string): Promise<import("axios").AxiosResponse<ITrackResponse[], any>>;
69
- getTracksForProject(projectId: string, programId: string, activeOnly?: boolean): Promise<import("axios").AxiosResponse<ITrackResponse[], any>>;
70
- assignTracksToProject(projectId: string, programId: string, trackIds: string[]): Promise<import("axios").AxiosResponse<any[], any>>;
71
- unassignTracksFromProject(projectId: string, programId: string, trackIds: string[]): Promise<import("axios").AxiosResponse<any[], any>>;
72
- getProjectsByTrack(communityId: string, programId: string, trackId?: string): Promise<import("axios").AxiosResponse<IProjectTrackResponse[], any>>;
64
+ }): Promise<import("axios").AxiosResponse<ITrackResponse, any, {}>>;
65
+ archiveTrack(id: string): Promise<import("axios").AxiosResponse<ITrackResponse, any, {}>>;
66
+ assignTracksToProgram(programId: string, trackIds: string[]): Promise<import("axios").AxiosResponse<ITrackAssignmentResponse[], any, {}>>;
67
+ unassignTrackFromProgram(programId: string, trackId: string): Promise<import("axios").AxiosResponse<ITrackAssignmentResponse, any, {}>>;
68
+ getTracksForProgram(programId: string): Promise<import("axios").AxiosResponse<ITrackResponse[], any, {}>>;
69
+ getTracksForProject(projectId: string, programId: string, activeOnly?: boolean): Promise<import("axios").AxiosResponse<ITrackResponse[], any, {}>>;
70
+ assignTracksToProject(projectId: string, programId: string, trackIds: string[]): Promise<import("axios").AxiosResponse<any[], any, {}>>;
71
+ unassignTracksFromProject(projectId: string, programId: string, trackIds: string[]): Promise<import("axios").AxiosResponse<any[], any, {}>>;
72
+ getProjectsByTrack(communityId: string, programId: string, trackId?: string): Promise<import("axios").AxiosResponse<IProjectTrackResponse[], any, {}>>;
73
73
  }
@@ -146,7 +146,8 @@ export interface IGrantDetails extends IAttestationResponse {
146
146
  query: string;
147
147
  explanation: string;
148
148
  }[];
149
- startDate: number;
149
+ startDate?: number;
150
+ receivedDate?: number;
150
151
  programId?: string;
151
152
  type: "grant-details";
152
153
  fundUsage?: string;
@@ -48,6 +48,7 @@ export interface IGrantDetails {
48
48
  questions?: IGrantDetailsQuestion[];
49
49
  type?: string;
50
50
  startDate?: number;
51
+ receivedDate?: number;
51
52
  programId?: string;
52
53
  fundUsage?: string;
53
54
  selectedTrackIds?: string[];
@@ -65,6 +66,7 @@ export declare class GrantDetails extends Attestation<IGrantDetails> implements
65
66
  questions?: IGrantDetailsQuestion[];
66
67
  type: string;
67
68
  startDate?: number;
69
+ receivedDate?: number;
68
70
  fundUsage?: string;
69
71
  selectedTrackIds?: string[];
70
72
  }
package/core/consts.js CHANGED
@@ -43,7 +43,6 @@ exports.Networks = {
43
43
  optimism: {
44
44
  chainId: 10,
45
45
  url: "https://optimism.easscan.org/graphql",
46
- rpcUrl: "https://opt-mainnet.g.alchemy.com/v2/fx2SlVDrPbXwPMQT4v0lRT1PABA16Myl",
47
46
  contracts: {
48
47
  eas: "0x4200000000000000000000000000000000000021",
49
48
  schema: "0x4200000000000000000000000000000000000020",
@@ -98,7 +97,6 @@ exports.Networks = {
98
97
  "optimism-sepolia": {
99
98
  chainId: 11155420,
100
99
  url: "https://optimism-sepolia.easscan.org/graphql",
101
- rpcUrl: "https://opt-sepolia.g.alchemy.com/v2/9FEqTNKmgO7X7ll92ALJrEih7Jjhldf-",
102
100
  contracts: {
103
101
  communityResolver: "0xa5B7bbFD545A1a816aa8cBE28a1F0F2Cca58363d",
104
102
  eas: "0x4200000000000000000000000000000000000021",
@@ -153,7 +151,6 @@ exports.Networks = {
153
151
  arbitrum: {
154
152
  chainId: 42161,
155
153
  url: "https://arbitrum.easscan.org/graphql",
156
- rpcUrl: "https://arb-mainnet.g.alchemy.com/v2/okcKBSKXvLuSCbas6QWGvKuh-IcHHSOr",
157
154
  contracts: {
158
155
  eas: "0xbD75f629A22Dc1ceD33dDA0b68c546A1c035c458",
159
156
  schema: "0xA310da9c5B885E7fb3fbA9D66E9Ba6Df512b78eB",
@@ -208,7 +205,6 @@ exports.Networks = {
208
205
  sepolia: {
209
206
  chainId: 11155111,
210
207
  url: "https://sepolia.easscan.org/graphql",
211
- rpcUrl: "https://eth-sepolia.g.alchemy.com/v2/_M6YQg_DoVKuMisaFHSVZL-EcdkTbhUi",
212
208
  contracts: {
213
209
  eas: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e",
214
210
  schema: "0x0a7E2Ff54e76B8E6659aedc9103FB21c038050D0",
@@ -237,7 +233,6 @@ exports.Networks = {
237
233
  "base-sepolia": {
238
234
  chainId: 84532,
239
235
  url: "https://base-sepolia.easscan.org/graphql",
240
- rpcUrl: "https://sepolia.base.org",
241
236
  contracts: {
242
237
  eas: "0x4200000000000000000000000000000000000021",
243
238
  schema: "0x4200000000000000000000000000000000000020",
@@ -265,7 +260,6 @@ exports.Networks = {
265
260
  celo: {
266
261
  chainId: 42220,
267
262
  url: "https://celo.easscan.org/graphql",
268
- rpcUrl: "https://forno.celo.org",
269
263
  contracts: {
270
264
  eas: "0x72E1d8ccf5299fb36fEfD8CC4394B8ef7e98Af92",
271
265
  schema: "0x5ece93bE4BDCF293Ed61FA78698B594F2135AF34",
@@ -320,7 +314,6 @@ exports.Networks = {
320
314
  sei: {
321
315
  chainId: 1329,
322
316
  url: "https://sei.easscan.org/graphql",
323
- rpcUrl: "https://muddy-orbital-arrow.sei-pacific.quiknode.pro/594552c3ab4ed4106b40402c16dba137ab279d40",
324
317
  contracts: {
325
318
  eas: "0x391020888b0adBA584A67693458b374e4141f838",
326
319
  schema: "0x80A4B50f549a8271e10A6C8e79172cb56f35fD57",
@@ -375,7 +368,6 @@ exports.Networks = {
375
368
  "sei-testnet": {
376
369
  chainId: 1328,
377
370
  url: "https://sei-testnet.easscan.org/graphql",
378
- rpcUrl: "https://evm-rpc-testnet.sei-apis.com",
379
371
  contracts: {
380
372
  eas: "0x4F166ed0A038ECdEEefa7Dc508f15991762974Fe",
381
373
  schema: "0x906a57aCa067178e76e6eBDF4C7b26CBcAEC0Edd",
@@ -403,7 +395,6 @@ exports.Networks = {
403
395
  lisk: {
404
396
  chainId: 1135,
405
397
  url: "https://lisk.easscan.org/graphql",
406
- rpcUrl: "https://lisk.drpc.org",
407
398
  contracts: {
408
399
  eas: "0x4200000000000000000000000000000000000021",
409
400
  schema: "0x4200000000000000000000000000000000000020",
@@ -431,7 +422,6 @@ exports.Networks = {
431
422
  scroll: {
432
423
  chainId: 534352,
433
424
  url: "https://scroll.easscan.org/graphql",
434
- rpcUrl: "https://scroll-mainnet.g.alchemy.com/v2/SsQRSwtqtBMGmXQCDH9lYb4U8p9QnqXK",
435
425
  contracts: {
436
426
  eas: "0xC47300428b6AD2c7D03BB76D05A176058b47E6B0",
437
427
  schema: "0xD2CDF46556543316e7D34e8eDc4624e2bB95e3B6",
@@ -459,7 +449,6 @@ exports.Networks = {
459
449
  "base": {
460
450
  chainId: 8453,
461
451
  url: "https://base.easscan.org/graphql",
462
- rpcUrl: "https://mainnet.base.org",
463
452
  contracts: {
464
453
  eas: "0x4200000000000000000000000000000000000021",
465
454
  schema: "0x4200000000000000000000000000000000000020",
@@ -487,7 +476,6 @@ exports.Networks = {
487
476
  "polygon": {
488
477
  chainId: 137,
489
478
  url: "https://polygon.easscan.org/graphql",
490
- rpcUrl: "https://polygon-rpc.com/",
491
479
  contracts: {
492
480
  eas: "0x5E634ef5355f45A855d02D66eCD687b1502AF790",
493
481
  schema: "0x7876EEF51A891E737AF8ba5A5E0f0Fd29073D5a7",
package/core/types.d.ts CHANGED
@@ -31,6 +31,24 @@ export type TSchemaName = "Community" | "CommunityDetails" | "Grant" | "GrantDet
31
31
  export type TResolvedSchemaNames = "Community" | "Grant" | "GrantVerified" | "MemberOf" | "MilestoneCompleted" | "MilestoneApproved" | "Project" | "Details" | "ProjectUpdateStatus" | "GrantUpdateStatus" | "ProjectUpdateStatus" | "ProjectMilestoneStatus" | "ContributorProfile";
32
32
  export type TExternalLink = "twitter" | "github" | "website" | "linkedin" | "discord" | "pitchDeck" | "demoVideo" | "farcaster" | "custom";
33
33
  export type TNetwork = "optimism" | "celo" | "optimism-sepolia" | "arbitrum" | "sepolia" | "sei" | "sei-testnet" | "base-sepolia" | "lisk" | "scroll" | "base" | "polygon";
34
+ /**
35
+ * Supported chain IDs for GAP SDK networks
36
+ */
37
+ export type SupportedChainId = 10 | 11155420 | 42161 | 11155111 | 84532 | 42220 | 1328 | 1329 | 1135 | 534352 | 8453 | 137;
38
+ /**
39
+ * RPC configuration for GAP SDK.
40
+ * Maps chain IDs to RPC URLs.
41
+ * Only configure the networks you need to use.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * const rpcUrls: GAPRpcConfig = {
46
+ * 10: "https://opt-mainnet.g.alchemy.com/v2/YOUR_KEY",
47
+ * 42161: "https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY",
48
+ * };
49
+ * ```
50
+ */
51
+ export type GAPRpcConfig = Partial<Record<SupportedChainId, string>>;
34
52
  /**
35
53
  * Generic GAP Facade interface.
36
54
  * This supplies the GAP class with the necessary properties.
@@ -61,7 +79,6 @@ export interface MultiAttestData {
61
79
  export type MultiAttestPayload = [Attestation, RawMultiAttestPayload][];
62
80
  export interface EASNetworkConfig {
63
81
  url: string;
64
- rpcUrl: string;
65
82
  chainId: number;
66
83
  contracts: {
67
84
  eas: Hex;
@@ -116,16 +133,3 @@ export interface SchemaRes {
116
133
  attestations: IAttestation[];
117
134
  };
118
135
  }
119
- /**
120
- * Valid remote storage types
121
- */
122
- export declare const enum STORAGE_TYPE {
123
- IPFS = 0,
124
- ARWEAVE = 1,
125
- SWARM = 2,
126
- UNKNOWN = 3
127
- }
128
- export type TRemoteStorageOutput<T = unknown> = {
129
- hash: T;
130
- storageType: number;
131
- };
@@ -1,2 +1,17 @@
1
1
  import { ethers } from "ethers";
2
- export declare const getWeb3Provider: (chainId: number) => ethers.JsonRpcProvider;
2
+ import { GAPRpcConfig } from "../types";
3
+ /**
4
+ * Get a Web3 provider for a specific chain ID using the provided RPC configuration.
5
+ *
6
+ * @param chainId - The chain ID to get a provider for
7
+ * @param config - RPC URL configuration mapping chain IDs to RPC URLs
8
+ * @returns An ethers JsonRpcProvider for the specified chain
9
+ * @throws Error if no RPC URL is configured for the chain ID or if the URL is invalid
10
+ */
11
+ export declare const getWeb3Provider: (chainId: number, config: GAPRpcConfig) => ethers.JsonRpcProvider;
12
+ /**
13
+ * Clear all cached providers.
14
+ * Useful for testing or when reconfiguring the SDK.
15
+ * @internal - This is an internal function, not part of the public API.
16
+ */
17
+ export declare const clearProviderCache: () => void;
@@ -1,18 +1,58 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getWeb3Provider = void 0;
4
- const consts_1 = require("../consts");
3
+ exports.clearProviderCache = exports.getWeb3Provider = void 0;
5
4
  const ethers_1 = require("ethers");
6
- const providers = {};
7
- const getWeb3Provider = (chainId) => {
8
- const rpcUrl = Object.values(consts_1.Networks).find((n) => n.chainId === chainId)
9
- ?.rpcUrl;
5
+ /**
6
+ * Global provider cache keyed by "chainId:rpcUrl" to allow caching
7
+ * while supporting different RPC URLs for the same chain.
8
+ */
9
+ const providers = new Map();
10
+ /**
11
+ * Validate that a string is a valid URL.
12
+ * @internal
13
+ */
14
+ const isValidUrl = (url) => {
15
+ try {
16
+ new URL(url);
17
+ return true;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ };
23
+ /**
24
+ * Get a Web3 provider for a specific chain ID using the provided RPC configuration.
25
+ *
26
+ * @param chainId - The chain ID to get a provider for
27
+ * @param config - RPC URL configuration mapping chain IDs to RPC URLs
28
+ * @returns An ethers JsonRpcProvider for the specified chain
29
+ * @throws Error if no RPC URL is configured for the chain ID or if the URL is invalid
30
+ */
31
+ const getWeb3Provider = (chainId, config) => {
32
+ const rpcUrl = config[chainId];
10
33
  if (!rpcUrl) {
11
- throw new Error(`No rpcUrl found for chainId ${chainId}`);
34
+ throw new Error(`RPC URL not configured for chain ${chainId}. ` +
35
+ `Please provide an RPC URL in the rpcUrls configuration when initializing GAP.`);
12
36
  }
13
- if (!providers[chainId]) {
14
- providers[chainId] = new ethers_1.ethers.JsonRpcProvider(rpcUrl);
37
+ if (!isValidUrl(rpcUrl)) {
38
+ throw new Error(`Invalid RPC URL for chain ${chainId}: "${rpcUrl}". ` +
39
+ `Please provide a valid URL (e.g., "https://mainnet.infura.io/v3/YOUR_KEY").`);
15
40
  }
16
- return providers[chainId];
41
+ const cacheKey = `${chainId}:${rpcUrl}`;
42
+ let provider = providers.get(cacheKey);
43
+ if (!provider) {
44
+ provider = new ethers_1.ethers.JsonRpcProvider(rpcUrl);
45
+ providers.set(cacheKey, provider);
46
+ }
47
+ return provider;
17
48
  };
18
49
  exports.getWeb3Provider = getWeb3Provider;
50
+ /**
51
+ * Clear all cached providers.
52
+ * Useful for testing or when reconfiguring the SDK.
53
+ * @internal - This is an internal function, not part of the public API.
54
+ */
55
+ const clearProviderCache = () => {
56
+ providers.clear();
57
+ };
58
+ exports.clearProviderCache = clearProviderCache;
@@ -1,7 +1,7 @@
1
1
  export * from './gelato';
2
2
  export * from './get-date';
3
+ export { clearProviderCache } from './get-web3-provider';
3
4
  export * from './gql-queries';
4
5
  export * from './map-filter';
5
6
  export * from './serialize-bigint';
6
7
  export * from './to-unix';
7
- export * from './get-ipfs-data';
@@ -14,10 +14,14 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.clearProviderCache = void 0;
17
18
  __exportStar(require("./gelato"), exports);
18
19
  __exportStar(require("./get-date"), exports);
20
+ // Note: get-web3-provider functions are internal. Use gap.getProvider() instead.
21
+ // clearProviderCache is exported only for testing purposes.
22
+ var get_web3_provider_1 = require("./get-web3-provider");
23
+ Object.defineProperty(exports, "clearProviderCache", { enumerable: true, get: function () { return get_web3_provider_1.clearProviderCache; } });
19
24
  __exportStar(require("./gql-queries"), exports);
20
25
  __exportStar(require("./map-filter"), exports);
21
26
  __exportStar(require("./serialize-bigint"), exports);
22
27
  __exportStar(require("./to-unix"), exports);
23
- __exportStar(require("./get-ipfs-data"), exports);
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.4.19",
6
+ "version": "0.4.21",
7
7
  "description": "Simple and easy interface between EAS and Karma GAP.",
8
8
  "main": "./index.js",
9
9
  "author": "KarmaHQ",
@@ -14,6 +14,8 @@
14
14
  "type": "git"
15
15
  },
16
16
  "scripts": {
17
+ "build": "tsc -p tsconfig.json",
18
+ "test": "npx tsc -p tsconfig.json --noEmit",
17
19
  "deploy": "npx ts-node ./core/scripts/deploy.ts",
18
20
  "csv-upload": "npx ts-node ./csv-upload/scripts/run.ts",
19
21
  "test-file": "npx ts-node ./test-file-indexer-api.ts",
@@ -1,23 +0,0 @@
1
- import { RemoteStorage } from "./RemoteStorage";
2
- import { TRemoteStorageOutput } from "core/types";
3
- export interface IpfsStorageOptions {
4
- token: string;
5
- }
6
- export declare class IpfsStorage extends RemoteStorage {
7
- private pinataJWTToken;
8
- constructor(opts: IpfsStorageOptions,
9
- /**
10
- * If set, will send request to another server instead of
11
- * using the local instance
12
- */
13
- sponsor?: RemoteStorage["sponsor"]);
14
- private assert;
15
- save<T = unknown>(data: T): Promise<string>;
16
- encode(data: string): TRemoteStorageOutput<string>;
17
- get<T = unknown>(args: {
18
- cid: string;
19
- }): Promise<T>;
20
- saveAndGetCID(data: any, pinataMetadata?: {
21
- name: string;
22
- }): Promise<any>;
23
- }
@@ -1,56 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.IpfsStorage = void 0;
7
- const RemoteStorage_1 = require("./RemoteStorage");
8
- const SchemaError_1 = require("../SchemaError");
9
- const utils_1 = require("../../utils");
10
- const axios_1 = __importDefault(require("axios"));
11
- class IpfsStorage extends RemoteStorage_1.RemoteStorage {
12
- constructor(opts,
13
- /**
14
- * If set, will send request to another server instead of
15
- * using the local instance
16
- */
17
- sponsor) {
18
- super(0 /* STORAGE_TYPE.IPFS */, sponsor);
19
- this.assert(opts);
20
- this.pinataJWTToken = opts.token;
21
- }
22
- assert(opts) { }
23
- async save(data) {
24
- try {
25
- const cid = await this.saveAndGetCID(data);
26
- return cid;
27
- }
28
- catch (error) {
29
- throw new SchemaError_1.RemoteStorageError("REMOTE_STORAGE_UPLOAD", `Error adding data to IPFS`);
30
- }
31
- }
32
- encode(data) {
33
- return { hash: data, storageType: this.storageType };
34
- }
35
- async get(args) {
36
- return (0, utils_1.getIPFSData)(args.cid);
37
- }
38
- async saveAndGetCID(data, pinataMetadata = { name: "via karma-gap-sdk" }) {
39
- try {
40
- const res = await axios_1.default.post("https://api.pinata.cloud/pinning/pinJSONToIPFS", {
41
- pinataContent: data,
42
- pinataMetadata: pinataMetadata,
43
- }, {
44
- headers: {
45
- "Content-Type": "application/json",
46
- Authorization: `Bearer ${this.pinataJWTToken}`,
47
- },
48
- });
49
- return res.data.IpfsHash;
50
- }
51
- catch (error) {
52
- throw new SchemaError_1.RemoteStorageError("REMOTE_STORAGE_UPLOAD", `Error adding data to IPFS`);
53
- }
54
- }
55
- }
56
- exports.IpfsStorage = IpfsStorage;
@@ -1,41 +0,0 @@
1
- import { STORAGE_TYPE, TRemoteStorageOutput } from 'core/types';
2
- interface SponsoredRemote {
3
- url: string;
4
- responseParser: (response: any) => string;
5
- }
6
- export declare abstract class RemoteStorage<C = unknown> {
7
- protected client: C;
8
- readonly storageType: number;
9
- readonly sponsor?: SponsoredRemote;
10
- constructor(storageType: STORAGE_TYPE,
11
- /**
12
- * If set, will try to POST request to another server instead of
13
- * using the local instance.
14
- *
15
- * > If a response parser is not set, it will try to get { cid: string }.
16
- */
17
- sponsor: SponsoredRemote);
18
- /**
19
- * Try to save data to remote storage and return the CID.
20
- * IF sponsorUrl is set, this method will be automatically
21
- * intercepted and will send a POST request to the sponsorUrl
22
- * with the contents: `{ data: T, type: "<AttestationType>" }`
23
- */
24
- abstract save<T = unknown>(data: T, schemaName: string): Promise<string>;
25
- /**
26
- * Encodes the data according to the remote storage type parameters
27
- * OR returns the data as is if no encoding is required
28
- */
29
- abstract encode(data: unknown): TRemoteStorageOutput;
30
- /**
31
- * Get data from Remote Storage
32
- */
33
- abstract get<T = unknown>(args: unknown): Promise<T>;
34
- /**
35
- * If sponsorUrl is set, intercept the save method and send a POST request
36
- * to the sponsorUrl instead of using the local instance.
37
- * @returns
38
- */
39
- private interceptRemoteStorage;
40
- }
41
- export {};
@@ -1,38 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.RemoteStorage = void 0;
7
- const axios_1 = __importDefault(require("axios"));
8
- class RemoteStorage {
9
- constructor(storageType,
10
- /**
11
- * If set, will try to POST request to another server instead of
12
- * using the local instance.
13
- *
14
- * > If a response parser is not set, it will try to get { cid: string }.
15
- */
16
- sponsor) {
17
- this.storageType = storageType;
18
- this.sponsor = sponsor;
19
- this.interceptRemoteStorage();
20
- }
21
- /**
22
- * If sponsorUrl is set, intercept the save method and send a POST request
23
- * to the sponsorUrl instead of using the local instance.
24
- * @returns
25
- */
26
- interceptRemoteStorage() {
27
- if (!this.sponsor?.url)
28
- return;
29
- this.save = async (data, schemaName) => {
30
- const { data: response } = await axios_1.default.post(this.sponsor.url, {
31
- data: data,
32
- type: schemaName,
33
- });
34
- return this.sponsor.responseParser?.(response) || response.cid;
35
- };
36
- }
37
- }
38
- exports.RemoteStorage = RemoteStorage;
@@ -1 +0,0 @@
1
- export declare function getIPFSData<T>(cid: string): Promise<T>;
@@ -1,19 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getIPFSData = getIPFSData;
7
- const axios_1 = __importDefault(require("axios"));
8
- async function getIPFSData(cid) {
9
- try {
10
- const { data } = await axios_1.default.get(`https://ipfs.io/ipfs/${cid}`, {
11
- timeout: 5000,
12
- });
13
- return data;
14
- }
15
- catch (err) {
16
- console.error(err);
17
- throw new Error(`Error to retrive data for CID: ${cid}`);
18
- }
19
- }