crewpay-solana-agent-kit-plugin 0.0.0-stage → 0.1.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CrewPay / fxams
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,36 @@
1
- # Temporary Holding Version
1
+ # crewpay-solana-agent-kit-plugin
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Solana Agent Kit v2 plugin for [CrewPay](https://crewpay.dev).
4
+
5
+ ```bash
6
+ npm i crewpay-solana-agent-kit-plugin
7
+ ```
8
+
9
+ ```ts
10
+ import { SolanaAgentKit } from 'solana-agent-kit'
11
+ import { CrewPayPlugin } from 'crewpay-solana-agent-kit-plugin'
12
+
13
+ const agent = new SolanaAgentKit(wallet, rpcUrl, config).use(CrewPayPlugin)
14
+ await agent.methods.crewDryRun({ name: 'Desk Cat', ticker: 'DCAT', autoHire: { seats: 3 } })
15
+ // human confirms with APPROVE_SOL_SPEND…
16
+ await agent.methods.crewLaunch({
17
+ name: 'Desk Cat',
18
+ ticker: 'DCAT',
19
+ autoHire: { seats: 3 },
20
+ dryRunToken: '<from dry-run>',
21
+ humanConfirmed: true,
22
+ confirmPhrase: 'APPROVE_SOL_SPEND',
23
+ })
24
+ ```
25
+
26
+ ## Safety
27
+
28
+ - Dry-run first; launch needs `dryRunToken` + `humanConfirmed: true` + `confirmPhrase: "APPROVE_SOL_SPEND"`
29
+ - Env keys only (`CREWPAY_API_KEY` / `CREW_AGENT_API_KEY`, `CREW_LAUNCHER_KEY`)
30
+ - Fee map **60/15/25**; buyback cron not live yet
31
+ - Prefer MCP: `npx -y crewpay-mcp@1.2.1` or https://mcp.crewpay.dev/mcp
32
+
33
+ ## Links
34
+
35
+ - Source: https://github.com/fxams/solana-agent-kit-plugin-crewpay
36
+ - Upstream kit: https://github.com/sendaifun/solana-agent-kit
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Minimal CrewPay REST client for framework plugins.
3
+ * Keys from env only — never accept private keys as function arguments.
4
+ *
5
+ * Spend gates: dry-run issues a short-lived dryRunToken; launch/wire require that
6
+ * token (launch) plus the exact confirmPhrase APPROVE_SOL_SPEND (not a free-form
7
+ * boolean the model can invent from chat alone).
8
+ */
9
+ export declare const DEFAULT_API_URL = "https://api.crewpay.dev";
10
+ /** Exact phrase a human must supply for SOL-spending calls. */
11
+ export declare const SOL_SPEND_CONFIRM_PHRASE = "APPROVE_SOL_SPEND";
12
+ export type CrewPayEnv = {
13
+ apiUrl?: string;
14
+ apiKey?: string;
15
+ launcherKey?: string;
16
+ };
17
+ export declare function loadCrewPayEnv(overrides?: CrewPayEnv): Required<Pick<CrewPayEnv, 'apiUrl'>> & CrewPayEnv;
18
+ /** Canonical hash of launch fields so dry-run and launch bodies must match. */
19
+ export declare function hashLaunchBody(body: Record<string, unknown>): string;
20
+ export declare class CrewPayClient {
21
+ private readonly env;
22
+ constructor(env?: ReturnType<typeof loadCrewPayEnv>);
23
+ private headers;
24
+ fetch(path: string, init?: RequestInit & {
25
+ auth?: boolean;
26
+ launcher?: boolean;
27
+ }): Promise<unknown>;
28
+ discover(): Promise<unknown>;
29
+ claimKey(body?: {
30
+ label?: string;
31
+ agentName?: string;
32
+ model?: string;
33
+ }): Promise<unknown>;
34
+ autohire(body: Record<string, unknown>): Promise<unknown>;
35
+ dryRun(body: Record<string, unknown>): Promise<{
36
+ dryRunToken: string;
37
+ confirmPhraseRequired: string;
38
+ tip: string;
39
+ }>;
40
+ /**
41
+ * Real launch — spends SOL. Requires a prior dryRunToken for this body plus
42
+ * humanConfirmed and confirmPhrase APPROVE_SOL_SPEND.
43
+ */
44
+ launch(body: Record<string, unknown>, opts: {
45
+ humanConfirmed: boolean;
46
+ confirmPhrase: string;
47
+ dryRunToken: string;
48
+ }): Promise<unknown>;
49
+ wireFees(body: {
50
+ mint: string;
51
+ mode?: string;
52
+ crew?: unknown[];
53
+ }, opts: {
54
+ humanConfirmed: boolean;
55
+ confirmPhrase: string;
56
+ }): Promise<unknown>;
57
+ crank(body: {
58
+ mint: string;
59
+ }): Promise<unknown>;
60
+ proof(): Promise<unknown>;
61
+ }
package/dist/client.js ADDED
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Minimal CrewPay REST client for framework plugins.
3
+ * Keys from env only — never accept private keys as function arguments.
4
+ *
5
+ * Spend gates: dry-run issues a short-lived dryRunToken; launch/wire require that
6
+ * token (launch) plus the exact confirmPhrase APPROVE_SOL_SPEND (not a free-form
7
+ * boolean the model can invent from chat alone).
8
+ */
9
+ import { createHash, randomBytes } from 'node:crypto';
10
+ export const DEFAULT_API_URL = 'https://api.crewpay.dev';
11
+ /** Exact phrase a human must supply for SOL-spending calls. */
12
+ export const SOL_SPEND_CONFIRM_PHRASE = 'APPROVE_SOL_SPEND';
13
+ const pendingDryRuns = new Map();
14
+ const DRY_RUN_TTL_MS = 30 * 60 * 1000;
15
+ export function loadCrewPayEnv(overrides = {}) {
16
+ return {
17
+ apiUrl: (overrides.apiUrl || process.env.CREW_API_URL || DEFAULT_API_URL).replace(/\/$/, ''),
18
+ apiKey: overrides.apiKey ||
19
+ process.env.CREWPAY_API_KEY?.trim() ||
20
+ process.env.CREW_AGENT_API_KEY?.trim() ||
21
+ '',
22
+ launcherKey: overrides.launcherKey ||
23
+ process.env.CREW_LAUNCHER_KEY?.trim() ||
24
+ '',
25
+ };
26
+ }
27
+ /** Canonical hash of launch fields so dry-run and launch bodies must match. */
28
+ export function hashLaunchBody(body) {
29
+ const pick = {
30
+ name: body.name,
31
+ ticker: body.ticker,
32
+ description: body.description ?? null,
33
+ mode: body.mode ?? 'agent',
34
+ initialBuySol: body.initialBuySol ?? 0,
35
+ imageUrl: body.imageUrl ?? null,
36
+ autoHire: body.autoHire ?? null,
37
+ crew: body.crew ?? null,
38
+ holderKol: body.holderKol ?? false,
39
+ };
40
+ return createHash('sha256').update(JSON.stringify(pick)).digest('hex');
41
+ }
42
+ function assertSpendConfirm(opts, action) {
43
+ if (opts.humanConfirmed !== true) {
44
+ throw new Error(`${action} blocked: humanConfirmed must be true after an explicit human approval`);
45
+ }
46
+ if (opts.confirmPhrase !== SOL_SPEND_CONFIRM_PHRASE) {
47
+ throw new Error(`${action} blocked: confirmPhrase must be exactly "${SOL_SPEND_CONFIRM_PHRASE}" (human-supplied; do not invent)`);
48
+ }
49
+ }
50
+ export class CrewPayClient {
51
+ env;
52
+ constructor(env = loadCrewPayEnv()) {
53
+ this.env = env;
54
+ }
55
+ headers(opts) {
56
+ const h = new Headers({ accept: 'application/json', 'content-type': 'application/json' });
57
+ if (this.env.apiKey)
58
+ h.set('x-crew-api-key', this.env.apiKey);
59
+ if (opts?.launcher) {
60
+ if (!this.env.launcherKey) {
61
+ throw new Error('Missing CREW_LAUNCHER_KEY in env — use a dedicated low-SOL burner. Never pass secrets as arguments.');
62
+ }
63
+ h.set('x-launcher-key', this.env.launcherKey);
64
+ }
65
+ return h;
66
+ }
67
+ async fetch(path, init) {
68
+ const headers = this.headers({ launcher: init?.launcher });
69
+ if (init?.auth && !this.env.apiKey) {
70
+ throw new Error('Missing CREWPAY_API_KEY / CREW_AGENT_API_KEY — claim via POST /api/agent/keys/claim');
71
+ }
72
+ const res = await fetch(`${this.env.apiUrl}${path}`, { ...init, headers });
73
+ const text = await res.text();
74
+ let json = null;
75
+ try {
76
+ json = text ? JSON.parse(text) : null;
77
+ }
78
+ catch {
79
+ json = { raw: text.slice(0, 500) };
80
+ }
81
+ if (!res.ok) {
82
+ const err = typeof json === 'object' && json && 'error' in json
83
+ ? String(json.error)
84
+ : text.slice(0, 300);
85
+ throw new Error(`CREW API ${res.status}: ${err}`);
86
+ }
87
+ return json;
88
+ }
89
+ discover() {
90
+ return this.fetch('/api/agent');
91
+ }
92
+ claimKey(body = {}) {
93
+ return this.fetch('/api/agent/keys/claim', {
94
+ method: 'POST',
95
+ body: JSON.stringify({ label: 'agent', ...body }),
96
+ });
97
+ }
98
+ autohire(body) {
99
+ return this.fetch('/api/agent/autohire', {
100
+ method: 'POST',
101
+ auth: true,
102
+ body: JSON.stringify(body),
103
+ });
104
+ }
105
+ async dryRun(body) {
106
+ const data = await this.fetch('/api/agent/launch/dry-run', {
107
+ method: 'POST',
108
+ auth: true,
109
+ body: JSON.stringify(body),
110
+ });
111
+ const dryRunToken = randomBytes(16).toString('hex');
112
+ pendingDryRuns.set(dryRunToken, {
113
+ bodyHash: hashLaunchBody(body),
114
+ expiresAt: Date.now() + DRY_RUN_TTL_MS,
115
+ });
116
+ return {
117
+ ...(typeof data === 'object' && data ? data : { result: data }),
118
+ dryRunToken,
119
+ confirmPhraseRequired: SOL_SPEND_CONFIRM_PHRASE,
120
+ tip: `To launch: pass the same body + dryRunToken + humanConfirmed:true + confirmPhrase:"${SOL_SPEND_CONFIRM_PHRASE}" (human must supply the phrase).`,
121
+ };
122
+ }
123
+ /**
124
+ * Real launch — spends SOL. Requires a prior dryRunToken for this body plus
125
+ * humanConfirmed and confirmPhrase APPROVE_SOL_SPEND.
126
+ */
127
+ launch(body, opts) {
128
+ assertSpendConfirm(opts, 'Launch');
129
+ const pending = pendingDryRuns.get(opts.dryRunToken);
130
+ if (!pending || pending.expiresAt < Date.now()) {
131
+ throw new Error('Launch blocked: missing/expired dryRunToken — call dryRun first and reuse its dryRunToken');
132
+ }
133
+ if (pending.bodyHash !== hashLaunchBody(body)) {
134
+ throw new Error('Launch blocked: body does not match the dry-run that issued dryRunToken');
135
+ }
136
+ pendingDryRuns.delete(opts.dryRunToken);
137
+ return this.fetch('/api/agent/launch', {
138
+ method: 'POST',
139
+ auth: true,
140
+ launcher: true,
141
+ body: JSON.stringify(body),
142
+ });
143
+ }
144
+ wireFees(body, opts) {
145
+ assertSpendConfirm(opts, 'Wire-fees');
146
+ return this.fetch('/api/agent/wire-fees', {
147
+ method: 'POST',
148
+ auth: true,
149
+ launcher: true,
150
+ body: JSON.stringify(body),
151
+ });
152
+ }
153
+ crank(body) {
154
+ return this.fetch('/api/agent/crank', {
155
+ method: 'POST',
156
+ auth: true,
157
+ body: JSON.stringify(body),
158
+ });
159
+ }
160
+ proof() {
161
+ return this.fetch('/api/proof');
162
+ }
163
+ }
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Solana Agent Kit v2 plugin scaffold for CrewPay.
3
+ * Docs: https://docs.sendai.fun/docs/v2/setup/quickstart
4
+ */
5
+ import { z } from 'zod';
6
+ export declare const CrewPayPlugin: {
7
+ name: string;
8
+ methods: {
9
+ crewDiscover: () => Promise<unknown>;
10
+ crewAutohire: (_agent: unknown, body: Record<string, unknown>) => Promise<unknown>;
11
+ crewDryRun: (_agent: unknown, body: Record<string, unknown>) => Promise<{
12
+ dryRunToken: string;
13
+ confirmPhraseRequired: string;
14
+ tip: string;
15
+ }>;
16
+ crewLaunch: (_agent: unknown, body: Record<string, unknown>) => Promise<unknown>;
17
+ crewWireFees: (_agent: unknown, body: {
18
+ mint: string;
19
+ mode?: string;
20
+ humanConfirmed?: boolean;
21
+ confirmPhrase?: string;
22
+ }) => Promise<unknown>;
23
+ crewCrank: (_agent: unknown, body: {
24
+ mint: string;
25
+ }) => Promise<unknown>;
26
+ crewProof: () => Promise<unknown>;
27
+ };
28
+ actions: ({
29
+ name: string;
30
+ similes: string[];
31
+ description: string;
32
+ schema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
33
+ handler: () => Promise<{
34
+ status: string;
35
+ data: unknown;
36
+ }>;
37
+ } | {
38
+ name: string;
39
+ similes: string[];
40
+ description: string;
41
+ schema: z.ZodObject<{
42
+ name: z.ZodString;
43
+ ticker: z.ZodString;
44
+ description: z.ZodOptional<z.ZodString>;
45
+ seats: z.ZodOptional<z.ZodNumber>;
46
+ }, "strip", z.ZodTypeAny, {
47
+ name: string;
48
+ ticker: string;
49
+ description?: string | undefined;
50
+ seats?: number | undefined;
51
+ }, {
52
+ name: string;
53
+ ticker: string;
54
+ description?: string | undefined;
55
+ seats?: number | undefined;
56
+ }>;
57
+ handler: (_agent: unknown, input: Record<string, unknown>) => Promise<{
58
+ status: string;
59
+ data: unknown;
60
+ }>;
61
+ } | {
62
+ name: string;
63
+ similes: string[];
64
+ description: string;
65
+ schema: z.ZodObject<Omit<{
66
+ name: z.ZodString;
67
+ ticker: z.ZodString;
68
+ description: z.ZodOptional<z.ZodString>;
69
+ mode: z.ZodOptional<z.ZodEnum<["split", "buyback", "raid", "agent"]>>;
70
+ initialBuySol: z.ZodOptional<z.ZodNumber>;
71
+ imageUrl: z.ZodOptional<z.ZodString>;
72
+ autoHire: z.ZodOptional<z.ZodObject<{
73
+ seats: z.ZodOptional<z.ZodNumber>;
74
+ }, "strip", z.ZodTypeAny, {
75
+ seats?: number | undefined;
76
+ }, {
77
+ seats?: number | undefined;
78
+ }>>;
79
+ humanConfirmed: z.ZodOptional<z.ZodBoolean>;
80
+ confirmPhrase: z.ZodOptional<z.ZodString>;
81
+ dryRunToken: z.ZodOptional<z.ZodString>;
82
+ }, "humanConfirmed" | "confirmPhrase" | "dryRunToken">, "passthrough", z.ZodTypeAny, z.objectOutputType<Omit<{
83
+ name: z.ZodString;
84
+ ticker: z.ZodString;
85
+ description: z.ZodOptional<z.ZodString>;
86
+ mode: z.ZodOptional<z.ZodEnum<["split", "buyback", "raid", "agent"]>>;
87
+ initialBuySol: z.ZodOptional<z.ZodNumber>;
88
+ imageUrl: z.ZodOptional<z.ZodString>;
89
+ autoHire: z.ZodOptional<z.ZodObject<{
90
+ seats: z.ZodOptional<z.ZodNumber>;
91
+ }, "strip", z.ZodTypeAny, {
92
+ seats?: number | undefined;
93
+ }, {
94
+ seats?: number | undefined;
95
+ }>>;
96
+ humanConfirmed: z.ZodOptional<z.ZodBoolean>;
97
+ confirmPhrase: z.ZodOptional<z.ZodString>;
98
+ dryRunToken: z.ZodOptional<z.ZodString>;
99
+ }, "humanConfirmed" | "confirmPhrase" | "dryRunToken">, z.ZodTypeAny, "passthrough">, z.objectInputType<Omit<{
100
+ name: z.ZodString;
101
+ ticker: z.ZodString;
102
+ description: z.ZodOptional<z.ZodString>;
103
+ mode: z.ZodOptional<z.ZodEnum<["split", "buyback", "raid", "agent"]>>;
104
+ initialBuySol: z.ZodOptional<z.ZodNumber>;
105
+ imageUrl: z.ZodOptional<z.ZodString>;
106
+ autoHire: z.ZodOptional<z.ZodObject<{
107
+ seats: z.ZodOptional<z.ZodNumber>;
108
+ }, "strip", z.ZodTypeAny, {
109
+ seats?: number | undefined;
110
+ }, {
111
+ seats?: number | undefined;
112
+ }>>;
113
+ humanConfirmed: z.ZodOptional<z.ZodBoolean>;
114
+ confirmPhrase: z.ZodOptional<z.ZodString>;
115
+ dryRunToken: z.ZodOptional<z.ZodString>;
116
+ }, "humanConfirmed" | "confirmPhrase" | "dryRunToken">, z.ZodTypeAny, "passthrough">>;
117
+ handler: (_agent: unknown, input: Record<string, unknown>) => Promise<{
118
+ status: string;
119
+ data: {
120
+ dryRunToken: string;
121
+ confirmPhraseRequired: string;
122
+ tip: string;
123
+ };
124
+ }>;
125
+ } | {
126
+ name: string;
127
+ similes: string[];
128
+ description: string;
129
+ schema: z.ZodObject<{
130
+ name: z.ZodString;
131
+ ticker: z.ZodString;
132
+ description: z.ZodOptional<z.ZodString>;
133
+ mode: z.ZodOptional<z.ZodEnum<["split", "buyback", "raid", "agent"]>>;
134
+ initialBuySol: z.ZodOptional<z.ZodNumber>;
135
+ imageUrl: z.ZodOptional<z.ZodString>;
136
+ autoHire: z.ZodOptional<z.ZodObject<{
137
+ seats: z.ZodOptional<z.ZodNumber>;
138
+ }, "strip", z.ZodTypeAny, {
139
+ seats?: number | undefined;
140
+ }, {
141
+ seats?: number | undefined;
142
+ }>>;
143
+ humanConfirmed: z.ZodOptional<z.ZodBoolean>;
144
+ confirmPhrase: z.ZodOptional<z.ZodString>;
145
+ dryRunToken: z.ZodOptional<z.ZodString>;
146
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
147
+ name: z.ZodString;
148
+ ticker: z.ZodString;
149
+ description: z.ZodOptional<z.ZodString>;
150
+ mode: z.ZodOptional<z.ZodEnum<["split", "buyback", "raid", "agent"]>>;
151
+ initialBuySol: z.ZodOptional<z.ZodNumber>;
152
+ imageUrl: z.ZodOptional<z.ZodString>;
153
+ autoHire: z.ZodOptional<z.ZodObject<{
154
+ seats: z.ZodOptional<z.ZodNumber>;
155
+ }, "strip", z.ZodTypeAny, {
156
+ seats?: number | undefined;
157
+ }, {
158
+ seats?: number | undefined;
159
+ }>>;
160
+ humanConfirmed: z.ZodOptional<z.ZodBoolean>;
161
+ confirmPhrase: z.ZodOptional<z.ZodString>;
162
+ dryRunToken: z.ZodOptional<z.ZodString>;
163
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
164
+ name: z.ZodString;
165
+ ticker: z.ZodString;
166
+ description: z.ZodOptional<z.ZodString>;
167
+ mode: z.ZodOptional<z.ZodEnum<["split", "buyback", "raid", "agent"]>>;
168
+ initialBuySol: z.ZodOptional<z.ZodNumber>;
169
+ imageUrl: z.ZodOptional<z.ZodString>;
170
+ autoHire: z.ZodOptional<z.ZodObject<{
171
+ seats: z.ZodOptional<z.ZodNumber>;
172
+ }, "strip", z.ZodTypeAny, {
173
+ seats?: number | undefined;
174
+ }, {
175
+ seats?: number | undefined;
176
+ }>>;
177
+ humanConfirmed: z.ZodOptional<z.ZodBoolean>;
178
+ confirmPhrase: z.ZodOptional<z.ZodString>;
179
+ dryRunToken: z.ZodOptional<z.ZodString>;
180
+ }, z.ZodTypeAny, "passthrough">>;
181
+ handler: (_agent: unknown, input: Record<string, unknown>) => Promise<{
182
+ status: string;
183
+ data: unknown;
184
+ }>;
185
+ } | {
186
+ name: string;
187
+ similes: string[];
188
+ description: string;
189
+ schema: z.ZodObject<{
190
+ mint: z.ZodString;
191
+ mode: z.ZodOptional<z.ZodString>;
192
+ humanConfirmed: z.ZodBoolean;
193
+ confirmPhrase: z.ZodString;
194
+ }, "strip", z.ZodTypeAny, {
195
+ humanConfirmed: boolean;
196
+ confirmPhrase: string;
197
+ mint: string;
198
+ mode?: string | undefined;
199
+ }, {
200
+ humanConfirmed: boolean;
201
+ confirmPhrase: string;
202
+ mint: string;
203
+ mode?: string | undefined;
204
+ }>;
205
+ handler: (_agent: unknown, input: {
206
+ mint: string;
207
+ mode?: string;
208
+ humanConfirmed: boolean;
209
+ confirmPhrase: string;
210
+ }) => Promise<{
211
+ status: string;
212
+ data: unknown;
213
+ }>;
214
+ } | {
215
+ name: string;
216
+ similes: string[];
217
+ description: string;
218
+ schema: z.ZodObject<{
219
+ mint: z.ZodString;
220
+ }, "strip", z.ZodTypeAny, {
221
+ mint: string;
222
+ }, {
223
+ mint: string;
224
+ }>;
225
+ handler: (_agent: unknown, input: {
226
+ mint: string;
227
+ }) => Promise<{
228
+ status: string;
229
+ data: unknown;
230
+ }>;
231
+ })[];
232
+ initialize(): void;
233
+ };
234
+ export default CrewPayPlugin;
package/dist/index.js ADDED
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Solana Agent Kit v2 plugin scaffold for CrewPay.
3
+ * Docs: https://docs.sendai.fun/docs/v2/setup/quickstart
4
+ */
5
+ import { z } from 'zod';
6
+ import { CrewPayClient, loadCrewPayEnv, SOL_SPEND_CONFIRM_PHRASE, } from './client.js';
7
+ const launchBodySchema = z
8
+ .object({
9
+ name: z.string().min(2).max(32),
10
+ ticker: z.string().min(2).max(13),
11
+ description: z.string().max(204).optional(),
12
+ mode: z.enum(['split', 'buyback', 'raid', 'agent']).optional(),
13
+ initialBuySol: z.number().min(0).max(10).optional(),
14
+ imageUrl: z.string().url().optional(),
15
+ autoHire: z.object({ seats: z.number().int().min(1).max(10).optional() }).optional(),
16
+ humanConfirmed: z.boolean().optional(),
17
+ confirmPhrase: z.string().optional(),
18
+ dryRunToken: z.string().optional(),
19
+ })
20
+ .passthrough();
21
+ function api() {
22
+ return new CrewPayClient(loadCrewPayEnv());
23
+ }
24
+ function stripGateFields(body) {
25
+ const { humanConfirmed: _h, confirmPhrase: _c, dryRunToken: _d, ...rest } = body;
26
+ return rest;
27
+ }
28
+ export const CrewPayPlugin = {
29
+ name: 'crewpay',
30
+ methods: {
31
+ crewDiscover: async () => api().discover(),
32
+ crewAutohire: async (_agent, body) => api().autohire(body),
33
+ crewDryRun: async (_agent, body) => api().dryRun(body),
34
+ crewLaunch: async (_agent, body) => {
35
+ const parsed = launchBodySchema.parse(body);
36
+ return api().launch(stripGateFields(parsed), {
37
+ humanConfirmed: parsed.humanConfirmed === true,
38
+ confirmPhrase: parsed.confirmPhrase || '',
39
+ dryRunToken: parsed.dryRunToken || '',
40
+ });
41
+ },
42
+ crewWireFees: async (_agent, body) => api().wireFees({ mint: body.mint, mode: body.mode }, {
43
+ humanConfirmed: body.humanConfirmed === true,
44
+ confirmPhrase: body.confirmPhrase || '',
45
+ }),
46
+ crewCrank: async (_agent, body) => api().crank(body),
47
+ crewProof: async () => api().proof(),
48
+ },
49
+ actions: [
50
+ {
51
+ name: 'CREW_DISCOVER',
52
+ similes: ['crewpay discover', 'crew api info'],
53
+ description: 'Discover CrewPay agent API / fee map / MCP surfaces',
54
+ schema: z.object({}),
55
+ handler: async () => ({ status: 'success', data: await api().discover() }),
56
+ },
57
+ {
58
+ name: 'CREW_AUTOHIRE',
59
+ similes: ['autohire kols', 'hire crew'],
60
+ description: 'Preview Autohire KOL crew (no SOL)',
61
+ schema: z.object({
62
+ name: z.string(),
63
+ ticker: z.string(),
64
+ description: z.string().optional(),
65
+ seats: z.number().int().min(1).max(10).optional(),
66
+ }),
67
+ handler: async (_agent, input) => ({
68
+ status: 'success',
69
+ data: await api().autohire(input),
70
+ }),
71
+ },
72
+ {
73
+ name: 'CREW_LAUNCH_DRY_RUN',
74
+ similes: ['crew dry run', 'dry-run launch'],
75
+ description: 'Dry-run launch — returns dryRunToken required for CREW_LAUNCH',
76
+ schema: launchBodySchema.omit({ humanConfirmed: true, confirmPhrase: true, dryRunToken: true }),
77
+ handler: async (_agent, input) => ({
78
+ status: 'success',
79
+ data: await api().dryRun(input),
80
+ }),
81
+ },
82
+ {
83
+ name: 'CREW_LAUNCH',
84
+ similes: ['crew launch', 'launch pump coin'],
85
+ description: `Mainnet launch. Requires dryRunToken + humanConfirmed + confirmPhrase ${SOL_SPEND_CONFIRM_PHRASE}. Fee map 60/15/25; buyback not live.`,
86
+ schema: launchBodySchema,
87
+ handler: async (_agent, input) => {
88
+ const parsed = launchBodySchema.parse(input);
89
+ return {
90
+ status: 'success',
91
+ data: await api().launch(stripGateFields(parsed), {
92
+ humanConfirmed: parsed.humanConfirmed === true,
93
+ confirmPhrase: parsed.confirmPhrase || '',
94
+ dryRunToken: parsed.dryRunToken || '',
95
+ }),
96
+ };
97
+ },
98
+ },
99
+ {
100
+ name: 'CREW_WIRE_FEES',
101
+ similes: ['wire fees', 'lock fee shares'],
102
+ description: `Wire fee-shares (SOL). Requires humanConfirmed + confirmPhrase ${SOL_SPEND_CONFIRM_PHRASE}.`,
103
+ schema: z.object({
104
+ mint: z.string(),
105
+ mode: z.string().optional(),
106
+ humanConfirmed: z.boolean(),
107
+ confirmPhrase: z.string(),
108
+ }),
109
+ handler: async (_agent, input) => ({
110
+ status: 'success',
111
+ data: await api().wireFees({ mint: input.mint, mode: input.mode }, { humanConfirmed: input.humanConfirmed, confirmPhrase: input.confirmPhrase }),
112
+ }),
113
+ },
114
+ {
115
+ name: 'CREW_CRANK',
116
+ similes: ['crank remits', 'distribute creator fees'],
117
+ description: 'Crank distributeCreatorFeesV2 via POST /api/agent/crank',
118
+ schema: z.object({ mint: z.string() }),
119
+ handler: async (_agent, input) => ({
120
+ status: 'success',
121
+ data: await api().crank(input),
122
+ }),
123
+ },
124
+ {
125
+ name: 'CREW_PROOF',
126
+ similes: ['crew proof tape'],
127
+ description: 'Public proof tape GET /api/proof',
128
+ schema: z.object({}),
129
+ handler: async () => ({ status: 'success', data: await api().proof() }),
130
+ },
131
+ ],
132
+ initialize() { },
133
+ };
134
+ export default CrewPayPlugin;
package/package.json CHANGED
@@ -1,6 +1,52 @@
1
1
  {
2
2
  "name": "crewpay-solana-agent-kit-plugin",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "Solana Agent Kit plugin for CrewPay — discover/autohire/dry-run/launch/wire/crank/proof. Fee map 60/15/25; buyback not live; dryRunToken + APPROVE_SOL_SPEND required.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc -p tsconfig.json",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "keywords": [
24
+ "solana-agent-kit",
25
+ "crewpay",
26
+ "solana",
27
+ "pump.fun",
28
+ "kol",
29
+ "ai-agent"
30
+ ],
31
+ "license": "MIT",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/fxams/solana-agent-kit-plugin-crewpay.git"
35
+ },
36
+ "homepage": "https://crewpay.dev/agents",
37
+ "peerDependencies": {
38
+ "solana-agent-kit": "*",
39
+ "zod": "*"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^22.10.0",
43
+ "typescript": "^5.7.0",
44
+ "zod": "^3.24.0"
45
+ },
46
+ "engines": {
47
+ "node": ">=20"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ }
52
+ }