@spraay/langchain-agent-wallet 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 ADDED
@@ -0,0 +1,77 @@
1
+ # 💧 @spraay/langchain-agent-wallet
2
+
3
+ LangChain tools for Spraay Agent Wallet — provision smart wallets, manage session keys, and predict addresses on Base via x402 USDC micropayments.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @spraay/langchain-agent-wallet @langchain/core
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { ChatOpenAI } from "@langchain/openai";
15
+ import { createToolCallingAgent, AgentExecutor } from "langchain/agents";
16
+ import { ChatPromptTemplate } from "@langchain/core/prompts";
17
+ import { createSpraayWalletTools } from "@spraay/langchain-agent-wallet";
18
+
19
+ const tools = createSpraayWalletTools({
20
+ privateKey: process.env.EVM_PRIVATE_KEY!,
21
+ // gatewayUrl: "https://gateway.spraay.app" // default
22
+ });
23
+
24
+ const llm = new ChatOpenAI({ model: "gpt-4o" });
25
+
26
+ const prompt = ChatPromptTemplate.fromMessages([
27
+ ["system", "You are a Web3 agent that can manage smart wallets on Base."],
28
+ ["human", "{input}"],
29
+ ["placeholder", "{agent_scratchpad}"],
30
+ ]);
31
+
32
+ const agent = createToolCallingAgent({ llm, tools, prompt });
33
+ const executor = new AgentExecutor({ agent, tools });
34
+
35
+ const result = await executor.invoke({
36
+ input: "Deploy a new agent wallet for 0x1234...abcd",
37
+ });
38
+ ```
39
+
40
+ ## Tools
41
+
42
+ | Tool | Description | Cost |
43
+ |------|-------------|------|
44
+ | `spraay_provision_wallet` | Deploy a new smart wallet on Base | $0.05 |
45
+ | `spraay_add_session_key` | Grant scoped permissions to an address | $0.02 |
46
+ | `spraay_get_wallet_info` | Query wallet details and balance | $0.005 |
47
+ | `spraay_revoke_session_key` | Remove a session key | $0.02 |
48
+ | `spraay_predict_address` | Pre-compute CREATE2 wallet address | $0.001 |
49
+
50
+ ## Individual Tool Usage
51
+
52
+ ```typescript
53
+ import { SpraayProvisionWalletTool } from "@spraay/langchain-agent-wallet";
54
+
55
+ const provisionTool = new SpraayProvisionWalletTool({
56
+ privateKey: process.env.EVM_PRIVATE_KEY!,
57
+ });
58
+
59
+ // Use with any LangChain agent or chain
60
+ ```
61
+
62
+ ## Environment
63
+
64
+ ```env
65
+ EVM_PRIVATE_KEY=0x... # Required — signs x402 payments
66
+ SPRAAY_GATEWAY_URL=https://... # Optional — override default gateway
67
+ ```
68
+
69
+ ## Links
70
+
71
+ - [Spraay Docs](https://docs.spraay.app)
72
+ - [x402 Protocol](https://x402.org)
73
+ - [LangChain.js](https://js.langchain.com)
74
+
75
+ ## License
76
+
77
+ MIT — [@plagtech](https://github.com/plagtech)
@@ -0,0 +1,112 @@
1
+ import { StructuredTool } from '@langchain/core/tools';
2
+ import { z } from 'zod';
3
+
4
+ interface SpraayToolConfig {
5
+ privateKey: string;
6
+ gatewayUrl?: string;
7
+ }
8
+ declare class SpraayProvisionWalletTool extends StructuredTool {
9
+ name: string;
10
+ description: string;
11
+ schema: z.ZodObject<{
12
+ ownerAddress: z.ZodString;
13
+ label: z.ZodOptional<z.ZodString>;
14
+ }, "strip", z.ZodTypeAny, {
15
+ ownerAddress: string;
16
+ label?: string | undefined;
17
+ }, {
18
+ ownerAddress: string;
19
+ label?: string | undefined;
20
+ }>;
21
+ private config;
22
+ constructor(config: SpraayToolConfig);
23
+ _call(input: z.infer<typeof this.schema>): Promise<string>;
24
+ }
25
+ declare class SpraayAddSessionKeyTool extends StructuredTool {
26
+ name: string;
27
+ description: string;
28
+ schema: z.ZodObject<{
29
+ walletAddress: z.ZodString;
30
+ sessionKeyAddress: z.ZodString;
31
+ permissions: z.ZodArray<z.ZodString, "many">;
32
+ expiresIn: z.ZodOptional<z.ZodNumber>;
33
+ }, "strip", z.ZodTypeAny, {
34
+ walletAddress: string;
35
+ sessionKeyAddress: string;
36
+ permissions: string[];
37
+ expiresIn?: number | undefined;
38
+ }, {
39
+ walletAddress: string;
40
+ sessionKeyAddress: string;
41
+ permissions: string[];
42
+ expiresIn?: number | undefined;
43
+ }>;
44
+ private config;
45
+ constructor(config: SpraayToolConfig);
46
+ _call(input: z.infer<typeof this.schema>): Promise<string>;
47
+ }
48
+ declare class SpraayGetWalletInfoTool extends StructuredTool {
49
+ name: string;
50
+ description: string;
51
+ schema: z.ZodObject<{
52
+ walletAddress: z.ZodString;
53
+ }, "strip", z.ZodTypeAny, {
54
+ walletAddress: string;
55
+ }, {
56
+ walletAddress: string;
57
+ }>;
58
+ private config;
59
+ constructor(config: SpraayToolConfig);
60
+ _call(input: z.infer<typeof this.schema>): Promise<string>;
61
+ }
62
+ declare class SpraayRevokeSessionKeyTool extends StructuredTool {
63
+ name: string;
64
+ description: string;
65
+ schema: z.ZodObject<{
66
+ walletAddress: z.ZodString;
67
+ sessionKeyAddress: z.ZodString;
68
+ }, "strip", z.ZodTypeAny, {
69
+ walletAddress: string;
70
+ sessionKeyAddress: string;
71
+ }, {
72
+ walletAddress: string;
73
+ sessionKeyAddress: string;
74
+ }>;
75
+ private config;
76
+ constructor(config: SpraayToolConfig);
77
+ _call(input: z.infer<typeof this.schema>): Promise<string>;
78
+ }
79
+ declare class SpraayPredictAddressTool extends StructuredTool {
80
+ name: string;
81
+ description: string;
82
+ schema: z.ZodObject<{
83
+ ownerAddress: z.ZodString;
84
+ salt: z.ZodOptional<z.ZodString>;
85
+ }, "strip", z.ZodTypeAny, {
86
+ ownerAddress: string;
87
+ salt?: string | undefined;
88
+ }, {
89
+ ownerAddress: string;
90
+ salt?: string | undefined;
91
+ }>;
92
+ private config;
93
+ constructor(config: SpraayToolConfig);
94
+ _call(input: z.infer<typeof this.schema>): Promise<string>;
95
+ }
96
+ /**
97
+ * Create all 5 Spraay Agent Wallet tools for LangChain.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * import { createSpraayWalletTools } from "@spraay/langchain-agent-wallet";
102
+ *
103
+ * const tools = createSpraayWalletTools({
104
+ * privateKey: process.env.EVM_PRIVATE_KEY!,
105
+ * });
106
+ *
107
+ * const agent = createToolCallingAgent({ llm, tools, prompt });
108
+ * ```
109
+ */
110
+ declare function createSpraayWalletTools(config: SpraayToolConfig): StructuredTool[];
111
+
112
+ export { SpraayAddSessionKeyTool, SpraayGetWalletInfoTool, SpraayPredictAddressTool, SpraayProvisionWalletTool, SpraayRevokeSessionKeyTool, createSpraayWalletTools };
@@ -0,0 +1,112 @@
1
+ import { StructuredTool } from '@langchain/core/tools';
2
+ import { z } from 'zod';
3
+
4
+ interface SpraayToolConfig {
5
+ privateKey: string;
6
+ gatewayUrl?: string;
7
+ }
8
+ declare class SpraayProvisionWalletTool extends StructuredTool {
9
+ name: string;
10
+ description: string;
11
+ schema: z.ZodObject<{
12
+ ownerAddress: z.ZodString;
13
+ label: z.ZodOptional<z.ZodString>;
14
+ }, "strip", z.ZodTypeAny, {
15
+ ownerAddress: string;
16
+ label?: string | undefined;
17
+ }, {
18
+ ownerAddress: string;
19
+ label?: string | undefined;
20
+ }>;
21
+ private config;
22
+ constructor(config: SpraayToolConfig);
23
+ _call(input: z.infer<typeof this.schema>): Promise<string>;
24
+ }
25
+ declare class SpraayAddSessionKeyTool extends StructuredTool {
26
+ name: string;
27
+ description: string;
28
+ schema: z.ZodObject<{
29
+ walletAddress: z.ZodString;
30
+ sessionKeyAddress: z.ZodString;
31
+ permissions: z.ZodArray<z.ZodString, "many">;
32
+ expiresIn: z.ZodOptional<z.ZodNumber>;
33
+ }, "strip", z.ZodTypeAny, {
34
+ walletAddress: string;
35
+ sessionKeyAddress: string;
36
+ permissions: string[];
37
+ expiresIn?: number | undefined;
38
+ }, {
39
+ walletAddress: string;
40
+ sessionKeyAddress: string;
41
+ permissions: string[];
42
+ expiresIn?: number | undefined;
43
+ }>;
44
+ private config;
45
+ constructor(config: SpraayToolConfig);
46
+ _call(input: z.infer<typeof this.schema>): Promise<string>;
47
+ }
48
+ declare class SpraayGetWalletInfoTool extends StructuredTool {
49
+ name: string;
50
+ description: string;
51
+ schema: z.ZodObject<{
52
+ walletAddress: z.ZodString;
53
+ }, "strip", z.ZodTypeAny, {
54
+ walletAddress: string;
55
+ }, {
56
+ walletAddress: string;
57
+ }>;
58
+ private config;
59
+ constructor(config: SpraayToolConfig);
60
+ _call(input: z.infer<typeof this.schema>): Promise<string>;
61
+ }
62
+ declare class SpraayRevokeSessionKeyTool extends StructuredTool {
63
+ name: string;
64
+ description: string;
65
+ schema: z.ZodObject<{
66
+ walletAddress: z.ZodString;
67
+ sessionKeyAddress: z.ZodString;
68
+ }, "strip", z.ZodTypeAny, {
69
+ walletAddress: string;
70
+ sessionKeyAddress: string;
71
+ }, {
72
+ walletAddress: string;
73
+ sessionKeyAddress: string;
74
+ }>;
75
+ private config;
76
+ constructor(config: SpraayToolConfig);
77
+ _call(input: z.infer<typeof this.schema>): Promise<string>;
78
+ }
79
+ declare class SpraayPredictAddressTool extends StructuredTool {
80
+ name: string;
81
+ description: string;
82
+ schema: z.ZodObject<{
83
+ ownerAddress: z.ZodString;
84
+ salt: z.ZodOptional<z.ZodString>;
85
+ }, "strip", z.ZodTypeAny, {
86
+ ownerAddress: string;
87
+ salt?: string | undefined;
88
+ }, {
89
+ ownerAddress: string;
90
+ salt?: string | undefined;
91
+ }>;
92
+ private config;
93
+ constructor(config: SpraayToolConfig);
94
+ _call(input: z.infer<typeof this.schema>): Promise<string>;
95
+ }
96
+ /**
97
+ * Create all 5 Spraay Agent Wallet tools for LangChain.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * import { createSpraayWalletTools } from "@spraay/langchain-agent-wallet";
102
+ *
103
+ * const tools = createSpraayWalletTools({
104
+ * privateKey: process.env.EVM_PRIVATE_KEY!,
105
+ * });
106
+ *
107
+ * const agent = createToolCallingAgent({ llm, tools, prompt });
108
+ * ```
109
+ */
110
+ declare function createSpraayWalletTools(config: SpraayToolConfig): StructuredTool[];
111
+
112
+ export { SpraayAddSessionKeyTool, SpraayGetWalletInfoTool, SpraayPredictAddressTool, SpraayProvisionWalletTool, SpraayRevokeSessionKeyTool, createSpraayWalletTools };
package/dist/index.js ADDED
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ SpraayAddSessionKeyTool: () => SpraayAddSessionKeyTool,
24
+ SpraayGetWalletInfoTool: () => SpraayGetWalletInfoTool,
25
+ SpraayPredictAddressTool: () => SpraayPredictAddressTool,
26
+ SpraayProvisionWalletTool: () => SpraayProvisionWalletTool,
27
+ SpraayRevokeSessionKeyTool: () => SpraayRevokeSessionKeyTool,
28
+ createSpraayWalletTools: () => createSpraayWalletTools
29
+ });
30
+ module.exports = __toCommonJS(index_exports);
31
+
32
+ // src/tools.ts
33
+ var import_tools = require("@langchain/core/tools");
34
+ var import_zod = require("zod");
35
+ var import_ethers = require("ethers");
36
+ var USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
37
+ var SPRAAY_PAYMENT_ADDRESS = "0xAd62f03C7514bb8c51f1eA70C2b75C37404695c8";
38
+ async function makePaymentHeader(wallet, amountUsd) {
39
+ const payload = {
40
+ amount: amountUsd.toString(),
41
+ token: USDC_BASE,
42
+ recipient: SPRAAY_PAYMENT_ADDRESS,
43
+ chain: "base",
44
+ timestamp: Date.now()
45
+ };
46
+ const signature = await wallet.signMessage(JSON.stringify(payload));
47
+ const header = Buffer.from(
48
+ JSON.stringify({ ...payload, signature })
49
+ ).toString("base64");
50
+ return { "X-PAYMENT": header, "Content-Type": "application/json" };
51
+ }
52
+ async function gatewayRequest(wallet, baseUrl, method, path, costUsd, body) {
53
+ const headers = await makePaymentHeader(wallet, costUsd);
54
+ const url = `${baseUrl}${path}`;
55
+ const options = { method, headers };
56
+ if (body && method === "POST") {
57
+ options.body = JSON.stringify(body);
58
+ }
59
+ const res = await fetch(url, options);
60
+ const data = await res.json();
61
+ if (!res.ok) {
62
+ throw new Error(data.error || `HTTP ${res.status}`);
63
+ }
64
+ return JSON.stringify(data, null, 2);
65
+ }
66
+ function createWallet(config) {
67
+ const key = config.privateKey.startsWith("0x") ? config.privateKey : `0x${config.privateKey}`;
68
+ return {
69
+ wallet: new import_ethers.ethers.Wallet(key),
70
+ baseUrl: config.gatewayUrl || "https://gateway.spraay.app"
71
+ };
72
+ }
73
+ var SpraayProvisionWalletTool = class extends import_tools.StructuredTool {
74
+ name = "spraay_provision_wallet";
75
+ description = `\u{1F4A7} Provision (deploy) a new Spraay smart wallet on Base for an AI agent.
76
+ Use this when the user wants to create/deploy a new agent wallet.
77
+ Costs $0.05 USDC per call via x402 micropayment on Base.
78
+ Factory: 0xFBD832Db6D9a05A0434cd497707a1bDC43389CfD
79
+ Returns the new wallet address and deployment transaction hash.`;
80
+ schema = import_zod.z.object({
81
+ ownerAddress: import_zod.z.string().describe("The EVM address (0x...) that will own the new wallet"),
82
+ label: import_zod.z.string().optional().describe("Optional human-readable label for the wallet")
83
+ });
84
+ config;
85
+ constructor(config) {
86
+ super();
87
+ this.config = config;
88
+ }
89
+ async _call(input) {
90
+ const { wallet, baseUrl } = createWallet(this.config);
91
+ return gatewayRequest(
92
+ wallet,
93
+ baseUrl,
94
+ "POST",
95
+ "/api/v1/agent-wallet/provision",
96
+ 0.05,
97
+ { ownerAddress: input.ownerAddress, label: input.label }
98
+ );
99
+ }
100
+ };
101
+ var SpraayAddSessionKeyTool = class extends import_tools.StructuredTool {
102
+ name = "spraay_add_session_key";
103
+ description = `\u{1F4A7} Add a session key to an existing Spraay agent wallet.
104
+ Grants scoped permissions (transfer, swap, approve, etc.) to another address.
105
+ Use when the user wants to delegate limited wallet access.
106
+ Costs $0.02 USDC per call via x402 on Base.`;
107
+ schema = import_zod.z.object({
108
+ walletAddress: import_zod.z.string().describe("The agent wallet address to add the session key to"),
109
+ sessionKeyAddress: import_zod.z.string().describe("The address to grant session key access"),
110
+ permissions: import_zod.z.array(import_zod.z.string()).describe('Array of permissions, e.g. ["transfer", "swap"]'),
111
+ expiresIn: import_zod.z.number().optional().describe("Optional expiry in seconds")
112
+ });
113
+ config;
114
+ constructor(config) {
115
+ super();
116
+ this.config = config;
117
+ }
118
+ async _call(input) {
119
+ const { wallet, baseUrl } = createWallet(this.config);
120
+ return gatewayRequest(
121
+ wallet,
122
+ baseUrl,
123
+ "POST",
124
+ "/api/v1/agent-wallet/session-key",
125
+ 0.02,
126
+ input
127
+ );
128
+ }
129
+ };
130
+ var SpraayGetWalletInfoTool = class extends import_tools.StructuredTool {
131
+ name = "spraay_get_wallet_info";
132
+ description = `\u{1F4A7} Get information about a Spraay agent wallet.
133
+ Returns the owner, active session keys with permissions, USDC balance, and label.
134
+ Use when the user asks about wallet status, balance, or active keys.
135
+ Costs $0.005 USDC per call via x402 on Base.`;
136
+ schema = import_zod.z.object({
137
+ walletAddress: import_zod.z.string().describe("The agent wallet address to query")
138
+ });
139
+ config;
140
+ constructor(config) {
141
+ super();
142
+ this.config = config;
143
+ }
144
+ async _call(input) {
145
+ const { wallet, baseUrl } = createWallet(this.config);
146
+ return gatewayRequest(
147
+ wallet,
148
+ baseUrl,
149
+ "GET",
150
+ `/api/v1/agent-wallet/info?walletAddress=${input.walletAddress}`,
151
+ 5e-3
152
+ );
153
+ }
154
+ };
155
+ var SpraayRevokeSessionKeyTool = class extends import_tools.StructuredTool {
156
+ name = "spraay_revoke_session_key";
157
+ description = `\u{1F4A7} Revoke a session key from a Spraay agent wallet.
158
+ Removes all permissions from the specified session key address.
159
+ Use when the user wants to remove access or disable a key.
160
+ Costs $0.02 USDC per call via x402 on Base.`;
161
+ schema = import_zod.z.object({
162
+ walletAddress: import_zod.z.string().describe("The agent wallet that has the session key"),
163
+ sessionKeyAddress: import_zod.z.string().describe("The session key address to revoke")
164
+ });
165
+ config;
166
+ constructor(config) {
167
+ super();
168
+ this.config = config;
169
+ }
170
+ async _call(input) {
171
+ const { wallet, baseUrl } = createWallet(this.config);
172
+ return gatewayRequest(
173
+ wallet,
174
+ baseUrl,
175
+ "POST",
176
+ "/api/v1/agent-wallet/revoke-key",
177
+ 0.02,
178
+ input
179
+ );
180
+ }
181
+ };
182
+ var SpraayPredictAddressTool = class extends import_tools.StructuredTool {
183
+ name = "spraay_predict_address";
184
+ description = `\u{1F4A7} Predict the counterfactual address of a Spraay agent wallet before deploying it.
185
+ Uses CREATE2 deterministic addressing \u2014 the wallet can be deployed later.
186
+ Use when the user wants to know what address their wallet will have.
187
+ Costs $0.001 USDC per call via x402 on Base.`;
188
+ schema = import_zod.z.object({
189
+ ownerAddress: import_zod.z.string().describe("The EVM address that would own the wallet"),
190
+ salt: import_zod.z.string().optional().describe("Optional salt for CREATE2 derivation")
191
+ });
192
+ config;
193
+ constructor(config) {
194
+ super();
195
+ this.config = config;
196
+ }
197
+ async _call(input) {
198
+ const { wallet, baseUrl } = createWallet(this.config);
199
+ const qs = `ownerAddress=${input.ownerAddress}${input.salt ? `&salt=${input.salt}` : ""}`;
200
+ return gatewayRequest(
201
+ wallet,
202
+ baseUrl,
203
+ "GET",
204
+ `/api/v1/agent-wallet/predict?${qs}`,
205
+ 1e-3
206
+ );
207
+ }
208
+ };
209
+ function createSpraayWalletTools(config) {
210
+ return [
211
+ new SpraayProvisionWalletTool(config),
212
+ new SpraayAddSessionKeyTool(config),
213
+ new SpraayGetWalletInfoTool(config),
214
+ new SpraayRevokeSessionKeyTool(config),
215
+ new SpraayPredictAddressTool(config)
216
+ ];
217
+ }
218
+ // Annotate the CommonJS export names for ESM import in node:
219
+ 0 && (module.exports = {
220
+ SpraayAddSessionKeyTool,
221
+ SpraayGetWalletInfoTool,
222
+ SpraayPredictAddressTool,
223
+ SpraayProvisionWalletTool,
224
+ SpraayRevokeSessionKeyTool,
225
+ createSpraayWalletTools
226
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,194 @@
1
+ // src/tools.ts
2
+ import { StructuredTool } from "@langchain/core/tools";
3
+ import { z } from "zod";
4
+ import { ethers } from "ethers";
5
+ var USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
6
+ var SPRAAY_PAYMENT_ADDRESS = "0xAd62f03C7514bb8c51f1eA70C2b75C37404695c8";
7
+ async function makePaymentHeader(wallet, amountUsd) {
8
+ const payload = {
9
+ amount: amountUsd.toString(),
10
+ token: USDC_BASE,
11
+ recipient: SPRAAY_PAYMENT_ADDRESS,
12
+ chain: "base",
13
+ timestamp: Date.now()
14
+ };
15
+ const signature = await wallet.signMessage(JSON.stringify(payload));
16
+ const header = Buffer.from(
17
+ JSON.stringify({ ...payload, signature })
18
+ ).toString("base64");
19
+ return { "X-PAYMENT": header, "Content-Type": "application/json" };
20
+ }
21
+ async function gatewayRequest(wallet, baseUrl, method, path, costUsd, body) {
22
+ const headers = await makePaymentHeader(wallet, costUsd);
23
+ const url = `${baseUrl}${path}`;
24
+ const options = { method, headers };
25
+ if (body && method === "POST") {
26
+ options.body = JSON.stringify(body);
27
+ }
28
+ const res = await fetch(url, options);
29
+ const data = await res.json();
30
+ if (!res.ok) {
31
+ throw new Error(data.error || `HTTP ${res.status}`);
32
+ }
33
+ return JSON.stringify(data, null, 2);
34
+ }
35
+ function createWallet(config) {
36
+ const key = config.privateKey.startsWith("0x") ? config.privateKey : `0x${config.privateKey}`;
37
+ return {
38
+ wallet: new ethers.Wallet(key),
39
+ baseUrl: config.gatewayUrl || "https://gateway.spraay.app"
40
+ };
41
+ }
42
+ var SpraayProvisionWalletTool = class extends StructuredTool {
43
+ name = "spraay_provision_wallet";
44
+ description = `\u{1F4A7} Provision (deploy) a new Spraay smart wallet on Base for an AI agent.
45
+ Use this when the user wants to create/deploy a new agent wallet.
46
+ Costs $0.05 USDC per call via x402 micropayment on Base.
47
+ Factory: 0xFBD832Db6D9a05A0434cd497707a1bDC43389CfD
48
+ Returns the new wallet address and deployment transaction hash.`;
49
+ schema = z.object({
50
+ ownerAddress: z.string().describe("The EVM address (0x...) that will own the new wallet"),
51
+ label: z.string().optional().describe("Optional human-readable label for the wallet")
52
+ });
53
+ config;
54
+ constructor(config) {
55
+ super();
56
+ this.config = config;
57
+ }
58
+ async _call(input) {
59
+ const { wallet, baseUrl } = createWallet(this.config);
60
+ return gatewayRequest(
61
+ wallet,
62
+ baseUrl,
63
+ "POST",
64
+ "/api/v1/agent-wallet/provision",
65
+ 0.05,
66
+ { ownerAddress: input.ownerAddress, label: input.label }
67
+ );
68
+ }
69
+ };
70
+ var SpraayAddSessionKeyTool = class extends StructuredTool {
71
+ name = "spraay_add_session_key";
72
+ description = `\u{1F4A7} Add a session key to an existing Spraay agent wallet.
73
+ Grants scoped permissions (transfer, swap, approve, etc.) to another address.
74
+ Use when the user wants to delegate limited wallet access.
75
+ Costs $0.02 USDC per call via x402 on Base.`;
76
+ schema = z.object({
77
+ walletAddress: z.string().describe("The agent wallet address to add the session key to"),
78
+ sessionKeyAddress: z.string().describe("The address to grant session key access"),
79
+ permissions: z.array(z.string()).describe('Array of permissions, e.g. ["transfer", "swap"]'),
80
+ expiresIn: z.number().optional().describe("Optional expiry in seconds")
81
+ });
82
+ config;
83
+ constructor(config) {
84
+ super();
85
+ this.config = config;
86
+ }
87
+ async _call(input) {
88
+ const { wallet, baseUrl } = createWallet(this.config);
89
+ return gatewayRequest(
90
+ wallet,
91
+ baseUrl,
92
+ "POST",
93
+ "/api/v1/agent-wallet/session-key",
94
+ 0.02,
95
+ input
96
+ );
97
+ }
98
+ };
99
+ var SpraayGetWalletInfoTool = class extends StructuredTool {
100
+ name = "spraay_get_wallet_info";
101
+ description = `\u{1F4A7} Get information about a Spraay agent wallet.
102
+ Returns the owner, active session keys with permissions, USDC balance, and label.
103
+ Use when the user asks about wallet status, balance, or active keys.
104
+ Costs $0.005 USDC per call via x402 on Base.`;
105
+ schema = z.object({
106
+ walletAddress: z.string().describe("The agent wallet address to query")
107
+ });
108
+ config;
109
+ constructor(config) {
110
+ super();
111
+ this.config = config;
112
+ }
113
+ async _call(input) {
114
+ const { wallet, baseUrl } = createWallet(this.config);
115
+ return gatewayRequest(
116
+ wallet,
117
+ baseUrl,
118
+ "GET",
119
+ `/api/v1/agent-wallet/info?walletAddress=${input.walletAddress}`,
120
+ 5e-3
121
+ );
122
+ }
123
+ };
124
+ var SpraayRevokeSessionKeyTool = class extends StructuredTool {
125
+ name = "spraay_revoke_session_key";
126
+ description = `\u{1F4A7} Revoke a session key from a Spraay agent wallet.
127
+ Removes all permissions from the specified session key address.
128
+ Use when the user wants to remove access or disable a key.
129
+ Costs $0.02 USDC per call via x402 on Base.`;
130
+ schema = z.object({
131
+ walletAddress: z.string().describe("The agent wallet that has the session key"),
132
+ sessionKeyAddress: z.string().describe("The session key address to revoke")
133
+ });
134
+ config;
135
+ constructor(config) {
136
+ super();
137
+ this.config = config;
138
+ }
139
+ async _call(input) {
140
+ const { wallet, baseUrl } = createWallet(this.config);
141
+ return gatewayRequest(
142
+ wallet,
143
+ baseUrl,
144
+ "POST",
145
+ "/api/v1/agent-wallet/revoke-key",
146
+ 0.02,
147
+ input
148
+ );
149
+ }
150
+ };
151
+ var SpraayPredictAddressTool = class extends StructuredTool {
152
+ name = "spraay_predict_address";
153
+ description = `\u{1F4A7} Predict the counterfactual address of a Spraay agent wallet before deploying it.
154
+ Uses CREATE2 deterministic addressing \u2014 the wallet can be deployed later.
155
+ Use when the user wants to know what address their wallet will have.
156
+ Costs $0.001 USDC per call via x402 on Base.`;
157
+ schema = z.object({
158
+ ownerAddress: z.string().describe("The EVM address that would own the wallet"),
159
+ salt: z.string().optional().describe("Optional salt for CREATE2 derivation")
160
+ });
161
+ config;
162
+ constructor(config) {
163
+ super();
164
+ this.config = config;
165
+ }
166
+ async _call(input) {
167
+ const { wallet, baseUrl } = createWallet(this.config);
168
+ const qs = `ownerAddress=${input.ownerAddress}${input.salt ? `&salt=${input.salt}` : ""}`;
169
+ return gatewayRequest(
170
+ wallet,
171
+ baseUrl,
172
+ "GET",
173
+ `/api/v1/agent-wallet/predict?${qs}`,
174
+ 1e-3
175
+ );
176
+ }
177
+ };
178
+ function createSpraayWalletTools(config) {
179
+ return [
180
+ new SpraayProvisionWalletTool(config),
181
+ new SpraayAddSessionKeyTool(config),
182
+ new SpraayGetWalletInfoTool(config),
183
+ new SpraayRevokeSessionKeyTool(config),
184
+ new SpraayPredictAddressTool(config)
185
+ ];
186
+ }
187
+ export {
188
+ SpraayAddSessionKeyTool,
189
+ SpraayGetWalletInfoTool,
190
+ SpraayPredictAddressTool,
191
+ SpraayProvisionWalletTool,
192
+ SpraayRevokeSessionKeyTool,
193
+ createSpraayWalletTools
194
+ };
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@spraay/langchain-agent-wallet",
3
+ "version": "1.0.0",
4
+ "description": "💧 LangChain tools for Spraay Agent Wallet — provision smart wallets, manage session keys on Base via x402",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsup src/index.ts --format cjs,esm --dts",
9
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
10
+ "test": "vitest run"
11
+ },
12
+ "keywords": [
13
+ "langchain",
14
+ "spraay",
15
+ "agent-wallet",
16
+ "x402",
17
+ "base",
18
+ "smart-wallet",
19
+ "usdc",
20
+ "ai-tools"
21
+ ],
22
+ "author": "plagtech",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/plagtech/langchain-spraay-wallet"
27
+ },
28
+ "peerDependencies": {
29
+ "@langchain/core": ">=0.2.0"
30
+ },
31
+ "dependencies": {
32
+ "spraay-agent-wallet": "^1.0.0",
33
+ "ethers": "^6.13.0",
34
+ "zod": "^3.22.0"
35
+ },
36
+ "devDependencies": {
37
+ "@langchain/core": "^0.2.0",
38
+ "tsup": "^8.0.0",
39
+ "typescript": "^5.3.0",
40
+ "vitest": "^1.0.0"
41
+ }
42
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export {
2
+ SpraayProvisionWalletTool,
3
+ SpraayAddSessionKeyTool,
4
+ SpraayGetWalletInfoTool,
5
+ SpraayRevokeSessionKeyTool,
6
+ SpraayPredictAddressTool,
7
+ createSpraayWalletTools,
8
+ } from "./tools";
package/src/tools.ts ADDED
@@ -0,0 +1,292 @@
1
+ import { StructuredTool } from "@langchain/core/tools";
2
+ import { z } from "zod";
3
+ import { ethers } from "ethers";
4
+
5
+ // ── Shared Config ─────────────────────────────────────────────────
6
+
7
+ const USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
8
+ const SPRAAY_PAYMENT_ADDRESS = "0xAd62f03C7514bb8c51f1eA70C2b75C37404695c8";
9
+
10
+ interface SpraayToolConfig {
11
+ privateKey: string;
12
+ gatewayUrl?: string;
13
+ }
14
+
15
+ async function makePaymentHeader(
16
+ wallet: ethers.Wallet,
17
+ amountUsd: number
18
+ ): Promise<Record<string, string>> {
19
+ const payload = {
20
+ amount: amountUsd.toString(),
21
+ token: USDC_BASE,
22
+ recipient: SPRAAY_PAYMENT_ADDRESS,
23
+ chain: "base",
24
+ timestamp: Date.now(),
25
+ };
26
+ const signature = await wallet.signMessage(JSON.stringify(payload));
27
+ const header = Buffer.from(
28
+ JSON.stringify({ ...payload, signature })
29
+ ).toString("base64");
30
+ return { "X-PAYMENT": header, "Content-Type": "application/json" };
31
+ }
32
+
33
+ async function gatewayRequest(
34
+ wallet: ethers.Wallet,
35
+ baseUrl: string,
36
+ method: "GET" | "POST",
37
+ path: string,
38
+ costUsd: number,
39
+ body?: Record<string, unknown>
40
+ ): Promise<string> {
41
+ const headers = await makePaymentHeader(wallet, costUsd);
42
+ const url = `${baseUrl}${path}`;
43
+ const options: RequestInit = { method, headers };
44
+ if (body && method === "POST") {
45
+ options.body = JSON.stringify(body);
46
+ }
47
+ const res = await fetch(url, options);
48
+ const data = await res.json();
49
+ if (!res.ok) {
50
+ throw new Error(data.error || `HTTP ${res.status}`);
51
+ }
52
+ return JSON.stringify(data, null, 2);
53
+ }
54
+
55
+ function createWallet(config: SpraayToolConfig): {
56
+ wallet: ethers.Wallet;
57
+ baseUrl: string;
58
+ } {
59
+ const key = config.privateKey.startsWith("0x")
60
+ ? config.privateKey
61
+ : `0x${config.privateKey}`;
62
+ return {
63
+ wallet: new ethers.Wallet(key),
64
+ baseUrl: config.gatewayUrl || "https://gateway.spraay.app",
65
+ };
66
+ }
67
+
68
+ // ── Tool 1: Provision Agent Wallet ────────────────────────────────
69
+
70
+ export class SpraayProvisionWalletTool extends StructuredTool {
71
+ name = "spraay_provision_wallet";
72
+ description = `💧 Provision (deploy) a new Spraay smart wallet on Base for an AI agent.
73
+ Use this when the user wants to create/deploy a new agent wallet.
74
+ Costs $0.05 USDC per call via x402 micropayment on Base.
75
+ Factory: 0xFBD832Db6D9a05A0434cd497707a1bDC43389CfD
76
+ Returns the new wallet address and deployment transaction hash.`;
77
+
78
+ schema = z.object({
79
+ ownerAddress: z
80
+ .string()
81
+ .describe("The EVM address (0x...) that will own the new wallet"),
82
+ label: z
83
+ .string()
84
+ .optional()
85
+ .describe("Optional human-readable label for the wallet"),
86
+ });
87
+
88
+ private config: SpraayToolConfig;
89
+
90
+ constructor(config: SpraayToolConfig) {
91
+ super();
92
+ this.config = config;
93
+ }
94
+
95
+ async _call(input: z.infer<typeof this.schema>): Promise<string> {
96
+ const { wallet, baseUrl } = createWallet(this.config);
97
+ return gatewayRequest(
98
+ wallet,
99
+ baseUrl,
100
+ "POST",
101
+ "/api/v1/agent-wallet/provision",
102
+ 0.05,
103
+ { ownerAddress: input.ownerAddress, label: input.label }
104
+ );
105
+ }
106
+ }
107
+
108
+ // ── Tool 2: Add Session Key ───────────────────────────────────────
109
+
110
+ export class SpraayAddSessionKeyTool extends StructuredTool {
111
+ name = "spraay_add_session_key";
112
+ description = `💧 Add a session key to an existing Spraay agent wallet.
113
+ Grants scoped permissions (transfer, swap, approve, etc.) to another address.
114
+ Use when the user wants to delegate limited wallet access.
115
+ Costs $0.02 USDC per call via x402 on Base.`;
116
+
117
+ schema = z.object({
118
+ walletAddress: z
119
+ .string()
120
+ .describe("The agent wallet address to add the session key to"),
121
+ sessionKeyAddress: z
122
+ .string()
123
+ .describe("The address to grant session key access"),
124
+ permissions: z
125
+ .array(z.string())
126
+ .describe('Array of permissions, e.g. ["transfer", "swap"]'),
127
+ expiresIn: z
128
+ .number()
129
+ .optional()
130
+ .describe("Optional expiry in seconds"),
131
+ });
132
+
133
+ private config: SpraayToolConfig;
134
+
135
+ constructor(config: SpraayToolConfig) {
136
+ super();
137
+ this.config = config;
138
+ }
139
+
140
+ async _call(input: z.infer<typeof this.schema>): Promise<string> {
141
+ const { wallet, baseUrl } = createWallet(this.config);
142
+ return gatewayRequest(
143
+ wallet,
144
+ baseUrl,
145
+ "POST",
146
+ "/api/v1/agent-wallet/session-key",
147
+ 0.02,
148
+ input
149
+ );
150
+ }
151
+ }
152
+
153
+ // ── Tool 3: Get Wallet Info ───────────────────────────────────────
154
+
155
+ export class SpraayGetWalletInfoTool extends StructuredTool {
156
+ name = "spraay_get_wallet_info";
157
+ description = `💧 Get information about a Spraay agent wallet.
158
+ Returns the owner, active session keys with permissions, USDC balance, and label.
159
+ Use when the user asks about wallet status, balance, or active keys.
160
+ Costs $0.005 USDC per call via x402 on Base.`;
161
+
162
+ schema = z.object({
163
+ walletAddress: z
164
+ .string()
165
+ .describe("The agent wallet address to query"),
166
+ });
167
+
168
+ private config: SpraayToolConfig;
169
+
170
+ constructor(config: SpraayToolConfig) {
171
+ super();
172
+ this.config = config;
173
+ }
174
+
175
+ async _call(input: z.infer<typeof this.schema>): Promise<string> {
176
+ const { wallet, baseUrl } = createWallet(this.config);
177
+ return gatewayRequest(
178
+ wallet,
179
+ baseUrl,
180
+ "GET",
181
+ `/api/v1/agent-wallet/info?walletAddress=${input.walletAddress}`,
182
+ 0.005
183
+ );
184
+ }
185
+ }
186
+
187
+ // ── Tool 4: Revoke Session Key ────────────────────────────────────
188
+
189
+ export class SpraayRevokeSessionKeyTool extends StructuredTool {
190
+ name = "spraay_revoke_session_key";
191
+ description = `💧 Revoke a session key from a Spraay agent wallet.
192
+ Removes all permissions from the specified session key address.
193
+ Use when the user wants to remove access or disable a key.
194
+ Costs $0.02 USDC per call via x402 on Base.`;
195
+
196
+ schema = z.object({
197
+ walletAddress: z
198
+ .string()
199
+ .describe("The agent wallet that has the session key"),
200
+ sessionKeyAddress: z
201
+ .string()
202
+ .describe("The session key address to revoke"),
203
+ });
204
+
205
+ private config: SpraayToolConfig;
206
+
207
+ constructor(config: SpraayToolConfig) {
208
+ super();
209
+ this.config = config;
210
+ }
211
+
212
+ async _call(input: z.infer<typeof this.schema>): Promise<string> {
213
+ const { wallet, baseUrl } = createWallet(this.config);
214
+ return gatewayRequest(
215
+ wallet,
216
+ baseUrl,
217
+ "POST",
218
+ "/api/v1/agent-wallet/revoke-key",
219
+ 0.02,
220
+ input
221
+ );
222
+ }
223
+ }
224
+
225
+ // ── Tool 5: Predict Wallet Address ────────────────────────────────
226
+
227
+ export class SpraayPredictAddressTool extends StructuredTool {
228
+ name = "spraay_predict_address";
229
+ description = `💧 Predict the counterfactual address of a Spraay agent wallet before deploying it.
230
+ Uses CREATE2 deterministic addressing — the wallet can be deployed later.
231
+ Use when the user wants to know what address their wallet will have.
232
+ Costs $0.001 USDC per call via x402 on Base.`;
233
+
234
+ schema = z.object({
235
+ ownerAddress: z
236
+ .string()
237
+ .describe("The EVM address that would own the wallet"),
238
+ salt: z
239
+ .string()
240
+ .optional()
241
+ .describe("Optional salt for CREATE2 derivation"),
242
+ });
243
+
244
+ private config: SpraayToolConfig;
245
+
246
+ constructor(config: SpraayToolConfig) {
247
+ super();
248
+ this.config = config;
249
+ }
250
+
251
+ async _call(input: z.infer<typeof this.schema>): Promise<string> {
252
+ const { wallet, baseUrl } = createWallet(this.config);
253
+ const qs = `ownerAddress=${input.ownerAddress}${
254
+ input.salt ? `&salt=${input.salt}` : ""
255
+ }`;
256
+ return gatewayRequest(
257
+ wallet,
258
+ baseUrl,
259
+ "GET",
260
+ `/api/v1/agent-wallet/predict?${qs}`,
261
+ 0.001
262
+ );
263
+ }
264
+ }
265
+
266
+ // ── Convenience: Create All Tools ─────────────────────────────────
267
+
268
+ /**
269
+ * Create all 5 Spraay Agent Wallet tools for LangChain.
270
+ *
271
+ * @example
272
+ * ```ts
273
+ * import { createSpraayWalletTools } from "@spraay/langchain-agent-wallet";
274
+ *
275
+ * const tools = createSpraayWalletTools({
276
+ * privateKey: process.env.EVM_PRIVATE_KEY!,
277
+ * });
278
+ *
279
+ * const agent = createToolCallingAgent({ llm, tools, prompt });
280
+ * ```
281
+ */
282
+ export function createSpraayWalletTools(
283
+ config: SpraayToolConfig
284
+ ): StructuredTool[] {
285
+ return [
286
+ new SpraayProvisionWalletTool(config),
287
+ new SpraayAddSessionKeyTool(config),
288
+ new SpraayGetWalletInfoTool(config),
289
+ new SpraayRevokeSessionKeyTool(config),
290
+ new SpraayPredictAddressTool(config),
291
+ ];
292
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "declaration": true,
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true
14
+ },
15
+ "include": ["src"],
16
+ "exclude": ["node_modules", "dist"]
17
+ }