@namera-ai/cli 0.1.4 → 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/README.md +91 -221
- package/dist/index.js +1660 -0
- package/dist/index.js.map +1 -0
- package/package.json +57 -50
- package/LICENSE +0 -201
- package/dist/commands/index.mjs +0 -21
- package/dist/commands/index.mjs.map +0 -1
- package/dist/commands/keystore/create.mjs +0 -74
- package/dist/commands/keystore/create.mjs.map +0 -1
- package/dist/commands/keystore/decrypt.mjs +0 -71
- package/dist/commands/keystore/decrypt.mjs.map +0 -1
- package/dist/commands/keystore/import.mjs +0 -84
- package/dist/commands/keystore/import.mjs.map +0 -1
- package/dist/commands/keystore/index.mjs +0 -28
- package/dist/commands/keystore/index.mjs.map +0 -1
- package/dist/commands/keystore/info.mjs +0 -62
- package/dist/commands/keystore/info.mjs.map +0 -1
- package/dist/commands/keystore/list.mjs +0 -46
- package/dist/commands/keystore/list.mjs.map +0 -1
- package/dist/commands/keystore/remove.mjs +0 -51
- package/dist/commands/keystore/remove.mjs.map +0 -1
- package/dist/commands/mcp/index.mjs +0 -13
- package/dist/commands/mcp/index.mjs.map +0 -1
- package/dist/commands/mcp/start.mjs +0 -82
- package/dist/commands/mcp/start.mjs.map +0 -1
- package/dist/commands/schema/index.mjs +0 -53
- package/dist/commands/schema/index.mjs.map +0 -1
- package/dist/commands/session-key/create/index.mjs +0 -87
- package/dist/commands/session-key/create/index.mjs.map +0 -1
- package/dist/commands/session-key/create/prompts/base.mjs +0 -52
- package/dist/commands/session-key/create/prompts/base.mjs.map +0 -1
- package/dist/commands/session-key/create/prompts/call.mjs +0 -85
- package/dist/commands/session-key/create/prompts/call.mjs.map +0 -1
- package/dist/commands/session-key/create/prompts/common.mjs +0 -27
- package/dist/commands/session-key/create/prompts/common.mjs.map +0 -1
- package/dist/commands/session-key/create/prompts/gas.mjs +0 -19
- package/dist/commands/session-key/create/prompts/gas.mjs.map +0 -1
- package/dist/commands/session-key/create/prompts/index.mjs +0 -44
- package/dist/commands/session-key/create/prompts/index.mjs.map +0 -1
- package/dist/commands/session-key/create/prompts/rate-limit.mjs +0 -40
- package/dist/commands/session-key/create/prompts/rate-limit.mjs.map +0 -1
- package/dist/commands/session-key/create/prompts/signature-caller.mjs +0 -26
- package/dist/commands/session-key/create/prompts/signature-caller.mjs.map +0 -1
- package/dist/commands/session-key/create/prompts/timestamp.mjs +0 -32
- package/dist/commands/session-key/create/prompts/timestamp.mjs.map +0 -1
- package/dist/commands/session-key/index.mjs +0 -26
- package/dist/commands/session-key/index.mjs.map +0 -1
- package/dist/commands/session-key/info.mjs +0 -64
- package/dist/commands/session-key/info.mjs.map +0 -1
- package/dist/commands/session-key/list.mjs +0 -54
- package/dist/commands/session-key/list.mjs.map +0 -1
- package/dist/commands/session-key/remove.mjs +0 -51
- package/dist/commands/session-key/remove.mjs.map +0 -1
- package/dist/commands/session-key/status.mjs +0 -64
- package/dist/commands/session-key/status.mjs.map +0 -1
- package/dist/commands/smart-account/create.mjs +0 -94
- package/dist/commands/smart-account/create.mjs.map +0 -1
- package/dist/commands/smart-account/import.mjs +0 -45
- package/dist/commands/smart-account/import.mjs.map +0 -1
- package/dist/commands/smart-account/index.mjs +0 -30
- package/dist/commands/smart-account/index.mjs.map +0 -1
- package/dist/commands/smart-account/info.mjs +0 -66
- package/dist/commands/smart-account/info.mjs.map +0 -1
- package/dist/commands/smart-account/list.mjs +0 -48
- package/dist/commands/smart-account/list.mjs.map +0 -1
- package/dist/commands/smart-account/remove.mjs +0 -54
- package/dist/commands/smart-account/remove.mjs.map +0 -1
- package/dist/commands/smart-account/status.mjs +0 -63
- package/dist/commands/smart-account/status.mjs.map +0 -1
- package/dist/dto/index.mjs +0 -6
- package/dist/dto/keystore.mjs +0 -44
- package/dist/dto/keystore.mjs.map +0 -1
- package/dist/dto/mcp.mjs +0 -13
- package/dist/dto/mcp.mjs.map +0 -1
- package/dist/dto/session-key.mjs +0 -54
- package/dist/dto/session-key.mjs.map +0 -1
- package/dist/dto/smart-account.mjs +0 -45
- package/dist/dto/smart-account.mjs.map +0 -1
- package/dist/flags/global.mjs +0 -29
- package/dist/flags/global.mjs.map +0 -1
- package/dist/flags/shared.mjs +0 -11
- package/dist/flags/shared.mjs.map +0 -1
- package/dist/helpers/humanize.mjs +0 -153
- package/dist/helpers/humanize.mjs.map +0 -1
- package/dist/helpers/paths.mjs +0 -31
- package/dist/helpers/paths.mjs.map +0 -1
- package/dist/helpers/policy.mjs +0 -89
- package/dist/helpers/policy.mjs.map +0 -1
- package/dist/helpers/pretty.mjs +0 -71
- package/dist/helpers/pretty.mjs.map +0 -1
- package/dist/index.d.mts +0 -2
- package/dist/index.mjs +0 -36
- package/dist/index.mjs.map +0 -1
- package/dist/layers/config.mjs +0 -124
- package/dist/layers/config.mjs.map +0 -1
- package/dist/layers/index.mjs +0 -11
- package/dist/layers/keystore.mjs +0 -225
- package/dist/layers/keystore.mjs.map +0 -1
- package/dist/layers/mcp-context.mjs +0 -8
- package/dist/layers/mcp-context.mjs.map +0 -1
- package/dist/layers/mcp.mjs +0 -31
- package/dist/layers/mcp.mjs.map +0 -1
- package/dist/layers/output.mjs +0 -21
- package/dist/layers/output.mjs.map +0 -1
- package/dist/layers/prompt.mjs +0 -78
- package/dist/layers/prompt.mjs.map +0 -1
- package/dist/layers/session-key.mjs +0 -218
- package/dist/layers/session-key.mjs.map +0 -1
- package/dist/layers/smart-account.mjs +0 -175
- package/dist/layers/smart-account.mjs.map +0 -1
- package/dist/layers/web3.mjs +0 -83
- package/dist/layers/web3.mjs.map +0 -1
- package/dist/mcp/helpers/common.mjs +0 -9
- package/dist/mcp/helpers/common.mjs.map +0 -1
- package/dist/mcp/helpers/index.mjs +0 -4
- package/dist/mcp/helpers/session-key.mjs +0 -129
- package/dist/mcp/helpers/session-key.mjs.map +0 -1
- package/dist/mcp/index.mjs +0 -43
- package/dist/mcp/index.mjs.map +0 -1
- package/dist/mcp/mcp.mjs +0 -15
- package/dist/mcp/mcp.mjs.map +0 -1
- package/dist/mcp/tools/account/address.mjs +0 -20
- package/dist/mcp/tools/account/address.mjs.map +0 -1
- package/dist/mcp/tools/account/get-balance.mjs +0 -54
- package/dist/mcp/tools/account/get-balance.mjs.map +0 -1
- package/dist/mcp/tools/account/index.mjs +0 -15
- package/dist/mcp/tools/account/index.mjs.map +0 -1
- package/dist/mcp/tools/read/index.mjs +0 -11
- package/dist/mcp/tools/read/index.mjs.map +0 -1
- package/dist/mcp/tools/read/read-contract.mjs +0 -49
- package/dist/mcp/tools/read/read-contract.mjs.map +0 -1
- package/dist/mcp/tools/transaction/execute-transaction.mjs +0 -38
- package/dist/mcp/tools/transaction/execute-transaction.mjs.map +0 -1
- package/dist/mcp/tools/transaction/index.mjs +0 -15
- package/dist/mcp/tools/transaction/index.mjs.map +0 -1
- package/dist/mcp/tools/transaction/native-transfer.mjs +0 -59
- package/dist/mcp/tools/transaction/native-transfer.mjs.map +0 -1
- package/dist/schema/chain.mjs +0 -124
- package/dist/schema/chain.mjs.map +0 -1
- package/dist/schema/common.mjs +0 -29
- package/dist/schema/common.mjs.map +0 -1
- package/dist/schema/index.mjs +0 -5
- package/dist/schema/policy.mjs +0 -114
- package/dist/schema/policy.mjs.map +0 -1
- package/dist/schema/tx.mjs +0 -19
- package/dist/schema/tx.mjs.map +0 -1
- package/dist/types/index.mjs +0 -11
- package/dist/types/index.mjs.map +0 -1
package/dist/layers/keystore.mjs
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { ConfigManager } from "./config.mjs";
|
|
3
|
-
import { PromptManager } from "./prompt.mjs";
|
|
4
|
-
import { Context, Data, Effect, Layer, Redacted } from "effect";
|
|
5
|
-
import { Wallet } from "@ethereumjs/wallet";
|
|
6
|
-
import { hexToBytes, toHex } from "viem";
|
|
7
|
-
import { privateKeyToAccount } from "viem/accounts";
|
|
8
|
-
//#region src/layers/keystore.ts
|
|
9
|
-
/**
|
|
10
|
-
* Service tag for resolving {@link KeystoreManager} from the Effect context.
|
|
11
|
-
*/
|
|
12
|
-
const KeystoreManager = Context.Service("@namera-ai/cli/KeystoreManager");
|
|
13
|
-
/**
|
|
14
|
-
* Domain error for keystore management operations.
|
|
15
|
-
*/
|
|
16
|
-
var KeystoreManagerError = class extends Data.TaggedError("@namera-ai/cli/KeystoreManagerError") {};
|
|
17
|
-
/**
|
|
18
|
-
* Live layer wiring the keystore manager with configuration and prompts.
|
|
19
|
-
*/
|
|
20
|
-
const layer = Layer.effect(KeystoreManager, Effect.gen(function* () {
|
|
21
|
-
const configManager = yield* ConfigManager;
|
|
22
|
-
const promptManager = yield* PromptManager;
|
|
23
|
-
const getKeystore = (params) => Effect.gen(function* () {
|
|
24
|
-
const res = yield* configManager.getEntity({
|
|
25
|
-
alias: params.alias,
|
|
26
|
-
type: "keystore"
|
|
27
|
-
});
|
|
28
|
-
const parsedKeystore = yield* Effect.try({
|
|
29
|
-
catch: () => new KeystoreManagerError({
|
|
30
|
-
code: "KeystoreParseError",
|
|
31
|
-
message: "Unable to parse keystore"
|
|
32
|
-
}),
|
|
33
|
-
try: () => JSON.parse(res.content)
|
|
34
|
-
});
|
|
35
|
-
return {
|
|
36
|
-
alias: res.alias,
|
|
37
|
-
data: {
|
|
38
|
-
...parsedKeystore,
|
|
39
|
-
address: `0x${parsedKeystore.address}`
|
|
40
|
-
},
|
|
41
|
-
path: res.path
|
|
42
|
-
};
|
|
43
|
-
});
|
|
44
|
-
const listKeystores = () => Effect.gen(function* () {
|
|
45
|
-
const effects = (yield* configManager.getEntitiesForType("keystore")).map((entity) => Effect.gen(function* () {
|
|
46
|
-
const parsedKeystore = yield* Effect.try({
|
|
47
|
-
catch: () => new KeystoreManagerError({
|
|
48
|
-
code: "KeystoreParseError",
|
|
49
|
-
message: "Unable to parse keystore"
|
|
50
|
-
}),
|
|
51
|
-
try: () => JSON.parse(entity.content)
|
|
52
|
-
});
|
|
53
|
-
return {
|
|
54
|
-
alias: entity.alias,
|
|
55
|
-
data: {
|
|
56
|
-
...parsedKeystore,
|
|
57
|
-
address: `0x${parsedKeystore.address}`
|
|
58
|
-
},
|
|
59
|
-
path: entity.path
|
|
60
|
-
};
|
|
61
|
-
}));
|
|
62
|
-
return yield* Effect.all(effects, { concurrency: "unbounded" });
|
|
63
|
-
});
|
|
64
|
-
const createKeystore = (params) => Effect.gen(function* () {
|
|
65
|
-
const entityPath = yield* configManager.getEntityPath({
|
|
66
|
-
alias: params.alias,
|
|
67
|
-
type: "keystore"
|
|
68
|
-
});
|
|
69
|
-
if (yield* configManager.checkEntityExists({
|
|
70
|
-
alias: params.alias,
|
|
71
|
-
type: "keystore"
|
|
72
|
-
})) return yield* Effect.fail(new KeystoreManagerError({
|
|
73
|
-
code: "KeystoreAlreadyExists",
|
|
74
|
-
message: `Keystore with alias ${params.alias} already exists`
|
|
75
|
-
}));
|
|
76
|
-
const keystoreString = yield* Effect.tryPromise({
|
|
77
|
-
catch: () => new KeystoreManagerError({
|
|
78
|
-
code: "KeystoreCreationFailed",
|
|
79
|
-
message: "Failed to create keystore"
|
|
80
|
-
}),
|
|
81
|
-
try: () => Wallet.generate().toV3String(params.password)
|
|
82
|
-
});
|
|
83
|
-
yield* configManager.storeEntity({
|
|
84
|
-
alias: params.alias,
|
|
85
|
-
content: keystoreString,
|
|
86
|
-
path: entityPath,
|
|
87
|
-
type: "keystore"
|
|
88
|
-
});
|
|
89
|
-
const keystore = yield* Effect.try({
|
|
90
|
-
catch: () => new KeystoreManagerError({
|
|
91
|
-
code: "KeystoreParseError",
|
|
92
|
-
message: "Unable to parse keystore"
|
|
93
|
-
}),
|
|
94
|
-
try: () => JSON.parse(keystoreString)
|
|
95
|
-
});
|
|
96
|
-
return {
|
|
97
|
-
alias: params.alias,
|
|
98
|
-
data: {
|
|
99
|
-
...keystore,
|
|
100
|
-
address: `0x${keystore.address}`
|
|
101
|
-
},
|
|
102
|
-
path: entityPath
|
|
103
|
-
};
|
|
104
|
-
});
|
|
105
|
-
const decryptKeystore = (params) => Effect.gen(function* () {
|
|
106
|
-
const keystore = yield* getKeystore({ alias: params.alias });
|
|
107
|
-
const wallet = yield* Effect.tryPromise({
|
|
108
|
-
catch: () => new KeystoreManagerError({
|
|
109
|
-
code: "KeystoreDecryptionFailed",
|
|
110
|
-
message: "Failed to decrypt keystore"
|
|
111
|
-
}),
|
|
112
|
-
try: () => Wallet.fromV3(keystore.data, params.password)
|
|
113
|
-
});
|
|
114
|
-
return {
|
|
115
|
-
address: wallet.getChecksumAddressString(),
|
|
116
|
-
alias: params.alias,
|
|
117
|
-
privateKey: Redacted.make(wallet.getPrivateKeyString()),
|
|
118
|
-
publicKey: wallet.getPublicKeyString()
|
|
119
|
-
};
|
|
120
|
-
});
|
|
121
|
-
const selectKeystore = (params) => Effect.gen(function* () {
|
|
122
|
-
const keystores = yield* listKeystores();
|
|
123
|
-
return yield* promptManager.selectPrompt({
|
|
124
|
-
message: params.message,
|
|
125
|
-
choices: keystores.map((k) => ({
|
|
126
|
-
title: k.alias,
|
|
127
|
-
value: k,
|
|
128
|
-
description: k.data.address
|
|
129
|
-
}))
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
const importKeystore = (params) => Effect.gen(function* () {
|
|
133
|
-
const entityPath = yield* configManager.getEntityPath({
|
|
134
|
-
alias: params.alias,
|
|
135
|
-
type: "keystore"
|
|
136
|
-
});
|
|
137
|
-
if (yield* configManager.checkEntityExists({
|
|
138
|
-
alias: params.alias,
|
|
139
|
-
type: "keystore"
|
|
140
|
-
})) return yield* Effect.fail(new KeystoreManagerError({
|
|
141
|
-
code: "KeystoreAlreadyExists",
|
|
142
|
-
message: `Keystore with alias ${params.alias} already exists`
|
|
143
|
-
}));
|
|
144
|
-
const keystoreString = yield* Effect.tryPromise({
|
|
145
|
-
catch: () => new KeystoreManagerError({
|
|
146
|
-
code: "KeystoreCreationFailed",
|
|
147
|
-
message: "Failed to create keystore"
|
|
148
|
-
}),
|
|
149
|
-
try: () => Wallet.fromPrivateKey(hexToBytes(params.privateKey)).toV3String(params.password)
|
|
150
|
-
});
|
|
151
|
-
yield* configManager.storeEntity({
|
|
152
|
-
alias: params.alias,
|
|
153
|
-
content: keystoreString,
|
|
154
|
-
path: entityPath,
|
|
155
|
-
type: "keystore"
|
|
156
|
-
});
|
|
157
|
-
const keystore = yield* Effect.try({
|
|
158
|
-
catch: () => new KeystoreManagerError({
|
|
159
|
-
code: "KeystoreParseError",
|
|
160
|
-
message: "Unable to parse keystore"
|
|
161
|
-
}),
|
|
162
|
-
try: () => JSON.parse(keystoreString)
|
|
163
|
-
});
|
|
164
|
-
return {
|
|
165
|
-
alias: params.alias,
|
|
166
|
-
data: keystore,
|
|
167
|
-
path: entityPath
|
|
168
|
-
};
|
|
169
|
-
});
|
|
170
|
-
const removeKeystore = (params) => Effect.gen(function* () {
|
|
171
|
-
if (!(yield* configManager.checkEntityExists({
|
|
172
|
-
alias: params.alias,
|
|
173
|
-
type: "keystore"
|
|
174
|
-
}))) return yield* Effect.fail(new KeystoreManagerError({
|
|
175
|
-
code: "KeystoreNotFound",
|
|
176
|
-
message: `Keystore with alias ${params.alias} does not exist`
|
|
177
|
-
}));
|
|
178
|
-
return yield* configManager.removeEntity({
|
|
179
|
-
alias: params.alias,
|
|
180
|
-
type: "keystore"
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
const getSigner = (params) => Effect.gen(function* () {
|
|
184
|
-
const keystore = yield* getKeystore({ alias: params.alias });
|
|
185
|
-
return privateKeyToAccount(toHex((yield* Effect.tryPromise({
|
|
186
|
-
catch: () => new KeystoreManagerError({
|
|
187
|
-
code: "KeystoreDecryptionFailed",
|
|
188
|
-
message: "Failed to decrypt keystore"
|
|
189
|
-
}),
|
|
190
|
-
try: () => Wallet.fromV3(keystore.data, params.password)
|
|
191
|
-
})).getPrivateKey()));
|
|
192
|
-
});
|
|
193
|
-
const getKeystorePassword = (params) => Effect.gen(function* () {
|
|
194
|
-
const keystore = yield* getKeystore({ alias: params.alias });
|
|
195
|
-
return yield* promptManager.passwordPrompt({
|
|
196
|
-
message: params.message,
|
|
197
|
-
validate: (v) => Effect.gen(function* () {
|
|
198
|
-
if (v.trim() === "") return yield* Effect.fail("Password cannot be empty");
|
|
199
|
-
yield* Effect.tryPromise({
|
|
200
|
-
try: () => Wallet.fromV3(keystore.data, v),
|
|
201
|
-
catch: () => new KeystoreManagerError({
|
|
202
|
-
code: "DecryptError",
|
|
203
|
-
message: `Invalid password for keystore ${params.alias}`
|
|
204
|
-
})
|
|
205
|
-
}).pipe(Effect.catch(() => Effect.fail("Invalid password")));
|
|
206
|
-
return v;
|
|
207
|
-
})
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
return KeystoreManager.of({
|
|
211
|
-
createKeystore,
|
|
212
|
-
decryptKeystore,
|
|
213
|
-
getKeystore,
|
|
214
|
-
listKeystores,
|
|
215
|
-
selectKeystore,
|
|
216
|
-
importKeystore,
|
|
217
|
-
removeKeystore,
|
|
218
|
-
getSigner,
|
|
219
|
-
getKeystorePassword
|
|
220
|
-
});
|
|
221
|
-
}));
|
|
222
|
-
//#endregion
|
|
223
|
-
export { KeystoreManager, layer };
|
|
224
|
-
|
|
225
|
-
//# sourceMappingURL=keystore.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"keystore.mjs","names":["EthereumJSWallet"],"sources":["../../src/layers/keystore.ts"],"sourcesContent":["import { Wallet as EthereumJSWallet, Wallet } from \"@ethereumjs/wallet\";\nimport { Context, Data, Effect, Layer, Redacted } from \"effect\";\nimport type { QuitError } from \"effect/Terminal\";\nimport type { Prompt } from \"effect/unstable/cli\";\nimport type { Environment } from \"effect/unstable/cli/Prompt\";\nimport { type Hex, hexToBytes, toHex } from \"viem\";\nimport { type LocalAccount, privateKeyToAccount } from \"viem/accounts\";\n\nimport type {\n CreateKeystoreParams,\n DecryptKeystoreParams,\n DecryptKeystoreResponse,\n GetKeystoreParams,\n GetSignerParams,\n ImportKeystoreParams,\n Keystore,\n KeystoreData,\n RemoveKeystoreParams,\n} from \"@/dto\";\n\nimport { ConfigManager, type ConfigManagerError } from \"./config\";\nimport { PromptManager } from \"./prompt\";\n\n/**\n * Effect service for keystore CRUD, selection, and decryption operations.\n */\nexport type KeystoreManager = {\n /**\n * Loads a keystore by alias and parses it into a typed keystore data object.\n *\n * @param params - Alias for the keystore to load.\n */\n getKeystore: (\n params: GetKeystoreParams,\n ) => Effect.Effect<KeystoreData, ConfigManagerError | KeystoreManagerError>;\n /**\n * Lists all stored keystores, parsing each into a typed keystore data object.\n */\n listKeystores: () => Effect.Effect<\n KeystoreData[],\n ConfigManagerError | KeystoreManagerError\n >;\n /**\n * Opens an interactive prompt to select a keystore from stored entries.\n *\n * @param params - Prompt message.\n */\n selectKeystore: (params: {\n message: string;\n }) => Effect.Effect<\n KeystoreData,\n ConfigManagerError | KeystoreManagerError | QuitError,\n Environment\n >;\n /**\n * Creates a new random wallet, encrypts it, and stores as a keystore.\n *\n * @param params - Alias and password used for the new keystore.\n */\n createKeystore: (\n params: CreateKeystoreParams,\n ) => Effect.Effect<KeystoreData, ConfigManagerError | KeystoreManagerError>;\n /**\n * Decrypts a keystore and returns key material.\n *\n * @param params - Alias and password for the keystore to decrypt.\n */\n decryptKeystore: (\n params: DecryptKeystoreParams,\n ) => Effect.Effect<\n DecryptKeystoreResponse,\n KeystoreManagerError | ConfigManagerError\n >;\n /**\n * Imports a keystore from a private key and stores as a keystore.\n *\n * @param params - Alias and private key for the keystore to import.\n */\n importKeystore: (\n params: ImportKeystoreParams,\n ) => Effect.Effect<\n KeystoreData,\n ConfigManagerError | KeystoreManagerError,\n never\n >;\n /**\n * Removes a keystore from storage.\n *\n * @param params - Alias of the keystore to remove.\n */\n removeKeystore: (params: {\n readonly alias: string;\n }) => Effect.Effect<void, ConfigManagerError | KeystoreManagerError, never>;\n getSigner: (\n params: GetSignerParams,\n ) => Effect.Effect<LocalAccount, ConfigManagerError | KeystoreManagerError>;\n /**\n * Prompts the user to enter the password for a keystore.\n *\n * @param params - Alias of the keystore and message to display.\n * @returns The password for the keystore.\n */\n getKeystorePassword: (params: {\n alias: string;\n message: string;\n }) => Effect.Effect<\n Redacted.Redacted<string>,\n ConfigManagerError | KeystoreManagerError | QuitError,\n Prompt.Environment\n >;\n};\n\n/**\n * Service tag for resolving {@link KeystoreManager} from the Effect context.\n */\nexport const KeystoreManager = Context.Service<KeystoreManager>(\n \"@namera-ai/cli/KeystoreManager\",\n);\n\n/**\n * Domain error for keystore management operations.\n */\nexport class KeystoreManagerError extends Data.TaggedError(\n \"@namera-ai/cli/KeystoreManagerError\",\n)<{\n code:\n | \"KeystoreParseError\"\n | \"KeystoreAlreadyExists\"\n | \"KeystoreCreationFailed\"\n | \"KeystoreDecryptionFailed\"\n | \"KeystoreNotFound\"\n | \"DecryptError\";\n message: string;\n}> {}\n\n/**\n * Live layer wiring the keystore manager with configuration and prompts.\n */\nexport const layer = Layer.effect(\n KeystoreManager,\n Effect.gen(function* () {\n const configManager = yield* ConfigManager;\n const promptManager = yield* PromptManager;\n\n const getKeystore = (params: GetKeystoreParams) =>\n Effect.gen(function* () {\n const res = yield* configManager.getEntity({\n alias: params.alias,\n type: \"keystore\",\n });\n\n const parsedKeystore = yield* Effect.try({\n catch: () =>\n new KeystoreManagerError({\n code: \"KeystoreParseError\",\n message: \"Unable to parse keystore\",\n }),\n try: () => JSON.parse(res.content) as Keystore,\n });\n\n const wallet: KeystoreData = {\n alias: res.alias,\n data: {\n ...parsedKeystore,\n address: `0x${parsedKeystore.address}`,\n },\n path: res.path,\n };\n\n return wallet;\n });\n\n const listKeystores = () =>\n Effect.gen(function* () {\n const res = yield* configManager.getEntitiesForType(\"keystore\");\n\n const effects = res.map((entity) =>\n Effect.gen(function* () {\n const parsedKeystore = yield* Effect.try({\n catch: () =>\n new KeystoreManagerError({\n code: \"KeystoreParseError\",\n message: \"Unable to parse keystore\",\n }),\n try: () => JSON.parse(entity.content) as Keystore,\n });\n\n const wallet: KeystoreData = {\n alias: entity.alias,\n data: {\n ...parsedKeystore,\n address: `0x${parsedKeystore.address}`,\n },\n path: entity.path,\n };\n\n return wallet;\n }),\n );\n\n return yield* Effect.all(effects, { concurrency: \"unbounded\" });\n });\n\n const createKeystore = (params: CreateKeystoreParams) =>\n Effect.gen(function* () {\n const entityPath = yield* configManager.getEntityPath({\n alias: params.alias,\n type: \"keystore\",\n });\n\n // Check if alias is already taken\n const aliasTaken = yield* configManager.checkEntityExists({\n alias: params.alias,\n type: \"keystore\",\n });\n\n if (aliasTaken) {\n return yield* Effect.fail(\n new KeystoreManagerError({\n code: \"KeystoreAlreadyExists\",\n message: `Keystore with alias ${params.alias} already exists`,\n }),\n );\n }\n\n const keystoreString = yield* Effect.tryPromise({\n catch: () =>\n new KeystoreManagerError({\n code: \"KeystoreCreationFailed\",\n message: \"Failed to create keystore\",\n }),\n try: () => EthereumJSWallet.generate().toV3String(params.password),\n });\n\n // Store Entity\n yield* configManager.storeEntity({\n alias: params.alias,\n content: keystoreString,\n path: entityPath,\n type: \"keystore\",\n });\n\n const keystore = yield* Effect.try({\n catch: () =>\n new KeystoreManagerError({\n code: \"KeystoreParseError\",\n message: \"Unable to parse keystore\",\n }),\n try: () => JSON.parse(keystoreString) as Keystore,\n });\n\n const data: KeystoreData = {\n alias: params.alias,\n data: {\n ...keystore,\n address: `0x${keystore.address}`,\n },\n path: entityPath,\n };\n\n return data;\n });\n\n const decryptKeystore = (params: DecryptKeystoreParams) =>\n Effect.gen(function* () {\n const keystore = yield* getKeystore({\n alias: params.alias,\n });\n\n const wallet = yield* Effect.tryPromise({\n catch: () =>\n new KeystoreManagerError({\n code: \"KeystoreDecryptionFailed\",\n message: \"Failed to decrypt keystore\",\n }),\n try: () => EthereumJSWallet.fromV3(keystore.data, params.password),\n });\n\n return {\n address: wallet.getChecksumAddressString(),\n alias: params.alias,\n privateKey: Redacted.make(wallet.getPrivateKeyString()),\n publicKey: wallet.getPublicKeyString(),\n };\n });\n\n const selectKeystore = (params: { message: string }) =>\n Effect.gen(function* () {\n const keystores = yield* listKeystores();\n\n const res = yield* promptManager.selectPrompt({\n message: params.message,\n choices: keystores.map((k) => ({\n title: k.alias,\n value: k,\n description: k.data.address,\n })) satisfies Prompt.SelectChoice<KeystoreData>[],\n });\n\n return res;\n });\n\n const importKeystore = (params: ImportKeystoreParams) =>\n Effect.gen(function* () {\n const entityPath = yield* configManager.getEntityPath({\n alias: params.alias,\n type: \"keystore\",\n });\n\n // Check if alias is already taken\n const aliasTaken = yield* configManager.checkEntityExists({\n alias: params.alias,\n type: \"keystore\",\n });\n\n if (aliasTaken) {\n return yield* Effect.fail(\n new KeystoreManagerError({\n code: \"KeystoreAlreadyExists\",\n message: `Keystore with alias ${params.alias} already exists`,\n }),\n );\n }\n\n const keystoreString = yield* Effect.tryPromise({\n catch: () =>\n new KeystoreManagerError({\n code: \"KeystoreCreationFailed\",\n message: \"Failed to create keystore\",\n }),\n try: () =>\n EthereumJSWallet.fromPrivateKey(\n hexToBytes(params.privateKey as Hex),\n ).toV3String(params.password),\n });\n\n // Store Entity\n yield* configManager.storeEntity({\n alias: params.alias,\n content: keystoreString,\n path: entityPath,\n type: \"keystore\",\n });\n\n const keystore = yield* Effect.try({\n catch: () =>\n new KeystoreManagerError({\n code: \"KeystoreParseError\",\n message: \"Unable to parse keystore\",\n }),\n try: () => JSON.parse(keystoreString) as Keystore,\n });\n\n const data: KeystoreData = {\n alias: params.alias,\n data: keystore,\n path: entityPath,\n };\n\n return data;\n });\n\n const removeKeystore = (params: RemoveKeystoreParams) =>\n Effect.gen(function* () {\n // Check if alias exists\n const exists = yield* configManager.checkEntityExists({\n alias: params.alias,\n type: \"keystore\",\n });\n\n if (!exists) {\n return yield* Effect.fail(\n new KeystoreManagerError({\n code: \"KeystoreNotFound\",\n message: `Keystore with alias ${params.alias} does not exist`,\n }),\n );\n }\n\n return yield* configManager.removeEntity({\n alias: params.alias,\n type: \"keystore\",\n });\n });\n\n const getSigner = (params: GetSignerParams) =>\n Effect.gen(function* () {\n const keystore = yield* getKeystore({ alias: params.alias });\n\n const wallet = yield* Effect.tryPromise({\n catch: () =>\n new KeystoreManagerError({\n code: \"KeystoreDecryptionFailed\",\n message: \"Failed to decrypt keystore\",\n }),\n try: () => EthereumJSWallet.fromV3(keystore.data, params.password),\n });\n\n return privateKeyToAccount(\n toHex(wallet.getPrivateKey()),\n ) as LocalAccount;\n });\n\n const getKeystorePassword = (params: { alias: string; message: string }) =>\n Effect.gen(function* () {\n const keystore = yield* getKeystore({ alias: params.alias });\n\n const password = yield* promptManager.passwordPrompt({\n message: params.message,\n validate: (v) =>\n Effect.gen(function* () {\n if (v.trim() === \"\") {\n return yield* Effect.fail(\"Password cannot be empty\");\n }\n\n yield* Effect.tryPromise({\n try: () => Wallet.fromV3(keystore.data, v),\n catch: () =>\n new KeystoreManagerError({\n code: \"DecryptError\",\n message: `Invalid password for keystore ${params.alias}`,\n }),\n }).pipe(Effect.catch(() => Effect.fail(\"Invalid password\")));\n\n return v;\n }),\n });\n\n return password;\n });\n\n return KeystoreManager.of({\n createKeystore,\n decryptKeystore,\n getKeystore,\n listKeystores,\n selectKeystore,\n importKeystore,\n removeKeystore,\n getSigner,\n getKeystorePassword,\n });\n }),\n);\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-context.mjs","names":[],"sources":["../../src/layers/mcp-context.ts"],"sourcesContent":["import { Context } from \"effect\";\nimport type { LocalAccount } from \"viem\";\n\nimport type { LocalSmartAccount, SessionKeyData } from \"@/dto\";\n\nexport type McpContext = {\n smartAccount: LocalSmartAccount;\n sessionKeys: (SessionKeyData & {\n signer: LocalAccount;\n })[];\n};\n\nexport const McpContext = Context.Service<McpContext>(\n \"@namera-ai/cli/McpContext\",\n);\n"],"mappings":";;;AAYA,MAAa,aAAa,QAAQ,QAChC,4BACD"}
|
package/dist/layers/mcp.mjs
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { McpContext } from "./mcp-context.mjs";
|
|
3
|
-
import { startMcpHttpServer, startMcpStdioServer } from "../mcp/index.mjs";
|
|
4
|
-
import { SmartAccountManager } from "./smart-account.mjs";
|
|
5
|
-
import { SessionKeyManager } from "./session-key.mjs";
|
|
6
|
-
import { Context, Effect, Layer } from "effect";
|
|
7
|
-
//#region src/layers/mcp.ts
|
|
8
|
-
const McpManager = Context.Service("@namera-ai/cli/McpManager");
|
|
9
|
-
const layer = Layer.effect(McpManager, Effect.gen(function* () {
|
|
10
|
-
const smartAccountManager = yield* SmartAccountManager;
|
|
11
|
-
const sessionKeyManager = yield* SessionKeyManager;
|
|
12
|
-
const startMcpServer = (params) => Effect.gen(function* () {
|
|
13
|
-
const sa = yield* smartAccountManager.getSmartAccount({ alias: params.smartAccountAlias });
|
|
14
|
-
const sessionKeys = Object.entries(params.sessionKeys);
|
|
15
|
-
const sessionKeysWithSigners = yield* Effect.all(sessionKeys.map(([alias, password]) => sessionKeyManager.getSessionKeySigner({
|
|
16
|
-
alias,
|
|
17
|
-
password
|
|
18
|
-
})));
|
|
19
|
-
const context = McpContext.of({
|
|
20
|
-
smartAccount: sa.data,
|
|
21
|
-
sessionKeys: sessionKeysWithSigners
|
|
22
|
-
});
|
|
23
|
-
if (params.transport === "stdio") yield* startMcpStdioServer().pipe(Effect.provideService(McpContext, context));
|
|
24
|
-
else yield* startMcpHttpServer(params.port ?? 8080).pipe(Effect.provideService(McpContext, context));
|
|
25
|
-
});
|
|
26
|
-
return McpManager.of({ startMcpServer });
|
|
27
|
-
}));
|
|
28
|
-
//#endregion
|
|
29
|
-
export { McpManager, layer };
|
|
30
|
-
|
|
31
|
-
//# sourceMappingURL=mcp.mjs.map
|
package/dist/layers/mcp.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.mjs","names":[],"sources":["../../src/layers/mcp.ts"],"sourcesContent":["import { Context, Effect, Layer } from \"effect\";\nimport type { QuitError } from \"effect/Terminal\";\nimport type { ServeError } from \"effect/unstable/http/HttpServerError\";\n\nimport type { StartMcpServerParams } from \"@/dto/mcp\";\nimport { startMcpHttpServer, startMcpStdioServer } from \"@/mcp\";\n\nimport type { ConfigManagerError } from \"./config\";\nimport { McpContext } from \"./mcp-context\";\nimport { SessionKeyManager, type SessionKeyManagerError } from \"./session-key\";\nimport { SmartAccountManager } from \"./smart-account\";\n\nexport type McpManager = {\n startMcpServer: (\n params: StartMcpServerParams,\n ) => Effect.Effect<\n void,\n SessionKeyManagerError | ConfigManagerError | QuitError | ServeError\n >;\n};\n\nexport const McpManager = Context.Service<McpManager>(\n \"@namera-ai/cli/McpManager\",\n);\n\nexport const layer = Layer.effect(\n McpManager,\n Effect.gen(function* () {\n const smartAccountManager = yield* SmartAccountManager;\n const sessionKeyManager = yield* SessionKeyManager;\n\n const startMcpServer = (params: StartMcpServerParams) =>\n Effect.gen(function* () {\n const sa = yield* smartAccountManager.getSmartAccount({\n alias: params.smartAccountAlias,\n });\n\n const sessionKeys = Object.entries(params.sessionKeys);\n\n const sessionKeysWithSigners = yield* Effect.all(\n sessionKeys.map(([alias, password]) =>\n sessionKeyManager.getSessionKeySigner({\n alias,\n password,\n }),\n ),\n );\n\n const context = McpContext.of({\n smartAccount: sa.data,\n sessionKeys: sessionKeysWithSigners,\n });\n\n if (params.transport === \"stdio\") {\n yield* startMcpStdioServer().pipe(\n Effect.provideService(McpContext, context),\n );\n } else {\n yield* startMcpHttpServer(params.port ?? 8080).pipe(\n Effect.provideService(McpContext, context),\n );\n }\n });\n return McpManager.of({ startMcpServer });\n }),\n);\n"],"mappings":";;;;;;;AAqBA,MAAa,aAAa,QAAQ,QAChC,4BACD;AAED,MAAa,QAAQ,MAAM,OACzB,YACA,OAAO,IAAI,aAAa;CACtB,MAAM,sBAAsB,OAAO;CACnC,MAAM,oBAAoB,OAAO;CAEjC,MAAM,kBAAkB,WACtB,OAAO,IAAI,aAAa;EACtB,MAAM,KAAK,OAAO,oBAAoB,gBAAgB,EACpD,OAAO,OAAO,mBACf,CAAC;EAEF,MAAM,cAAc,OAAO,QAAQ,OAAO,YAAY;EAEtD,MAAM,yBAAyB,OAAO,OAAO,IAC3C,YAAY,KAAK,CAAC,OAAO,cACvB,kBAAkB,oBAAoB;GACpC;GACA;GACD,CAAC,CACH,CACF;EAED,MAAM,UAAU,WAAW,GAAG;GAC5B,cAAc,GAAG;GACjB,aAAa;GACd,CAAC;AAEF,MAAI,OAAO,cAAc,QACvB,QAAO,qBAAqB,CAAC,KAC3B,OAAO,eAAe,YAAY,QAAQ,CAC3C;MAED,QAAO,mBAAmB,OAAO,QAAQ,KAAK,CAAC,KAC7C,OAAO,eAAe,YAAY,QAAQ,CAC3C;GAEH;AACJ,QAAO,WAAW,GAAG,EAAE,gBAAgB,CAAC;EACxC,CACH"}
|
package/dist/layers/output.mjs
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { prettyFormat } from "../helpers/pretty.mjs";
|
|
3
|
-
import { Context, Effect, Layer } from "effect";
|
|
4
|
-
//#region src/layers/output.ts
|
|
5
|
-
/**
|
|
6
|
-
* Service tag for resolving {@link OutputFormatter} from the Effect context.
|
|
7
|
-
*/
|
|
8
|
-
const OutputFormatter = Context.Service("@namera-ai/cli/OutputFormatter");
|
|
9
|
-
/**
|
|
10
|
-
* Live layer that formats output as pretty, JSON, or NDJSON.
|
|
11
|
-
*/
|
|
12
|
-
const layer = Layer.succeed(OutputFormatter, OutputFormatter.of({ format: (data, format) => Effect.gen(function* () {
|
|
13
|
-
if (format === "pretty") return prettyFormat(data);
|
|
14
|
-
if (format === "json") return JSON.stringify(data, null, 2);
|
|
15
|
-
if (Array.isArray(data)) return `${data.map((item) => JSON.stringify(item)).join("\n")}\n`;
|
|
16
|
-
return `${JSON.stringify(data)}\n`;
|
|
17
|
-
}) }));
|
|
18
|
-
//#endregion
|
|
19
|
-
export { OutputFormatter, layer };
|
|
20
|
-
|
|
21
|
-
//# sourceMappingURL=output.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"output.mjs","names":[],"sources":["../../src/layers/output.ts"],"sourcesContent":["import { Context, Effect, Layer } from \"effect\";\n\nimport { prettyFormat } from \"@/helpers/pretty\";\n\n/**\n * Effect service for formatting command output into CLI-friendly formats.\n */\nexport type OutputFormatter = {\n /**\n * Formats command output into a CLI-friendly string.\n *\n * @param data - The object or list of objects to format.\n * @param format - Output mode: pretty (human), json, or ndjson.\n */\n format: (\n data: object | object[],\n format: \"pretty\" | \"json\" | \"ndjson\",\n ) => Effect.Effect<string>;\n};\n\n/**\n * Service tag for resolving {@link OutputFormatter} from the Effect context.\n */\nexport const OutputFormatter = Context.Service<OutputFormatter>(\n \"@namera-ai/cli/OutputFormatter\",\n);\n\n/**\n * Live layer that formats output as pretty, JSON, or NDJSON.\n */\nexport const layer = Layer.succeed(\n OutputFormatter,\n OutputFormatter.of({\n format: (data, format) =>\n Effect.gen(function* () {\n if (format === \"pretty\") {\n return prettyFormat(data);\n }\n if (format === \"json\") {\n return JSON.stringify(data, null, 2);\n }\n\n if (Array.isArray(data)) {\n return `${data.map((item) => JSON.stringify(item)).join(\"\\n\")}\\n`;\n }\n\n return `${JSON.stringify(data)}\\n`;\n }),\n }),\n);\n"],"mappings":";;;;;;;AAuBA,MAAa,kBAAkB,QAAQ,QACrC,iCACD;;;;AAKD,MAAa,QAAQ,MAAM,QACzB,iBACA,gBAAgB,GAAG,EACjB,SAAS,MAAM,WACb,OAAO,IAAI,aAAa;AACtB,KAAI,WAAW,SACb,QAAO,aAAa,KAAK;AAE3B,KAAI,WAAW,OACb,QAAO,KAAK,UAAU,MAAM,MAAM,EAAE;AAGtC,KAAI,MAAM,QAAQ,KAAK,CACrB,QAAO,GAAG,KAAK,KAAK,SAAS,KAAK,UAAU,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC;AAGhE,QAAO,GAAG,KAAK,UAAU,KAAK,CAAC;EAC/B,EACL,CAAC,CACH"}
|
package/dist/layers/prompt.mjs
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { entityName } from "../types/index.mjs";
|
|
3
|
-
import { ConfigManager } from "./config.mjs";
|
|
4
|
-
import { Context, Data, Effect, Layer } from "effect";
|
|
5
|
-
import { Prompt } from "effect/unstable/cli";
|
|
6
|
-
import { hexToBytes, isHex } from "viem";
|
|
7
|
-
//#region src/layers/prompt.ts
|
|
8
|
-
/**
|
|
9
|
-
* Service tag for resolving {@link PromptManager} from the Effect context.
|
|
10
|
-
*/
|
|
11
|
-
const PromptManager = Context.Service("@namera-ai/cli/PromptManager");
|
|
12
|
-
Data.TaggedError("@namera-ai/cli/PromptManagerError");
|
|
13
|
-
/**
|
|
14
|
-
* Live layer that validates and returns interactive prompt input.
|
|
15
|
-
*/
|
|
16
|
-
const layer = Layer.effect(PromptManager, Effect.gen(function* () {
|
|
17
|
-
const configManager = yield* ConfigManager;
|
|
18
|
-
const aliasPrompt = (params) => Effect.gen(function* () {
|
|
19
|
-
return yield* Prompt.text({
|
|
20
|
-
message: params.message,
|
|
21
|
-
validate: (v) => Effect.gen(function* () {
|
|
22
|
-
if (v.trim() === "") return yield* Effect.fail("Alias cannot be empty");
|
|
23
|
-
const exists = yield* configManager.checkEntityExists({
|
|
24
|
-
alias: v,
|
|
25
|
-
type: params.type
|
|
26
|
-
}).pipe(Effect.catchTag("@namera-ai/cli/ConfigManagerError", (e) => Effect.fail(e.message)));
|
|
27
|
-
if (params.aliasType === "new" && exists) return yield* Effect.fail(`${entityName[params.type]} with alias ${v} already exists`);
|
|
28
|
-
if (params.aliasType === "existing" && !exists) return yield* Effect.fail(`${entityName[params.type]} with alias ${v} does not exist`);
|
|
29
|
-
return v;
|
|
30
|
-
})
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
const passwordPrompt = (params) => Effect.gen(function* () {
|
|
34
|
-
return yield* Prompt.password({
|
|
35
|
-
message: params.message,
|
|
36
|
-
validate: (v) => Effect.gen(function* () {
|
|
37
|
-
if (v.trim() === "") return yield* Effect.fail("Password cannot be empty");
|
|
38
|
-
if (params.validate) return yield* params.validate(v);
|
|
39
|
-
return v;
|
|
40
|
-
})
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
const selectPrompt = (params) => Effect.gen(function* () {
|
|
44
|
-
return yield* Prompt.select(params);
|
|
45
|
-
});
|
|
46
|
-
const multiSelectPrompt = (params) => Effect.gen(function* () {
|
|
47
|
-
return yield* Prompt.multiSelect(params);
|
|
48
|
-
});
|
|
49
|
-
function hexPrompt(params) {
|
|
50
|
-
return Effect.gen(function* () {
|
|
51
|
-
const validate = (v) => Effect.gen(function* () {
|
|
52
|
-
if (v.trim() === "") return yield* Effect.fail("Hex cannot be empty");
|
|
53
|
-
if (!isHex(v)) return yield* Effect.fail("Invalid hex value");
|
|
54
|
-
if (hexToBytes(v).length !== params.length) return yield* Effect.fail(`Hex value must be ${params.length} bytes`);
|
|
55
|
-
return v;
|
|
56
|
-
});
|
|
57
|
-
if (params.redacted) return yield* Prompt.password({
|
|
58
|
-
message: params.message,
|
|
59
|
-
validate
|
|
60
|
-
});
|
|
61
|
-
return yield* Prompt.text({
|
|
62
|
-
message: params.message,
|
|
63
|
-
validate
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
return PromptManager.of({
|
|
68
|
-
aliasPrompt,
|
|
69
|
-
passwordPrompt,
|
|
70
|
-
selectPrompt,
|
|
71
|
-
hexPrompt,
|
|
72
|
-
multiSelectPrompt
|
|
73
|
-
});
|
|
74
|
-
}));
|
|
75
|
-
//#endregion
|
|
76
|
-
export { PromptManager, layer };
|
|
77
|
-
|
|
78
|
-
//# sourceMappingURL=prompt.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.mjs","names":[],"sources":["../../src/layers/prompt.ts"],"sourcesContent":["import { Context, Data, Effect, Layer, type Redacted } from \"effect\";\nimport type { QuitError } from \"effect/Terminal\";\nimport { Prompt } from \"effect/unstable/cli\";\nimport { type Hex, hexToBytes, isHex } from \"viem\";\n\nimport { type EntityType, entityName } from \"@/types\";\n\nimport { ConfigManager } from \"./config\";\n\n/**\n * Effect service for interactive CLI prompts.\n */\nexport type PromptManager = {\n /**\n * Prompts for an alias and validates it against existing storage.\n *\n * @param params - Prompt text, entity type, and expected alias semantics.\n */\n aliasPrompt: (\n params: AliasPromptParams,\n ) => Effect.Effect<string, QuitError, Prompt.Environment>;\n /**\n * Prompts for a password, optionally validating the input.\n *\n * @param params - Prompt text and optional validator.\n * @returns The redacted password.\n */\n passwordPrompt: (\n params: PasswordPromptParams,\n ) => Effect.Effect<Redacted.Redacted<string>, QuitError, Prompt.Environment>;\n /**\n * Prompts the user to select a value from a list of choices.\n *\n * @param params - Selection prompt options and choices.\n * @returns The selected value.\n */\n selectPrompt: <const A>(\n params: Prompt.SelectOptions<A>,\n ) => Effect.Effect<A, QuitError, Prompt.Environment>;\n /**\n * Prompts the user to enter a hex value.\n *\n * @param params - Prompt text and expected length of the hex value.\n * @returns The hex value entered by the user.\n */\n hexPrompt: <TRedacted extends boolean>(\n params: HexPromptParams<TRedacted>,\n ) => Effect.Effect<\n TRedacted extends true ? Redacted.Redacted<Hex> : Hex,\n QuitError,\n Prompt.Environment\n >;\n /**\n * Prompt the user to select multiple options from a list.\n *\n * @param params - Prompt options and multi-select options.\n * @returns A list of selected options.\n */\n multiSelectPrompt: <const A>(\n params: Prompt.SelectOptions<A> & Prompt.MultiSelectOptions,\n ) => Effect.Effect<A[], QuitError, Prompt.Environment>;\n};\n\n/**\n * Service tag for resolving {@link PromptManager} from the Effect context.\n */\nexport const PromptManager = Context.Service<PromptManager>(\n \"@namera-ai/cli/PromptManager\",\n);\n\n/**\n * Domain error for prompt-related failures.\n */\nexport class PromptManagerError extends Data.TaggedError(\n \"@namera-ai/cli/PromptManagerError\",\n)<{\n code: \"\";\n message: string;\n}> {}\n\n/**\n * Parameters for prompting a user for an entity alias.\n */\nexport type AliasPromptParams = {\n /**\n * Prompt message shown to the user.\n */\n message: string;\n /**\n * Entity type used to validate alias existence.\n */\n type: EntityType;\n /**\n * Whether the alias must be new or already exist.\n */\n aliasType: \"new\" | \"existing\";\n};\n\n/**\n * Parameters for prompting a user for a password.\n */\nexport type PasswordPromptParams = {\n /**\n * Prompt message shown to the user.\n */\n message: string;\n /**\n * Optional validator returning the original value or a failure message.\n */\n validate?: (v: string) => Effect.Effect<string, string, never>;\n};\n\n/**\n * Parameters for prompting a user for a hex value.\n */\nexport type HexPromptParams<TRedacted extends boolean> = {\n /**\n * Expected length of the hex value.\n */\n length: number;\n /**\n * Prompt message shown to the user.\n */\n message: string;\n /**\n * Whether the hex value should be redacted.\n */\n redacted: TRedacted;\n};\n\n/**\n * Live layer that validates and returns interactive prompt input.\n */\nexport const layer = Layer.effect(\n PromptManager,\n Effect.gen(function* () {\n const configManager = yield* ConfigManager;\n\n const aliasPrompt = (params: AliasPromptParams) =>\n Effect.gen(function* () {\n const alias = yield* Prompt.text({\n message: params.message,\n validate: (v) =>\n Effect.gen(function* () {\n if (v.trim() === \"\") {\n return yield* Effect.fail(\"Alias cannot be empty\");\n }\n\n const exists = yield* configManager\n .checkEntityExists({\n alias: v,\n type: params.type,\n })\n .pipe(\n Effect.catchTag(\"@namera-ai/cli/ConfigManagerError\", (e) =>\n Effect.fail(e.message),\n ),\n );\n\n if (params.aliasType === \"new\" && exists) {\n return yield* Effect.fail(\n `${entityName[params.type]} with alias ${v} already exists`,\n );\n }\n\n if (params.aliasType === \"existing\" && !exists) {\n return yield* Effect.fail(\n `${entityName[params.type]} with alias ${v} does not exist`,\n );\n }\n\n return v;\n }),\n });\n\n return alias;\n });\n\n const passwordPrompt = (params: PasswordPromptParams) =>\n Effect.gen(function* () {\n const password = yield* Prompt.password({\n message: params.message,\n validate: (v) =>\n Effect.gen(function* () {\n if (v.trim() === \"\") {\n return yield* Effect.fail(\"Password cannot be empty\");\n }\n\n if (params.validate) {\n return yield* params.validate(v);\n }\n\n return v;\n }),\n });\n\n return password;\n });\n\n const selectPrompt = <const A>(params: Prompt.SelectOptions<A>) =>\n Effect.gen(function* () {\n return yield* Prompt.select(params);\n });\n\n const multiSelectPrompt = <const A>(\n params: Prompt.SelectOptions<A> & Prompt.MultiSelectOptions,\n ) =>\n Effect.gen(function* () {\n return yield* Prompt.multiSelect(params);\n });\n\n function hexPrompt(\n params: HexPromptParams<true>,\n ): Effect.Effect<Redacted.Redacted<Hex>, QuitError, Prompt.Environment>;\n\n function hexPrompt(\n params: HexPromptParams<false>,\n ): Effect.Effect<Hex, QuitError, Prompt.Environment>;\n\n function hexPrompt(params: HexPromptParams<boolean>) {\n return Effect.gen(function* () {\n const validate = (v: string) =>\n Effect.gen(function* () {\n if (v.trim() === \"\") {\n return yield* Effect.fail(\"Hex cannot be empty\");\n }\n\n if (!isHex(v)) {\n return yield* Effect.fail(\"Invalid hex value\");\n }\n\n const len = hexToBytes(v).length;\n\n if (len !== params.length) {\n return yield* Effect.fail(\n `Hex value must be ${params.length} bytes`,\n );\n }\n\n return v;\n });\n\n if (params.redacted) {\n return yield* Prompt.password({\n message: params.message,\n validate,\n });\n }\n\n return yield* Prompt.text({\n message: params.message,\n validate,\n });\n });\n }\n\n return PromptManager.of({\n aliasPrompt,\n passwordPrompt,\n selectPrompt,\n hexPrompt,\n multiSelectPrompt,\n });\n }),\n);\n"],"mappings":";;;;;;;;;;AAkEA,MAAa,gBAAgB,QAAQ,QACnC,+BACD;AAKuC,KAAK,YAC3C,oCACD;;;;AA0DD,MAAa,QAAQ,MAAM,OACzB,eACA,OAAO,IAAI,aAAa;CACtB,MAAM,gBAAgB,OAAO;CAE7B,MAAM,eAAe,WACnB,OAAO,IAAI,aAAa;AAoCtB,SAAO,OAnCc,OAAO,KAAK;GAC/B,SAAS,OAAO;GAChB,WAAW,MACT,OAAO,IAAI,aAAa;AACtB,QAAI,EAAE,MAAM,KAAK,GACf,QAAO,OAAO,OAAO,KAAK,wBAAwB;IAGpD,MAAM,SAAS,OAAO,cACnB,kBAAkB;KACjB,OAAO;KACP,MAAM,OAAO;KACd,CAAC,CACD,KACC,OAAO,SAAS,sCAAsC,MACpD,OAAO,KAAK,EAAE,QAAQ,CACvB,CACF;AAEH,QAAI,OAAO,cAAc,SAAS,OAChC,QAAO,OAAO,OAAO,KACnB,GAAG,WAAW,OAAO,MAAM,cAAc,EAAE,iBAC5C;AAGH,QAAI,OAAO,cAAc,cAAc,CAAC,OACtC,QAAO,OAAO,OAAO,KACnB,GAAG,WAAW,OAAO,MAAM,cAAc,EAAE,iBAC5C;AAGH,WAAO;KACP;GACL,CAAC;GAGF;CAEJ,MAAM,kBAAkB,WACtB,OAAO,IAAI,aAAa;AAiBtB,SAAO,OAhBiB,OAAO,SAAS;GACtC,SAAS,OAAO;GAChB,WAAW,MACT,OAAO,IAAI,aAAa;AACtB,QAAI,EAAE,MAAM,KAAK,GACf,QAAO,OAAO,OAAO,KAAK,2BAA2B;AAGvD,QAAI,OAAO,SACT,QAAO,OAAO,OAAO,SAAS,EAAE;AAGlC,WAAO;KACP;GACL,CAAC;GAGF;CAEJ,MAAM,gBAAyB,WAC7B,OAAO,IAAI,aAAa;AACtB,SAAO,OAAO,OAAO,OAAO,OAAO;GACnC;CAEJ,MAAM,qBACJ,WAEA,OAAO,IAAI,aAAa;AACtB,SAAO,OAAO,OAAO,YAAY,OAAO;GACxC;CAUJ,SAAS,UAAU,QAAkC;AACnD,SAAO,OAAO,IAAI,aAAa;GAC7B,MAAM,YAAY,MAChB,OAAO,IAAI,aAAa;AACtB,QAAI,EAAE,MAAM,KAAK,GACf,QAAO,OAAO,OAAO,KAAK,sBAAsB;AAGlD,QAAI,CAAC,MAAM,EAAE,CACX,QAAO,OAAO,OAAO,KAAK,oBAAoB;AAKhD,QAFY,WAAW,EAAE,CAAC,WAEd,OAAO,OACjB,QAAO,OAAO,OAAO,KACnB,qBAAqB,OAAO,OAAO,QACpC;AAGH,WAAO;KACP;AAEJ,OAAI,OAAO,SACT,QAAO,OAAO,OAAO,SAAS;IAC5B,SAAS,OAAO;IAChB;IACD,CAAC;AAGJ,UAAO,OAAO,OAAO,KAAK;IACxB,SAAS,OAAO;IAChB;IACD,CAAC;IACF;;AAGJ,QAAO,cAAc,GAAG;EACtB;EACA;EACA;EACA;EACA;EACD,CAAC;EACF,CACH"}
|
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { chainIdToChainName } from "../schema/chain.mjs";
|
|
3
|
-
import "../schema/index.mjs";
|
|
4
|
-
import { SessionKey } from "../dto/session-key.mjs";
|
|
5
|
-
import "../dto/index.mjs";
|
|
6
|
-
import { ConfigManager } from "./config.mjs";
|
|
7
|
-
import { PromptManager } from "./prompt.mjs";
|
|
8
|
-
import { KeystoreManager } from "./keystore.mjs";
|
|
9
|
-
import { Web3Service } from "./web3.mjs";
|
|
10
|
-
import { policyParamsToPolicies } from "../helpers/policy.mjs";
|
|
11
|
-
import { SmartAccountManager } from "./smart-account.mjs";
|
|
12
|
-
import { Context, Data, Effect, Layer, Schema } from "effect";
|
|
13
|
-
import { Wallet } from "@ethereumjs/wallet";
|
|
14
|
-
import { hexToBytes, toHex } from "viem";
|
|
15
|
-
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
|
|
16
|
-
import { createSessionKey, isSessionKeyInstalled } from "@namera-ai/sdk/session-key";
|
|
17
|
-
//#region src/layers/session-key.ts
|
|
18
|
-
const SessionKeyManager = Context.Service("@namera-ai/cli/SessionKeyManager");
|
|
19
|
-
var SessionKeyManagerError = class extends Data.TaggedError("@namera-ai/cli/SessionKeyManagerError") {};
|
|
20
|
-
const layer = Layer.effect(SessionKeyManager, Effect.gen(function* () {
|
|
21
|
-
const configManager = yield* ConfigManager;
|
|
22
|
-
const promptManager = yield* PromptManager;
|
|
23
|
-
const keystoreManager = yield* KeystoreManager;
|
|
24
|
-
const smartAccountManager = yield* SmartAccountManager;
|
|
25
|
-
const web3Service = yield* Web3Service;
|
|
26
|
-
const createSessionKey$1 = (params) => Effect.gen(function* () {
|
|
27
|
-
if (yield* configManager.checkEntityExists({
|
|
28
|
-
alias: params.alias,
|
|
29
|
-
type: "session-key"
|
|
30
|
-
})) return yield* Effect.fail(new SessionKeyManagerError({
|
|
31
|
-
code: "SessionKeyAlreadyExists",
|
|
32
|
-
message: `Session key for alias ${params.alias} already exists`
|
|
33
|
-
}));
|
|
34
|
-
const entityPath = yield* configManager.getEntityPath({
|
|
35
|
-
alias: params.alias,
|
|
36
|
-
type: "session-key"
|
|
37
|
-
});
|
|
38
|
-
const sa = yield* smartAccountManager.getSmartAccount({ alias: params.smartAccountAlias });
|
|
39
|
-
const ownerSigner = yield* keystoreManager.getSigner({
|
|
40
|
-
alias: sa.data.ownerAlias,
|
|
41
|
-
password: params.ownerKeystorePassword
|
|
42
|
-
});
|
|
43
|
-
const policies = policyParamsToPolicies(params.policyParams);
|
|
44
|
-
const clients = yield* Effect.all(params.chains.map((chain) => web3Service.getPublicClient({ chain })), { concurrency: "unbounded" });
|
|
45
|
-
const sessionPrivateKey = generatePrivateKey();
|
|
46
|
-
const sessionKeyAccount = privateKeyToAccount(sessionPrivateKey);
|
|
47
|
-
const res = yield* Effect.promise(() => createSessionKey({
|
|
48
|
-
type: "ecdsa",
|
|
49
|
-
accountType: "ecdsa",
|
|
50
|
-
sessionPrivateKey,
|
|
51
|
-
clients,
|
|
52
|
-
entrypointVersion: sa.data.entryPointVersion,
|
|
53
|
-
kernelVersion: sa.data.kernelVersion,
|
|
54
|
-
index: sa.data.index,
|
|
55
|
-
signer: ownerSigner,
|
|
56
|
-
policies
|
|
57
|
-
}));
|
|
58
|
-
const encData = yield* Effect.tryPromise({
|
|
59
|
-
try: () => Wallet.fromPrivateKey(hexToBytes(sessionPrivateKey)).toV3(params.sessionKeyPassword),
|
|
60
|
-
catch: () => new SessionKeyManagerError({
|
|
61
|
-
code: "EncryptionError",
|
|
62
|
-
message: "Failed to encrypt session key"
|
|
63
|
-
})
|
|
64
|
-
});
|
|
65
|
-
const data = {
|
|
66
|
-
sessionKeyType: "ecdsa",
|
|
67
|
-
serializedAccounts: res.serializedAccounts.map((a) => ({
|
|
68
|
-
chain: chainIdToChainName(a.chainId),
|
|
69
|
-
serializedAccount: a.serializedAccount
|
|
70
|
-
})),
|
|
71
|
-
sessionKeyAddress: sessionKeyAccount.address,
|
|
72
|
-
smartAccountAlias: sa.alias,
|
|
73
|
-
...encData
|
|
74
|
-
};
|
|
75
|
-
yield* configManager.storeEntity({
|
|
76
|
-
alias: params.alias,
|
|
77
|
-
content: JSON.stringify(data),
|
|
78
|
-
path: entityPath,
|
|
79
|
-
type: "session-key"
|
|
80
|
-
});
|
|
81
|
-
return {
|
|
82
|
-
alias: params.alias,
|
|
83
|
-
data,
|
|
84
|
-
path: entityPath
|
|
85
|
-
};
|
|
86
|
-
});
|
|
87
|
-
const getSessionKey = (params) => Effect.gen(function* () {
|
|
88
|
-
const res = yield* configManager.getEntity({
|
|
89
|
-
alias: params.alias,
|
|
90
|
-
type: "session-key"
|
|
91
|
-
});
|
|
92
|
-
const parsed = Schema.decodeUnknownOption(Schema.fromJsonString(SessionKey))(res.content);
|
|
93
|
-
if (parsed._tag === "None") return yield* Effect.fail(new SessionKeyManagerError({
|
|
94
|
-
code: "SessionKeyParseError",
|
|
95
|
-
message: "Unable to parse session key"
|
|
96
|
-
}));
|
|
97
|
-
return {
|
|
98
|
-
alias: res.alias,
|
|
99
|
-
data: parsed.value,
|
|
100
|
-
path: res.path
|
|
101
|
-
};
|
|
102
|
-
});
|
|
103
|
-
const listSessionKeys = (params) => Effect.gen(function* () {
|
|
104
|
-
const effects = (yield* configManager.getEntitiesForType("session-key")).map((entity) => Effect.gen(function* () {
|
|
105
|
-
const parsed = Schema.decodeUnknownOption(Schema.fromJsonString(SessionKey))(entity.content);
|
|
106
|
-
if (parsed._tag === "None") return yield* Effect.fail(new SessionKeyManagerError({
|
|
107
|
-
code: "SessionKeyParseError",
|
|
108
|
-
message: "Unable to parse session key"
|
|
109
|
-
}));
|
|
110
|
-
return {
|
|
111
|
-
alias: entity.alias,
|
|
112
|
-
data: parsed.value,
|
|
113
|
-
path: entity.path
|
|
114
|
-
};
|
|
115
|
-
}));
|
|
116
|
-
const allKeys = yield* Effect.all(effects, { concurrency: "unbounded" });
|
|
117
|
-
if (params.smartAccount) return allKeys.filter((k) => k.data.smartAccountAlias === params.smartAccount);
|
|
118
|
-
return allKeys;
|
|
119
|
-
});
|
|
120
|
-
const selectSessionKey = (params) => Effect.gen(function* () {
|
|
121
|
-
const sessionKeys = yield* listSessionKeys({});
|
|
122
|
-
return yield* promptManager.selectPrompt({
|
|
123
|
-
message: params.message,
|
|
124
|
-
choices: sessionKeys.map((sk) => ({
|
|
125
|
-
title: sk.alias,
|
|
126
|
-
value: sk,
|
|
127
|
-
description: `${sk.data.sessionKeyType === "ecdsa" ? sk.data.sessionKeyAddress : sk.data.passKeyName} (${sk.data.smartAccountAlias})`
|
|
128
|
-
}))
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
const getSessionKeyStatus = (params) => Effect.gen(function* () {
|
|
132
|
-
const sessionKey = yield* getSessionKey({ alias: params.alias });
|
|
133
|
-
const sa = yield* smartAccountManager.getSmartAccount({ alias: sessionKey.data.smartAccountAlias });
|
|
134
|
-
const publicClient = yield* web3Service.getPublicClient({
|
|
135
|
-
chain: params.chain,
|
|
136
|
-
rpcUrl: params.rpcUrl
|
|
137
|
-
});
|
|
138
|
-
if (sessionKey.data.sessionKeyType !== "ecdsa") return yield* Effect.fail(new SessionKeyManagerError({
|
|
139
|
-
code: "SessionKeyParseError",
|
|
140
|
-
message: "Only ECDSA session keys have an on-chain status"
|
|
141
|
-
}));
|
|
142
|
-
const sessionKeyAddress = sessionKey.data.sessionKeyAddress;
|
|
143
|
-
return yield* Effect.tryPromise({
|
|
144
|
-
try: () => isSessionKeyInstalled(publicClient, {
|
|
145
|
-
accountAddress: sa.data.smartAccountAddress,
|
|
146
|
-
sessionKeyAddress
|
|
147
|
-
}),
|
|
148
|
-
catch: () => false
|
|
149
|
-
}).pipe(Effect.catch(() => Effect.succeed(false)));
|
|
150
|
-
});
|
|
151
|
-
const multiSelectSessionKeys = (params) => Effect.gen(function* () {
|
|
152
|
-
const allKeys = yield* listSessionKeys({ smartAccount: params.smartAccount });
|
|
153
|
-
return yield* promptManager.multiSelectPrompt({
|
|
154
|
-
message: params.message,
|
|
155
|
-
choices: allKeys.map((k) => ({
|
|
156
|
-
title: k.alias,
|
|
157
|
-
value: k,
|
|
158
|
-
description: `${k.data.sessionKeyType === "ecdsa" ? k.data.sessionKeyAddress : k.data.passKeyName} (${k.data.smartAccountAlias})`
|
|
159
|
-
})),
|
|
160
|
-
min: 1
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
const getSessionKeyPassword = (params) => Effect.gen(function* () {
|
|
164
|
-
const key = yield* getSessionKey({ alias: params.alias });
|
|
165
|
-
return yield* promptManager.passwordPrompt({
|
|
166
|
-
message: params.message,
|
|
167
|
-
validate: (v) => Effect.gen(function* () {
|
|
168
|
-
if (v.trim() === "") return yield* Effect.fail("Password cannot be empty");
|
|
169
|
-
yield* Effect.tryPromise({
|
|
170
|
-
try: () => Wallet.fromV3(key.data, v),
|
|
171
|
-
catch: () => new SessionKeyManagerError({
|
|
172
|
-
code: "DecryptError",
|
|
173
|
-
message: `Invalid password for session key ${params.alias}`
|
|
174
|
-
})
|
|
175
|
-
}).pipe(Effect.catch(() => Effect.fail("Invalid password")));
|
|
176
|
-
return v;
|
|
177
|
-
})
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
const getSessionKeySigner = (params) => Effect.gen(function* () {
|
|
181
|
-
const key = yield* getSessionKey({ alias: params.alias });
|
|
182
|
-
const signer = yield* Effect.tryPromise({
|
|
183
|
-
try: async () => {
|
|
184
|
-
return privateKeyToAccount(toHex((await Wallet.fromV3(key.data, params.password)).getPrivateKey()));
|
|
185
|
-
},
|
|
186
|
-
catch: () => new SessionKeyManagerError({
|
|
187
|
-
code: "DecryptError",
|
|
188
|
-
message: `Invalid password for session key ${params.alias}`
|
|
189
|
-
})
|
|
190
|
-
});
|
|
191
|
-
return {
|
|
192
|
-
...key,
|
|
193
|
-
signer
|
|
194
|
-
};
|
|
195
|
-
});
|
|
196
|
-
const removeSessionKey = (params) => Effect.gen(function* () {
|
|
197
|
-
const key = yield* getSessionKey({ alias: params.alias });
|
|
198
|
-
return yield* configManager.removeEntity({
|
|
199
|
-
alias: key.alias,
|
|
200
|
-
type: "session-key"
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
return SessionKeyManager.of({
|
|
204
|
-
createSessionKey: createSessionKey$1,
|
|
205
|
-
getSessionKey,
|
|
206
|
-
listSessionKeys,
|
|
207
|
-
selectSessionKey,
|
|
208
|
-
getSessionKeyStatus,
|
|
209
|
-
multiSelectSessionKeys,
|
|
210
|
-
getSessionKeyPassword,
|
|
211
|
-
getSessionKeySigner,
|
|
212
|
-
removeSessionKey
|
|
213
|
-
});
|
|
214
|
-
}));
|
|
215
|
-
//#endregion
|
|
216
|
-
export { SessionKeyManager, layer };
|
|
217
|
-
|
|
218
|
-
//# sourceMappingURL=session-key.mjs.map
|