@totalreclaw/totalreclaw 1.1.0 → 1.2.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/README.md +57 -40
- package/embedding.ts +25 -34
- package/index.ts +30 -11
- package/lsh.ts +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -3
- package/subgraph-store.ts +6 -4
package/README.md
CHANGED
|
@@ -1,32 +1,52 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="../../docs/assets/logo.png" alt="TotalReclaw" width="80" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">@totalreclaw/totalreclaw</h1>
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>End-to-end encrypted memory for OpenClaw -- fully automatic, yours forever</strong>
|
|
9
|
+
</p>
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://totalreclaw.xyz">Website</a> ·
|
|
13
|
+
<a href="https://www.npmjs.com/package/@totalreclaw/totalreclaw">npm</a> ·
|
|
14
|
+
<a href="../../docs/guides/beta-tester-guide.md">Getting Started</a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<a href="https://www.npmjs.com/package/@totalreclaw/totalreclaw"><img src="https://img.shields.io/npm/v/@totalreclaw/totalreclaw?color=7B5CFF" alt="npm version"></a>
|
|
19
|
+
<a href="https://www.npmjs.com/package/@totalreclaw/totalreclaw"><img src="https://img.shields.io/npm/dm/@totalreclaw/totalreclaw" alt="npm downloads"></a>
|
|
20
|
+
<a href="../../LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="License"></a>
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
Your AI agent remembers everything -- preferences, decisions, facts -- encrypted so only you can read it. Built for [OpenClaw](https://openclaw.ai) with fully automatic memory extraction and recall.
|
|
8
26
|
|
|
9
27
|
## Install
|
|
10
28
|
|
|
29
|
+
Ask your OpenClaw agent:
|
|
30
|
+
|
|
31
|
+
> "Install the @totalreclaw/totalreclaw plugin"
|
|
32
|
+
|
|
33
|
+
Or from the terminal:
|
|
34
|
+
|
|
11
35
|
```bash
|
|
12
36
|
openclaw plugins install @totalreclaw/totalreclaw
|
|
13
37
|
```
|
|
14
38
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
> "Install the totalreclaw plugin"
|
|
18
|
-
|
|
19
|
-
The agent handles setup: generates your encryption keys and registers you. You'll be asked to write down a 12-word recovery phrase — that's the only thing you need to keep safe.
|
|
39
|
+
The agent handles setup: generates your encryption keys, asks you to save a 12-word recovery phrase, and registers you. After that, memory is fully automatic.
|
|
20
40
|
|
|
21
41
|
## How It Works
|
|
22
42
|
|
|
23
|
-
After setup,
|
|
43
|
+
After setup, everything happens in the background:
|
|
24
44
|
|
|
25
|
-
- **Start of conversation**
|
|
26
|
-
- **
|
|
27
|
-
- **Before context compaction**
|
|
45
|
+
- **Start of conversation** -- loads relevant memories from your encrypted vault
|
|
46
|
+
- **During conversation** -- extracts facts, preferences, and decisions automatically
|
|
47
|
+
- **Before context compaction** -- saves important context before the window is trimmed
|
|
28
48
|
|
|
29
|
-
All encryption happens client-side using AES-256-GCM.
|
|
49
|
+
All encryption happens client-side using AES-256-GCM. The server never sees your plaintext data.
|
|
30
50
|
|
|
31
51
|
## Tools
|
|
32
52
|
|
|
@@ -39,48 +59,45 @@ Your agent gets these tools automatically:
|
|
|
39
59
|
| `totalreclaw_forget` | Delete a specific memory |
|
|
40
60
|
| `totalreclaw_export` | Export all memories as plaintext |
|
|
41
61
|
| `totalreclaw_status` | Check billing status and quota |
|
|
62
|
+
| `totalreclaw_consolidate` | Merge duplicate memories |
|
|
63
|
+
| `totalreclaw_import_from` | Import from Mem0 or MCP Memory Server |
|
|
42
64
|
|
|
43
|
-
Most of the time you won't use these directly
|
|
65
|
+
Most of the time you won't use these directly -- the automatic hooks handle memory for you.
|
|
44
66
|
|
|
45
67
|
## Features
|
|
46
68
|
|
|
47
|
-
- **
|
|
48
|
-
- **
|
|
49
|
-
- **
|
|
50
|
-
- **
|
|
51
|
-
- **On-chain storage**
|
|
52
|
-
- **Portable**
|
|
53
|
-
- **Import**
|
|
69
|
+
- **End-to-end encrypted** -- AES-256-GCM encryption, blind index search, HKDF auth
|
|
70
|
+
- **Automatic extraction** -- LLM extracts facts from conversations, no manual input needed
|
|
71
|
+
- **Semantic search** -- Local embeddings + BM25 + cosine reranking with RRF fusion
|
|
72
|
+
- **Smart dedup** -- Cosine similarity catches paraphrases; LLM-guided dedup catches contradictions (Pro)
|
|
73
|
+
- **On-chain storage** -- Encrypted data stored on Gnosis Chain, indexed by The Graph
|
|
74
|
+
- **Portable** -- One 12-word phrase. Any device, same memories, no lock-in
|
|
75
|
+
- **Import** -- Migrate from Mem0 or MCP Memory Server
|
|
54
76
|
|
|
55
77
|
## Free Tier & Pricing
|
|
56
78
|
|
|
57
|
-
| Tier |
|
|
58
|
-
|
|
59
|
-
| **Free** |
|
|
60
|
-
| **Pro** |
|
|
61
|
-
|
|
62
|
-
Pay with card (Stripe) or crypto (Coinbase Commerce). Counter resets monthly.
|
|
63
|
-
|
|
64
|
-
## Configuration
|
|
79
|
+
| Tier | Memories | Reads | Storage | Price |
|
|
80
|
+
|------|----------|-------|---------|-------|
|
|
81
|
+
| **Free** | 500/month | Unlimited | Testnet (trial) | $0 |
|
|
82
|
+
| **Pro** | Unlimited | Unlimited | Permanent on-chain (Gnosis) | $5/month |
|
|
65
83
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
| Variable | Description | Default |
|
|
69
|
-
|----------|-------------|---------|
|
|
70
|
-
| `TOTALRECLAW_SERVER_URL` | Server URL | `https://api.totalreclaw.xyz` |
|
|
71
|
-
| `TOTALRECLAW_CREDENTIALS_PATH` | Path to credentials file | `~/.totalreclaw/credentials.json` |
|
|
72
|
-
| `TOTALRECLAW_SELF_HOSTED` | Set to `true` to use your own self-hosted server instead of the managed service | `false` (managed service) |
|
|
73
|
-
| `TOTALRECLAW_EXTRACT_EVERY_TURNS` | Auto-extract interval (turns) | `5` (Free) / `2` (Pro min) |
|
|
84
|
+
Pay with card via Stripe. Counter resets monthly.
|
|
74
85
|
|
|
75
86
|
## Using with Other Agents
|
|
76
87
|
|
|
77
88
|
TotalReclaw also works outside OpenClaw:
|
|
78
89
|
|
|
79
|
-
- **Claude Desktop / Cursor / Windsurf**
|
|
80
|
-
- **NanoClaw**
|
|
90
|
+
- **Claude Desktop / Cursor / Windsurf** -- Use [@totalreclaw/mcp-server](https://www.npmjs.com/package/@totalreclaw/mcp-server)
|
|
91
|
+
- **NanoClaw** -- Built-in support via MCP bridge
|
|
81
92
|
|
|
82
93
|
Same encryption, same recovery phrase, same memories across all agents.
|
|
83
94
|
|
|
95
|
+
## Learn More
|
|
96
|
+
|
|
97
|
+
- [Getting Started Guide](../../docs/guides/beta-tester-guide.md)
|
|
98
|
+
- [totalreclaw.xyz](https://totalreclaw.xyz)
|
|
99
|
+
- [Main Repository](https://github.com/p-diogo/totalreclaw)
|
|
100
|
+
|
|
84
101
|
## License
|
|
85
102
|
|
|
86
103
|
MIT
|
package/embedding.ts
CHANGED
|
@@ -1,73 +1,64 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TotalReclaw Plugin - Local Embedding via @huggingface/transformers
|
|
3
3
|
*
|
|
4
|
-
* Uses the
|
|
4
|
+
* Uses the Qwen3-Embedding-0.6B ONNX model to generate 1024-dimensional
|
|
5
5
|
* text embeddings locally. No API key needed, no data leaves the machine.
|
|
6
|
+
* Supports 100+ languages (EN, PT, ES, ZH, etc.).
|
|
6
7
|
*
|
|
7
|
-
* This preserves the
|
|
8
|
+
* This preserves the E2EE guarantee: embeddings are generated
|
|
8
9
|
* CLIENT-SIDE before encryption, so no plaintext ever reaches an external API.
|
|
9
10
|
*
|
|
10
11
|
* Model details:
|
|
11
|
-
* - Quantized (int8) ONNX model: ~
|
|
12
|
+
* - Quantized (int8) ONNX model: ~600MB download on first use
|
|
12
13
|
* - Cached in ~/.cache/huggingface/ after first download
|
|
13
|
-
* - Lazy initialization: first call ~
|
|
14
|
-
* - Output:
|
|
15
|
-
* -
|
|
16
|
-
* (documents/passages should NOT be prefixed)
|
|
14
|
+
* - Lazy initialization: first call ~3-5s (model load), subsequent ~100ms
|
|
15
|
+
* - Output: 1024-dimensional normalized embedding vector
|
|
16
|
+
* - No instruction prefix needed (bare queries perform better)
|
|
17
17
|
*
|
|
18
|
-
* Dependencies: @huggingface/transformers (handles model download,
|
|
19
|
-
* tokenization, ONNX inference,
|
|
18
|
+
* Dependencies: @huggingface/transformers (handles model download,
|
|
19
|
+
* tokenization, ONNX inference, last-token pooling, and normalization).
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
// @ts-ignore - @huggingface/transformers types may not be perfect
|
|
23
23
|
import { pipeline, type FeatureExtractionPipeline } from '@huggingface/transformers';
|
|
24
24
|
|
|
25
|
-
/** ONNX-optimized
|
|
26
|
-
const MODEL_ID = '
|
|
25
|
+
/** ONNX-optimized Qwen3-Embedding-0.6B from HuggingFace Hub. */
|
|
26
|
+
const MODEL_ID = 'onnx-community/Qwen3-Embedding-0.6B-ONNX';
|
|
27
27
|
|
|
28
|
-
/** Fixed output dimensionality for
|
|
29
|
-
const EMBEDDING_DIM =
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Query instruction prefix for bge-small-en-v1.5 retrieval tasks.
|
|
33
|
-
*
|
|
34
|
-
* Per the BAAI model card: prepend this to short queries when searching
|
|
35
|
-
* for relevant passages. Do NOT prepend for documents/passages being stored.
|
|
36
|
-
*/
|
|
37
|
-
const QUERY_PREFIX = 'Represent this sentence for searching relevant passages: ';
|
|
28
|
+
/** Fixed output dimensionality for Qwen3-Embedding-0.6B. */
|
|
29
|
+
const EMBEDDING_DIM = 1024;
|
|
38
30
|
|
|
39
31
|
/** Lazily initialized feature extraction pipeline. */
|
|
40
32
|
let extractor: FeatureExtractionPipeline | null = null;
|
|
41
33
|
|
|
42
34
|
/**
|
|
43
|
-
* Generate a
|
|
35
|
+
* Generate a 1024-dimensional embedding vector for the given text.
|
|
44
36
|
*
|
|
45
|
-
* On first call, downloads and loads the ONNX model (~
|
|
46
|
-
* Subsequent calls reuse the loaded model and run in ~
|
|
37
|
+
* On first call, downloads and loads the ONNX model (~600MB, cached).
|
|
38
|
+
* Subsequent calls reuse the loaded model and run in ~100ms.
|
|
47
39
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* (`isQuery: false`) so no prefix is added.
|
|
40
|
+
* The isQuery option is accepted for forward compatibility but does not
|
|
41
|
+
* change behavior -- Qwen3 performs better without instruction prefixes.
|
|
51
42
|
*
|
|
52
43
|
* @param text - The text to embed.
|
|
53
44
|
* @param options - Optional settings.
|
|
54
|
-
* @param options.isQuery -
|
|
55
|
-
*
|
|
56
|
-
* @returns 384-dimensional normalized embedding as a number array.
|
|
45
|
+
* @param options.isQuery - Accepted for forward compatibility (no-op).
|
|
46
|
+
* @returns 1024-dimensional normalized embedding as a number array.
|
|
57
47
|
*/
|
|
58
48
|
export async function generateEmbedding(
|
|
59
49
|
text: string,
|
|
60
50
|
options?: { isQuery?: boolean },
|
|
61
51
|
): Promise<number[]> {
|
|
62
52
|
if (!extractor) {
|
|
53
|
+
console.log('Downloading embedding model (one-time setup, ~600MB)...');
|
|
63
54
|
extractor = await pipeline('feature-extraction', MODEL_ID, {
|
|
64
|
-
// Use quantized (int8) model for smaller download (~33.8MB vs ~67MB)
|
|
65
55
|
quantized: true,
|
|
66
56
|
});
|
|
57
|
+
console.log('Embedding model ready.');
|
|
67
58
|
}
|
|
68
59
|
|
|
69
|
-
const input =
|
|
70
|
-
const output = await extractor(input, { pooling: '
|
|
60
|
+
const input = text;
|
|
61
|
+
const output = await extractor(input, { pooling: 'last_token', normalize: true });
|
|
71
62
|
// output.data is a Float32Array; convert to plain number[]
|
|
72
63
|
return Array.from(output.data as Float32Array);
|
|
73
64
|
}
|
|
@@ -75,7 +66,7 @@ export async function generateEmbedding(
|
|
|
75
66
|
/**
|
|
76
67
|
* Get the embedding vector dimensionality.
|
|
77
68
|
*
|
|
78
|
-
* Always returns
|
|
69
|
+
* Always returns 1024 (fixed for Qwen3-Embedding-0.6B).
|
|
79
70
|
* This is needed by downstream code (e.g. LSH hasher) to know the vector
|
|
80
71
|
* size without calling the embedding model.
|
|
81
72
|
*/
|
package/index.ts
CHANGED
|
@@ -126,7 +126,10 @@ const SEMANTIC_SKIP_THRESHOLD = parseFloat(process.env.TOTALRECLAW_SEMANTIC_SKIP
|
|
|
126
126
|
|
|
127
127
|
// Auto-extract throttle (C3): only extract every N turns in agent_end hook
|
|
128
128
|
let turnsSinceLastExtraction = 0;
|
|
129
|
-
const AUTO_EXTRACT_EVERY_TURNS_ENV = parseInt(process.env.TOTALRECLAW_EXTRACT_EVERY_TURNS ?? '
|
|
129
|
+
const AUTO_EXTRACT_EVERY_TURNS_ENV = parseInt(process.env.TOTALRECLAW_EXTRACT_EVERY_TURNS ?? '3', 10);
|
|
130
|
+
|
|
131
|
+
// Hard cap on facts per extraction to prevent LLM over-extraction from dense conversations
|
|
132
|
+
const MAX_FACTS_PER_EXTRACTION = 15;
|
|
130
133
|
|
|
131
134
|
// Store-time near-duplicate detection (consolidation module)
|
|
132
135
|
const STORE_DEDUP_ENABLED = process.env.TOTALRECLAW_STORE_DEDUP !== 'false';
|
|
@@ -188,13 +191,11 @@ function isLlmDedupEnabled(): boolean {
|
|
|
188
191
|
}
|
|
189
192
|
|
|
190
193
|
/**
|
|
191
|
-
* Get the effective extraction interval
|
|
192
|
-
*
|
|
194
|
+
* Get the effective extraction interval.
|
|
195
|
+
* Unified to 3 turns for all tiers (quota is per-transaction, not per-memory).
|
|
193
196
|
*/
|
|
194
197
|
function getExtractInterval(): number {
|
|
195
|
-
|
|
196
|
-
const minInterval = cache?.features?.min_extract_interval ?? 5;
|
|
197
|
-
return Math.max(AUTO_EXTRACT_EVERY_TURNS_ENV, minInterval);
|
|
198
|
+
return AUTO_EXTRACT_EVERY_TURNS_ENV;
|
|
198
199
|
}
|
|
199
200
|
|
|
200
201
|
/**
|
|
@@ -517,7 +518,7 @@ async function generateEmbeddingAndLSH(
|
|
|
517
518
|
const hasher = getLSHHasher(logger);
|
|
518
519
|
const lshBuckets = hasher ? hasher.hash(embedding) : [];
|
|
519
520
|
|
|
520
|
-
// Encrypt the embedding (JSON array of numbers) for
|
|
521
|
+
// Encrypt the embedding (JSON array of numbers) for server-blind storage
|
|
521
522
|
const encryptedEmbedding = encryptToHex(JSON.stringify(embedding), encryptionKey!);
|
|
522
523
|
|
|
523
524
|
return { embedding, lshBuckets, encryptedEmbedding };
|
|
@@ -1177,7 +1178,7 @@ async function handlePluginImportFrom(
|
|
|
1177
1178
|
const plugin = {
|
|
1178
1179
|
id: 'totalreclaw',
|
|
1179
1180
|
name: 'TotalReclaw',
|
|
1180
|
-
description: '
|
|
1181
|
+
description: 'End-to-end encrypted memory vault for AI agents',
|
|
1181
1182
|
kind: 'memory' as const,
|
|
1182
1183
|
configSchema: {
|
|
1183
1184
|
type: 'object',
|
|
@@ -2548,7 +2549,13 @@ const plugin = {
|
|
|
2548
2549
|
? await fetchExistingMemoriesForExtraction(api.logger, 20, evt.messages)
|
|
2549
2550
|
: [];
|
|
2550
2551
|
const rawFacts = await extractFacts(evt.messages, 'turn', existingMemories);
|
|
2551
|
-
const { kept:
|
|
2552
|
+
const { kept: importanceFiltered } = filterByImportance(rawFacts, api.logger);
|
|
2553
|
+
if (importanceFiltered.length > MAX_FACTS_PER_EXTRACTION) {
|
|
2554
|
+
api.logger.info(
|
|
2555
|
+
`Capped extraction from ${importanceFiltered.length} to ${MAX_FACTS_PER_EXTRACTION} facts`,
|
|
2556
|
+
);
|
|
2557
|
+
}
|
|
2558
|
+
const facts = importanceFiltered.slice(0, MAX_FACTS_PER_EXTRACTION);
|
|
2552
2559
|
if (facts.length > 0) {
|
|
2553
2560
|
await storeExtractedFacts(facts, api.logger);
|
|
2554
2561
|
}
|
|
@@ -2584,7 +2591,13 @@ const plugin = {
|
|
|
2584
2591
|
? await fetchExistingMemoriesForExtraction(api.logger, 50, evt.messages)
|
|
2585
2592
|
: [];
|
|
2586
2593
|
const rawCompactFacts = await extractFacts(evt.messages, 'full', existingMemories);
|
|
2587
|
-
const { kept:
|
|
2594
|
+
const { kept: compactImportanceFiltered } = filterByImportance(rawCompactFacts, api.logger);
|
|
2595
|
+
if (compactImportanceFiltered.length > MAX_FACTS_PER_EXTRACTION) {
|
|
2596
|
+
api.logger.info(
|
|
2597
|
+
`Capped compaction extraction from ${compactImportanceFiltered.length} to ${MAX_FACTS_PER_EXTRACTION} facts`,
|
|
2598
|
+
);
|
|
2599
|
+
}
|
|
2600
|
+
const facts = compactImportanceFiltered.slice(0, MAX_FACTS_PER_EXTRACTION);
|
|
2588
2601
|
if (facts.length > 0) {
|
|
2589
2602
|
await storeExtractedFacts(facts, api.logger);
|
|
2590
2603
|
}
|
|
@@ -2619,7 +2632,13 @@ const plugin = {
|
|
|
2619
2632
|
? await fetchExistingMemoriesForExtraction(api.logger, 50, evt.messages)
|
|
2620
2633
|
: [];
|
|
2621
2634
|
const rawResetFacts = await extractFacts(evt.messages, 'full', existingMemories);
|
|
2622
|
-
const { kept:
|
|
2635
|
+
const { kept: resetImportanceFiltered } = filterByImportance(rawResetFacts, api.logger);
|
|
2636
|
+
if (resetImportanceFiltered.length > MAX_FACTS_PER_EXTRACTION) {
|
|
2637
|
+
api.logger.info(
|
|
2638
|
+
`Capped reset extraction from ${resetImportanceFiltered.length} to ${MAX_FACTS_PER_EXTRACTION} facts`,
|
|
2639
|
+
);
|
|
2640
|
+
}
|
|
2641
|
+
const facts = resetImportanceFiltered.slice(0, MAX_FACTS_PER_EXTRACTION);
|
|
2623
2642
|
if (facts.length > 0) {
|
|
2624
2643
|
await storeExtractedFacts(facts, api.logger);
|
|
2625
2644
|
}
|
package/lsh.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TotalReclaw Plugin - LSH Hasher (Locality-Sensitive Hashing)
|
|
3
3
|
*
|
|
4
|
-
* Pure TypeScript implementation of Random Hyperplane LSH for
|
|
4
|
+
* Pure TypeScript implementation of Random Hyperplane LSH for server-blind
|
|
5
5
|
* semantic search. Generates deterministic hyperplane matrices from a seed
|
|
6
6
|
* derived from the user's master key, so the same embedding always hashes to
|
|
7
7
|
* the same buckets across sessions.
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@totalreclaw/totalreclaw",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "End-to-end encrypted memory for AI agents — portable, yours forever. Automatic extraction, semantic search, and on-chain storage",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"totalreclaw",
|
|
8
8
|
"openclaw",
|
|
9
9
|
"ai-memory",
|
|
10
10
|
"ai-agent",
|
|
11
|
-
"
|
|
11
|
+
"e2e-encryption",
|
|
12
12
|
"encryption",
|
|
13
13
|
"e2ee",
|
|
14
14
|
"lsh",
|
package/subgraph-store.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { createPublicClient, http, type Hex, type Address, type Chain } from 'viem';
|
|
14
14
|
import { entryPoint07Address } from 'viem/account-abstraction';
|
|
15
15
|
import { mnemonicToAccount } from 'viem/accounts';
|
|
16
|
-
import { gnosis, gnosisChiado } from 'viem/chains';
|
|
16
|
+
import { gnosis, gnosisChiado, baseSepolia } from 'viem/chains';
|
|
17
17
|
import { createSmartAccountClient } from 'permissionless';
|
|
18
18
|
import { toSimpleSmartAccount } from 'permissionless/accounts';
|
|
19
19
|
import { createPimlicoClient } from 'permissionless/clients/pimlico';
|
|
@@ -32,7 +32,7 @@ export interface SubgraphStoreConfig {
|
|
|
32
32
|
relayUrl: string; // TotalReclaw relay server URL (proxies bundler + subgraph)
|
|
33
33
|
mnemonic: string; // BIP-39 mnemonic for key derivation
|
|
34
34
|
cachePath: string; // Hot cache file path
|
|
35
|
-
chainId: number; // 100 for Gnosis mainnet, 10200 for Chiado testnet
|
|
35
|
+
chainId: number; // 100 for Gnosis mainnet, 10200 for Chiado testnet, 84532 for Base Sepolia
|
|
36
36
|
dataEdgeAddress: string; // EventfulDataEdge contract address
|
|
37
37
|
entryPointAddress: string; // ERC-4337 EntryPoint v0.7
|
|
38
38
|
authKeyHex?: string; // HKDF auth key for relay server Authorization header
|
|
@@ -151,8 +151,10 @@ function getChainFromId(chainId: number): Chain {
|
|
|
151
151
|
return gnosis;
|
|
152
152
|
case 10200:
|
|
153
153
|
return gnosisChiado;
|
|
154
|
+
case 84532:
|
|
155
|
+
return baseSepolia;
|
|
154
156
|
default:
|
|
155
|
-
return
|
|
157
|
+
return gnosis;
|
|
156
158
|
}
|
|
157
159
|
}
|
|
158
160
|
|
|
@@ -311,7 +313,7 @@ export function isSubgraphMode(): boolean {
|
|
|
311
313
|
* This is the on-chain owner identity used in the subgraph.
|
|
312
314
|
*/
|
|
313
315
|
export async function deriveSmartAccountAddress(mnemonic: string, chainId?: number): Promise<string> {
|
|
314
|
-
const chain: Chain = (chainId ?? 100)
|
|
316
|
+
const chain: Chain = getChainFromId(chainId ?? 100);
|
|
315
317
|
const ownerAccount = mnemonicToAccount(mnemonic);
|
|
316
318
|
const entryPointAddr = (process.env.TOTALRECLAW_ENTRYPOINT_ADDRESS || DEFAULT_ENTRYPOINT_ADDRESS) as Address;
|
|
317
319
|
const rpcUrl = process.env.TOTALRECLAW_RPC_URL;
|