@show-karma/karma-gap-sdk 0.4.27 → 0.4.29

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.
@@ -30,6 +30,7 @@ export declare class Milestone extends Attestation<IMilestone> implements IMiles
30
30
  completed: MilestoneCompleted;
31
31
  approved: MilestoneCompleted;
32
32
  rejected: MilestoneCompleted;
33
+ cancelled: MilestoneCompleted;
33
34
  verified: MilestoneCompleted[];
34
35
  type: string;
35
36
  priority?: number;
@@ -93,6 +94,23 @@ export declare class Milestone extends Attestation<IMilestone> implements IMiles
93
94
  tx: Transaction[];
94
95
  uids: `0x${string}`[];
95
96
  }>;
97
+ /**
98
+ * Cancels this milestone. A cancelled milestone will not be delivered and is
99
+ * kept, badged "cancelled", for the program's records. Only milestones that
100
+ * are not yet completed or verified can be cancelled.
101
+ * @param signer
102
+ * @param reason
103
+ */
104
+ cancel(signer: SignerOrProvider, reason?: string, callback?: Function): Promise<AttestationWithTx>;
105
+ /**
106
+ * Revokes the cancelled status of the milestone (un-cancel). If the milestone
107
+ * is not cancelled, it will throw an error.
108
+ * @param signer
109
+ */
110
+ revokeCancel(signer: SignerOrProvider): Promise<{
111
+ tx: Transaction[];
112
+ uids: `0x${string}`[];
113
+ }>;
96
114
  /**
97
115
  * Revokes multiple milestone attestations at once.
98
116
  * This method can be used to revoke multiple milestone attestations in a single transaction.
@@ -31,7 +31,7 @@ class Milestone extends Attestation_1.Attestation {
31
31
  * @param callback - Optional callback function for status updates
32
32
  */
33
33
  async edit(signer, newData, callback) {
34
- if (this.completed || this.approved || this.verified?.length) {
34
+ if (this.completed || this.approved || this.verified?.length || this.cancelled) {
35
35
  throw new SchemaError_1.AttestationError("ATTEST_ERROR", "Cannot edit milestone that is not in PENDING state");
36
36
  }
37
37
  // Step 1: Revoke current attestation
@@ -216,6 +216,55 @@ class Milestone extends Attestation_1.Attestation {
216
216
  ]);
217
217
  return { tx, uids };
218
218
  }
