slashvibe-mcp 0.2.2 → 0.2.4
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 +1 -0
- package/analytics.js +107 -0
- package/config.js +174 -3
- package/index.js +163 -34
- package/intelligence/index.js +45 -0
- package/intelligence/infer.js +316 -0
- package/intelligence/interests.js +369 -0
- package/intelligence/patterns.js +651 -0
- package/intelligence/proactive.js +358 -0
- package/intelligence/serendipity.js +306 -0
- package/notification-emitter.js +77 -0
- package/notify.js +141 -18
- package/package.json +14 -6
- package/presence.js +5 -1
- package/protocol/index.js +88 -1
- package/protocol/telegram-commands.js +199 -0
- package/store/api.js +469 -29
- package/store/index.js +7 -7
- package/store/local.js +67 -11
- package/store/profiles.js +435 -0
- package/store/reservations.js +321 -0
- package/store/skills.js +378 -0
- package/tools/_actions.js +491 -22
- package/tools/_connection-queue.js +257 -0
- package/tools/_discovery-enhanced.js +290 -0
- package/tools/_discovery.js +439 -0
- package/tools/_proactive-discovery.js +301 -0
- package/tools/_shared/index.js +64 -0
- package/tools/_work-context.js +338 -0
- package/tools/_work-context.manual-test.js +199 -0
- package/tools/_work-context.test.js +260 -0
- package/tools/admin-inbox.js +218 -0
- package/tools/agent-treasury.js +288 -0
- package/tools/agents.js +122 -0
- package/tools/analytics.js +191 -0
- package/tools/approve.js +197 -0
- package/tools/arcade.js +173 -0
- package/tools/artifact-create.js +247 -0
- package/tools/artifact-view.js +174 -0
- package/tools/artifacts-price.js +107 -0
- package/tools/ask-expert.js +160 -0
- package/tools/auto-suggest-connections.js +304 -0
- package/tools/away.js +68 -0
- package/tools/back.js +51 -0
- package/tools/become-expert.js +150 -0
- package/tools/bootstrap-skills.js +231 -0
- package/tools/bridge-dashboard.js +342 -0
- package/tools/bridge-health.js +400 -0
- package/tools/bridge-live.js +384 -0
- package/tools/bridges.js +383 -0
- package/tools/broadcast.js +286 -0
- package/tools/bye.js +4 -0
- package/tools/chat.js +202 -0
- package/tools/collaborative-drawing.js +286 -0
- package/tools/colorguess.js +281 -0
- package/tools/crossword.js +369 -0
- package/tools/discover-insights.js +379 -0
- package/tools/discover-momentum.js +256 -0
- package/tools/discover.js +675 -0
- package/tools/discovery-analytics.js +345 -0
- package/tools/discovery-auto-suggest.js +275 -0
- package/tools/discovery-bootstrap.js +267 -0
- package/tools/discovery-daily.js +375 -0
- package/tools/discovery-dashboard.js +385 -0
- package/tools/discovery-digest.js +314 -0
- package/tools/discovery-hub.js +357 -0
- package/tools/discovery-insights.js +384 -0
- package/tools/discovery-momentum.js +281 -0
- package/tools/discovery-monitor.js +319 -0
- package/tools/discovery-proactive.js +300 -0
- package/tools/dm.js +84 -14
- package/tools/draw.js +317 -0
- package/tools/drawing.js +310 -0
- package/tools/earnings.js +126 -0
- package/tools/echo.js +16 -0
- package/tools/farcaster.js +307 -0
- package/tools/feed.js +215 -0
- package/tools/follow.js +224 -0
- package/tools/friends.js +192 -0
- package/tools/game.js +218 -110
- package/tools/games-catalog.js +376 -0
- package/tools/games.js +313 -0
- package/tools/genesis.js +233 -0
- package/tools/gig-browse.js +206 -0
- package/tools/gig-complete.js +139 -0
- package/tools/guessnumber.js +194 -0
- package/tools/hangman.js +129 -0
- package/tools/help.js +269 -0
- package/tools/idea.js +217 -0
- package/tools/inbox.js +291 -25
- package/tools/init.js +657 -33
- package/tools/insights.js +123 -0
- package/tools/invite.js +142 -21
- package/tools/l2-bridge.js +272 -0
- package/tools/l2-status.js +217 -0
- package/tools/l2.js +206 -0
- package/tools/migrate.js +156 -0
- package/tools/mint.js +377 -0
- package/tools/multiplayer-game.js +275 -0
- package/tools/multiplayer-tictactoe.js +303 -0
- package/tools/mute.js +97 -0
- package/tools/notifications.js +415 -0
- package/tools/observe.js +200 -0
- package/tools/onboarding.js +147 -0
- package/tools/open.js +52 -3
- package/tools/party-game.js +314 -0
- package/tools/plan.js +225 -0
- package/tools/presence-agent.js +167 -0
- package/tools/profile.js +219 -0
- package/tools/proof-of-work.js +139 -0
- package/tools/pulse.js +218 -0
- package/tools/react.js +4 -0
- package/tools/release.js +83 -0
- package/tools/report.js +109 -0
- package/tools/reputation.js +175 -0
- package/tools/request.js +231 -0
- package/tools/reservations.js +116 -0
- package/tools/reserve.js +111 -0
- package/tools/riddle.js +240 -0
- package/tools/run-bootstrap.js +69 -0
- package/tools/schedule.js +367 -0
- package/tools/session.js +420 -0
- package/tools/session_price.js +128 -0
- package/tools/settings.js +200 -0
- package/tools/ship.js +188 -0
- package/tools/shipback.js +326 -0
- package/tools/skills-analytics.js +349 -0
- package/tools/skills-bootstrap.js +301 -0
- package/tools/skills-dashboard.js +268 -0
- package/tools/skills-exchange.js +342 -0
- package/tools/skills.js +380 -0
- package/tools/smart-intro.js +353 -0
- package/tools/social-inbox.js +326 -69
- package/tools/social-post.js +251 -66
- package/tools/social-processor.js +445 -0
- package/tools/solo-game.js +390 -0
- package/tools/start.js +296 -81
- package/tools/status.js +53 -6
- package/tools/storybuilder.js +331 -0
- package/tools/stuck.js +297 -0
- package/tools/subscribe.js +148 -0
- package/tools/subscriptions.js +134 -0
- package/tools/suggest-tags.js +184 -0
- package/tools/tag-suggestions.js +257 -0
- package/tools/telegram-bot.js +183 -0
- package/tools/telegram-setup.js +214 -0
- package/tools/tictactoe.js +155 -0
- package/tools/tip.js +120 -0
- package/tools/token.js +103 -0
- package/tools/twentyquestions.js +143 -0
- package/tools/update.js +1 -1
- package/tools/wallet.js +127 -0
- package/tools/watch.js +157 -0
- package/tools/webhook-test.js +388 -0
- package/tools/who.js +118 -25
- package/tools/withdraw.js +145 -0
- package/tools/wordassociation.js +247 -0
- package/tools/work-summary.js +96 -0
- package/tools/workshop-buddy.js +394 -0
- package/tools/workshop.js +327 -0
- package/version.json +12 -3
- package/tools/board.js +0 -130
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vibe insights — View your behavioral patterns
|
|
3
|
+
*
|
|
4
|
+
* Shows accumulated insights about your work, social, and creative patterns.
|
|
5
|
+
* All data is stored locally (~/.vibe/work-patterns.json) and never transmitted.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const patterns = require('../intelligence/patterns');
|
|
9
|
+
const { requireInit, header, divider } = require('./_shared');
|
|
10
|
+
|
|
11
|
+
const definition = {
|
|
12
|
+
name: 'vibe_insights',
|
|
13
|
+
description: 'View your accumulated work, social, and creative patterns.',
|
|
14
|
+
inputSchema: {
|
|
15
|
+
type: 'object',
|
|
16
|
+
properties: {
|
|
17
|
+
category: {
|
|
18
|
+
type: 'string',
|
|
19
|
+
enum: ['work', 'social', 'creative', 'all'],
|
|
20
|
+
description: 'Which patterns to show (default: all)'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function formatTimeAgo(timestamp) {
|
|
27
|
+
if (!timestamp) return 'unknown';
|
|
28
|
+
const seconds = Math.floor((Date.now() - timestamp) / 1000);
|
|
29
|
+
if (seconds < 60) return 'just now';
|
|
30
|
+
if (seconds < 3600) return Math.floor(seconds / 60) + 'm ago';
|
|
31
|
+
if (seconds < 86400) return Math.floor(seconds / 3600) + 'h ago';
|
|
32
|
+
return Math.floor(seconds / 86400) + 'd ago';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function handler(args) {
|
|
36
|
+
const initCheck = requireInit();
|
|
37
|
+
if (initCheck) return initCheck;
|
|
38
|
+
|
|
39
|
+
const category = args.category || 'all';
|
|
40
|
+
let display = header('Your Patterns');
|
|
41
|
+
display += '\n_Local only_\n\n';
|
|
42
|
+
|
|
43
|
+
const data = patterns.load();
|
|
44
|
+
|
|
45
|
+
if (!patterns.hasEnoughData()) {
|
|
46
|
+
display += '_Not enough data yet — keep vibing!_\n';
|
|
47
|
+
display += '_Sessions: ' + data.sessions.total + '_';
|
|
48
|
+
return { display };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Work patterns
|
|
52
|
+
if (category === 'all' || category === 'work') {
|
|
53
|
+
const rhythm = patterns.getSessionRhythm();
|
|
54
|
+
const peakHours = patterns.getPeakHours();
|
|
55
|
+
const dominantState = patterns.getDominantState();
|
|
56
|
+
const topModules = patterns.getTopModules(3);
|
|
57
|
+
|
|
58
|
+
display += '**Work**\n';
|
|
59
|
+
display += rhythm.totalSessions + ' sessions · ' + rhythm.totalHours + 'h total\n';
|
|
60
|
+
display += 'avg ' + rhythm.averageMinutes + 'm · longest ' + rhythm.longestMinutes + 'm\n';
|
|
61
|
+
|
|
62
|
+
if (peakHours.length > 0) {
|
|
63
|
+
const hours = peakHours.map(h => h.hour + ':00').join(', ');
|
|
64
|
+
display += 'peak: ' + hours + '\n';
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (dominantState) {
|
|
68
|
+
display += 'usually: ' + dominantState.state + ' (' + dominantState.percentage + '%)\n';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (topModules.length > 0) {
|
|
72
|
+
const mods = topModules.map(m => m.name).join(', ');
|
|
73
|
+
display += 'focus: ' + mods + '\n';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
display += '\n';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Social patterns
|
|
80
|
+
if (category === 'all' || category === 'social') {
|
|
81
|
+
const social = patterns.getSocialSummary();
|
|
82
|
+
const topConnections = patterns.getTopConnections(3);
|
|
83
|
+
|
|
84
|
+
display += '**Social**\n';
|
|
85
|
+
display += social.messagesSent + ' sent · ' + social.messagesReceived + ' received\n';
|
|
86
|
+
display += social.uniqueConnections + ' connections\n';
|
|
87
|
+
|
|
88
|
+
if (topConnections.length > 0) {
|
|
89
|
+
const names = topConnections.map(c => '@' + c.handle).join(', ');
|
|
90
|
+
display += 'closest: ' + names + '\n';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
display += '\n';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Creative patterns
|
|
97
|
+
if (category === 'all' || category === 'creative') {
|
|
98
|
+
const creative = patterns.getCreativeSummary();
|
|
99
|
+
const topDomains = patterns.getTopDomains(3);
|
|
100
|
+
const inspirations = patterns.getInspirations(3);
|
|
101
|
+
|
|
102
|
+
display += '**Creative**\n';
|
|
103
|
+
display += creative.totalShips + ' ships · ' + creative.totalIdeas + ' ideas · ' + creative.totalRiffs + ' riffs\n';
|
|
104
|
+
|
|
105
|
+
if (topDomains.length > 0) {
|
|
106
|
+
const domains = topDomains.map(d => '#' + d.domain).join(' ');
|
|
107
|
+
display += 'domains: ' + domains + '\n';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (inspirations.length > 0) {
|
|
111
|
+
const names = inspirations.map(i => '@' + i.handle).join(', ');
|
|
112
|
+
display += 'inspired by: ' + names + '\n';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
display += '\n';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
display += divider() + '_since ' + formatTimeAgo(new Date(data.firstSeen).getTime()) + '_';
|
|
119
|
+
|
|
120
|
+
return { display };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
module.exports = { definition, handler };
|
package/tools/invite.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* vibe invite — Generate
|
|
2
|
+
* vibe invite — Generate invite codes and shareable messages
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Actions:
|
|
5
|
+
* - generate: Create a new invite code
|
|
6
|
+
* - list: See your existing codes
|
|
7
|
+
* - (default): Generate a shareable message with your code
|
|
5
8
|
*/
|
|
6
9
|
|
|
7
10
|
const config = require('../config');
|
|
11
|
+
const store = require('../store');
|
|
8
12
|
const { requireInit } = require('./_shared');
|
|
9
13
|
|
|
10
14
|
const definition = {
|
|
@@ -13,6 +17,10 @@ const definition = {
|
|
|
13
17
|
inputSchema: {
|
|
14
18
|
type: 'object',
|
|
15
19
|
properties: {
|
|
20
|
+
action: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'Action: "generate" to create code, "list" to see your codes, or omit for shareable message'
|
|
23
|
+
},
|
|
16
24
|
name: {
|
|
17
25
|
type: 'string',
|
|
18
26
|
description: 'Optional: Friend\'s name for personalized message'
|
|
@@ -36,15 +44,118 @@ async function handler(args) {
|
|
|
36
44
|
const initCheck = requireInit();
|
|
37
45
|
if (initCheck) return initCheck;
|
|
38
46
|
|
|
39
|
-
const { name, format } = args;
|
|
47
|
+
const { action, name, format } = args;
|
|
40
48
|
const myHandle = config.getHandle();
|
|
41
49
|
|
|
42
|
-
|
|
50
|
+
// Generate a new invite code
|
|
51
|
+
if (action === 'generate') {
|
|
52
|
+
const result = await store.generateInviteCode(myHandle);
|
|
53
|
+
|
|
54
|
+
if (!result.success) {
|
|
55
|
+
return {
|
|
56
|
+
display: `## Could not generate invite code
|
|
57
|
+
|
|
58
|
+
${result.error || result.message || 'Unknown error'}
|
|
59
|
+
|
|
60
|
+
${result.remaining === 0 ? 'Share your existing codes first, or wait for them to be used.' : ''}`
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
display: `## New Invite Code Generated
|
|
66
|
+
|
|
67
|
+
**${result.code}**
|
|
68
|
+
|
|
69
|
+
Share link: ${result.share_url}
|
|
70
|
+
|
|
71
|
+
Expires: ${result.expires_at}
|
|
72
|
+
Remaining codes: ${result.remaining}
|
|
73
|
+
|
|
74
|
+
_When your friend redeems this code, you'll earn a bonus code._`
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// List existing codes
|
|
79
|
+
if (action === 'list') {
|
|
80
|
+
const result = await store.getMyInvites(myHandle);
|
|
81
|
+
|
|
82
|
+
if (!result.success) {
|
|
83
|
+
return {
|
|
84
|
+
display: `## Could not fetch invites
|
|
85
|
+
|
|
86
|
+
${result.error || 'Unknown error'}`
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!result.codes || result.codes.length === 0) {
|
|
91
|
+
return {
|
|
92
|
+
display: `## Your Invite Codes
|
|
93
|
+
|
|
94
|
+
No codes yet. Run \`vibe invite --action generate\` to create one.
|
|
95
|
+
|
|
96
|
+
You can have up to ${result.max_codes} unused codes at a time.`
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const available = result.codes.filter(c => c.status === 'available');
|
|
101
|
+
const used = result.codes.filter(c => c.status === 'used');
|
|
102
|
+
|
|
103
|
+
let display = `## Your Invite Codes
|
|
104
|
+
|
|
105
|
+
**Available** (${available.length}/${result.max_codes})
|
|
106
|
+
`;
|
|
107
|
+
|
|
108
|
+
if (available.length > 0) {
|
|
109
|
+
for (const code of available) {
|
|
110
|
+
display += `\n- **${code.code}** — ${code.share_url}`;
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
display += '\n_No available codes. Generate one or wait for existing codes to be used._';
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (used.length > 0) {
|
|
117
|
+
display += `\n\n**Used** (${used.length})`;
|
|
118
|
+
for (const code of used) {
|
|
119
|
+
display += `\n- ${code.code} → @${code.used_by} (${code.used_at?.split('T')[0] || 'unknown'})`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (result.can_generate) {
|
|
124
|
+
display += '\n\n_Run `vibe invite --action generate` to create a new code._';
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return { display };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Get an available code, or auto-generate one
|
|
131
|
+
let shareCode = null;
|
|
132
|
+
let justGenerated = false;
|
|
133
|
+
|
|
134
|
+
const codesResult = await store.getMyInvites(myHandle);
|
|
135
|
+
if (codesResult.success && codesResult.codes) {
|
|
136
|
+
const available = codesResult.codes.find(c => c.status === 'available');
|
|
137
|
+
if (available) {
|
|
138
|
+
shareCode = available.code;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Auto-generate if no available code and user can generate
|
|
143
|
+
if (!shareCode && codesResult.success && codesResult.can_generate) {
|
|
144
|
+
const genResult = await store.generateInviteCode(myHandle);
|
|
145
|
+
if (genResult.success) {
|
|
146
|
+
shareCode = genResult.code;
|
|
147
|
+
justGenerated = true;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const shareUrl = shareCode
|
|
152
|
+
? `slashvibe.dev/invite/${shareCode}`
|
|
153
|
+
: 'slashvibe.dev';
|
|
43
154
|
|
|
44
155
|
// Just the link
|
|
45
156
|
if (format === 'link') {
|
|
46
157
|
return {
|
|
47
|
-
display: `**${
|
|
158
|
+
display: `**${shareUrl}**
|
|
48
159
|
|
|
49
160
|
Copy and share this with anyone using Claude Code.`
|
|
50
161
|
};
|
|
@@ -58,38 +169,48 @@ Copy and share this with anyone using Claude Code.`
|
|
|
58
169
|
|
|
59
170
|
> ${randomMsg}
|
|
60
171
|
>
|
|
61
|
-
> ${
|
|
172
|
+
> ${shareUrl}
|
|
62
173
|
|
|
63
174
|
_Copy the above and send it._`
|
|
64
175
|
};
|
|
65
176
|
}
|
|
66
177
|
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
display: `## Invite to /vibe
|
|
178
|
+
// Default: Quick copy-ready format
|
|
179
|
+
// If name provided, make it personalized
|
|
180
|
+
if (name) {
|
|
181
|
+
return {
|
|
182
|
+
display: `## Invite for ${name}
|
|
73
183
|
|
|
74
184
|
---
|
|
75
185
|
|
|
76
|
-
${
|
|
186
|
+
Hey ${name}!
|
|
77
187
|
|
|
78
|
-
I've been using
|
|
188
|
+
I've been using /vibe in Claude Code — it's a social layer that lets you see who else is building and message people without leaving your terminal.
|
|
79
189
|
|
|
80
|
-
|
|
190
|
+
Just tell Claude: "go to slashvibe.dev and install /vibe"
|
|
81
191
|
|
|
82
|
-
|
|
192
|
+
Then say "let's vibe" to start. I'm @${myHandle} — ping me once you're on!
|
|
83
193
|
|
|
84
|
-
|
|
194
|
+
---
|
|
85
195
|
|
|
86
|
-
|
|
196
|
+
**${shareUrl}**
|
|
87
197
|
|
|
88
|
-
|
|
198
|
+
_Copy the link above and send it._`
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// No name: ultra-short copy-ready format
|
|
203
|
+
const genNote = justGenerated ? ' (just generated)' : '';
|
|
204
|
+
const randomMsg = INVITE_MESSAGES[Math.floor(Math.random() * INVITE_MESSAGES.length)];
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
display: `## Quick Invite${genNote}
|
|
89
208
|
|
|
90
|
-
|
|
209
|
+
> ${randomMsg}
|
|
210
|
+
>
|
|
211
|
+
> **${shareUrl}**
|
|
91
212
|
|
|
92
|
-
_Copy and send
|
|
213
|
+
_Copy and send. ${shareCode ? `Bonus code earned when they join.` : ''}_`
|
|
93
214
|
};
|
|
94
215
|
}
|
|
95
216
|
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vibe_bridge - Bridge ETH between Base and VIBE L2
|
|
3
|
+
*
|
|
4
|
+
* Move assets to VIBE L2 to mint artifacts and interact with
|
|
5
|
+
* the Shipback economy.
|
|
6
|
+
*
|
|
7
|
+
* Deposit: Base → VIBE L2 (~1 minute)
|
|
8
|
+
* Withdrawal: VIBE L2 → Base (~7 days, or ~1 hour with fast mode)
|
|
9
|
+
*
|
|
10
|
+
* Examples:
|
|
11
|
+
* - "vibe bridge deposit 0.1" - Move 0.1 ETH to VIBE L2
|
|
12
|
+
* - "vibe bridge status" - Check bridge status
|
|
13
|
+
* - "vibe bridge withdraw 0.05" - Move ETH back to Base
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fetch = require('node-fetch');
|
|
17
|
+
const config = require('../config');
|
|
18
|
+
|
|
19
|
+
const definition = {
|
|
20
|
+
name: 'vibe_bridge',
|
|
21
|
+
description: 'Bridge ETH between Base and VIBE L2. Deposit to mint artifacts, withdraw to cash out.',
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
action: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
description: 'Action: deposit, withdraw, status, estimate (default: status)'
|
|
28
|
+
},
|
|
29
|
+
amount: {
|
|
30
|
+
type: 'string',
|
|
31
|
+
description: 'Amount in ETH (e.g., "0.1")'
|
|
32
|
+
},
|
|
33
|
+
tx_hash: {
|
|
34
|
+
type: 'string',
|
|
35
|
+
description: 'Transaction hash to check status'
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
async function handler(args) {
|
|
42
|
+
const { action = 'status', amount, tx_hash } = args;
|
|
43
|
+
|
|
44
|
+
if (!config.isInitialized()) {
|
|
45
|
+
return {
|
|
46
|
+
display: 'Run `vibe init` first to set your identity.'
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const handle = config.getHandle();
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
switch (action) {
|
|
54
|
+
case 'status':
|
|
55
|
+
return await getBridgeStatus(handle, tx_hash);
|
|
56
|
+
|
|
57
|
+
case 'deposit':
|
|
58
|
+
return await initiateDeposit(handle, amount);
|
|
59
|
+
|
|
60
|
+
case 'withdraw':
|
|
61
|
+
return await initiateWithdraw(handle, amount);
|
|
62
|
+
|
|
63
|
+
case 'estimate':
|
|
64
|
+
return await estimateGas(amount);
|
|
65
|
+
|
|
66
|
+
default:
|
|
67
|
+
return {
|
|
68
|
+
display: `Unknown action: ${action}\n\nValid actions: deposit, withdraw, status, estimate`
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return {
|
|
73
|
+
display: `❌ Bridge operation failed: ${error.message}`
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get bridge status
|
|
80
|
+
*/
|
|
81
|
+
async function getBridgeStatus(handle, txHash) {
|
|
82
|
+
const formatted = `
|
|
83
|
+
┌────────────────────────────────────────────────────────────┐
|
|
84
|
+
│ 🌉 VIBE BRIDGE │
|
|
85
|
+
│ Base ←→ VIBE L2 │
|
|
86
|
+
├────────────────────────────────────────────────────────────┤
|
|
87
|
+
│ │
|
|
88
|
+
│ Deposit (Base → VIBE L2) │
|
|
89
|
+
│ ├─ Time: ~1 minute │
|
|
90
|
+
│ ├─ Supported: ETH, USDC │
|
|
91
|
+
│ └─ Use: Mint artifacts, interact with contracts │
|
|
92
|
+
│ │
|
|
93
|
+
│ Withdrawal (VIBE L2 → Base) │
|
|
94
|
+
│ ├─ Standard: ~7 days (challenge period) │
|
|
95
|
+
│ ├─ Fast: ~1 hour (OP Succinct, coming soon) │
|
|
96
|
+
│ └─ Supported: ETH, USDC │
|
|
97
|
+
│ │
|
|
98
|
+
├────────────────────────────────────────────────────────────┤
|
|
99
|
+
│ Commands: │
|
|
100
|
+
│ ├─ vibe bridge deposit 0.1 - Deposit 0.1 ETH │
|
|
101
|
+
│ ├─ vibe bridge withdraw 0.1 - Withdraw 0.1 ETH │
|
|
102
|
+
│ ├─ vibe bridge estimate - Estimate gas costs │
|
|
103
|
+
│ └─ vibe bridge status - This screen │
|
|
104
|
+
│ │
|
|
105
|
+
├────────────────────────────────────────────────────────────┤
|
|
106
|
+
│ Bridge UI: https://bridge.vibe.network │
|
|
107
|
+
│ Explorer: https://explorer.vibe.network │
|
|
108
|
+
└────────────────────────────────────────────────────────────┘
|
|
109
|
+
`.trim();
|
|
110
|
+
|
|
111
|
+
if (txHash) {
|
|
112
|
+
return {
|
|
113
|
+
display: formatted + `\n\n📍 Check your transaction: https://explorer.vibe.network/tx/${txHash}`,
|
|
114
|
+
explorerUrl: `https://explorer.vibe.network/tx/${txHash}`
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
display: formatted,
|
|
120
|
+
bridgeInfo: {
|
|
121
|
+
depositTime: '~1 minute',
|
|
122
|
+
withdrawTime: '~7 days (standard) / ~1 hour (fast)',
|
|
123
|
+
supportedAssets: ['ETH', 'USDC'],
|
|
124
|
+
bridgeUrl: 'https://bridge.vibe.network',
|
|
125
|
+
explorerUrl: 'https://explorer.vibe.network'
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Initiate deposit (Base → VIBE L2)
|
|
132
|
+
*/
|
|
133
|
+
async function initiateDeposit(handle, amount) {
|
|
134
|
+
if (!amount) {
|
|
135
|
+
return {
|
|
136
|
+
display: 'Amount required. Example: vibe bridge deposit 0.1'
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const amountFloat = parseFloat(amount);
|
|
141
|
+
if (isNaN(amountFloat) || amountFloat <= 0) {
|
|
142
|
+
return {
|
|
143
|
+
display: 'Invalid amount. Must be a positive number.'
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
display: `🌉 DEPOSIT ${amount} ETH to VIBE L2
|
|
149
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
150
|
+
|
|
151
|
+
Amount: ${amount} ETH
|
|
152
|
+
From: Base
|
|
153
|
+
To: VIBE L2
|
|
154
|
+
Time: ~1 minute
|
|
155
|
+
|
|
156
|
+
To complete this deposit:
|
|
157
|
+
|
|
158
|
+
Option 1: Bridge UI (Recommended)
|
|
159
|
+
Visit https://bridge.vibe.network
|
|
160
|
+
Connect your wallet
|
|
161
|
+
Select "Deposit" and enter ${amount} ETH
|
|
162
|
+
|
|
163
|
+
Option 2: Direct Contract Call
|
|
164
|
+
Contract: StandardBridge on Base
|
|
165
|
+
Function: depositETH
|
|
166
|
+
Gas Limit: ~100,000
|
|
167
|
+
|
|
168
|
+
Note: After depositing, your ETH will be available on
|
|
169
|
+
VIBE L2 within ~1 minute. You can then mint artifacts
|
|
170
|
+
and earn Shipback!`,
|
|
171
|
+
action: 'deposit_guidance',
|
|
172
|
+
amount,
|
|
173
|
+
bridgeUrl: `https://bridge.vibe.network?amount=${amount}&direction=deposit`
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Initiate withdrawal (VIBE L2 → Base)
|
|
179
|
+
*/
|
|
180
|
+
async function initiateWithdraw(handle, amount) {
|
|
181
|
+
if (!amount) {
|
|
182
|
+
return {
|
|
183
|
+
display: 'Amount required. Example: vibe bridge withdraw 0.1'
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const amountFloat = parseFloat(amount);
|
|
188
|
+
if (isNaN(amountFloat) || amountFloat <= 0) {
|
|
189
|
+
return {
|
|
190
|
+
display: 'Invalid amount. Must be a positive number.'
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
display: `🌉 WITHDRAW ${amount} ETH to Base
|
|
196
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
197
|
+
|
|
198
|
+
Amount: ${amount} ETH
|
|
199
|
+
From: VIBE L2
|
|
200
|
+
To: Base
|
|
201
|
+
Time: ~7 days (standard) or ~1 hour (fast mode)
|
|
202
|
+
|
|
203
|
+
⚠️ IMPORTANT: Withdrawals have a 7-day challenge period.
|
|
204
|
+
This is standard for OP Stack chains (same as Base, Optimism).
|
|
205
|
+
|
|
206
|
+
Fast withdrawals (~1 hour) will be available with OP Succinct.
|
|
207
|
+
|
|
208
|
+
To complete this withdrawal:
|
|
209
|
+
|
|
210
|
+
1. Visit https://bridge.vibe.network
|
|
211
|
+
2. Connect your wallet
|
|
212
|
+
3. Select "Withdraw" and enter ${amount} ETH
|
|
213
|
+
4. Submit the transaction on VIBE L2
|
|
214
|
+
5. Wait for challenge period
|
|
215
|
+
6. Finalize on Base
|
|
216
|
+
|
|
217
|
+
Alternative: Claim your Shipback earnings instead!
|
|
218
|
+
→ vibe shipback balance`,
|
|
219
|
+
action: 'withdraw_guidance',
|
|
220
|
+
amount,
|
|
221
|
+
standardTime: '7 days',
|
|
222
|
+
fastTime: '~1 hour (coming soon)',
|
|
223
|
+
bridgeUrl: `https://bridge.vibe.network?amount=${amount}&direction=withdraw`
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Estimate gas costs
|
|
229
|
+
*/
|
|
230
|
+
async function estimateGas(amount) {
|
|
231
|
+
const depositGas = 100000;
|
|
232
|
+
const withdrawGas = 150000;
|
|
233
|
+
const gasPrice = 0.001; // gwei on L2
|
|
234
|
+
const baseGasPrice = 0.5; // gwei on Base
|
|
235
|
+
|
|
236
|
+
const depositCostEth = (depositGas * baseGasPrice) / 1e9;
|
|
237
|
+
const withdrawCostL2 = (withdrawGas * gasPrice) / 1e9;
|
|
238
|
+
const withdrawCostBase = (depositGas * baseGasPrice) / 1e9;
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
display: `⛽ BRIDGE GAS ESTIMATES
|
|
242
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
243
|
+
|
|
244
|
+
Deposit (Base → VIBE L2):
|
|
245
|
+
Gas: ~${depositGas.toLocaleString()} units
|
|
246
|
+
Cost: ~${depositCostEth.toFixed(6)} ETH
|
|
247
|
+
Note: Paid on Base
|
|
248
|
+
|
|
249
|
+
Withdrawal (VIBE L2 → Base):
|
|
250
|
+
Initiate (on L2): ~${withdrawCostL2.toFixed(8)} ETH
|
|
251
|
+
Finalize (on Base): ~${withdrawCostBase.toFixed(6)} ETH
|
|
252
|
+
Total: ~${(withdrawCostL2 + withdrawCostBase).toFixed(6)} ETH
|
|
253
|
+
|
|
254
|
+
On VIBE L2:
|
|
255
|
+
Gas price: ~${gasPrice} gwei (ultra cheap!)
|
|
256
|
+
Mint cost: ~0.0001 ETH
|
|
257
|
+
|
|
258
|
+
💡 Tip: VIBE L2 has very low gas fees.
|
|
259
|
+
Deposit once, mint many artifacts cheaply!`,
|
|
260
|
+
estimates: {
|
|
261
|
+
deposit: { gas: depositGas, costEth: depositCostEth },
|
|
262
|
+
withdraw: {
|
|
263
|
+
initiateGas: withdrawGas,
|
|
264
|
+
finalizeCostEth: withdrawCostBase,
|
|
265
|
+
totalCostEth: withdrawCostL2 + withdrawCostBase
|
|
266
|
+
},
|
|
267
|
+
l2GasPrice: gasPrice
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
module.exports = { definition, handler };
|