@framers/agentos-ext-anchor-providers 1.1.0
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/CHANGELOG.md +16 -0
- package/README.md +353 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/EthereumProvider.d.ts +36 -0
- package/dist/providers/EthereumProvider.d.ts.map +1 -0
- package/dist/providers/EthereumProvider.js +66 -0
- package/dist/providers/EthereumProvider.js.map +1 -0
- package/dist/providers/OpenTimestampsProvider.d.ts +28 -0
- package/dist/providers/OpenTimestampsProvider.d.ts.map +1 -0
- package/dist/providers/OpenTimestampsProvider.js +72 -0
- package/dist/providers/OpenTimestampsProvider.js.map +1 -0
- package/dist/providers/RekorProvider.d.ts +28 -0
- package/dist/providers/RekorProvider.d.ts.map +1 -0
- package/dist/providers/RekorProvider.js +68 -0
- package/dist/providers/RekorProvider.js.map +1 -0
- package/dist/providers/SolanaProvider.d.ts +62 -0
- package/dist/providers/SolanaProvider.d.ts.map +1 -0
- package/dist/providers/SolanaProvider.js +256 -0
- package/dist/providers/SolanaProvider.js.map +1 -0
- package/dist/providers/WormSnapshotProvider.d.ts +35 -0
- package/dist/providers/WormSnapshotProvider.d.ts.map +1 -0
- package/dist/providers/WormSnapshotProvider.js +64 -0
- package/dist/providers/WormSnapshotProvider.js.map +1 -0
- package/dist/register.d.ts +31 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +47 -0
- package/dist/register.js.map +1 -0
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/http-client.d.ts +23 -0
- package/dist/utils/http-client.d.ts.map +1 -0
- package/dist/utils/http-client.js +53 -0
- package/dist/utils/http-client.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/serialization.d.ts +16 -0
- package/dist/utils/serialization.d.ts.map +1 -0
- package/dist/utils/serialization.js +30 -0
- package/dist/utils/serialization.js.map +1 -0
- package/manifest.json +100 -0
- package/package.json +103 -0
- package/src/index.ts +59 -0
- package/src/providers/EthereumProvider.ts +87 -0
- package/src/providers/OpenTimestampsProvider.ts +86 -0
- package/src/providers/RekorProvider.ts +82 -0
- package/src/providers/SolanaProvider.ts +439 -0
- package/src/providers/WormSnapshotProvider.ts +84 -0
- package/src/register.ts +69 -0
- package/src/types.ts +27 -0
- package/src/utils/http-client.ts +75 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/serialization.ts +33 -0
- package/test/integration.spec.ts +175 -0
- package/test/providers.spec.ts +163 -0
- package/test/register.spec.ts +69 -0
- package/test/types.spec.ts +55 -0
- package/test/utils.spec.ts +225 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file register.ts
|
|
3
|
+
* @description Registers all anchor provider factories with the core AgentOS factory.
|
|
4
|
+
* Call `registerExtensionProviders()` once at startup to enable config-driven
|
|
5
|
+
* provider creation via `createAnchorProvider()`.
|
|
6
|
+
*
|
|
7
|
+
* @module @framers/agentos-ext-anchor-providers
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Register all anchor provider factories with the core AgentOS provider registry.
|
|
11
|
+
* Call once at application startup, before creating any AnchorProvider via config.
|
|
12
|
+
*
|
|
13
|
+
* Safe to call multiple times — subsequent calls are no-ops.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { registerExtensionProviders } from '@framers/agentos-ext-anchor-providers';
|
|
18
|
+
* import { createAnchorProvider } from '@framers/agentos';
|
|
19
|
+
*
|
|
20
|
+
* // Register at startup
|
|
21
|
+
* registerExtensionProviders();
|
|
22
|
+
*
|
|
23
|
+
* // Now config-driven creation works:
|
|
24
|
+
* const provider = createAnchorProvider({
|
|
25
|
+
* type: 'rekor',
|
|
26
|
+
* options: { serverUrl: 'https://rekor.sigstore.dev' },
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function registerExtensionProviders(): void;
|
|
31
|
+
//# sourceMappingURL=register.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgBH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAwBjD"}
|
package/dist/register.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file register.ts
|
|
3
|
+
* @description Registers all anchor provider factories with the core AgentOS factory.
|
|
4
|
+
* Call `registerExtensionProviders()` once at startup to enable config-driven
|
|
5
|
+
* provider creation via `createAnchorProvider()`.
|
|
6
|
+
*
|
|
7
|
+
* @module @framers/agentos-ext-anchor-providers
|
|
8
|
+
*/
|
|
9
|
+
import { registerAnchorProviderFactory } from '@framers/agentos';
|
|
10
|
+
import { WormSnapshotProvider } from './providers/WormSnapshotProvider.js';
|
|
11
|
+
import { RekorProvider } from './providers/RekorProvider.js';
|
|
12
|
+
import { OpenTimestampsProvider } from './providers/OpenTimestampsProvider.js';
|
|
13
|
+
import { EthereumProvider } from './providers/EthereumProvider.js';
|
|
14
|
+
import { SolanaProvider } from './providers/SolanaProvider.js';
|
|
15
|
+
let registered = false;
|
|
16
|
+
/**
|
|
17
|
+
* Register all anchor provider factories with the core AgentOS provider registry.
|
|
18
|
+
* Call once at application startup, before creating any AnchorProvider via config.
|
|
19
|
+
*
|
|
20
|
+
* Safe to call multiple times — subsequent calls are no-ops.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { registerExtensionProviders } from '@framers/agentos-ext-anchor-providers';
|
|
25
|
+
* import { createAnchorProvider } from '@framers/agentos';
|
|
26
|
+
*
|
|
27
|
+
* // Register at startup
|
|
28
|
+
* registerExtensionProviders();
|
|
29
|
+
*
|
|
30
|
+
* // Now config-driven creation works:
|
|
31
|
+
* const provider = createAnchorProvider({
|
|
32
|
+
* type: 'rekor',
|
|
33
|
+
* options: { serverUrl: 'https://rekor.sigstore.dev' },
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function registerExtensionProviders() {
|
|
38
|
+
if (registered)
|
|
39
|
+
return;
|
|
40
|
+
registerAnchorProviderFactory('worm-snapshot', (opts) => new WormSnapshotProvider(opts));
|
|
41
|
+
registerAnchorProviderFactory('rekor', (opts) => new RekorProvider(opts));
|
|
42
|
+
registerAnchorProviderFactory('opentimestamps', (opts) => new OpenTimestampsProvider(opts));
|
|
43
|
+
registerAnchorProviderFactory('ethereum', (opts) => new EthereumProvider(opts));
|
|
44
|
+
registerAnchorProviderFactory('solana', (opts) => new SolanaProvider(opts));
|
|
45
|
+
registered = true;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAE3E,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAE/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAG/D,IAAI,UAAU,GAAG,KAAK,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,0BAA0B;IACxC,IAAI,UAAU;QAAE,OAAO;IAEvB,6BAA6B,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE,EAAE,CACtD,IAAI,oBAAoB,CAAC,IAA6C,CAAC,CACxE,CAAC;IAEF,6BAA6B,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAC9C,IAAI,aAAa,CAAC,IAAsC,CAAC,CAC1D,CAAC;IAEF,6BAA6B,CAAC,gBAAgB,EAAE,CAAC,IAAI,EAAE,EAAE,CACvD,IAAI,sBAAsB,CAAC,IAA+C,CAAC,CAC5E,CAAC;IAEF,6BAA6B,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CACjD,IAAI,gBAAgB,CAAC,IAAyC,CAAC,CAChE,CAAC;IAEF,6BAA6B,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAC/C,IAAI,cAAc,CAAC,IAAuC,CAAC,CAC5D,CAAC;IAEF,UAAU,GAAG,IAAI,CAAC;AACpB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file types.ts
|
|
3
|
+
* @description Shared types for anchor provider implementations.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Base configuration shared by all anchor providers.
|
|
7
|
+
*/
|
|
8
|
+
export interface BaseProviderConfig {
|
|
9
|
+
/** Request timeout in milliseconds. Default: 30000. */
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
/** Number of retries on transient failures. Default: 3. */
|
|
12
|
+
retries?: number;
|
|
13
|
+
/** Base delay between retries in milliseconds. Default: 1000. */
|
|
14
|
+
retryDelayMs?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolve a base config with defaults.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveBaseConfig(config?: Partial<BaseProviderConfig>): Required<BaseProviderConfig>;
|
|
20
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,QAAQ,CAAC,kBAAkB,CAAC,CAMpG"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file types.ts
|
|
3
|
+
* @description Shared types for anchor provider implementations.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Resolve a base config with defaults.
|
|
7
|
+
*/
|
|
8
|
+
export function resolveBaseConfig(config) {
|
|
9
|
+
return {
|
|
10
|
+
timeoutMs: config?.timeoutMs ?? 30_000,
|
|
11
|
+
retries: config?.retries ?? 3,
|
|
12
|
+
retryDelayMs: config?.retryDelayMs ?? 1_000,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAoC;IACpE,OAAO;QACL,SAAS,EAAE,MAAM,EAAE,SAAS,IAAI,MAAM;QACtC,OAAO,EAAE,MAAM,EAAE,OAAO,IAAI,CAAC;QAC7B,YAAY,EAAE,MAAM,EAAE,YAAY,IAAI,KAAK;KAC5C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file http-client.ts
|
|
3
|
+
* @description Shared HTTP fetch wrapper with retry and timeout for anchor providers.
|
|
4
|
+
*/
|
|
5
|
+
export interface HttpRequestOptions {
|
|
6
|
+
/** Request timeout in milliseconds. */
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
/** Number of retries on transient failures (5xx, network errors). */
|
|
9
|
+
retries?: number;
|
|
10
|
+
/** Base delay between retries in milliseconds (exponential backoff). */
|
|
11
|
+
retryDelayMs?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Fetch with exponential backoff retry on transient failures.
|
|
15
|
+
*
|
|
16
|
+
* @param url - The URL to fetch.
|
|
17
|
+
* @param init - Standard RequestInit options.
|
|
18
|
+
* @param options - Retry and timeout configuration.
|
|
19
|
+
* @returns The fetch Response.
|
|
20
|
+
* @throws On non-transient errors or after all retries exhausted.
|
|
21
|
+
*/
|
|
22
|
+
export declare function fetchWithRetry(url: string, init?: RequestInit, options?: HttpRequestOptions): Promise<Response>;
|
|
23
|
+
//# sourceMappingURL=http-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../src/utils/http-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,WAAgB,EACtB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,QAAQ,CAAC,CA2CnB"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file http-client.ts
|
|
3
|
+
* @description Shared HTTP fetch wrapper with retry and timeout for anchor providers.
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
6
|
+
const DEFAULT_RETRIES = 3;
|
|
7
|
+
const DEFAULT_RETRY_DELAY_MS = 1_000;
|
|
8
|
+
/**
|
|
9
|
+
* Fetch with exponential backoff retry on transient failures.
|
|
10
|
+
*
|
|
11
|
+
* @param url - The URL to fetch.
|
|
12
|
+
* @param init - Standard RequestInit options.
|
|
13
|
+
* @param options - Retry and timeout configuration.
|
|
14
|
+
* @returns The fetch Response.
|
|
15
|
+
* @throws On non-transient errors or after all retries exhausted.
|
|
16
|
+
*/
|
|
17
|
+
export async function fetchWithRetry(url, init = {}, options) {
|
|
18
|
+
const maxRetries = options?.retries ?? DEFAULT_RETRIES;
|
|
19
|
+
const baseDelay = options?.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
20
|
+
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
21
|
+
let lastError;
|
|
22
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
23
|
+
try {
|
|
24
|
+
const controller = new AbortController();
|
|
25
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
26
|
+
const response = await fetch(url, {
|
|
27
|
+
...init,
|
|
28
|
+
signal: controller.signal,
|
|
29
|
+
});
|
|
30
|
+
clearTimeout(timeout);
|
|
31
|
+
// Don't retry client errors (4xx), only server errors (5xx)
|
|
32
|
+
if (response.ok || (response.status >= 400 && response.status < 500)) {
|
|
33
|
+
return response;
|
|
34
|
+
}
|
|
35
|
+
// Server error — retry
|
|
36
|
+
lastError = new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
40
|
+
// Don't retry aborted requests (timeout)
|
|
41
|
+
if (lastError.name === 'AbortError') {
|
|
42
|
+
lastError = new Error(`Request timed out after ${timeoutMs}ms`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Exponential backoff before next retry
|
|
46
|
+
if (attempt < maxRetries) {
|
|
47
|
+
const delay = baseDelay * Math.pow(2, attempt);
|
|
48
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
throw lastError ?? new Error('Request failed after all retries');
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=http-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../src/utils/http-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAClC,MAAM,eAAe,GAAG,CAAC,CAAC;AAC1B,MAAM,sBAAsB,GAAG,KAAK,CAAC;AAErC;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAW,EACX,OAAoB,EAAE,EACtB,OAA4B;IAE5B,MAAM,UAAU,GAAG,OAAO,EAAE,OAAO,IAAI,eAAe,CAAC;IACvD,MAAM,SAAS,GAAG,OAAO,EAAE,YAAY,IAAI,sBAAsB,CAAC;IAClE,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,kBAAkB,CAAC;IAE3D,IAAI,SAA4B,CAAC;IAEjC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;YAEhE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,GAAG,IAAI;gBACP,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,YAAY,CAAC,OAAO,CAAC,CAAC;YAEtB,4DAA4D;YAC5D,IAAI,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC;gBACrE,OAAO,QAAQ,CAAC;YAClB,CAAC;YAED,uBAAuB;YACvB,SAAS,GAAG,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAC3E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,SAAS,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAEhE,yCAAyC;YACzC,IAAI,SAAS,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACpC,SAAS,GAAG,IAAI,KAAK,CAAC,2BAA2B,SAAS,IAAI,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAED,wCAAwC;QACxC,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;AACnE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file serialization.ts
|
|
3
|
+
* @description Deterministic serialization for anchor records before external publishing.
|
|
4
|
+
*/
|
|
5
|
+
import type { AnchorRecord } from '@framers/agentos';
|
|
6
|
+
/**
|
|
7
|
+
* Serialize an AnchorRecord to a canonical JSON string with sorted keys.
|
|
8
|
+
* Ensures all providers hash/publish the same byte representation.
|
|
9
|
+
*/
|
|
10
|
+
export declare function canonicalizeAnchor(anchor: AnchorRecord): string;
|
|
11
|
+
/**
|
|
12
|
+
* Compute a SHA-256 hex digest of the canonical anchor representation.
|
|
13
|
+
* Used by providers as the hash to publish externally.
|
|
14
|
+
*/
|
|
15
|
+
export declare function hashCanonicalAnchor(anchor: AnchorRecord): Promise<string>;
|
|
16
|
+
//# sourceMappingURL=serialization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialization.d.ts","sourceRoot":"","sources":["../../src/utils/serialization.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAW/D;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/E"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file serialization.ts
|
|
3
|
+
* @description Deterministic serialization for anchor records before external publishing.
|
|
4
|
+
*/
|
|
5
|
+
import { createHash } from 'crypto';
|
|
6
|
+
/**
|
|
7
|
+
* Serialize an AnchorRecord to a canonical JSON string with sorted keys.
|
|
8
|
+
* Ensures all providers hash/publish the same byte representation.
|
|
9
|
+
*/
|
|
10
|
+
export function canonicalizeAnchor(anchor) {
|
|
11
|
+
const canonical = {
|
|
12
|
+
eventCount: anchor.eventCount,
|
|
13
|
+
id: anchor.id,
|
|
14
|
+
merkleRoot: anchor.merkleRoot,
|
|
15
|
+
sequenceFrom: anchor.sequenceFrom,
|
|
16
|
+
sequenceTo: anchor.sequenceTo,
|
|
17
|
+
signature: anchor.signature,
|
|
18
|
+
timestamp: anchor.timestamp,
|
|
19
|
+
};
|
|
20
|
+
return JSON.stringify(canonical);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Compute a SHA-256 hex digest of the canonical anchor representation.
|
|
24
|
+
* Used by providers as the hash to publish externally.
|
|
25
|
+
*/
|
|
26
|
+
export async function hashCanonicalAnchor(anchor) {
|
|
27
|
+
const canonical = canonicalizeAnchor(anchor);
|
|
28
|
+
return createHash('sha256').update(canonical, 'utf8').digest('hex');
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=serialization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialization.js","sourceRoot":"","sources":["../../src/utils/serialization.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAoB;IACrD,MAAM,SAAS,GAAG;QAChB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAoB;IAC5D,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC7C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACtE,CAAC"}
|
package/manifest.json
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://agentos.sh/schemas/extension-manifest-v1.json",
|
|
3
|
+
"id": "com.framers.provenance.anchor-providers",
|
|
4
|
+
"name": "Provenance Anchor Providers",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"description": "External anchor providers for the AgentOS provenance system — WORM storage, transparency logs, and blockchain timestamping",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Frame.dev",
|
|
9
|
+
"email": "support@frame.dev",
|
|
10
|
+
"url": "https://github.com/framersai"
|
|
11
|
+
},
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"provenance",
|
|
15
|
+
"anchor",
|
|
16
|
+
"blockchain",
|
|
17
|
+
"ethereum",
|
|
18
|
+
"opentimestamps",
|
|
19
|
+
"rekor",
|
|
20
|
+
"sigstore",
|
|
21
|
+
"worm",
|
|
22
|
+
"s3-object-lock",
|
|
23
|
+
"transparency-log",
|
|
24
|
+
"tamper-evidence"
|
|
25
|
+
],
|
|
26
|
+
"agentosVersion": "^0.1.0",
|
|
27
|
+
"categories": ["provenance", "enterprise"],
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/framersai/agentos-extensions"
|
|
31
|
+
},
|
|
32
|
+
"extensions": [
|
|
33
|
+
{
|
|
34
|
+
"kind": "provenance",
|
|
35
|
+
"id": "wormSnapshotProvider",
|
|
36
|
+
"displayName": "WORM Snapshot Provider",
|
|
37
|
+
"description": "S3 Object Lock / WORM storage for compliance-grade anchor archival",
|
|
38
|
+
"entry": "./dist/providers/WormSnapshotProvider.js",
|
|
39
|
+
"proofLevel": "externally-archived"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"kind": "provenance",
|
|
43
|
+
"id": "rekorProvider",
|
|
44
|
+
"displayName": "Rekor Transparency Log Provider",
|
|
45
|
+
"description": "Sigstore Rekor transparency log for publicly auditable anchor records",
|
|
46
|
+
"entry": "./dist/providers/RekorProvider.js",
|
|
47
|
+
"proofLevel": "publicly-auditable"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"kind": "provenance",
|
|
51
|
+
"id": "openTimestampsProvider",
|
|
52
|
+
"displayName": "OpenTimestamps Provider",
|
|
53
|
+
"description": "Bitcoin-anchored timestamping via the OpenTimestamps protocol",
|
|
54
|
+
"entry": "./dist/providers/OpenTimestampsProvider.js",
|
|
55
|
+
"proofLevel": "publicly-timestamped"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"kind": "provenance",
|
|
59
|
+
"id": "ethereumProvider",
|
|
60
|
+
"displayName": "Ethereum On-Chain Anchor Provider",
|
|
61
|
+
"description": "Ethereum on-chain anchor with transaction receipt and finalized block proof",
|
|
62
|
+
"entry": "./dist/providers/EthereumProvider.js",
|
|
63
|
+
"proofLevel": "publicly-timestamped"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"kind": "provenance",
|
|
67
|
+
"id": "solanaProvider",
|
|
68
|
+
"displayName": "Solana On-Chain Anchor Provider",
|
|
69
|
+
"description": "Solana on-chain anchor via the Wunderland program (content hash + manifest hash)",
|
|
70
|
+
"entry": "./dist/providers/SolanaProvider.js",
|
|
71
|
+
"proofLevel": "publicly-timestamped"
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"configuration": {
|
|
75
|
+
"properties": {
|
|
76
|
+
"provider.type": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"enum": ["none", "worm-snapshot", "rekor", "opentimestamps", "ethereum", "solana", "composite"],
|
|
79
|
+
"default": "none",
|
|
80
|
+
"description": "Which anchor provider to use for external publishing"
|
|
81
|
+
},
|
|
82
|
+
"provider.endpoint": {
|
|
83
|
+
"type": "string",
|
|
84
|
+
"description": "Provider endpoint URL (e.g., Rekor server, Ethereum RPC)"
|
|
85
|
+
},
|
|
86
|
+
"provider.timeoutMs": {
|
|
87
|
+
"type": "number",
|
|
88
|
+
"default": 30000,
|
|
89
|
+
"description": "Request timeout in milliseconds"
|
|
90
|
+
},
|
|
91
|
+
"provider.retries": {
|
|
92
|
+
"type": "number",
|
|
93
|
+
"default": 3,
|
|
94
|
+
"minimum": 0,
|
|
95
|
+
"maximum": 10,
|
|
96
|
+
"description": "Number of retries on transient failures"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@framers/agentos-ext-anchor-providers",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "External anchor providers for AgentOS provenance — blockchain, WORM storage, and transparency log integrations",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./manifest.json": "./manifest.json",
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"test": "vitest run",
|
|
20
|
+
"test:watch": "vitest",
|
|
21
|
+
"test:coverage": "vitest run --coverage",
|
|
22
|
+
"lint": "eslint src --ext .ts",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"docs": "typedoc --out docs src/index.ts",
|
|
25
|
+
"clean": "rimraf dist"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"agentos",
|
|
29
|
+
"extension",
|
|
30
|
+
"provenance",
|
|
31
|
+
"anchor",
|
|
32
|
+
"blockchain",
|
|
33
|
+
"ethereum",
|
|
34
|
+
"opentimestamps",
|
|
35
|
+
"rekor",
|
|
36
|
+
"sigstore",
|
|
37
|
+
"worm",
|
|
38
|
+
"s3-object-lock",
|
|
39
|
+
"transparency-log"
|
|
40
|
+
],
|
|
41
|
+
"author": {
|
|
42
|
+
"name": "Framers AI",
|
|
43
|
+
"email": "team@frame.dev",
|
|
44
|
+
"url": "https://frame.dev"
|
|
45
|
+
},
|
|
46
|
+
"contributors": [
|
|
47
|
+
{
|
|
48
|
+
"name": "Johnny Dunn",
|
|
49
|
+
"email": "johnnyfived@protonmail.com",
|
|
50
|
+
"url": "https://github.com/jddunn"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "https://github.com/framersai/agentos-extensions.git",
|
|
57
|
+
"directory": "registry/curated/provenance/anchor-providers"
|
|
58
|
+
},
|
|
59
|
+
"publishConfig": {
|
|
60
|
+
"access": "public"
|
|
61
|
+
},
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"@framers/agentos": "^0.1.0",
|
|
64
|
+
"@aws-sdk/client-s3": "^3.0.0",
|
|
65
|
+
"@solana/web3.js": "^1.0.0",
|
|
66
|
+
"bs58": "^5.0.0",
|
|
67
|
+
"ethers": "^6.0.0",
|
|
68
|
+
"opentimestamps": "^0.4.0",
|
|
69
|
+
"sigstore": "^2.0.0"
|
|
70
|
+
},
|
|
71
|
+
"peerDependenciesMeta": {
|
|
72
|
+
"@aws-sdk/client-s3": {
|
|
73
|
+
"optional": true
|
|
74
|
+
},
|
|
75
|
+
"@solana/web3.js": {
|
|
76
|
+
"optional": true
|
|
77
|
+
},
|
|
78
|
+
"bs58": {
|
|
79
|
+
"optional": true
|
|
80
|
+
},
|
|
81
|
+
"ethers": {
|
|
82
|
+
"optional": true
|
|
83
|
+
},
|
|
84
|
+
"opentimestamps": {
|
|
85
|
+
"optional": true
|
|
86
|
+
},
|
|
87
|
+
"sigstore": {
|
|
88
|
+
"optional": true
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"devDependencies": {
|
|
92
|
+
"@framers/agentos": "^0.1.0",
|
|
93
|
+
"@types/node": "^20.12.12",
|
|
94
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
95
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
96
|
+
"@vitest/coverage-v8": "^1.6.0",
|
|
97
|
+
"eslint": "^9.11.0",
|
|
98
|
+
"rimraf": "^5.0.7",
|
|
99
|
+
"typedoc": "^0.25.13",
|
|
100
|
+
"typescript": "^5.4.5",
|
|
101
|
+
"vitest": "^1.6.0"
|
|
102
|
+
}
|
|
103
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file index.ts
|
|
3
|
+
* @description Main entry point for @framers/agentos-ext-anchor-providers.
|
|
4
|
+
*
|
|
5
|
+
* External anchor providers for the AgentOS provenance system:
|
|
6
|
+
* - **WormSnapshotProvider** — S3 Object Lock / WORM storage (externally-archived)
|
|
7
|
+
* - **RekorProvider** — Sigstore Rekor transparency log (publicly-auditable)
|
|
8
|
+
* - **OpenTimestampsProvider** — Bitcoin-anchored timestamping (publicly-timestamped)
|
|
9
|
+
* - **EthereumProvider** — Ethereum on-chain anchor (publicly-timestamped)
|
|
10
|
+
* - **SolanaProvider** — Solana on-chain anchor (publicly-timestamped)
|
|
11
|
+
*
|
|
12
|
+
* ## Quick Start
|
|
13
|
+
*
|
|
14
|
+
* ### Option 1: Config-driven (via registry)
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { registerExtensionProviders } from '@framers/agentos-ext-anchor-providers';
|
|
17
|
+
* import { createAnchorProvider } from '@framers/agentos';
|
|
18
|
+
*
|
|
19
|
+
* registerExtensionProviders();
|
|
20
|
+
* const provider = createAnchorProvider({ type: 'rekor' });
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* ### Option 2: Direct construction
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { RekorProvider } from '@framers/agentos-ext-anchor-providers';
|
|
26
|
+
*
|
|
27
|
+
* const provider = new RekorProvider({ serverUrl: 'https://rekor.sigstore.dev' });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @module @framers/agentos-ext-anchor-providers
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
// Registry
|
|
34
|
+
export { registerExtensionProviders } from './register.js';
|
|
35
|
+
|
|
36
|
+
// Providers
|
|
37
|
+
export { WormSnapshotProvider } from './providers/WormSnapshotProvider.js';
|
|
38
|
+
export type { WormSnapshotProviderConfig } from './providers/WormSnapshotProvider.js';
|
|
39
|
+
|
|
40
|
+
export { RekorProvider } from './providers/RekorProvider.js';
|
|
41
|
+
export type { RekorProviderConfig } from './providers/RekorProvider.js';
|
|
42
|
+
|
|
43
|
+
export { OpenTimestampsProvider } from './providers/OpenTimestampsProvider.js';
|
|
44
|
+
export type { OpenTimestampsProviderConfig } from './providers/OpenTimestampsProvider.js';
|
|
45
|
+
|
|
46
|
+
export { EthereumProvider } from './providers/EthereumProvider.js';
|
|
47
|
+
export type { EthereumProviderConfig } from './providers/EthereumProvider.js';
|
|
48
|
+
|
|
49
|
+
export { SolanaProvider } from './providers/SolanaProvider.js';
|
|
50
|
+
export type { SolanaProviderConfig } from './providers/SolanaProvider.js';
|
|
51
|
+
|
|
52
|
+
// Shared types
|
|
53
|
+
export type { BaseProviderConfig } from './types.js';
|
|
54
|
+
export { resolveBaseConfig } from './types.js';
|
|
55
|
+
|
|
56
|
+
// Utilities
|
|
57
|
+
export { fetchWithRetry } from './utils/http-client.js';
|
|
58
|
+
export type { HttpRequestOptions } from './utils/http-client.js';
|
|
59
|
+
export { canonicalizeAnchor, hashCanonicalAnchor } from './utils/serialization.js';
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file EthereumProvider.ts
|
|
3
|
+
* @description Ethereum on-chain anchor provider.
|
|
4
|
+
* Publishes anchor Merkle roots as calldata in Ethereum transactions.
|
|
5
|
+
*
|
|
6
|
+
* Proof level: `publicly-timestamped`
|
|
7
|
+
* Required peer dependency: `ethers`
|
|
8
|
+
*
|
|
9
|
+
* @module @framers/agentos-ext-anchor-providers
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { AnchorProvider, AnchorRecord, AnchorProviderResult, ProofLevel } from '@framers/agentos';
|
|
13
|
+
import type { BaseProviderConfig } from '../types.js';
|
|
14
|
+
import { resolveBaseConfig } from '../types.js';
|
|
15
|
+
import { hashCanonicalAnchor } from '../utils/serialization.js';
|
|
16
|
+
|
|
17
|
+
export interface EthereumProviderConfig extends BaseProviderConfig {
|
|
18
|
+
/** JSON-RPC endpoint URL. */
|
|
19
|
+
rpcUrl: string;
|
|
20
|
+
/** Contract address for anchor storage (optional — can use raw calldata tx). */
|
|
21
|
+
contractAddress?: string;
|
|
22
|
+
/** Private key hex for signing transactions. */
|
|
23
|
+
signerPrivateKey?: string;
|
|
24
|
+
/** Chain ID. Default: 1 (mainnet). */
|
|
25
|
+
chainId?: number;
|
|
26
|
+
/** Gas limit override. Default: auto-estimate. */
|
|
27
|
+
gasLimit?: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class EthereumProvider implements AnchorProvider {
|
|
31
|
+
readonly id = 'ethereum';
|
|
32
|
+
readonly name = 'Ethereum On-Chain Anchor';
|
|
33
|
+
readonly proofLevel: ProofLevel = 'publicly-timestamped';
|
|
34
|
+
|
|
35
|
+
private readonly config: EthereumProviderConfig;
|
|
36
|
+
private readonly baseConfig: Required<BaseProviderConfig>;
|
|
37
|
+
|
|
38
|
+
constructor(config: EthereumProviderConfig) {
|
|
39
|
+
this.config = {
|
|
40
|
+
chainId: 1,
|
|
41
|
+
...config,
|
|
42
|
+
};
|
|
43
|
+
this.baseConfig = resolveBaseConfig(config);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async publish(anchor: AnchorRecord): Promise<AnchorProviderResult> {
|
|
47
|
+
// TODO: Implement using ethers.js or viem
|
|
48
|
+
//
|
|
49
|
+
// Implementation outline:
|
|
50
|
+
// 1. Compute SHA-256 of canonical anchor: hashCanonicalAnchor(anchor)
|
|
51
|
+
// 2. Create ethers.JsonRpcProvider(this.config.rpcUrl)
|
|
52
|
+
// 3. Create ethers.Wallet(this.config.signerPrivateKey, provider)
|
|
53
|
+
// 4. If contractAddress is set:
|
|
54
|
+
// - ABI-encode call to `anchor(bytes32 merkleRoot)` on the contract
|
|
55
|
+
// - Send contract transaction
|
|
56
|
+
// 5. If no contractAddress (raw calldata):
|
|
57
|
+
// - Send self-transfer with 0x + anchorHash as calldata
|
|
58
|
+
// 6. Wait for transaction receipt (1 confirmation)
|
|
59
|
+
// 7. Return { success: true, externalRef: `eth:${chainId}:${txHash}`,
|
|
60
|
+
// metadata: { blockNumber, blockHash, gasUsed, chainId } }
|
|
61
|
+
try {
|
|
62
|
+
const _hash = await hashCanonicalAnchor(anchor);
|
|
63
|
+
throw new Error(
|
|
64
|
+
'EthereumProvider is not yet implemented. ' +
|
|
65
|
+
'Install ethers.js and implement the Ethereum on-chain anchor integration.',
|
|
66
|
+
);
|
|
67
|
+
} catch (e: unknown) {
|
|
68
|
+
return {
|
|
69
|
+
providerId: this.id,
|
|
70
|
+
success: false,
|
|
71
|
+
error: e instanceof Error ? e.message : String(e),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async verify(anchor: AnchorRecord): Promise<boolean> {
|
|
77
|
+
// TODO: Parse txHash from externalRef, fetch transaction receipt,
|
|
78
|
+
// decode calldata, compare with anchor hash
|
|
79
|
+
if (!anchor.externalRef) return false;
|
|
80
|
+
console.warn('[EthereumProvider] verify() is not yet implemented');
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async dispose(): Promise<void> {
|
|
85
|
+
// TODO: Disconnect provider if persistent connection was established
|
|
86
|
+
}
|
|
87
|
+
}
|