@framers/agentos-ext-anchor-providers 1.1.0 → 1.2.1
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/LICENSE +98 -0
- package/README.md +38 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/EthereumProvider.d.ts +48 -4
- package/dist/providers/EthereumProvider.d.ts.map +1 -1
- package/dist/providers/EthereumProvider.js +261 -27
- package/dist/providers/EthereumProvider.js.map +1 -1
- package/dist/providers/OpenTimestampsProvider.d.ts +26 -2
- package/dist/providers/OpenTimestampsProvider.d.ts.map +1 -1
- package/dist/providers/OpenTimestampsProvider.js +141 -26
- package/dist/providers/OpenTimestampsProvider.js.map +1 -1
- package/dist/providers/RekorProvider.d.ts +32 -3
- package/dist/providers/RekorProvider.d.ts.map +1 -1
- package/dist/providers/RekorProvider.js +212 -25
- package/dist/providers/RekorProvider.js.map +1 -1
- package/dist/providers/SolanaProvider.d.ts +58 -4
- package/dist/providers/SolanaProvider.d.ts.map +1 -1
- package/dist/providers/SolanaProvider.js +310 -25
- package/dist/providers/SolanaProvider.js.map +1 -1
- package/dist/providers/WormSnapshotProvider.d.ts +30 -2
- package/dist/providers/WormSnapshotProvider.d.ts.map +1 -1
- package/dist/providers/WormSnapshotProvider.js +176 -27
- package/dist/providers/WormSnapshotProvider.js.map +1 -1
- package/dist/register.d.ts.map +1 -1
- package/dist/register.js +1 -0
- package/dist/register.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/http-client.d.ts.map +1 -1
- package/dist/utils/http-client.js +1 -0
- package/dist/utils/http-client.js.map +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/serialization.d.ts.map +1 -1
- package/dist/utils/serialization.js +1 -0
- package/dist/utils/serialization.js.map +1 -1
- package/manifest.json +5 -5
- package/package.json +26 -21
- package/CHANGELOG.md +0 -16
- package/src/index.ts +0 -59
- package/src/providers/EthereumProvider.ts +0 -87
- package/src/providers/OpenTimestampsProvider.ts +0 -86
- package/src/providers/RekorProvider.ts +0 -82
- package/src/providers/SolanaProvider.ts +0 -439
- package/src/providers/WormSnapshotProvider.ts +0 -84
- package/src/register.ts +0 -69
- package/src/types.ts +0 -27
- package/src/utils/http-client.ts +0 -75
- package/src/utils/index.ts +0 -3
- package/src/utils/serialization.ts +0 -33
- package/test/integration.spec.ts +0 -175
- package/test/providers.spec.ts +0 -163
- package/test/register.spec.ts +0 -69
- package/test/types.spec.ts +0 -55
- package/test/utils.spec.ts +0 -225
- package/tsconfig.json +0 -21
package/test/utils.spec.ts
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file utils.spec.ts
|
|
3
|
-
* @description Tests for shared utility functions: canonicalization, hashing, and HTTP retry.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
7
|
-
import { canonicalizeAnchor, hashCanonicalAnchor } from '../src/utils/serialization.js';
|
|
8
|
-
import { fetchWithRetry } from '../src/utils/http-client.js';
|
|
9
|
-
import type { AnchorRecord } from '@framers/agentos';
|
|
10
|
-
|
|
11
|
-
// =============================================================================
|
|
12
|
-
// Test Fixtures
|
|
13
|
-
// =============================================================================
|
|
14
|
-
|
|
15
|
-
function createMockAnchor(overrides?: Partial<AnchorRecord>): AnchorRecord {
|
|
16
|
-
return {
|
|
17
|
-
id: 'anchor-001',
|
|
18
|
-
merkleRoot: 'abc123def456',
|
|
19
|
-
sequenceFrom: 1,
|
|
20
|
-
sequenceTo: 10,
|
|
21
|
-
eventCount: 10,
|
|
22
|
-
timestamp: '2025-01-15T00:00:00.000Z',
|
|
23
|
-
signature: 'mock-signature-base64',
|
|
24
|
-
...overrides,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// =============================================================================
|
|
29
|
-
// canonicalizeAnchor
|
|
30
|
-
// =============================================================================
|
|
31
|
-
|
|
32
|
-
describe('canonicalizeAnchor', () => {
|
|
33
|
-
it('should produce valid JSON with sorted keys', () => {
|
|
34
|
-
const anchor = createMockAnchor();
|
|
35
|
-
const canonical = canonicalizeAnchor(anchor);
|
|
36
|
-
const parsed = JSON.parse(canonical);
|
|
37
|
-
|
|
38
|
-
expect(Object.keys(parsed)).toEqual([
|
|
39
|
-
'eventCount',
|
|
40
|
-
'id',
|
|
41
|
-
'merkleRoot',
|
|
42
|
-
'sequenceFrom',
|
|
43
|
-
'sequenceTo',
|
|
44
|
-
'signature',
|
|
45
|
-
'timestamp',
|
|
46
|
-
]);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should produce deterministic output for the same anchor', () => {
|
|
50
|
-
const anchor = createMockAnchor();
|
|
51
|
-
const a = canonicalizeAnchor(anchor);
|
|
52
|
-
const b = canonicalizeAnchor(anchor);
|
|
53
|
-
expect(a).toBe(b);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('should exclude externalRef and providerResults', () => {
|
|
57
|
-
const anchor = createMockAnchor({
|
|
58
|
-
externalRef: 'rekor:12345',
|
|
59
|
-
providerResults: [{ providerId: 'rekor', success: true }],
|
|
60
|
-
});
|
|
61
|
-
const canonical = canonicalizeAnchor(anchor);
|
|
62
|
-
expect(canonical).not.toContain('externalRef');
|
|
63
|
-
expect(canonical).not.toContain('providerResults');
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should include all required fields', () => {
|
|
67
|
-
const anchor = createMockAnchor();
|
|
68
|
-
const canonical = canonicalizeAnchor(anchor);
|
|
69
|
-
const parsed = JSON.parse(canonical);
|
|
70
|
-
|
|
71
|
-
expect(parsed.id).toBe('anchor-001');
|
|
72
|
-
expect(parsed.merkleRoot).toBe('abc123def456');
|
|
73
|
-
expect(parsed.sequenceFrom).toBe(1);
|
|
74
|
-
expect(parsed.sequenceTo).toBe(10);
|
|
75
|
-
expect(parsed.eventCount).toBe(10);
|
|
76
|
-
expect(parsed.signature).toBe('mock-signature-base64');
|
|
77
|
-
expect(parsed.timestamp).toBe('2025-01-15T00:00:00.000Z');
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('should produce different output for different anchors', () => {
|
|
81
|
-
const a = canonicalizeAnchor(createMockAnchor({ id: 'anchor-A' }));
|
|
82
|
-
const b = canonicalizeAnchor(createMockAnchor({ id: 'anchor-B' }));
|
|
83
|
-
expect(a).not.toBe(b);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// =============================================================================
|
|
88
|
-
// hashCanonicalAnchor
|
|
89
|
-
// =============================================================================
|
|
90
|
-
|
|
91
|
-
describe('hashCanonicalAnchor', () => {
|
|
92
|
-
it('should produce a 64-character hex string (SHA-256)', async () => {
|
|
93
|
-
const anchor = createMockAnchor();
|
|
94
|
-
const hash = await hashCanonicalAnchor(anchor);
|
|
95
|
-
expect(hash).toMatch(/^[0-9a-f]{64}$/);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('should produce deterministic hashes', async () => {
|
|
99
|
-
const anchor = createMockAnchor();
|
|
100
|
-
const a = await hashCanonicalAnchor(anchor);
|
|
101
|
-
const b = await hashCanonicalAnchor(anchor);
|
|
102
|
-
expect(a).toBe(b);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('should produce different hashes for different anchors', async () => {
|
|
106
|
-
const a = await hashCanonicalAnchor(createMockAnchor({ id: 'anchor-A' }));
|
|
107
|
-
const b = await hashCanonicalAnchor(createMockAnchor({ id: 'anchor-B' }));
|
|
108
|
-
expect(a).not.toBe(b);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('should be sensitive to field changes', async () => {
|
|
112
|
-
const base = createMockAnchor();
|
|
113
|
-
const modified = createMockAnchor({ merkleRoot: 'different-root' });
|
|
114
|
-
const a = await hashCanonicalAnchor(base);
|
|
115
|
-
const b = await hashCanonicalAnchor(modified);
|
|
116
|
-
expect(a).not.toBe(b);
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
// =============================================================================
|
|
121
|
-
// fetchWithRetry
|
|
122
|
-
// =============================================================================
|
|
123
|
-
|
|
124
|
-
describe('fetchWithRetry', () => {
|
|
125
|
-
let fetchMock: ReturnType<typeof vi.fn>;
|
|
126
|
-
|
|
127
|
-
beforeEach(() => {
|
|
128
|
-
fetchMock = vi.fn();
|
|
129
|
-
vi.stubGlobal('fetch', fetchMock);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
afterEach(() => {
|
|
133
|
-
vi.unstubAllGlobals();
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('should return response on successful first attempt', async () => {
|
|
137
|
-
const mockResponse = new Response('ok', { status: 200 });
|
|
138
|
-
fetchMock.mockResolvedValue(mockResponse);
|
|
139
|
-
|
|
140
|
-
const response = await fetchWithRetry('https://example.com/api', {}, {
|
|
141
|
-
retries: 3,
|
|
142
|
-
retryDelayMs: 10,
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
expect(response.status).toBe(200);
|
|
146
|
-
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('should return 4xx errors without retrying', async () => {
|
|
150
|
-
const mockResponse = new Response('not found', { status: 404 });
|
|
151
|
-
fetchMock.mockResolvedValue(mockResponse);
|
|
152
|
-
|
|
153
|
-
const response = await fetchWithRetry('https://example.com/api', {}, {
|
|
154
|
-
retries: 3,
|
|
155
|
-
retryDelayMs: 10,
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
expect(response.status).toBe(404);
|
|
159
|
-
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it('should retry on 5xx errors', async () => {
|
|
163
|
-
const fail = new Response('error', { status: 500, statusText: 'Internal Server Error' });
|
|
164
|
-
const success = new Response('ok', { status: 200 });
|
|
165
|
-
|
|
166
|
-
fetchMock
|
|
167
|
-
.mockResolvedValueOnce(fail)
|
|
168
|
-
.mockResolvedValueOnce(fail)
|
|
169
|
-
.mockResolvedValueOnce(success);
|
|
170
|
-
|
|
171
|
-
const response = await fetchWithRetry('https://example.com/api', {}, {
|
|
172
|
-
retries: 3,
|
|
173
|
-
retryDelayMs: 10,
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
expect(response.status).toBe(200);
|
|
177
|
-
expect(fetchMock).toHaveBeenCalledTimes(3);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('should retry on network errors', async () => {
|
|
181
|
-
const success = new Response('ok', { status: 200 });
|
|
182
|
-
|
|
183
|
-
fetchMock
|
|
184
|
-
.mockRejectedValueOnce(new Error('Network error'))
|
|
185
|
-
.mockResolvedValueOnce(success);
|
|
186
|
-
|
|
187
|
-
const response = await fetchWithRetry('https://example.com/api', {}, {
|
|
188
|
-
retries: 3,
|
|
189
|
-
retryDelayMs: 10,
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
expect(response.status).toBe(200);
|
|
193
|
-
expect(fetchMock).toHaveBeenCalledTimes(2);
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it('should throw after exhausting all retries', async () => {
|
|
197
|
-
const fail = new Response('error', { status: 503, statusText: 'Service Unavailable' });
|
|
198
|
-
fetchMock.mockResolvedValue(fail);
|
|
199
|
-
|
|
200
|
-
await expect(
|
|
201
|
-
fetchWithRetry('https://example.com/api', {}, {
|
|
202
|
-
retries: 2,
|
|
203
|
-
retryDelayMs: 10,
|
|
204
|
-
}),
|
|
205
|
-
).rejects.toThrow('HTTP 503');
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('should use default values when options not provided', async () => {
|
|
209
|
-
const mockResponse = new Response('ok', { status: 200 });
|
|
210
|
-
fetchMock.mockResolvedValue(mockResponse);
|
|
211
|
-
|
|
212
|
-
const response = await fetchWithRetry('https://example.com/api');
|
|
213
|
-
expect(response.status).toBe(200);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('should pass AbortSignal for timeout', async () => {
|
|
217
|
-
const mockResponse = new Response('ok', { status: 200 });
|
|
218
|
-
fetchMock.mockResolvedValue(mockResponse);
|
|
219
|
-
|
|
220
|
-
await fetchWithRetry('https://example.com/api', {}, { timeoutMs: 5000, retries: 0 });
|
|
221
|
-
|
|
222
|
-
const callInit = fetchMock.mock.calls[0][1];
|
|
223
|
-
expect(callInit.signal).toBeDefined();
|
|
224
|
-
});
|
|
225
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"lib": ["ES2022"],
|
|
6
|
-
"outDir": "./dist",
|
|
7
|
-
"rootDir": "./src",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"forceConsistentCasingInFileNames": true,
|
|
12
|
-
"declaration": true,
|
|
13
|
-
"declarationMap": true,
|
|
14
|
-
"sourceMap": true,
|
|
15
|
-
"resolveJsonModule": true,
|
|
16
|
-
"moduleResolution": "Bundler",
|
|
17
|
-
"types": ["node"]
|
|
18
|
-
},
|
|
19
|
-
"include": ["src/**/*"],
|
|
20
|
-
"exclude": ["node_modules", "dist", "test"]
|
|
21
|
-
}
|