@namera-ai/cli 0.1.4 → 0.1.5
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/dist/commands/schema/index.mjs +3 -1
- package/dist/commands/schema/index.mjs.map +1 -1
- package/dist/commands/smart-account/create.mjs +1 -1
- package/dist/commands/smart-account/create.mjs.map +1 -1
- package/dist/dto/smart-account.mjs +3 -3
- package/dist/dto/smart-account.mjs.map +1 -1
- package/dist/index.mjs +3 -2
- package/dist/index.mjs.map +1 -1
- package/dist/layers/smart-account.mjs +2 -5
- package/dist/layers/smart-account.mjs.map +1 -1
- package/dist/mcp/index.mjs +24 -7
- package/dist/mcp/index.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -45,7 +45,9 @@ const command = Argument.choice("command", commands).pipe(Argument.withDescripti
|
|
|
45
45
|
const schemaCommand = Command.make("schema", { command }, ({ command }) => Effect.gen(function* () {
|
|
46
46
|
const schema = getSchema(schemas, command);
|
|
47
47
|
const json = Schema.toJsonSchemaDocument(schema);
|
|
48
|
-
yield* Console.log(JSON.stringify(json,
|
|
48
|
+
yield* Console.log(JSON.stringify(json, (_key, value) => {
|
|
49
|
+
return typeof value === "bigint" ? value.toString() : value;
|
|
50
|
+
}, 2));
|
|
49
51
|
})).pipe(Command.withDescription("Get the schema for a command"));
|
|
50
52
|
//#endregion
|
|
51
53
|
export { schemaCommand };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["Dto.CreateKeystoreParams","Dto.DecryptKeystoreParams","Dto.GetKeystoreParams","Dto.ListKeystoreParams","Dto.ImportKeystoreParams","Dto.RemoveKeystoreParams","Dto.CreateSmartAccountParams","Dto.ListSmartAccountParams","Dto.GetSmartAccountInfoParams","Dto.RemoveSmartAccountParams","Dto.GetSmartAccountStatusParams","Dto.ImportSmartAccountParams","Dto.CreateSessionKeyParams","Dto.ListSessionKeysParams","Dto.GetSessionKeyInfoParams","Dto.RemoveSessionKeyParams","Dto.GetSessionKeyStatusParams","Dto.StartMcpServerParams"],"sources":["../../../src/commands/schema/index.ts"],"sourcesContent":["import { Console, Effect, Schema } from \"effect\";\nimport { Argument, Command } from \"effect/unstable/cli\";\n\nimport * as Dto from \"@/dto\";\nimport { extractPaths, getSchema } from \"@/helpers/paths\";\n\n/**\n * Schema registry keyed by command path.\n */\nconst schemas = {\n keystore: {\n create: Dto.CreateKeystoreParams,\n decrypt: Dto.DecryptKeystoreParams,\n info: Dto.GetKeystoreParams,\n list: Dto.ListKeystoreParams,\n import: Dto.ImportKeystoreParams,\n remove: Dto.RemoveKeystoreParams,\n },\n \"smart-account\": {\n create: Dto.CreateSmartAccountParams,\n list: Dto.ListSmartAccountParams,\n info: Dto.GetSmartAccountInfoParams,\n remove: Dto.RemoveSmartAccountParams,\n status: Dto.GetSmartAccountStatusParams,\n import: Dto.ImportSmartAccountParams,\n },\n \"session-key\": {\n create: Dto.CreateSessionKeyParams,\n list: Dto.ListSessionKeysParams,\n info: Dto.GetSessionKeyInfoParams,\n remove: Dto.RemoveSessionKeyParams,\n status: Dto.GetSessionKeyStatusParams,\n },\n mcp: {\n start: Dto.StartMcpServerParams,\n },\n};\n\nconst commands = extractPaths(schemas);\nconst command = Argument.choice(\"command\", commands).pipe(\n Argument.withDescription(\"The command to get the schema for\"),\n);\n\n/**\n * Command that prints JSON Schema for a given CLI command.\n */\nexport const schemaCommand = Command.make(\n \"schema\",\n { command },\n ({ command }) =>\n Effect.gen(function* () {\n const schema = getSchema(schemas, command);\n const json = Schema.toJsonSchemaDocument(schema);\n\n yield* Console.log(JSON.stringify(json,
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["Dto.CreateKeystoreParams","Dto.DecryptKeystoreParams","Dto.GetKeystoreParams","Dto.ListKeystoreParams","Dto.ImportKeystoreParams","Dto.RemoveKeystoreParams","Dto.CreateSmartAccountParams","Dto.ListSmartAccountParams","Dto.GetSmartAccountInfoParams","Dto.RemoveSmartAccountParams","Dto.GetSmartAccountStatusParams","Dto.ImportSmartAccountParams","Dto.CreateSessionKeyParams","Dto.ListSessionKeysParams","Dto.GetSessionKeyInfoParams","Dto.RemoveSessionKeyParams","Dto.GetSessionKeyStatusParams","Dto.StartMcpServerParams"],"sources":["../../../src/commands/schema/index.ts"],"sourcesContent":["import { Console, Effect, Schema } from \"effect\";\nimport { Argument, Command } from \"effect/unstable/cli\";\n\nimport * as Dto from \"@/dto\";\nimport { extractPaths, getSchema } from \"@/helpers/paths\";\n\n/**\n * Schema registry keyed by command path.\n */\nconst schemas = {\n keystore: {\n create: Dto.CreateKeystoreParams,\n decrypt: Dto.DecryptKeystoreParams,\n info: Dto.GetKeystoreParams,\n list: Dto.ListKeystoreParams,\n import: Dto.ImportKeystoreParams,\n remove: Dto.RemoveKeystoreParams,\n },\n \"smart-account\": {\n create: Dto.CreateSmartAccountParams,\n list: Dto.ListSmartAccountParams,\n info: Dto.GetSmartAccountInfoParams,\n remove: Dto.RemoveSmartAccountParams,\n status: Dto.GetSmartAccountStatusParams,\n import: Dto.ImportSmartAccountParams,\n },\n \"session-key\": {\n create: Dto.CreateSessionKeyParams,\n list: Dto.ListSessionKeysParams,\n info: Dto.GetSessionKeyInfoParams,\n remove: Dto.RemoveSessionKeyParams,\n status: Dto.GetSessionKeyStatusParams,\n },\n mcp: {\n start: Dto.StartMcpServerParams,\n },\n};\n\nconst commands = extractPaths(schemas);\nconst command = Argument.choice(\"command\", commands).pipe(\n Argument.withDescription(\"The command to get the schema for\"),\n);\n\n/**\n * Command that prints JSON Schema for a given CLI command.\n */\nexport const schemaCommand = Command.make(\n \"schema\",\n { command },\n ({ command }) =>\n Effect.gen(function* () {\n const schema = getSchema(schemas, command);\n const json = Schema.toJsonSchemaDocument(schema);\n\n yield* Console.log(\n JSON.stringify(\n json,\n (_key, value) => {\n return typeof value === \"bigint\" ? value.toString() : value;\n },\n 2,\n ),\n );\n }),\n).pipe(Command.withDescription(\"Get the schema for a command\"));\n"],"mappings":";;;;;;;;;;;;;AASA,MAAM,UAAU;CACd,UAAU;EACR,QAAQA;EACR,SAASC;EACT,MAAMC;EACN,MAAMC;EACN,QAAQC;EACR,QAAQC;EACT;CACD,iBAAiB;EACf,QAAQC;EACR,MAAMC;EACN,MAAMC;EACN,QAAQC;EACR,QAAQC;EACR,QAAQC;EACT;CACD,eAAe;EACb,QAAQC;EACR,MAAMC;EACN,MAAMC;EACN,QAAQC;EACR,QAAQC;EACT;CACD,KAAK,EACH,OAAOC,sBACR;CACF;AAED,MAAM,WAAW,aAAa,QAAQ;AACtC,MAAM,UAAU,SAAS,OAAO,WAAW,SAAS,CAAC,KACnD,SAAS,gBAAgB,oCAAoC,CAC9D;;;;AAKD,MAAa,gBAAgB,QAAQ,KACnC,UACA,EAAE,SAAS,GACV,EAAE,cACD,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,UAAU,SAAS,QAAQ;CAC1C,MAAM,OAAO,OAAO,qBAAqB,OAAO;AAEhD,QAAO,QAAQ,IACb,KAAK,UACH,OACC,MAAM,UAAU;AACf,SAAO,OAAO,UAAU,WAAW,MAAM,UAAU,GAAG;IAExD,EACD,CACF;EACD,CACL,CAAC,KAAK,QAAQ,gBAAgB,+BAA+B,CAAC"}
|
|
@@ -49,7 +49,7 @@ const handler = (flagAlias, flagOwnerAlias, flagOwnerPassword, flagIndex) => Eff
|
|
|
49
49
|
const data = {
|
|
50
50
|
address: res.data.smartAccountAddress,
|
|
51
51
|
kernelVersion: res.data.kernelVersion,
|
|
52
|
-
index:
|
|
52
|
+
index: res.data.index,
|
|
53
53
|
owner: res.data.ownerAlias
|
|
54
54
|
};
|
|
55
55
|
if (globalFlags.quiet) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.mjs","names":["PromptManager.PromptManager","KeystoreManager.KeystoreManager","SmartAccountManager.SmartAccountManager","OutputFormatter.OutputFormatter"],"sources":["../../../src/commands/smart-account/create.ts"],"sourcesContent":["import { Console, Effect, type Option, Redacted, Schema } from \"effect\";\nimport { Command, Flag } from \"effect/unstable/cli\";\n\nimport { CreateSmartAccountParams } from \"@/dto\";\nimport { getGlobalFlags } from \"@/flags/global\";\nimport {\n KeystoreManager,\n OutputFormatter,\n PromptManager,\n SmartAccountManager,\n} from \"@/layers\";\n\nconst handler = (\n flagAlias: Option.Option<string>,\n flagOwnerAlias: Option.Option<string>,\n flagOwnerPassword: Option.Option<Redacted.Redacted<string>>,\n flagIndex: Option.Option<number>,\n) =>\n Effect.gen(function* () {\n const promptManager = yield* PromptManager.PromptManager;\n const keystoreManager = yield* KeystoreManager.KeystoreManager;\n const smartAccountManager = yield* SmartAccountManager.SmartAccountManager;\n const outputFormatter = yield* OutputFormatter.OutputFormatter;\n const globalFlags = yield* getGlobalFlags();\n\n let params: CreateSmartAccountParams;\n\n if (globalFlags.params._tag === \"Some\") {\n params = Schema.decodeUnknownSync(\n Schema.fromJsonString(CreateSmartAccountParams),\n )(globalFlags.params.value);\n } else {\n let alias: string;\n let ownerAlias: string;\n let ownerPassword: Redacted.Redacted<string>;\n let index: bigint;\n\n if (flagAlias._tag === \"Some\") {\n alias = flagAlias.value;\n } else {\n alias = yield* promptManager.aliasPrompt({\n aliasType: \"new\",\n message: \"Enter alias for smart account:\",\n type: \"smart-account\",\n });\n }\n\n if (flagOwnerAlias._tag === \"Some\") {\n ownerAlias = flagOwnerAlias.value;\n } else {\n ownerAlias = (yield* keystoreManager.selectKeystore({\n message: \"Select owner keystore:\",\n })).alias;\n }\n\n if (flagOwnerPassword._tag === \"Some\") {\n ownerPassword = flagOwnerPassword.value;\n } else {\n ownerPassword = yield* keystoreManager.getKeystorePassword({\n alias: ownerAlias,\n message: `Enter password for owner (${ownerAlias}):`,\n });\n }\n\n if (flagIndex._tag === \"Some\") {\n index = BigInt(flagIndex.value);\n } else {\n index = 0n;\n }\n\n params = {\n alias,\n ownerAlias,\n index,\n ownerPassword: Redacted.value(ownerPassword),\n };\n }\n\n const res = yield* smartAccountManager.createSmartAccount(params);\n\n const data = {\n address: res.data.smartAccountAddress,\n kernelVersion: res.data.kernelVersion,\n index:
|
|
1
|
+
{"version":3,"file":"create.mjs","names":["PromptManager.PromptManager","KeystoreManager.KeystoreManager","SmartAccountManager.SmartAccountManager","OutputFormatter.OutputFormatter"],"sources":["../../../src/commands/smart-account/create.ts"],"sourcesContent":["import { Console, Effect, type Option, Redacted, Schema } from \"effect\";\nimport { Command, Flag } from \"effect/unstable/cli\";\n\nimport { CreateSmartAccountParams } from \"@/dto\";\nimport { getGlobalFlags } from \"@/flags/global\";\nimport {\n KeystoreManager,\n OutputFormatter,\n PromptManager,\n SmartAccountManager,\n} from \"@/layers\";\n\nconst handler = (\n flagAlias: Option.Option<string>,\n flagOwnerAlias: Option.Option<string>,\n flagOwnerPassword: Option.Option<Redacted.Redacted<string>>,\n flagIndex: Option.Option<number>,\n) =>\n Effect.gen(function* () {\n const promptManager = yield* PromptManager.PromptManager;\n const keystoreManager = yield* KeystoreManager.KeystoreManager;\n const smartAccountManager = yield* SmartAccountManager.SmartAccountManager;\n const outputFormatter = yield* OutputFormatter.OutputFormatter;\n const globalFlags = yield* getGlobalFlags();\n\n let params: CreateSmartAccountParams;\n\n if (globalFlags.params._tag === \"Some\") {\n params = Schema.decodeUnknownSync(\n Schema.fromJsonString(CreateSmartAccountParams),\n )(globalFlags.params.value);\n } else {\n let alias: string;\n let ownerAlias: string;\n let ownerPassword: Redacted.Redacted<string>;\n let index: bigint;\n\n if (flagAlias._tag === \"Some\") {\n alias = flagAlias.value;\n } else {\n alias = yield* promptManager.aliasPrompt({\n aliasType: \"new\",\n message: \"Enter alias for smart account:\",\n type: \"smart-account\",\n });\n }\n\n if (flagOwnerAlias._tag === \"Some\") {\n ownerAlias = flagOwnerAlias.value;\n } else {\n ownerAlias = (yield* keystoreManager.selectKeystore({\n message: \"Select owner keystore:\",\n })).alias;\n }\n\n if (flagOwnerPassword._tag === \"Some\") {\n ownerPassword = flagOwnerPassword.value;\n } else {\n ownerPassword = yield* keystoreManager.getKeystorePassword({\n alias: ownerAlias,\n message: `Enter password for owner (${ownerAlias}):`,\n });\n }\n\n if (flagIndex._tag === \"Some\") {\n index = BigInt(flagIndex.value);\n } else {\n index = 0n;\n }\n\n params = {\n alias,\n ownerAlias,\n index,\n ownerPassword: Redacted.value(ownerPassword),\n };\n }\n\n const res = yield* smartAccountManager.createSmartAccount(params);\n\n const data = {\n address: res.data.smartAccountAddress,\n kernelVersion: res.data.kernelVersion,\n index: res.data.index,\n owner: res.data.ownerAlias,\n };\n\n if (globalFlags.quiet) return;\n\n const output = yield* outputFormatter.format(data, globalFlags.out);\n yield* Console.log(output);\n });\n\nconst alias = Flag.string(\"alias\").pipe(\n Flag.withDescription(\"The alias of the smart account to create\"),\n Flag.withAlias(\"a\"),\n Flag.optional,\n);\n\nconst ownerAlias = Flag.string(\"owner-alias\").pipe(\n Flag.withDescription(\"The alias of the owner keystore\"),\n Flag.withAlias(\"oa\"),\n Flag.optional,\n);\n\nconst ownerPassword = Flag.redacted(\"owner-password\").pipe(\n Flag.withDescription(\"The password of the owner keystore\"),\n Flag.withAlias(\"op\"),\n Flag.optional,\n);\n\nconst index = Flag.integer(\"index\").pipe(\n Flag.withDescription(\"The index of the smart account\"),\n Flag.withAlias(\"i\"),\n Flag.optional,\n);\n\n/**\n * Command that creates a new smart account and stores it locally.\n *\n * Accepts alias, owner alias, and index via flags or JSON params.\n */\nexport const createSmartAccountCommand = Command.make(\n \"create\",\n { alias, ownerAlias, ownerPassword, index },\n ({ alias, ownerAlias, ownerPassword, index }) =>\n handler(alias, ownerAlias, ownerPassword, index),\n).pipe(\n Command.withAlias(\"c\"),\n Command.withDescription(\"Creates a new smart account\"),\n Command.withExamples([\n {\n command: \"namera smart-account create\",\n description: \"Creates a new smart account with interactive prompts\",\n },\n {\n command:\n \"namera smart-account create --alias my-smart --owner-alias my-owner --index 0\",\n description:\n \"Creates a new smart account with alias 'my-smart', owner alias 'my-owner', and index 0\",\n },\n {\n command: `namera smart-account create --params '{\"alias\":\"my-smart\",\"owner-alias\":\"my-owner\",\"index\":0}'`,\n description: \"Creates a new smart account with json params\",\n },\n {\n command: \"namera schema smart-account.create\",\n description: \"Get the schema for the create command\",\n },\n ]),\n);\n"],"mappings":";;;;;;;;;;;;AAYA,MAAM,WACJ,WACA,gBACA,mBACA,cAEA,OAAO,IAAI,aAAa;CACtB,MAAM,gBAAgB,OAAOA;CAC7B,MAAM,kBAAkB,OAAOC;CAC/B,MAAM,sBAAsB,OAAOC;CACnC,MAAM,kBAAkB,OAAOC;CAC/B,MAAM,cAAc,OAAO,gBAAgB;CAE3C,IAAI;AAEJ,KAAI,YAAY,OAAO,SAAS,OAC9B,UAAS,OAAO,kBACd,OAAO,eAAe,yBAAyB,CAChD,CAAC,YAAY,OAAO,MAAM;MACtB;EACL,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;AAEJ,MAAI,UAAU,SAAS,OACrB,SAAQ,UAAU;MAElB,SAAQ,OAAO,cAAc,YAAY;GACvC,WAAW;GACX,SAAS;GACT,MAAM;GACP,CAAC;AAGJ,MAAI,eAAe,SAAS,OAC1B,cAAa,eAAe;MAE5B,eAAc,OAAO,gBAAgB,eAAe,EAClD,SAAS,0BACV,CAAC,EAAE;AAGN,MAAI,kBAAkB,SAAS,OAC7B,iBAAgB,kBAAkB;MAElC,iBAAgB,OAAO,gBAAgB,oBAAoB;GACzD,OAAO;GACP,SAAS,6BAA6B,WAAW;GAClD,CAAC;AAGJ,MAAI,UAAU,SAAS,OACrB,SAAQ,OAAO,UAAU,MAAM;MAE/B,SAAQ;AAGV,WAAS;GACP;GACA;GACA;GACA,eAAe,SAAS,MAAM,cAAc;GAC7C;;CAGH,MAAM,MAAM,OAAO,oBAAoB,mBAAmB,OAAO;CAEjE,MAAM,OAAO;EACX,SAAS,IAAI,KAAK;EAClB,eAAe,IAAI,KAAK;EACxB,OAAO,IAAI,KAAK;EAChB,OAAO,IAAI,KAAK;EACjB;AAED,KAAI,YAAY,MAAO;CAEvB,MAAM,SAAS,OAAO,gBAAgB,OAAO,MAAM,YAAY,IAAI;AACnE,QAAO,QAAQ,IAAI,OAAO;EAC1B;AAEJ,MAAM,QAAQ,KAAK,OAAO,QAAQ,CAAC,KACjC,KAAK,gBAAgB,2CAA2C,EAChE,KAAK,UAAU,IAAI,EACnB,KAAK,SACN;AAED,MAAM,aAAa,KAAK,OAAO,cAAc,CAAC,KAC5C,KAAK,gBAAgB,kCAAkC,EACvD,KAAK,UAAU,KAAK,EACpB,KAAK,SACN;AAED,MAAM,gBAAgB,KAAK,SAAS,iBAAiB,CAAC,KACpD,KAAK,gBAAgB,qCAAqC,EAC1D,KAAK,UAAU,KAAK,EACpB,KAAK,SACN;AAED,MAAM,QAAQ,KAAK,QAAQ,QAAQ,CAAC,KAClC,KAAK,gBAAgB,iCAAiC,EACtD,KAAK,UAAU,IAAI,EACnB,KAAK,SACN;;;;;;AAOD,MAAa,4BAA4B,QAAQ,KAC/C,UACA;CAAE;CAAO;CAAY;CAAe;CAAO,GAC1C,EAAE,OAAO,YAAY,eAAe,YACnC,QAAQ,OAAO,YAAY,eAAe,MAAM,CACnD,CAAC,KACA,QAAQ,UAAU,IAAI,EACtB,QAAQ,gBAAgB,8BAA8B,EACtD,QAAQ,aAAa;CACnB;EACE,SAAS;EACT,aAAa;EACd;CACD;EACE,SACE;EACF,aACE;EACH;CACD;EACE,SAAS;EACT,aAAa;EACd;CACD;EACE,SAAS;EACT,aAAa;EACd;CACF,CAAC,CACH"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { SupportedChain } from "../schema/chain.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { EntrypointVersion, EthereumAddress, KernelVersion, OwnerType } from "../schema/common.mjs";
|
|
4
4
|
import "../schema/index.mjs";
|
|
5
5
|
import { Schema } from "effect";
|
|
6
6
|
//#region src/dto/smart-account.ts
|
|
7
7
|
const LocalSmartAccount = Schema.Struct({
|
|
8
8
|
entryPointVersion: EntrypointVersion,
|
|
9
|
-
index: BigIntFromString,
|
|
9
|
+
index: Schema.BigIntFromString,
|
|
10
10
|
kernelVersion: KernelVersion,
|
|
11
11
|
ownerAlias: Schema.String,
|
|
12
12
|
ownerType: OwnerType,
|
|
@@ -21,7 +21,7 @@ const CreateSmartAccountParams = Schema.Struct({
|
|
|
21
21
|
alias: Schema.String.annotate({ description: "The alias of the smart account to create" }),
|
|
22
22
|
ownerAlias: Schema.String.annotate({ description: "The alias of the owner keystore" }),
|
|
23
23
|
ownerPassword: Schema.redact(Schema.String).annotate({ description: "The password of the owner keystore" }),
|
|
24
|
-
index: Schema.optional(BigIntFromString.check(Schema.makeFilter((v) => v >= 0n))).annotate({
|
|
24
|
+
index: Schema.optional(Schema.BigIntFromString.check(Schema.makeFilter((v) => v >= 0n))).annotate({
|
|
25
25
|
description: "The index of the smart account",
|
|
26
26
|
default: 0n
|
|
27
27
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smart-account.mjs","names":[],"sources":["../../src/dto/smart-account.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\nimport {\n
|
|
1
|
+
{"version":3,"file":"smart-account.mjs","names":[],"sources":["../../src/dto/smart-account.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\nimport {\n EntrypointVersion,\n EthereumAddress,\n KernelVersion,\n OwnerType,\n} from \"@/schema\";\nimport { SupportedChain } from \"@/schema/chain\";\n\nexport const LocalSmartAccount = Schema.Struct({\n entryPointVersion: EntrypointVersion,\n index: Schema.BigIntFromString,\n kernelVersion: KernelVersion,\n ownerAlias: Schema.String,\n ownerType: OwnerType,\n smartAccountAddress: EthereumAddress,\n});\n\nexport const LocalSmartAccountData = Schema.Struct({\n data: LocalSmartAccount,\n path: Schema.String,\n alias: Schema.String,\n});\n\nexport const CreateSmartAccountParams = Schema.Struct({\n alias: Schema.String.annotate({\n description: \"The alias of the smart account to create\",\n }),\n ownerAlias: Schema.String.annotate({\n description: \"The alias of the owner keystore\",\n }),\n ownerPassword: Schema.redact(Schema.String).annotate({\n description: \"The password of the owner keystore\",\n }),\n index: Schema.optional(\n Schema.BigIntFromString.check(Schema.makeFilter((v) => v >= 0n)),\n ).annotate({\n description: \"The index of the smart account\",\n default: 0n,\n }),\n});\n\nexport const GetSmartAccountParams = Schema.Struct({\n alias: Schema.String.annotate({\n description: \"The alias of the smart account to retrieve\",\n }),\n});\nexport const ListSmartAccountParams = Schema.Void;\n\nexport const GetSmartAccountInfoParams = Schema.Struct({\n alias: Schema.String.annotate({\n description: \"The alias of the smart account to retrieve\",\n }),\n});\n\nexport const RemoveSmartAccountParams = Schema.Struct({\n alias: Schema.String.annotate({\n description: \"The alias of the smart account to remove\",\n }),\n});\n\nexport const GetSmartAccountStatusParams = Schema.Struct({\n alias: Schema.String.annotate({\n description: \"The alias of the smart account\",\n }),\n chain: SupportedChain.annotate({\n description: \"The chain to get the status for\",\n }),\n rpcUrl: Schema.redact(Schema.String.pipe(Schema.optional)).annotate({\n description: \"The RPC URL to use for the chain\",\n default: \"Public RPC URL\",\n }),\n});\n\nexport const ImportSmartAccountParams = LocalSmartAccount.pipe(\n Schema.fieldsAssign({\n alias: Schema.String.annotate({\n description: \"The alias of the smart account to import\",\n }),\n }),\n);\n\nexport type LocalSmartAccount = typeof LocalSmartAccount.Type;\nexport type LocalSmartAccountData = typeof LocalSmartAccountData.Type;\nexport type CreateSmartAccountParams = typeof CreateSmartAccountParams.Type;\nexport type GetSmartAccountParams = typeof GetSmartAccountParams.Type;\nexport type ListSmartAccountParams = typeof ListSmartAccountParams.Type;\nexport type GetSmartAccountInfoParams = typeof GetSmartAccountInfoParams.Type;\nexport type RemoveSmartAccountParams = typeof RemoveSmartAccountParams.Type;\nexport type GetSmartAccountStatusParams =\n typeof GetSmartAccountStatusParams.Type;\n\nexport type ImportSmartAccountParams = typeof ImportSmartAccountParams.Type;\n"],"mappings":";;;;;;AAUA,MAAa,oBAAoB,OAAO,OAAO;CAC7C,mBAAmB;CACnB,OAAO,OAAO;CACd,eAAe;CACf,YAAY,OAAO;CACnB,WAAW;CACX,qBAAqB;CACtB,CAAC;AAEmC,OAAO,OAAO;CACjD,MAAM;CACN,MAAM,OAAO;CACb,OAAO,OAAO;CACf,CAAC;AAEF,MAAa,2BAA2B,OAAO,OAAO;CACpD,OAAO,OAAO,OAAO,SAAS,EAC5B,aAAa,4CACd,CAAC;CACF,YAAY,OAAO,OAAO,SAAS,EACjC,aAAa,mCACd,CAAC;CACF,eAAe,OAAO,OAAO,OAAO,OAAO,CAAC,SAAS,EACnD,aAAa,sCACd,CAAC;CACF,OAAO,OAAO,SACZ,OAAO,iBAAiB,MAAM,OAAO,YAAY,MAAM,KAAK,GAAG,CAAC,CACjE,CAAC,SAAS;EACT,aAAa;EACb,SAAS;EACV,CAAC;CACH,CAAC;AAEmC,OAAO,OAAO,EACjD,OAAO,OAAO,OAAO,SAAS,EAC5B,aAAa,8CACd,CAAC,EACH,CAAC;AACF,MAAa,yBAAyB,OAAO;AAE7C,MAAa,4BAA4B,OAAO,OAAO,EACrD,OAAO,OAAO,OAAO,SAAS,EAC5B,aAAa,8CACd,CAAC,EACH,CAAC;AAEF,MAAa,2BAA2B,OAAO,OAAO,EACpD,OAAO,OAAO,OAAO,SAAS,EAC5B,aAAa,4CACd,CAAC,EACH,CAAC;AAEF,MAAa,8BAA8B,OAAO,OAAO;CACvD,OAAO,OAAO,OAAO,SAAS,EAC5B,aAAa,kCACd,CAAC;CACF,OAAO,eAAe,SAAS,EAC7B,aAAa,mCACd,CAAC;CACF,QAAQ,OAAO,OAAO,OAAO,OAAO,KAAK,OAAO,SAAS,CAAC,CAAC,SAAS;EAClE,aAAa;EACb,SAAS;EACV,CAAC;CACH,CAAC;AAEF,MAAa,2BAA2B,kBAAkB,KACxD,OAAO,aAAa,EAClB,OAAO,OAAO,OAAO,SAAS,EAC5B,aAAa,4CACd,CAAC,EACH,CAAC,CACH"}
|
package/dist/index.mjs
CHANGED
|
@@ -10,11 +10,12 @@ import { layer as layer$6 } from "./layers/mcp.mjs";
|
|
|
10
10
|
import { layer as layer$7 } from "./layers/output.mjs";
|
|
11
11
|
import "./layers/index.mjs";
|
|
12
12
|
import { commands } from "./commands/index.mjs";
|
|
13
|
+
import { createRequire } from "node:module";
|
|
13
14
|
import "dotenv/config";
|
|
14
15
|
import { NodeRuntime, NodeServices } from "@effect/platform-node";
|
|
15
16
|
import { ConfigProvider, Console, Effect, Layer } from "effect";
|
|
16
17
|
import { CliError, Command } from "effect/unstable/cli";
|
|
17
|
-
|
|
18
|
+
const packageJson = createRequire(import.meta.url)("../package.json");
|
|
18
19
|
const command = Command.make("namera", {}, () => Effect.fail(new CliError.ShowHelp({
|
|
19
20
|
commandPath: ["namera"],
|
|
20
21
|
errors: []
|
|
@@ -28,7 +29,7 @@ const command = Command.make("namera", {}, () => Effect.fail(new CliError.ShowHe
|
|
|
28
29
|
const Layers = layer$6.pipe(Layer.provideMerge(layer$5), Layer.provideMerge(layer$4), Layer.provideMerge(layer$2), Layer.provideMerge(layer$3), Layer.provideMerge(layer$1), Layer.provideMerge(layer), Layer.provideMerge(layer$7), Layer.provideMerge(NodeServices.layer));
|
|
29
30
|
Effect.gen(function* () {
|
|
30
31
|
yield* (yield* ConfigManager).ensureConfigDirExists();
|
|
31
|
-
yield* Command.run(command, { version:
|
|
32
|
+
yield* Command.run(command, { version: packageJson.version });
|
|
32
33
|
}).pipe(Effect.provide(Layers), Effect.provideService(ConfigProvider.ConfigProvider, ConfigProvider.fromEnv()), Effect.catchTag("ShowHelp", () => Effect.succeed(void 0)), Effect.catch((e) => Console.error(e.message))).pipe(NodeRuntime.runMain);
|
|
33
34
|
//#endregion
|
|
34
35
|
export {};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["SessionKeyManager.layer","SmartAccountManager.layer","KeystoreManager.layer","Web3Service.layer","PromptManager.layer","ConfigManager.layer","OutputFormatter.layer","ConfigManager.ConfigManager"],"sources":["../src/index.ts"],"sourcesContent":["import \"dotenv/config\";\n\nimport { NodeRuntime, NodeServices } from \"@effect/platform-node\";\nimport { ConfigProvider, Console, Effect, Layer } from \"effect\";\nimport { CliError, Command } from \"effect/unstable/cli\";\n\nimport { commands } from \"./commands\";\nimport { globalFlags } from \"./flags/global\";\nimport {\n ConfigManager,\n KeystoreManager,\n McpManager,\n OutputFormatter,\n PromptManager,\n SessionKeyManager,\n SmartAccountManager,\n Web3Service,\n} from \"./layers\";\n\nconst command = Command.make(\"namera\", {}, () =>\n Effect.fail(\n new CliError.ShowHelp({\n commandPath: [\"namera\"],\n errors: [],\n }),\n ),\n).pipe(\n Command.withDescription(\n \"Programmable Session keys for Smart Contracts Accounts.\",\n ),\n Command.withGlobalFlags(globalFlags),\n Command.withSubcommands(commands),\n Command.withExamples([\n {\n command: \"namera --help\",\n description: \"Print help\",\n },\n {\n command: \"namera --version\",\n description: \"Print version\",\n },\n ]),\n);\n\nconst Layers = McpManager.layer.pipe(\n Layer.provideMerge(SessionKeyManager.layer),\n Layer.provideMerge(SmartAccountManager.layer),\n Layer.provideMerge(KeystoreManager.layer),\n Layer.provideMerge(Web3Service.layer),\n Layer.provideMerge(PromptManager.layer),\n Layer.provideMerge(ConfigManager.layer),\n Layer.provideMerge(OutputFormatter.layer),\n Layer.provideMerge(NodeServices.layer),\n);\n\nconst cli = Effect.gen(function* () {\n const configManager = yield* ConfigManager.ConfigManager;\n yield* configManager.ensureConfigDirExists();\n\n yield* Command.run(command, {\n version:
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["SessionKeyManager.layer","SmartAccountManager.layer","KeystoreManager.layer","Web3Service.layer","PromptManager.layer","ConfigManager.layer","OutputFormatter.layer","ConfigManager.ConfigManager"],"sources":["../src/index.ts"],"sourcesContent":["import \"dotenv/config\";\n\nimport { createRequire } from \"node:module\";\n\nimport { NodeRuntime, NodeServices } from \"@effect/platform-node\";\nimport { ConfigProvider, Console, Effect, Layer } from \"effect\";\nimport { CliError, Command } from \"effect/unstable/cli\";\n\nimport { commands } from \"./commands\";\nimport { globalFlags } from \"./flags/global\";\nimport {\n ConfigManager,\n KeystoreManager,\n McpManager,\n OutputFormatter,\n PromptManager,\n SessionKeyManager,\n SmartAccountManager,\n Web3Service,\n} from \"./layers\";\n\nconst require = createRequire(import.meta.url);\nconst packageJson = require(\"../package.json\");\n\nconst command = Command.make(\"namera\", {}, () =>\n Effect.fail(\n new CliError.ShowHelp({\n commandPath: [\"namera\"],\n errors: [],\n }),\n ),\n).pipe(\n Command.withDescription(\n \"Programmable Session keys for Smart Contracts Accounts.\",\n ),\n Command.withGlobalFlags(globalFlags),\n Command.withSubcommands(commands),\n Command.withExamples([\n {\n command: \"namera --help\",\n description: \"Print help\",\n },\n {\n command: \"namera --version\",\n description: \"Print version\",\n },\n ]),\n);\n\nconst Layers = McpManager.layer.pipe(\n Layer.provideMerge(SessionKeyManager.layer),\n Layer.provideMerge(SmartAccountManager.layer),\n Layer.provideMerge(KeystoreManager.layer),\n Layer.provideMerge(Web3Service.layer),\n Layer.provideMerge(PromptManager.layer),\n Layer.provideMerge(ConfigManager.layer),\n Layer.provideMerge(OutputFormatter.layer),\n Layer.provideMerge(NodeServices.layer),\n);\n\nconst cli = Effect.gen(function* () {\n const configManager = yield* ConfigManager.ConfigManager;\n yield* configManager.ensureConfigDirExists();\n\n yield* Command.run(command, {\n version: packageJson.version,\n });\n}).pipe(\n Effect.provide(Layers),\n Effect.provideService(\n ConfigProvider.ConfigProvider,\n ConfigProvider.fromEnv(),\n ),\n Effect.catchTag(\"ShowHelp\", () => Effect.succeed(void 0)),\n Effect.catch((e) => Console.error(e.message)),\n);\n\n// @ts-expect-error - TODO: fix this\ncli.pipe(NodeRuntime.runMain);\n"],"mappings":";;;;;;;;;;;;;;;;;AAsBA,MAAM,cADU,cAAc,OAAO,KAAK,IACtB,CAAQ,kBAAkB;AAE9C,MAAM,UAAU,QAAQ,KAAK,UAAU,EAAE,QACvC,OAAO,KACL,IAAI,SAAS,SAAS;CACpB,aAAa,CAAC,SAAS;CACvB,QAAQ,EAAE;CACX,CAAC,CACH,CACF,CAAC,KACA,QAAQ,gBACN,0DACD,EACD,QAAQ,gBAAgB,YAAY,EACpC,QAAQ,gBAAgB,SAAS,EACjC,QAAQ,aAAa,CACnB;CACE,SAAS;CACT,aAAa;CACd,EACD;CACE,SAAS;CACT,aAAa;CACd,CACF,CAAC,CACH;AAED,MAAM,SAAA,QAA0B,KAC9B,MAAM,aAAaA,QAAwB,EAC3C,MAAM,aAAaC,QAA0B,EAC7C,MAAM,aAAaC,QAAsB,EACzC,MAAM,aAAaC,QAAkB,EACrC,MAAM,aAAaC,QAAoB,EACvC,MAAM,aAAaC,MAAoB,EACvC,MAAM,aAAaC,QAAsB,EACzC,MAAM,aAAa,aAAa,MAAM,CACvC;AAEW,OAAO,IAAI,aAAa;AAElC,SAAO,OADsBC,eACR,uBAAuB;AAE5C,QAAO,QAAQ,IAAI,SAAS,EAC1B,SAAS,YAAY,SACtB,CAAC;EACF,CAAC,KACD,OAAO,QAAQ,OAAO,EACtB,OAAO,eACL,eAAe,gBACf,eAAe,SAAS,CACzB,EACD,OAAO,SAAS,kBAAkB,OAAO,QAAQ,KAAK,EAAE,CAAC,EACzD,OAAO,OAAO,MAAM,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAI/C,CAAI,KAAK,YAAY,QAAQ"}
|
|
@@ -7,7 +7,7 @@ import { KeystoreManager } from "./keystore.mjs";
|
|
|
7
7
|
import { Web3Service } from "./web3.mjs";
|
|
8
8
|
import { Context, Data, Effect, Layer, Schema } from "effect";
|
|
9
9
|
import { mainnet } from "viem/chains";
|
|
10
|
-
import {
|
|
10
|
+
import { http } from "viem";
|
|
11
11
|
import { createAccountClient } from "@namera-ai/sdk/account";
|
|
12
12
|
//#region src/layers/smart-account.ts
|
|
13
13
|
/**
|
|
@@ -60,10 +60,7 @@ const layer = Layer.effect(SmartAccountManager, Effect.gen(function* () {
|
|
|
60
60
|
alias: params.ownerAlias,
|
|
61
61
|
password: params.ownerPassword
|
|
62
62
|
});
|
|
63
|
-
const publicClient =
|
|
64
|
-
chain: mainnet,
|
|
65
|
-
transport: http()
|
|
66
|
-
});
|
|
63
|
+
const publicClient = yield* web3Service.getPublicClient({ chain: "eth-sepolia" });
|
|
67
64
|
const entryPointVersion = "0.7";
|
|
68
65
|
const kernelVersion = "0.3.2";
|
|
69
66
|
const index = BigInt(params.index ?? 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smart-account.mjs","names":[],"sources":["../../src/layers/smart-account.ts"],"sourcesContent":["import { createAccountClient } from \"@namera-ai/sdk/account\";\nimport { Context, Data, Effect, Layer, Schema } from \"effect\";\nimport type { QuitError } from \"effect/Terminal\";\nimport type { Prompt } from \"effect/unstable/cli\";\nimport type { Environment } from \"effect/unstable/cli/Prompt\";\nimport { createPublicClient, http, type PublicClient } from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\nimport {\n type CreateSmartAccountParams,\n type GetSmartAccountParams,\n type GetSmartAccountStatusParams,\n type ImportSmartAccountParams,\n LocalSmartAccount,\n type LocalSmartAccountData,\n type RemoveSmartAccountParams,\n} from \"@/dto\";\n\nimport { ConfigManager, type ConfigManagerError } from \"./config\";\nimport { KeystoreManager, type KeystoreManagerError } from \"./keystore\";\nimport { PromptManager } from \"./prompt\";\nimport { Web3Service } from \"./web3\";\n\nexport type SmartAccountManager = {\n /**\n * Loads a smart account by alias and parses the stored JSON payload.\n *\n * @param params Alias of the smart account to load.\n * @returns The parsed smart account data.\n */\n getSmartAccount: (\n params: GetSmartAccountParams,\n ) => Effect.Effect<LocalSmartAccountData, ConfigManagerError, never>;\n /**\n * Lists all locally stored smart accounts.\n *\n * @returns The list of smart account data.\n */\n listSmartAccounts: () => Effect.Effect<\n LocalSmartAccountData[],\n ConfigManagerError,\n never\n >;\n /**\n * Prompts the user to select a smart account from local storage.\n *\n * @param params - Prompt message to display.\n * @returns The selected smart account data.\n */\n selectSmartAccount: (params: {\n message: string;\n }) => Effect.Effect<\n LocalSmartAccountData,\n ConfigManagerError | KeystoreManagerError | QuitError,\n Environment\n >;\n /**\n * Creates a new smart account derived from a local keystore and index.\n *\n * @param params - Alias, owner alias, and optional index for derivation.\n * @returns The created smart account data.\n */\n createSmartAccount: (\n params: CreateSmartAccountParams,\n ) => Effect.Effect<\n LocalSmartAccountData,\n SmartAccountManagerError | ConfigManagerError | KeystoreManagerError,\n never\n >;\n /**\n * Removes a locally stored smart account by alias.\n *\n * @param params - Alias of the smart account to remove.\n */\n removeSmartAccount: (\n params: RemoveSmartAccountParams,\n ) => Effect.Effect<\n void,\n ConfigManagerError | SmartAccountManagerError,\n never\n >;\n /**\n * Checks if a smart account is deployed on the specified chain.\n *\n * @param params - Alias plus chain and optional RPC URL.\n * @returns Whether the smart account is deployed.\n */\n getSmartAccountStatus: (\n params: GetSmartAccountStatusParams,\n ) => Effect.Effect<boolean, ConfigManagerError, never>;\n /**\n * Imports a smart account with precomputed metadata and address.\n *\n * @param params - Smart account metadata and alias to store.\n * @returns The imported smart account data.\n */\n importSmartAccount: (\n params: ImportSmartAccountParams,\n ) => Effect.Effect<\n LocalSmartAccountData,\n SmartAccountManagerError | ConfigManagerError | KeystoreManagerError,\n never\n >;\n};\n\n/**\n * Service tag for resolving {@link SmartAccountManager} from the Effect context.\n */\nexport const SmartAccountManager = Context.Service<SmartAccountManager>(\n \"@namera-ai/cli/SmartAccountManager\",\n);\n\n/**\n * Domain error for smart account lifecycle operations.\n */\nexport class SmartAccountManagerError extends Data.TaggedError(\n \"@namera-ai/cli/SmartAccountManagerError\",\n)<{\n code:\n | \"KernelAddressGenerationError\"\n | \"SmartAccountAlreadyExists\"\n | \"SmartAccountNotFound\"\n | \"SmartAccountImportError\";\n message: string;\n}> {}\n\n/**\n * Live layer that manages smart account storage and derivation.\n */\nexport const layer = Layer.effect(\n SmartAccountManager,\n Effect.gen(function* () {\n const configManager = yield* ConfigManager;\n const keystoreManager = yield* KeystoreManager;\n const promptManager = yield* PromptManager;\n const web3Service = yield* Web3Service;\n\n const getSmartAccount = (params: GetSmartAccountParams) =>\n Effect.gen(function* () {\n const res = yield* configManager.getEntity({\n alias: params.alias,\n type: \"smart-account\",\n });\n\n const parsedSmartAccount = Schema.decodeUnknownSync(\n Schema.fromJsonString(LocalSmartAccount),\n )(res.content);\n\n return {\n alias: res.alias,\n data: parsedSmartAccount,\n path: res.path,\n } satisfies LocalSmartAccountData;\n });\n\n const listSmartAccounts = () =>\n Effect.gen(function* () {\n const res = yield* configManager.getEntitiesForType(\"smart-account\");\n\n const effects = res.map((entity) =>\n Effect.gen(function* () {\n const parsedSmartAccount = Schema.decodeUnknownSync(\n Schema.fromJsonString(LocalSmartAccount),\n )(entity.content);\n\n return {\n alias: entity.alias,\n data: parsedSmartAccount,\n path: entity.path,\n } satisfies LocalSmartAccountData;\n }),\n );\n\n return yield* Effect.all(effects, { concurrency: \"unbounded\" });\n });\n\n const createSmartAccount = (params: CreateSmartAccountParams) =>\n Effect.gen(function* () {\n const existingAccounts = yield* listSmartAccounts();\n\n const entityPath = yield* configManager.getEntityPath({\n alias: params.alias,\n type: \"smart-account\",\n });\n\n const ownerKeystore = yield* keystoreManager.getKeystore({\n alias: params.ownerAlias,\n });\n\n const ownerSigner = yield* keystoreManager.getSigner({\n alias: params.ownerAlias,\n password: params.ownerPassword,\n });\n\n // Doesn't matter because public client is only needed for 0.6 entrypoints\n const publicClient = createPublicClient({\n chain: mainnet,\n transport: http(),\n });\n\n const entryPointVersion = \"0.7\";\n const kernelVersion = \"0.3.2\";\n const index = BigInt(params.index ?? 0);\n const ownerType = \"ecdsa\";\n\n const res = yield* Effect.tryPromise({\n try: () =>\n createAccountClient({\n type: \"ecdsa\",\n bundlerTransport: http(),\n chain: mainnet,\n client: publicClient,\n entrypointVersion: entryPointVersion,\n kernelVersion,\n signer: ownerSigner,\n }),\n catch: () =>\n new SmartAccountManagerError({\n code: \"KernelAddressGenerationError\",\n message: `Unable to compute smart account address for Address: ${ownerKeystore.data.address} and Index: ${params.index}`,\n }),\n });\n\n const saAddress = res.account.address;\n\n const exists = existingAccounts.find(\n (d) => d.data.smartAccountAddress === saAddress,\n );\n\n if (exists) {\n return yield* Effect.fail(\n new SmartAccountManagerError({\n code: \"SmartAccountAlreadyExists\",\n message: `Smart account for owner: ${ownerKeystore.alias} and index: ${params.index} already exists`,\n }),\n );\n }\n\n const saData: LocalSmartAccount = {\n entryPointVersion,\n kernelVersion,\n ownerAlias: ownerKeystore.alias,\n ownerType,\n smartAccountAddress: saAddress,\n index,\n };\n\n const data: LocalSmartAccountData = {\n data: saData,\n path: entityPath,\n alias: params.alias,\n };\n\n const encoded = Schema.encodeSync(LocalSmartAccount)(saData);\n\n yield* configManager.storeEntity({\n alias: params.alias,\n content: JSON.stringify(encoded),\n path: entityPath,\n type: \"smart-account\",\n });\n\n return data;\n });\n\n const selectSmartAccount = (params: { message: string }) =>\n Effect.gen(function* () {\n const smartAccounts = yield* listSmartAccounts();\n\n const res = yield* promptManager.selectPrompt({\n message: params.message,\n choices: smartAccounts.map((a) => ({\n title: a.alias,\n value: a,\n description: a.data.smartAccountAddress,\n })) satisfies Prompt.SelectChoice<LocalSmartAccountData>[],\n });\n\n return res;\n });\n\n const removeSmartAccount = (params: RemoveSmartAccountParams) =>\n Effect.gen(function* () {\n const sa = yield* getSmartAccount({ alias: params.alias });\n\n return yield* configManager.removeEntity({\n alias: sa.alias,\n type: \"smart-account\",\n });\n });\n\n const getSmartAccountStatus = (params: GetSmartAccountStatusParams) =>\n Effect.gen(function* () {\n const sa = yield* getSmartAccount({ alias: params.alias });\n\n const publicClient = (yield* web3Service.getPublicClient({\n chain: params.chain,\n rpcUrl: params.rpcUrl,\n })) as PublicClient;\n\n const code = yield* Effect.promise(() =>\n publicClient.getCode({\n address: sa.data.smartAccountAddress,\n }),\n );\n\n return Boolean(code);\n });\n\n const importSmartAccount = (params: ImportSmartAccountParams) =>\n Effect.gen(function* () {\n const { alias, ...rest } = params;\n const entityPath = yield* configManager.getEntityPath({\n alias: params.alias,\n type: \"smart-account\",\n });\n\n const ownerKeystore = yield* keystoreManager.getKeystore({\n alias: params.ownerAlias,\n });\n\n const allAccounts = yield* listSmartAccounts();\n\n const exists = allAccounts.find(\n (d) => d.data.smartAccountAddress === rest.smartAccountAddress,\n );\n\n if (exists) {\n return yield* Effect.fail(\n new SmartAccountManagerError({\n code: \"SmartAccountAlreadyExists\",\n message: `Smart account for owner: ${ownerKeystore.alias} and address: ${rest.smartAccountAddress} already exists`,\n }),\n );\n }\n\n yield* configManager.storeEntity({\n alias: params.alias,\n content: JSON.stringify(Schema.encodeSync(LocalSmartAccount)(rest)),\n path: entityPath,\n type: \"smart-account\",\n });\n\n return {\n alias: params.alias,\n data: rest,\n path: entityPath,\n };\n });\n\n return SmartAccountManager.of({\n createSmartAccount,\n getSmartAccount,\n listSmartAccounts,\n selectSmartAccount,\n removeSmartAccount,\n getSmartAccountStatus,\n importSmartAccount,\n });\n }),\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"smart-account.mjs","names":[],"sources":["../../src/layers/smart-account.ts"],"sourcesContent":["import { createAccountClient } from \"@namera-ai/sdk/account\";\nimport { Context, Data, Effect, Layer, Schema } from \"effect\";\nimport type { QuitError } from \"effect/Terminal\";\nimport type { Prompt } from \"effect/unstable/cli\";\nimport type { Environment } from \"effect/unstable/cli/Prompt\";\nimport { http, type PublicClient } from \"viem\";\nimport { mainnet } from \"viem/chains\";\n\nimport {\n type CreateSmartAccountParams,\n type GetSmartAccountParams,\n type GetSmartAccountStatusParams,\n type ImportSmartAccountParams,\n LocalSmartAccount,\n type LocalSmartAccountData,\n type RemoveSmartAccountParams,\n} from \"@/dto\";\n\nimport { ConfigManager, type ConfigManagerError } from \"./config\";\nimport { KeystoreManager, type KeystoreManagerError } from \"./keystore\";\nimport { PromptManager } from \"./prompt\";\nimport { Web3Service } from \"./web3\";\n\nexport type SmartAccountManager = {\n /**\n * Loads a smart account by alias and parses the stored JSON payload.\n *\n * @param params Alias of the smart account to load.\n * @returns The parsed smart account data.\n */\n getSmartAccount: (\n params: GetSmartAccountParams,\n ) => Effect.Effect<LocalSmartAccountData, ConfigManagerError, never>;\n /**\n * Lists all locally stored smart accounts.\n *\n * @returns The list of smart account data.\n */\n listSmartAccounts: () => Effect.Effect<\n LocalSmartAccountData[],\n ConfigManagerError,\n never\n >;\n /**\n * Prompts the user to select a smart account from local storage.\n *\n * @param params - Prompt message to display.\n * @returns The selected smart account data.\n */\n selectSmartAccount: (params: {\n message: string;\n }) => Effect.Effect<\n LocalSmartAccountData,\n ConfigManagerError | KeystoreManagerError | QuitError,\n Environment\n >;\n /**\n * Creates a new smart account derived from a local keystore and index.\n *\n * @param params - Alias, owner alias, and optional index for derivation.\n * @returns The created smart account data.\n */\n createSmartAccount: (\n params: CreateSmartAccountParams,\n ) => Effect.Effect<\n LocalSmartAccountData,\n SmartAccountManagerError | ConfigManagerError | KeystoreManagerError,\n never\n >;\n /**\n * Removes a locally stored smart account by alias.\n *\n * @param params - Alias of the smart account to remove.\n */\n removeSmartAccount: (\n params: RemoveSmartAccountParams,\n ) => Effect.Effect<\n void,\n ConfigManagerError | SmartAccountManagerError,\n never\n >;\n /**\n * Checks if a smart account is deployed on the specified chain.\n *\n * @param params - Alias plus chain and optional RPC URL.\n * @returns Whether the smart account is deployed.\n */\n getSmartAccountStatus: (\n params: GetSmartAccountStatusParams,\n ) => Effect.Effect<boolean, ConfigManagerError, never>;\n /**\n * Imports a smart account with precomputed metadata and address.\n *\n * @param params - Smart account metadata and alias to store.\n * @returns The imported smart account data.\n */\n importSmartAccount: (\n params: ImportSmartAccountParams,\n ) => Effect.Effect<\n LocalSmartAccountData,\n SmartAccountManagerError | ConfigManagerError | KeystoreManagerError,\n never\n >;\n};\n\n/**\n * Service tag for resolving {@link SmartAccountManager} from the Effect context.\n */\nexport const SmartAccountManager = Context.Service<SmartAccountManager>(\n \"@namera-ai/cli/SmartAccountManager\",\n);\n\n/**\n * Domain error for smart account lifecycle operations.\n */\nexport class SmartAccountManagerError extends Data.TaggedError(\n \"@namera-ai/cli/SmartAccountManagerError\",\n)<{\n code:\n | \"KernelAddressGenerationError\"\n | \"SmartAccountAlreadyExists\"\n | \"SmartAccountNotFound\"\n | \"SmartAccountImportError\";\n message: string;\n}> {}\n\n/**\n * Live layer that manages smart account storage and derivation.\n */\nexport const layer = Layer.effect(\n SmartAccountManager,\n Effect.gen(function* () {\n const configManager = yield* ConfigManager;\n const keystoreManager = yield* KeystoreManager;\n const promptManager = yield* PromptManager;\n const web3Service = yield* Web3Service;\n\n const getSmartAccount = (params: GetSmartAccountParams) =>\n Effect.gen(function* () {\n const res = yield* configManager.getEntity({\n alias: params.alias,\n type: \"smart-account\",\n });\n\n const parsedSmartAccount = Schema.decodeUnknownSync(\n Schema.fromJsonString(LocalSmartAccount),\n )(res.content);\n\n return {\n alias: res.alias,\n data: parsedSmartAccount,\n path: res.path,\n } satisfies LocalSmartAccountData;\n });\n\n const listSmartAccounts = () =>\n Effect.gen(function* () {\n const res = yield* configManager.getEntitiesForType(\"smart-account\");\n\n const effects = res.map((entity) =>\n Effect.gen(function* () {\n const parsedSmartAccount = Schema.decodeUnknownSync(\n Schema.fromJsonString(LocalSmartAccount),\n )(entity.content);\n\n return {\n alias: entity.alias,\n data: parsedSmartAccount,\n path: entity.path,\n } satisfies LocalSmartAccountData;\n }),\n );\n\n return yield* Effect.all(effects, { concurrency: \"unbounded\" });\n });\n\n const createSmartAccount = (params: CreateSmartAccountParams) =>\n Effect.gen(function* () {\n const existingAccounts = yield* listSmartAccounts();\n\n const entityPath = yield* configManager.getEntityPath({\n alias: params.alias,\n type: \"smart-account\",\n });\n\n const ownerKeystore = yield* keystoreManager.getKeystore({\n alias: params.ownerAlias,\n });\n\n const ownerSigner = yield* keystoreManager.getSigner({\n alias: params.ownerAlias,\n password: params.ownerPassword,\n });\n\n // Doesn't matter because public client is only needed for 0.6 entrypoints\n const publicClient = yield* web3Service.getPublicClient({\n chain: \"eth-sepolia\",\n });\n\n const entryPointVersion = \"0.7\";\n const kernelVersion = \"0.3.2\";\n const index = BigInt(params.index ?? 0);\n const ownerType = \"ecdsa\";\n\n const res = yield* Effect.tryPromise({\n try: () =>\n createAccountClient({\n type: \"ecdsa\",\n bundlerTransport: http(),\n chain: mainnet,\n client: publicClient,\n entrypointVersion: entryPointVersion,\n kernelVersion,\n signer: ownerSigner,\n }),\n catch: () =>\n new SmartAccountManagerError({\n code: \"KernelAddressGenerationError\",\n message: `Unable to compute smart account address for Address: ${ownerKeystore.data.address} and Index: ${params.index}`,\n }),\n });\n\n const saAddress = res.account.address;\n\n const exists = existingAccounts.find(\n (d) => d.data.smartAccountAddress === saAddress,\n );\n\n if (exists) {\n return yield* Effect.fail(\n new SmartAccountManagerError({\n code: \"SmartAccountAlreadyExists\",\n message: `Smart account for owner: ${ownerKeystore.alias} and index: ${params.index} already exists`,\n }),\n );\n }\n\n const saData: LocalSmartAccount = {\n entryPointVersion,\n kernelVersion,\n ownerAlias: ownerKeystore.alias,\n ownerType,\n smartAccountAddress: saAddress,\n index,\n };\n\n const data: LocalSmartAccountData = {\n data: saData,\n path: entityPath,\n alias: params.alias,\n };\n\n const encoded = Schema.encodeSync(LocalSmartAccount)(saData);\n\n yield* configManager.storeEntity({\n alias: params.alias,\n content: JSON.stringify(encoded),\n path: entityPath,\n type: \"smart-account\",\n });\n\n return data;\n });\n\n const selectSmartAccount = (params: { message: string }) =>\n Effect.gen(function* () {\n const smartAccounts = yield* listSmartAccounts();\n\n const res = yield* promptManager.selectPrompt({\n message: params.message,\n choices: smartAccounts.map((a) => ({\n title: a.alias,\n value: a,\n description: a.data.smartAccountAddress,\n })) satisfies Prompt.SelectChoice<LocalSmartAccountData>[],\n });\n\n return res;\n });\n\n const removeSmartAccount = (params: RemoveSmartAccountParams) =>\n Effect.gen(function* () {\n const sa = yield* getSmartAccount({ alias: params.alias });\n\n return yield* configManager.removeEntity({\n alias: sa.alias,\n type: \"smart-account\",\n });\n });\n\n const getSmartAccountStatus = (params: GetSmartAccountStatusParams) =>\n Effect.gen(function* () {\n const sa = yield* getSmartAccount({ alias: params.alias });\n\n const publicClient = (yield* web3Service.getPublicClient({\n chain: params.chain,\n rpcUrl: params.rpcUrl,\n })) as PublicClient;\n\n const code = yield* Effect.promise(() =>\n publicClient.getCode({\n address: sa.data.smartAccountAddress,\n }),\n );\n\n return Boolean(code);\n });\n\n const importSmartAccount = (params: ImportSmartAccountParams) =>\n Effect.gen(function* () {\n const { alias, ...rest } = params;\n const entityPath = yield* configManager.getEntityPath({\n alias: params.alias,\n type: \"smart-account\",\n });\n\n const ownerKeystore = yield* keystoreManager.getKeystore({\n alias: params.ownerAlias,\n });\n\n const allAccounts = yield* listSmartAccounts();\n\n const exists = allAccounts.find(\n (d) => d.data.smartAccountAddress === rest.smartAccountAddress,\n );\n\n if (exists) {\n return yield* Effect.fail(\n new SmartAccountManagerError({\n code: \"SmartAccountAlreadyExists\",\n message: `Smart account for owner: ${ownerKeystore.alias} and address: ${rest.smartAccountAddress} already exists`,\n }),\n );\n }\n\n yield* configManager.storeEntity({\n alias: params.alias,\n content: JSON.stringify(Schema.encodeSync(LocalSmartAccount)(rest)),\n path: entityPath,\n type: \"smart-account\",\n });\n\n return {\n alias: params.alias,\n data: rest,\n path: entityPath,\n };\n });\n\n return SmartAccountManager.of({\n createSmartAccount,\n getSmartAccount,\n listSmartAccounts,\n selectSmartAccount,\n removeSmartAccount,\n getSmartAccountStatus,\n importSmartAccount,\n });\n }),\n);\n"],"mappings":"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"}
|
package/dist/mcp/index.mjs
CHANGED
|
@@ -1,23 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { McpLive } from "./mcp.mjs";
|
|
3
3
|
import { NodeHttpServer, NodeStdio } from "@effect/platform-node";
|
|
4
|
-
import { Layer, Logger } from "effect";
|
|
4
|
+
import { Effect, Layer, Logger } from "effect";
|
|
5
5
|
import { createServer } from "node:http";
|
|
6
6
|
import { McpServer } from "effect/unstable/ai";
|
|
7
|
-
import { HttpRouter } from "effect/unstable/http";
|
|
7
|
+
import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
|
|
8
8
|
//#region src/mcp/index.ts
|
|
9
9
|
const MCP_SERVER_NAME = "Namera MCP Server";
|
|
10
10
|
const MCP_SERVER_VERSION = "0.0.1";
|
|
11
|
-
const
|
|
11
|
+
const methodNotAllowed = HttpServerResponse.empty({
|
|
12
|
+
headers: { allow: "POST, OPTIONS" },
|
|
13
|
+
status: 405
|
|
14
|
+
});
|
|
15
|
+
const McpRouter = McpLive.pipe(Layer.provideMerge(HttpRouter.add("GET", "/mcp", methodNotAllowed)), Layer.provideMerge(McpServer.layerHttp({
|
|
12
16
|
name: MCP_SERVER_NAME,
|
|
13
17
|
path: "/mcp",
|
|
14
18
|
version: MCP_SERVER_VERSION
|
|
15
|
-
})), Layer.provideMerge(HttpRouter.
|
|
19
|
+
})), Layer.provideMerge(HttpRouter.middleware((httpEffect) => Effect.gen(function* () {
|
|
20
|
+
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
21
|
+
const response = yield* httpEffect;
|
|
22
|
+
const isMcpEndpoint = request.url.split("?")[0] === "/mcp";
|
|
23
|
+
const body = response.body;
|
|
24
|
+
if (request.method === "POST" && isMcpEndpoint && response.status === 200 && (body._tag === "Empty" || body._tag === "Stream" || body.contentLength === 0)) {
|
|
25
|
+
const { "content-type": _contentType, ...headers } = response.headers;
|
|
26
|
+
return HttpServerResponse.empty({
|
|
27
|
+
headers,
|
|
28
|
+
status: 202
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return response;
|
|
32
|
+
}), { global: true })), Layer.provideMerge(HttpRouter.cors({
|
|
16
33
|
allowedHeaders: [
|
|
17
34
|
"Content-Type",
|
|
18
35
|
"Authorization",
|
|
19
|
-
"mcp-
|
|
20
|
-
"mcp-
|
|
36
|
+
"mcp-protocol-version",
|
|
37
|
+
"mcp-session-id"
|
|
21
38
|
],
|
|
22
39
|
allowedMethods: [
|
|
23
40
|
"GET",
|
|
@@ -29,7 +46,7 @@ const McpRouter = McpLive.pipe(Layer.provideMerge(McpServer.layerHttp({
|
|
|
29
46
|
],
|
|
30
47
|
allowedOrigins: ["*"],
|
|
31
48
|
credentials: false,
|
|
32
|
-
exposedHeaders: ["mcp-session-id"
|
|
49
|
+
exposedHeaders: ["mcp-session-id"]
|
|
33
50
|
})));
|
|
34
51
|
const McpStdio = McpLive.pipe(Layer.provideMerge(McpServer.layerStdio({
|
|
35
52
|
name: MCP_SERVER_NAME,
|
package/dist/mcp/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/mcp/index.ts"],"sourcesContent":["import { createServer } from \"node:http\";\n\nimport { NodeHttpServer, NodeStdio } from \"@effect/platform-node\";\nimport { Layer, Logger } from \"effect\";\nimport { McpServer } from \"effect/unstable/ai\";\nimport {
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/mcp/index.ts"],"sourcesContent":["import { createServer } from \"node:http\";\n\nimport { NodeHttpServer, NodeStdio } from \"@effect/platform-node\";\nimport { Effect, Layer, Logger } from \"effect\";\nimport { McpServer } from \"effect/unstable/ai\";\nimport {\n HttpRouter,\n HttpServerRequest,\n HttpServerResponse,\n} from \"effect/unstable/http\";\n\nimport { McpLive } from \"./mcp\";\n\nconst MCP_SERVER_NAME = \"Namera MCP Server\";\nconst MCP_SERVER_VERSION = \"0.0.1\";\n\nconst methodNotAllowed = HttpServerResponse.empty({\n headers: { allow: \"POST, OPTIONS\" },\n status: 405,\n});\n\nconst McpRouter = McpLive.pipe(\n Layer.provideMerge(HttpRouter.add(\"GET\", \"/mcp\", methodNotAllowed)),\n Layer.provideMerge(\n McpServer.layerHttp({\n name: MCP_SERVER_NAME,\n path: \"/mcp\",\n version: MCP_SERVER_VERSION,\n }),\n ),\n Layer.provideMerge(\n HttpRouter.middleware(\n (httpEffect) =>\n Effect.gen(function* () {\n const request = yield* HttpServerRequest.HttpServerRequest;\n const response = yield* httpEffect;\n const isMcpEndpoint = request.url.split(\"?\")[0] === \"/mcp\";\n\n const body = response.body as {\n _tag: string;\n contentLength?: number;\n };\n\n if (\n request.method === \"POST\" &&\n isMcpEndpoint &&\n response.status === 200 &&\n (body._tag === \"Empty\" ||\n body._tag === \"Stream\" ||\n body.contentLength === 0)\n ) {\n const { \"content-type\": _contentType, ...headers } =\n response.headers;\n\n return HttpServerResponse.empty({\n headers,\n status: 202,\n });\n }\n\n return response;\n }),\n { global: true },\n ),\n ),\n Layer.provideMerge(\n HttpRouter.cors({\n allowedHeaders: [\n \"Content-Type\",\n \"Authorization\",\n \"mcp-protocol-version\",\n \"mcp-session-id\",\n ],\n allowedMethods: [\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"OPTIONS\"],\n allowedOrigins: [\"*\"],\n credentials: false,\n exposedHeaders: [\"mcp-session-id\"],\n }),\n ),\n);\n\nconst McpStdio = McpLive.pipe(\n Layer.provideMerge(\n McpServer.layerStdio({\n name: MCP_SERVER_NAME,\n version: MCP_SERVER_VERSION,\n }),\n ),\n Layer.provide(NodeStdio.layer),\n Layer.provide(Layer.succeed(Logger.LogToStderr)(true)),\n);\n\nexport const startMcpHttpServer = (port: number) =>\n Layer.launch(\n HttpRouter.serve(McpRouter).pipe(\n Layer.provideMerge(NodeHttpServer.layer(createServer, { port })),\n ),\n );\n\nexport const startMcpStdioServer = () => Layer.launch(McpStdio);\n"],"mappings":";;;;;;;;AAaA,MAAM,kBAAkB;AACxB,MAAM,qBAAqB;AAE3B,MAAM,mBAAmB,mBAAmB,MAAM;CAChD,SAAS,EAAE,OAAO,iBAAiB;CACnC,QAAQ;CACT,CAAC;AAEF,MAAM,YAAY,QAAQ,KACxB,MAAM,aAAa,WAAW,IAAI,OAAO,QAAQ,iBAAiB,CAAC,EACnE,MAAM,aACJ,UAAU,UAAU;CAClB,MAAM;CACN,MAAM;CACN,SAAS;CACV,CAAC,CACH,EACD,MAAM,aACJ,WAAW,YACR,eACC,OAAO,IAAI,aAAa;CACtB,MAAM,UAAU,OAAO,kBAAkB;CACzC,MAAM,WAAW,OAAO;CACxB,MAAM,gBAAgB,QAAQ,IAAI,MAAM,IAAI,CAAC,OAAO;CAEpD,MAAM,OAAO,SAAS;AAKtB,KACE,QAAQ,WAAW,UACnB,iBACA,SAAS,WAAW,QACnB,KAAK,SAAS,WACb,KAAK,SAAS,YACd,KAAK,kBAAkB,IACzB;EACA,MAAM,EAAE,gBAAgB,cAAc,GAAG,YACvC,SAAS;AAEX,SAAO,mBAAmB,MAAM;GAC9B;GACA,QAAQ;GACT,CAAC;;AAGJ,QAAO;EACP,EACJ,EAAE,QAAQ,MAAM,CACjB,CACF,EACD,MAAM,aACJ,WAAW,KAAK;CACd,gBAAgB;EACd;EACA;EACA;EACA;EACD;CACD,gBAAgB;EAAC;EAAO;EAAQ;EAAO;EAAU;EAAS;EAAU;CACpE,gBAAgB,CAAC,IAAI;CACrB,aAAa;CACb,gBAAgB,CAAC,iBAAiB;CACnC,CAAC,CACH,CACF;AAED,MAAM,WAAW,QAAQ,KACvB,MAAM,aACJ,UAAU,WAAW;CACnB,MAAM;CACN,SAAS;CACV,CAAC,CACH,EACD,MAAM,QAAQ,UAAU,MAAM,EAC9B,MAAM,QAAQ,MAAM,QAAQ,OAAO,YAAY,CAAC,KAAK,CAAC,CACvD;AAED,MAAa,sBAAsB,SACjC,MAAM,OACJ,WAAW,MAAM,UAAU,CAAC,KAC1B,MAAM,aAAa,eAAe,MAAM,cAAc,EAAE,MAAM,CAAC,CAAC,CACjE,CACF;AAEH,MAAa,4BAA4B,MAAM,OAAO,SAAS"}
|
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"effect": "4.0.0-beta.60",
|
|
14
14
|
"tslib": "2.8.1",
|
|
15
15
|
"viem": "2.48.8",
|
|
16
|
-
"@namera-ai/sdk": "0.1.
|
|
16
|
+
"@namera-ai/sdk": "0.1.1"
|
|
17
17
|
},
|
|
18
18
|
"description": "Agent-first smart account interface with session keys and scoped permissions, enabling fully local multichain automation.",
|
|
19
19
|
"devDependencies": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"sideEffects": false,
|
|
55
55
|
"type": "module",
|
|
56
|
-
"version": "0.1.
|
|
56
|
+
"version": "0.1.5",
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "tsdown",
|
|
59
59
|
"dev": "tsdown --watch",
|