219
+ /**
220
+ * Cancels this milestone. A cancelled milestone will not be delivered and is
221
+ * kept, badged "cancelled", for the program's records. Only milestones that
222
+ * are not yet completed or verified can be cancelled.
223
+ * @param signer
224
+ * @param reason
225
+ */
226
+ async cancel(signer, reason = "", callback) {
227
+ if (this.completed || this.verified?.length)
228
+ throw new SchemaError_1.AttestationError("ATTEST_ERROR", "Cannot cancel a completed or verified milestone");
229
+ if (this.cancelled)
230
+ throw new SchemaError_1.AttestationError("ATTEST_ERROR", "Milestone is already cancelled");
231
+ const schema = this.schema.gap.findSchema("MilestoneCompleted");
232
+ if (this.schema.isJsonSchema()) {
233
+ schema.setValue("json", JSON.stringify({ type: "cancelled", reason }));
234
+ }
235
+ else {
236
+ schema.setValue("type", "cancelled");
237
+ schema.setValue("reason", reason);
238
+ }
239
+ const { tx, uids } = await this.attestStatus(signer, schema, callback);
240
+ this.cancelled = new attestations_1.MilestoneCompleted({
241
+ data: {
242
+ type: "cancelled",
243
+ reason,
244
+ },
245
+ refUID: this.uid,
246
+ uid: uids?.[0],
247
+ schema: schema,
248
+ recipient: this.recipient,
249
+ });
250
+ return { tx, uids };
251
+ }
252
+ /**
253
+ * Revokes the cancelled status of the milestone (un-cancel). If the milestone
254
+ * is not cancelled, it will throw an error.
255
+ * @param signer
256
+ */
257
+ async revokeCancel(signer) {
258
+ if (!this.cancelled)
259
+ throw new SchemaError_1.AttestationError("ATTEST_ERROR", "Milestone is not cancelled");
260
+ const { tx, uids } = await this.cancelled.schema.multiRevoke(signer, [
261
+ {
262
+ schemaId: this.cancelled.schema.uid,
263
+ uid: this.cancelled.uid,
264
+ },
265
+ ]);
266
+ return { tx, uids };
267
+ }
219
268
  /**
220
269
  * Revokes multiple milestone attestations at once.
221
270
  * This method can be used to revoke multiple milestone attestations in a single transaction.
@@ -589,6 +638,16 @@ class Milestone extends Attestation_1.Attestation {
589
638
  chainID: attestation.chainID,
590
639
  });
591
640
  }
641
+ if (attestation.cancelled) {
642
+ milestone.cancelled = new attestations_1.MilestoneCompleted({
643
+ ...attestation.cancelled,
644
+ data: {
645
+ ...attestation.cancelled.data,
646
+ },
647
+ schema: new AllGapSchemas_1.AllGapSchemas().findSchema("MilestoneCompleted", consts_1.chainIdToNetwork[attestation.chainID]),
648
+ chainID: attestation.chainID,
649
+ });
650
+ }
592
651
  if (attestation.verified?.length > 0) {
593
652
  milestone.verified = attestation.verified.map((m) => new attestations_1.MilestoneCompleted({
594
653
  ...m,
@@ -50,6 +50,7 @@ export interface IMilestoneResponse extends IAttestationResponse {
50
50
  completed?: IMilestoneCompleted;
51
51
  approved?: IMilestoneCompleted;
52
52
  rejected?: IMilestoneCompleted;
53
+ cancelled?: IMilestoneCompleted;
53
54
  verified?: IMilestoneCompleted[];
54
55
  data: {
55
56
  title: string;
@@ -91,12 +91,12 @@ export declare class MemberDetails extends Attestation<IMemberDetails> implement
91
91
  profilePictureURL: string;
92
92
  }
93
93
  export interface IMilestoneCompleted {
94
- type?: "approved" | "rejected" | "completed" | "verified";
94
+ type?: "approved" | "rejected" | "completed" | "verified" | "cancelled";
95
95
  reason?: string;
96
96
  proofOfWork?: string;
97
97
  }
98
98
  export declare class MilestoneCompleted extends Attestation<IMilestoneCompleted> implements IMilestoneCompleted {
99
- type: "approved" | "rejected" | "completed" | "verified";
99
+ type: "approved" | "rejected" | "completed" | "verified" | "cancelled";
100
100
  reason?: string;
101
101
  proofOfWork?: string;
102
102
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.4.27",
6
+ "version": "0.4.29",
7
7
  "description": "Simple and easy interface between EAS and Karma.",
8
8
  "main": "./index.js",
9
9
  "author": "KarmaHQ",
@@ -1,20 +0,0 @@
1
- /**
2
- * Tests for Milestone.edit() and Milestone.editCompletion() convenience methods.
3
- *
4
- * Phase 3: edit() performs revoke-and-re-attest for milestone definitions:
5
- * 1. Guard: only PENDING milestones (no completed, approved, or verified)
6
- * 2. Revoke the current attestation via this.revoke()
7
- * 3. Update data via this.setValues() (merges old + new fields)
8
- * 4. Re-attest via this.attest()
9
- *
10
- * Phase 4: editCompletion() performs revoke-and-re-complete for completed milestones:
11
- * 1. Guard: must be COMPLETED but not APPROVED or VERIFIED
12
- * 2. Revoke current completion via this.revokeCompletion()
13
- * 3. Re-complete with updated data via this.complete()
14
- *
15
- * Since the SDK has no Jest config, these tests define the behavioral contract.
16
- * They simulate the methods' behavior to validate the expected flow without
17
- * requiring the full EAS/blockchain dependency chain. When a Jest config is added,
18
- * they will become directly runnable.
19
- */
20
- export {};
@@ -1,328 +0,0 @@
1
- "use strict";
2
- /**
3
- * Tests for Milestone.edit() and Milestone.editCompletion() convenience methods.
4
- *
5
- * Phase 3: edit() performs revoke-and-re-attest for milestone definitions:
6
- * 1. Guard: only PENDING milestones (no completed, approved, or verified)
7
- * 2. Revoke the current attestation via this.revoke()
8
- * 3. Update data via this.setValues() (merges old + new fields)
9
- * 4. Re-attest via this.attest()
10
- *
11
- * Phase 4: editCompletion() performs revoke-and-re-complete for completed milestones:
12
- * 1. Guard: must be COMPLETED but not APPROVED or VERIFIED
13
- * 2. Revoke current completion via this.revokeCompletion()
14
- * 3. Re-complete with updated data via this.complete()
15
- *
16
- * Since the SDK has no Jest config, these tests define the behavioral contract.
17
- * They simulate the methods' behavior to validate the expected flow without
18
- * requiring the full EAS/blockchain dependency chain. When a Jest config is added,
19
- * they will become directly runnable.
20
- */
21
- Object.defineProperty(exports, "__esModule", { value: true });
22
- // ---------------------------------------------------------------------------
23
- // Phase 3: Milestone.edit()
24
- // ---------------------------------------------------------------------------
25
- describe("Milestone.edit()", () => {
26
- let mockSigner;
27
- beforeEach(() => {
28
- mockSigner = {};
29
- });
30
- /**
31
- * Creates a test milestone simulating the real Milestone class behavior.
32
- * Uses revoke() + setValues() + attest() internally, matching the actual
33
- * implementation in core/class/entities/Milestone.ts.
34
- */
35
- function createTestMilestone(overrides) {
36
- const revokeMock = jest.fn().mockResolvedValue({ tx: {}, uids: [] });
37
- const attestMock = jest.fn().mockResolvedValue({
38
- tx: { hash: "0xTxHash" },
39
- uids: ["0xNewUID"]
40
- });
41
- const setValuesMock = jest.fn();
42
- const milestone = {
43
- uid: "0xOldMilestoneUID",
44
- title: "Original Title",
45
- description: "Original Description",
46
- endsAt: 1735689600,
47
- startsAt: 1704067200,
48
- type: "milestone",
49
- completed: overrides?.completed || undefined,
50
- approved: overrides?.approved || undefined,
51
- verified: overrides?.verified || [],
52
- recipient: "0xRecipient",
53
- data: {
54
- title: "Original Title",
55
- description: "Original Description",
56
- endsAt: 1735689600,
57
- startsAt: 1704067200
58
- },
59
- // Mock methods matching real Attestation class
60
- revoke: revokeMock,
61
- attest: attestMock,
62
- setValues: setValuesMock,
63
- // Expose mocks for assertions
64
- _mocks: { revoke: revokeMock, attest: attestMock, setValues: setValuesMock }
65
- };
66
- // Simulate the edit method matching the real implementation
67
- milestone.edit = async function (signer, newData, callback) {
68
- // Guard: only PENDING milestones
69
- if (this.completed || this.approved || (this.verified && this.verified.length > 0)) {
70
- throw new Error("Cannot edit milestone that is not in PENDING state");
71
- }
72
- // Step 1: Revoke current attestation
73
- await this.revoke(signer, callback);
74
- // Step 2: Update data with new fields
75
- const updatedData = { ...this.data, ...newData };
76
- this.setValues(updatedData);
77
- // Step 3: Re-attest with updated data
78
- return this.attest(signer, callback);
79
- };
80
- return milestone;
81
- }
82
- describe("successful edit (PENDING milestone)", () => {
83
- it("should call revoke on current attestation, then re-attest", async () => {
84
- const milestone = createTestMilestone();
85
- await milestone.edit(mockSigner, {
86
- title: "Updated Title",
87
- description: "Updated Description"
88
- });
89
- expect(milestone._mocks.revoke).toHaveBeenCalledTimes(1);
90
- expect(milestone._mocks.revoke).toHaveBeenCalledWith(mockSigner, undefined);
91
- expect(milestone._mocks.attest).toHaveBeenCalledTimes(1);
92
- expect(milestone._mocks.attest).toHaveBeenCalledWith(mockSigner, undefined);
93
- });
94
- it("should call setValues with merged data (old + new)", async () => {
95
- const milestone = createTestMilestone();
96
- await milestone.edit(mockSigner, {
97
- title: "New Title"
98
- });
99
- expect(milestone._mocks.setValues).toHaveBeenCalledTimes(1);
100
- expect(milestone._mocks.setValues).toHaveBeenCalledWith(expect.objectContaining({
101
- title: "New Title",
102
- description: "Original Description",
103
- endsAt: 1735689600,
104
- startsAt: 1704067200
105
- }));
106
- });
107
- it("should preserve unchanged fields during partial update", async () => {
108
- const milestone = createTestMilestone();
109
- await milestone.edit(mockSigner, {
110
- title: "New Title Only"
111
- });
112
- const setValuesArg = milestone._mocks.setValues.mock.calls[0][0];
113
- expect(setValuesArg.description).toBe("Original Description");
114
- expect(setValuesArg.endsAt).toBe(1735689600);
115
- expect(setValuesArg.startsAt).toBe(1704067200);
116
- });
117
- it("should update all supported fields when fully provided", async () => {
118
- const milestone = createTestMilestone();
119
- await milestone.edit(mockSigner, {
120
- title: "New Title",
121
- description: "New Description",
122
- endsAt: 1767225600,
123
- startsAt: 1735689600,
124
- priority: 1
125
- });
126
- const setValuesArg = milestone._mocks.setValues.mock.calls[0][0];
127
- expect(setValuesArg.title).toBe("New Title");
128
- expect(setValuesArg.description).toBe("New Description");
129
- expect(setValuesArg.endsAt).toBe(1767225600);
130
- expect(setValuesArg.startsAt).toBe(1735689600);
131
- expect(setValuesArg.priority).toBe(1);
132
- });
133
- it("should return the result from attest()", async () => {
134
- const milestone = createTestMilestone();
135
- const result = await milestone.edit(mockSigner, { title: "New" });
136
- expect(result).toEqual({
137
- tx: { hash: "0xTxHash" },
138
- uids: ["0xNewUID"]
139
- });
140
- });
141
- });
142
- describe("state guards", () => {
143
- it("should throw for COMPLETED milestones", async () => {
144
- const milestone = createTestMilestone({
145
- completed: {
146
- uid: "0xCompletedUID",
147
- data: { type: "completed", reason: "Done" }
148
- }
149
- });
150
- await expect(milestone.edit(mockSigner, { title: "Nope" })).rejects.toThrow("Cannot edit milestone that is not in PENDING state");
151
- expect(milestone._mocks.revoke).not.toHaveBeenCalled();
152
- });
153
- it("should throw for APPROVED milestones", async () => {
154
- const milestone = createTestMilestone({
155
- approved: {
156
- uid: "0xApprovedUID",
157
- data: { type: "approved", reason: "Good" }
158
- }
159
- });
160
- await expect(milestone.edit(mockSigner, { title: "Nope" })).rejects.toThrow("Cannot edit milestone that is not in PENDING state");
161
- });
162
- it("should throw for VERIFIED milestones (verified.length > 0)", async () => {
163
- const milestone = createTestMilestone({
164
- verified: [
165
- {
166
- uid: "0xVerifiedUID",
167
- data: { type: "verified", reason: "Verified" }
168
- }
169
- ]
170
- });
171
- await expect(milestone.edit(mockSigner, { title: "Nope" })).rejects.toThrow("Cannot edit milestone that is not in PENDING state");
172
- });
173
- it("should allow edit when completed/approved/verified are all falsy/empty", async () => {
174
- const milestone = createTestMilestone({
175
- completed: undefined,
176
- approved: undefined,
177
- verified: []
178
- });
179
- await expect(milestone.edit(mockSigner, { title: "Allowed" })).resolves.not.toThrow();
180
- expect(milestone._mocks.revoke).toHaveBeenCalledTimes(1);
181
- expect(milestone._mocks.attest).toHaveBeenCalledTimes(1);
182
- });
183
- });
184
- describe("execution order", () => {
185
- it("should call revoke BEFORE setValues and attest (correct ordering)", async () => {
186
- const callOrder = [];
187
- const milestone = createTestMilestone();
188
- milestone._mocks.revoke.mockImplementation(async () => {
189
- callOrder.push("revoke");
190
- return { tx: {}, uids: [] };
191
- });
192
- milestone._mocks.setValues.mockImplementation(() => {
193
- callOrder.push("setValues");
194
- });
195
- milestone._mocks.attest.mockImplementation(async () => {
196
- callOrder.push("attest");
197
- return { tx: {}, uids: ["0xNew"] };
198
- });
199
- await milestone.edit(mockSigner, {
200
- title: "New"
201
- });
202
- expect(callOrder).toEqual(["revoke", "setValues", "attest"]);
203
- });
204
- });
205
- });
206
- // ---------------------------------------------------------------------------
207
- // Phase 4: Milestone.editCompletion()
208
- // ---------------------------------------------------------------------------
209
- describe("Milestone.editCompletion()", () => {
210
- let mockSigner;
211
- beforeEach(() => {
212
- mockSigner = {};
213
- });
214
- /**
215
- * Creates a test milestone with completion data for testing editCompletion().
216
- */
217
- function createCompletedMilestone(overrides) {
218
- const revokeCompletionMock = jest
219
- .fn()
220
- .mockResolvedValue({ tx: {}, uids: [] });
221
- const completeMock = jest.fn().mockResolvedValue({
222
- tx: { hash: "0xCompletionTxHash" },
223
- uids: ["0xNewCompletionUID"]
224
- });
225
- const milestone = {
226
- uid: "0xMilestoneUID",
227
- completed: {
228
- uid: "0xOldCompletionUID",
229
- data: {
230
- reason: "Original completion reason",
231
- proofOfWork: "https://example.com/original-proof"
232
- }
233
- },
234
- approved: overrides?.approved || undefined,
235
- verified: overrides?.verified || [],
236
- revokeCompletion: revokeCompletionMock,
237
- complete: completeMock,
238
- _mocks: { revokeCompletion: revokeCompletionMock, complete: completeMock }
239
- };
240
- // Simulate editCompletion matching real implementation
241
- milestone.editCompletion = async function (signer, newData, callback) {
242
- if (!this.completed) {
243
- throw new Error("Milestone is not completed");
244
- }
245
- if (this.approved) {
246
- throw new Error("Cannot edit completion of an approved milestone");
247
- }
248
- if (this.verified && this.verified.length > 0) {
249
- throw new Error("Cannot edit completion of a verified milestone");
250
- }
251
- await this.revokeCompletion(signer, callback);
252
- const completionData = {
253
- reason: newData.reason ?? this.completed?.data?.reason ?? "",
254
- proofOfWork: newData.proofOfWork ?? this.completed?.data?.proofOfWork ?? ""
255
- };
256
- return this.complete(signer, completionData, callback);
257
- };
258
- return milestone;
259
- }
260
- describe("successful editCompletion", () => {
261
- it("should revoke old completion and re-complete with updated data", async () => {
262
- const milestone = createCompletedMilestone();
263
- await milestone.editCompletion(mockSigner, {
264
- reason: "Updated completion reason",
265
- proofOfWork: "https://example.com/updated-proof"
266
- });
267
- expect(milestone._mocks.revokeCompletion).toHaveBeenCalledTimes(1);
268
- expect(milestone._mocks.complete).toHaveBeenCalledTimes(1);
269
- expect(milestone._mocks.complete).toHaveBeenCalledWith(mockSigner, {
270
- reason: "Updated completion reason",
271
- proofOfWork: "https://example.com/updated-proof"
272
- }, undefined);
273
- });
274
- it("should preserve unchanged fields from original completion", async () => {
275
- const milestone = createCompletedMilestone();
276
- // Only update reason, proofOfWork should be preserved from original
277
- await milestone.editCompletion(mockSigner, {
278
- reason: "New reason only"
279
- });
280
- expect(milestone._mocks.complete).toHaveBeenCalledWith(mockSigner, {
281
- reason: "New reason only",
282
- proofOfWork: "https://example.com/original-proof"
283
- }, undefined);
284
- });
285
- it("should return the result from complete()", async () => {
286
- const milestone = createCompletedMilestone();
287
- const result = await milestone.editCompletion(mockSigner, { reason: "Updated" });
288
- expect(result).toEqual({
289
- tx: { hash: "0xCompletionTxHash" },
290
- uids: ["0xNewCompletionUID"]
291
- });
292
- });
293
- });
294
- describe("state guards", () => {
295
- it("should throw if milestone is not completed", async () => {
296
- const milestone = createCompletedMilestone();
297
- milestone.completed = undefined;
298
- await expect(milestone.editCompletion(mockSigner, {
299
- reason: "Nope"
300
- })).rejects.toThrow("Milestone is not completed");
301
- expect(milestone._mocks.revokeCompletion).not.toHaveBeenCalled();
302
- });
303
- it("should throw if milestone is approved", async () => {
304
- const milestone = createCompletedMilestone({
305
- approved: {
306
- uid: "0xApprovedUID",
307
- data: { type: "approved", reason: "Approved" }
308
- }
309
- });
310
- await expect(milestone.editCompletion(mockSigner, {
311
- reason: "Nope"
312
- })).rejects.toThrow("Cannot edit completion of an approved milestone");
313
- });
314
- it("should throw if milestone is verified", async () => {
315
- const milestone = createCompletedMilestone({
316
- verified: [
317
- {
318
- uid: "0xVerifiedUID",
319
- data: { type: "verified" }
320
- }
321
- ]
322
- });
323
- await expect(milestone.editCompletion(mockSigner, {
324
- reason: "Nope"
325
- })).rejects.toThrow("Cannot edit completion of a verified milestone");
326
- });
327
- });
328
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,39 +0,0 @@
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,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
- }