epistery 1.0.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/Architecture.md +84 -0
- package/CLI.md +291 -0
- package/LICENSE +21 -0
- package/MONGODB_GOTCHA.md +69 -0
- package/README.md +50 -0
- package/SESSION.md +98 -0
- package/cli/epistery.mjs +576 -0
- package/client/client.js +18 -0
- package/client/ethers.js +24441 -0
- package/client/ethers.min.js +1 -0
- package/client/export.js +67 -0
- package/client/status.html +707 -0
- package/client/wallet.js +213 -0
- package/client/witness.js +663 -0
- package/contracts/agent.sol +108 -0
- package/default.ini +14 -0
- package/docs/EpisteryModuleConfig.md +317 -0
- package/docs/blog-unified-config.md +125 -0
- package/hardhat.config.js +33 -0
- package/index.mjs +385 -0
- package/package.json +46 -0
- package/scripts/deploy-agent.js +33 -0
- package/scripts/verify-agent.js +39 -0
- package/src/epistery.ts +275 -0
- package/src/utils/Aqua.ts +194 -0
- package/src/utils/CliWallet.ts +334 -0
- package/src/utils/Config.ts +196 -0
- package/src/utils/Utils.ts +571 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/types.ts +114 -0
- package/test/README.md +50 -0
- package/test/index.html +13 -0
- package/test/package.json +15 -0
- package/test/server.mjs +87 -0
- package/tsconfig.json +26 -0
package/client/wallet.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Wallet - Base class for client wallets
|
|
3
|
+
*
|
|
4
|
+
* Handles wallet creation, persistence, and signing for Epistery
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Base Wallet class
|
|
8
|
+
export class Wallet {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.address = null;
|
|
11
|
+
this.publicKey = null;
|
|
12
|
+
this.source = null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Serialize only the essential data for persistence
|
|
16
|
+
toJSON() {
|
|
17
|
+
return {
|
|
18
|
+
address: this.address,
|
|
19
|
+
publicKey: this.publicKey,
|
|
20
|
+
source: this.source
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Factory method to create appropriate wallet type from saved data
|
|
25
|
+
static async fromJSON(data, ethers) {
|
|
26
|
+
if (data.source === 'web3') {
|
|
27
|
+
return await Web3Wallet.fromJSON(data, ethers);
|
|
28
|
+
} else if (data.source === 'local') {
|
|
29
|
+
return await BrowserWallet.fromJSON(data, ethers);
|
|
30
|
+
}
|
|
31
|
+
throw new Error(`Unknown wallet source: ${data.source}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Abstract methods - must be implemented by subclasses
|
|
35
|
+
async sign(message) {
|
|
36
|
+
throw new Error('sign() must be implemented by subclass');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static async create(ethers) {
|
|
40
|
+
throw new Error('create() must be implemented by subclass');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Web3 Wallet (MetaMask, etc.)
|
|
45
|
+
export class Web3Wallet extends Wallet {
|
|
46
|
+
constructor() {
|
|
47
|
+
super();
|
|
48
|
+
this.source = 'web3';
|
|
49
|
+
this.signer = null;
|
|
50
|
+
this.provider = null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
toJSON() {
|
|
54
|
+
// Only persist the essential data, not the complex objects
|
|
55
|
+
return {
|
|
56
|
+
...super.toJSON(),
|
|
57
|
+
// Don't serialize signer/provider - they'll be recreated
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static async fromJSON(data, ethers) {
|
|
62
|
+
const wallet = new Web3Wallet();
|
|
63
|
+
wallet.address = data.address;
|
|
64
|
+
wallet.publicKey = data.publicKey;
|
|
65
|
+
|
|
66
|
+
// Attempt to reconnect to Web3 provider
|
|
67
|
+
await wallet.reconnectWeb3(ethers);
|
|
68
|
+
return wallet;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static async create(ethers) {
|
|
72
|
+
const wallet = new Web3Wallet();
|
|
73
|
+
|
|
74
|
+
if (await wallet.connectWeb3(ethers)) {
|
|
75
|
+
return wallet;
|
|
76
|
+
}
|
|
77
|
+
return null; // Connection failed
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async connectWeb3(ethers) {
|
|
81
|
+
try {
|
|
82
|
+
if (typeof window !== 'undefined' && (window.ethereum || window.web3)) {
|
|
83
|
+
const provider = window.ethereum || window.web3.currentProvider;
|
|
84
|
+
|
|
85
|
+
// Request account access
|
|
86
|
+
const accounts = await provider.request({
|
|
87
|
+
method: 'eth_requestAccounts'
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (accounts && accounts.length > 0) {
|
|
91
|
+
this.address = accounts[0];
|
|
92
|
+
this.provider = new ethers.providers.Web3Provider(provider);
|
|
93
|
+
this.signer = this.provider.getSigner();
|
|
94
|
+
|
|
95
|
+
// Get public key from first signature
|
|
96
|
+
this.publicKey = await this.derivePublicKeyPlaceholder();
|
|
97
|
+
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return false;
|
|
102
|
+
} catch (error) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async reconnectWeb3(ethers) {
|
|
108
|
+
try {
|
|
109
|
+
if (typeof window !== 'undefined' && (window.ethereum || window.web3)) {
|
|
110
|
+
const provider = window.ethereum || window.web3.currentProvider;
|
|
111
|
+
this.provider = new ethers.providers.Web3Provider(provider);
|
|
112
|
+
this.signer = this.provider.getSigner();
|
|
113
|
+
|
|
114
|
+
// Verify the address matches what we have stored
|
|
115
|
+
const currentAddress = await this.signer.getAddress();
|
|
116
|
+
if (currentAddress.toLowerCase() !== this.address.toLowerCase()) {
|
|
117
|
+
this.address = currentAddress;
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
} catch (error) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async sign(message, ethers) {
|
|
128
|
+
if (!this.signer) {
|
|
129
|
+
throw new Error('Web3 signer not available');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const signature = await this.signer.signMessage(message);
|
|
133
|
+
|
|
134
|
+
// Always update public key from signature for Web3 wallets
|
|
135
|
+
if (ethers) {
|
|
136
|
+
this.publicKey = await this.derivePublicKeyFromSignature(message, signature, ethers);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return signature;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async derivePublicKeyPlaceholder() {
|
|
143
|
+
// Placeholder until we get a real signature
|
|
144
|
+
return `0x04${this.address.slice(2)}${'0'.repeat(64)}`;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async derivePublicKeyFromSignature(message, signature, ethers) {
|
|
148
|
+
try {
|
|
149
|
+
const messageHash = ethers.utils.hashMessage(message);
|
|
150
|
+
return ethers.utils.recoverPublicKey(messageHash, signature);
|
|
151
|
+
} catch (error) {
|
|
152
|
+
console.error('Failed to derive public key from signature:', error);
|
|
153
|
+
return this.derivePublicKeyPlaceholder();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Browser Wallet (Local Storage)
|
|
159
|
+
export class BrowserWallet extends Wallet {
|
|
160
|
+
constructor() {
|
|
161
|
+
super();
|
|
162
|
+
this.source = 'local';
|
|
163
|
+
this.mnemonic = null;
|
|
164
|
+
this.privateKey = null;
|
|
165
|
+
this.signer = null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
toJSON() {
|
|
169
|
+
return {
|
|
170
|
+
...super.toJSON(),
|
|
171
|
+
mnemonic: this.mnemonic,
|
|
172
|
+
privateKey: this.privateKey
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
static async fromJSON(data, ethers) {
|
|
177
|
+
const wallet = new BrowserWallet();
|
|
178
|
+
wallet.address = data.address;
|
|
179
|
+
wallet.publicKey = data.publicKey;
|
|
180
|
+
wallet.mnemonic = data.mnemonic;
|
|
181
|
+
wallet.privateKey = data.privateKey;
|
|
182
|
+
|
|
183
|
+
// Recreate the signer
|
|
184
|
+
if (wallet.mnemonic) {
|
|
185
|
+
wallet.signer = ethers.Wallet.fromMnemonic(wallet.mnemonic);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return wallet;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
static async create(ethers) {
|
|
192
|
+
const wallet = new BrowserWallet();
|
|
193
|
+
|
|
194
|
+
// Generate new wallet
|
|
195
|
+
const ethersWallet = ethers.Wallet.createRandom();
|
|
196
|
+
|
|
197
|
+
wallet.address = ethersWallet.address;
|
|
198
|
+
wallet.mnemonic = ethersWallet.mnemonic?.phrase || '';
|
|
199
|
+
wallet.publicKey = ethersWallet.publicKey;
|
|
200
|
+
wallet.privateKey = ethersWallet.privateKey;
|
|
201
|
+
wallet.signer = ethersWallet;
|
|
202
|
+
|
|
203
|
+
return wallet;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async sign(message) {
|
|
207
|
+
if (!this.signer) {
|
|
208
|
+
throw new Error('Browser wallet signer not available');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return await this.signer.signMessage(message);
|
|
212
|
+
}
|
|
213
|
+
}
|