slashvibe-mcp 0.3.21 → 0.3.23
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 +21 -0
- package/README.md +280 -47
- package/auto-update.js +10 -15
- package/config.js +36 -31
- package/crypto.js +1 -6
- package/debug.js +12 -0
- package/discord.js +19 -19
- package/eslint.config.js +54 -0
- package/index.js +217 -207
- package/intelligence/index.js +2 -9
- package/intelligence/infer.js +10 -16
- package/intelligence/patterns.js +23 -18
- package/intelligence/proactive.js +16 -15
- package/intelligence/serendipity.js +57 -20
- package/memory.js +13 -8
- package/migrate-v2.js +72 -0
- package/notification-emitter.js +2 -2
- package/notify.js +39 -14
- package/package.json +28 -29
- package/post-install.js +141 -0
- package/presence.js +2 -2
- package/prompts.js +5 -9
- package/protocol/index.js +123 -87
- package/protocol/telegram-commands.js +36 -37
- package/store/api.js +358 -529
- package/store/local.js +9 -10
- package/store/profiles.js +48 -192
- package/store/reservations.js +2 -9
- package/store/skills.js +69 -71
- package/store/sqlite.js +355 -0
- package/test-skills-bootstrap.js +20 -0
- package/test-v2-integration.js +385 -0
- package/tools/_actions.js +48 -387
- package/tools/_connection-queue.js +45 -56
- package/tools/_discovery-enhanced.js +52 -57
- package/tools/_discovery.js +87 -185
- package/tools/{l2-status.js → _experimental/l2-status.js} +68 -70
- package/tools/{shipback.js → _experimental/shipback.js} +4 -3
- package/tools/_proactive-discovery.js +60 -73
- package/tools/_shared/index.js +41 -64
- package/tools/admin-inbox.js +10 -15
- package/tools/agents.js +1 -1
- package/tools/artifact-create.js +13 -23
- package/tools/artifact-view.js +4 -4
- package/tools/{_deprecated/back.js → back.js} +1 -1
- package/tools/bye.js +3 -5
- package/tools/consent.js +2 -2
- package/tools/context.js +9 -10
- package/tools/crossword.js +3 -2
- package/tools/discover.js +94 -356
- package/tools/dm.js +27 -86
- package/tools/doctor.js +12 -41
- package/tools/drawing.js +34 -20
- package/tools/echo.js +11 -11
- package/tools/feed.js +30 -58
- package/tools/follow.js +64 -187
- package/tools/{_deprecated/forget.js → forget.js} +4 -7
- package/tools/game.js +144 -48
- package/tools/handoff.js +6 -8
- package/tools/help.js +3 -3
- package/tools/idea.js +15 -27
- package/tools/inbox.js +121 -293
- package/tools/init.js +54 -151
- package/tools/invite.js +8 -21
- package/tools/migrate.js +27 -24
- package/tools/multiplayer-game.js +50 -40
- package/tools/{_deprecated/mute.js → mute.js} +4 -3
- package/tools/notifications.js +58 -48
- package/tools/observe.js +12 -15
- package/tools/onboarding.js +8 -11
- package/tools/open.js +13 -144
- package/tools/party-game.js +23 -12
- package/tools/patterns.js +2 -1
- package/tools/ping.js +5 -7
- package/tools/react.js +28 -30
- package/tools/{_deprecated/recall.js → recall.js} +5 -10
- package/tools/release.js +4 -2
- package/tools/{_deprecated/remember.js → remember.js} +4 -6
- package/tools/report.js +2 -2
- package/tools/request.js +6 -26
- package/tools/reserve.js +1 -1
- package/tools/session-fork.js +97 -0
- package/tools/session-save.js +109 -0
- package/tools/settings.js +30 -99
- package/tools/ship.js +74 -56
- package/tools/{_deprecated/skills-exchange.js → skills-exchange.js} +38 -39
- package/tools/social-inbox.js +22 -28
- package/tools/social-post.js +24 -27
- package/tools/solo-game.js +54 -46
- package/tools/start.js +14 -148
- package/tools/status.js +21 -68
- package/tools/submit.js +4 -2
- package/tools/suggest-tags.js +36 -33
- package/tools/summarize.js +19 -16
- package/tools/tag-suggestions.js +72 -73
- package/tools/test.js +1 -1
- package/tools/{_deprecated/tictactoe.js → tictactoe.js} +26 -26
- package/tools/token.js +4 -4
- package/tools/update.js +1 -2
- package/tools/watch.js +132 -112
- package/tools/who.js +20 -40
- package/tools/{_deprecated/wordassociation.js → wordassociation.js} +23 -20
- package/tools/workshop-buddy.js +52 -53
- package/tools/x-mentions.js +0 -1
- package/tools/x-reply.js +0 -1
- package/twitter.js +14 -20
- package/version.json +8 -10
- package/webhook-runner.js +132 -0
- package/auth-store.js +0 -148
- package/bridges/bridge-monitor.js +0 -388
- package/bridges/discord-bot.js +0 -431
- package/bridges/farcaster.js +0 -299
- package/bridges/telegram.js +0 -261
- package/bridges/webhook-health.js +0 -420
- package/bridges/webhook-server.js +0 -437
- package/bridges/whatsapp.js +0 -441
- package/bridges/x-webhook.js +0 -423
- package/games/arcade.js +0 -406
- package/games/chess.js +0 -451
- package/games/colorguess.js +0 -343
- package/games/crossword-words.js +0 -171
- package/games/crossword.js +0 -461
- package/games/drawing.js +0 -347
- package/games/gameroulette.js +0 -300
- package/games/gamerouter.js +0 -336
- package/games/gamestatus.js +0 -337
- package/games/guessnumber.js +0 -209
- package/games/hangman.js +0 -279
- package/games/memory.js +0 -338
- package/games/multiplayer-tictactoe.js +0 -389
- package/games/pixelart.js +0 -399
- package/games/quickduel.js +0 -354
- package/games/riddle.js +0 -371
- package/games/rockpaperscissors.js +0 -291
- package/games/snake.js +0 -406
- package/games/storybuilder.js +0 -343
- package/games/tictactoe.js +0 -345
- package/games/twentyquestions.js +0 -286
- package/games/twotruths.js +0 -207
- package/games/werewolf.js +0 -508
- package/games/wordassociation.js +0 -247
- package/games/wordchain.js +0 -135
- package/intelligence/interests.js +0 -369
- package/setup.js +0 -480
- package/smart-inbox.js +0 -276
- package/tools/_deprecated/auto-suggest-connections.js +0 -304
- package/tools/_deprecated/bootstrap-skills.js +0 -231
- package/tools/_deprecated/bridge-dashboard.js +0 -342
- package/tools/_deprecated/bridge-health.js +0 -400
- package/tools/_deprecated/bridge-live.js +0 -384
- package/tools/_deprecated/bridges.js +0 -383
- package/tools/_deprecated/colorguess.js +0 -281
- package/tools/_deprecated/discover-insights.js +0 -379
- package/tools/_deprecated/discover-momentum.js +0 -256
- package/tools/_deprecated/discovery-analytics.js +0 -345
- package/tools/_deprecated/discovery-auto-suggest.js +0 -275
- package/tools/_deprecated/discovery-bootstrap.js +0 -267
- package/tools/_deprecated/discovery-daily.js +0 -375
- package/tools/_deprecated/discovery-dashboard.js +0 -385
- package/tools/_deprecated/discovery-digest.js +0 -314
- package/tools/_deprecated/discovery-hub.js +0 -357
- package/tools/_deprecated/discovery-insights.js +0 -384
- package/tools/_deprecated/discovery-momentum.js +0 -281
- package/tools/_deprecated/discovery-monitor.js +0 -319
- package/tools/_deprecated/discovery-proactive.js +0 -300
- package/tools/_deprecated/draw.js +0 -317
- package/tools/_deprecated/farcaster.js +0 -307
- package/tools/_deprecated/games-catalog.js +0 -376
- package/tools/_deprecated/games.js +0 -313
- package/tools/_deprecated/guessnumber.js +0 -194
- package/tools/_deprecated/hangman.js +0 -129
- package/tools/_deprecated/multiplayer-tictactoe.js +0 -303
- package/tools/_deprecated/riddle.js +0 -240
- package/tools/_deprecated/run-bootstrap.js +0 -69
- package/tools/_deprecated/skills-analytics.js +0 -349
- package/tools/_deprecated/skills-bootstrap.js +0 -301
- package/tools/_deprecated/skills-dashboard.js +0 -268
- package/tools/_deprecated/skills.js +0 -380
- package/tools/_deprecated/smart-intro.js +0 -353
- package/tools/_deprecated/storybuilder.js +0 -331
- package/tools/_deprecated/telegram-bot.js +0 -183
- package/tools/_deprecated/telegram-setup.js +0 -214
- package/tools/_deprecated/twentyquestions.js +0 -143
- package/tools/_shared.js +0 -234
- package/tools/_work-context.js +0 -338
- package/tools/_work-context.manual-test.js +0 -199
- package/tools/_work-context.test.js +0 -260
- package/tools/activity.js +0 -220
- package/tools/agent-treasury.js +0 -288
- package/tools/analytics.js +0 -191
- package/tools/approve.js +0 -197
- package/tools/arcade.js +0 -173
- package/tools/artifacts-price.js +0 -107
- package/tools/ask-expert.js +0 -160
- package/tools/available.js +0 -120
- package/tools/become-expert.js +0 -150
- package/tools/broadcast.js +0 -325
- package/tools/chat.js +0 -202
- package/tools/collaborative-drawing.js +0 -286
- package/tools/connection-status.js +0 -178
- package/tools/earnings.js +0 -126
- package/tools/friends.js +0 -207
- package/tools/genesis.js +0 -233
- package/tools/gig-browse.js +0 -206
- package/tools/gig-complete.js +0 -144
- package/tools/health.js +0 -87
- package/tools/leaderboard.js +0 -117
- package/tools/lib/git-apply.js +0 -206
- package/tools/lib/git-bundle.js +0 -407
- package/tools/mint.js +0 -377
- package/tools/plan.js +0 -225
- package/tools/profile.js +0 -219
- package/tools/proof-of-work.js +0 -144
- package/tools/pulse.js +0 -218
- package/tools/reply.js +0 -166
- package/tools/reputation.js +0 -175
- package/tools/schedule.js +0 -367
- package/tools/search-messages.js +0 -123
- package/tools/session.js +0 -467
- package/tools/session_price.js +0 -128
- package/tools/smart-check.js +0 -201
- package/tools/social-processor.js +0 -445
- package/tools/streak.js +0 -147
- package/tools/stuck.js +0 -297
- package/tools/subscribe.js +0 -148
- package/tools/subscriptions.js +0 -134
- package/tools/tip.js +0 -193
- package/tools/wallet.js +0 -269
- package/tools/webhook-test.js +0 -388
- package/tools/withdraw.js +0 -145
- package/tools/work-summary.js +0 -96
- package/tools/workshop.js +0 -327
- /package/tools/{l2-bridge.js → _experimental/l2-bridge.js} +0 -0
- /package/tools/{l2.js → _experimental/l2.js} +0 -0
- /package/tools/{_deprecated/away.js → away.js} +0 -0
package/tools/tip.js
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe_tip - Send an instant on-chain USDC tip
|
|
3
|
-
*
|
|
4
|
-
* Real crypto tips with instant settlement on Base Sepolia.
|
|
5
|
-
* No fees - creator gets 100% of the tip.
|
|
6
|
-
* Gas is sponsored by /vibe.
|
|
7
|
-
*
|
|
8
|
-
* Examples:
|
|
9
|
-
* - "tip @alice $5 for helping debug"
|
|
10
|
-
* - "send @bob $1 thanks for the intro"
|
|
11
|
-
* - "vibe tip @charlie 10"
|
|
12
|
-
*
|
|
13
|
-
* Preset amounts: $1 (default), $5, $10
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
const config = require('../config');
|
|
17
|
-
const { requireInit, normalizeHandle, displayHandle } = require('./_shared');
|
|
18
|
-
const { actions, formatActions } = require('./_actions');
|
|
19
|
-
|
|
20
|
-
// Preset tip amounts in cents
|
|
21
|
-
const TIP_PRESETS = {
|
|
22
|
-
1: 100, // $1
|
|
23
|
-
5: 500, // $5
|
|
24
|
-
10: 1000 // $10
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const definition = {
|
|
28
|
-
name: 'vibe_tip',
|
|
29
|
-
description: 'Send an instant on-chain USDC tip. 0% fee - creator gets 100%. Gas is sponsored. Amounts: $1 (default), $5, $10.',
|
|
30
|
-
inputSchema: {
|
|
31
|
-
type: 'object',
|
|
32
|
-
properties: {
|
|
33
|
-
to: {
|
|
34
|
-
type: 'string',
|
|
35
|
-
description: 'Recipient handle (e.g., @alice)'
|
|
36
|
-
},
|
|
37
|
-
amount: {
|
|
38
|
-
type: 'number',
|
|
39
|
-
description: 'Amount in USD (1, 5, or 10). Default: 1'
|
|
40
|
-
},
|
|
41
|
-
message: {
|
|
42
|
-
type: 'string',
|
|
43
|
-
description: 'Optional message to include with the tip'
|
|
44
|
-
},
|
|
45
|
-
context: {
|
|
46
|
-
type: 'object',
|
|
47
|
-
description: 'Optional context (type: dm_reply|ship|profile|gig_bonus, reference_id)',
|
|
48
|
-
properties: {
|
|
49
|
-
type: {
|
|
50
|
-
type: 'string',
|
|
51
|
-
enum: ['dm_reply', 'ship', 'profile', 'gig_bonus']
|
|
52
|
-
},
|
|
53
|
-
reference_id: {
|
|
54
|
-
type: 'string'
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
required: ['to']
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
async function handler(args) {
|
|
64
|
-
const initCheck = requireInit();
|
|
65
|
-
if (initCheck) return initCheck;
|
|
66
|
-
|
|
67
|
-
const { to, message, context } = args;
|
|
68
|
-
let { amount = 1 } = args;
|
|
69
|
-
|
|
70
|
-
const myHandle = config.getHandle();
|
|
71
|
-
const token = config.getToken();
|
|
72
|
-
|
|
73
|
-
if (!token) {
|
|
74
|
-
return {
|
|
75
|
-
display: '❌ **Not authenticated**\n\nRun `vibe init` to authenticate with GitHub first.'
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Normalize recipient handle
|
|
80
|
-
const recipient = normalizeHandle(to);
|
|
81
|
-
if (!recipient) {
|
|
82
|
-
return {
|
|
83
|
-
display: '❌ **Missing recipient**\n\nPlease specify who to tip (e.g., `tip @alice 5`).'
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Validate and normalize amount to preset
|
|
88
|
-
amount = parseFloat(amount);
|
|
89
|
-
if (isNaN(amount) || amount <= 0) {
|
|
90
|
-
amount = 1;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Round to nearest preset
|
|
94
|
-
let amountCents;
|
|
95
|
-
if (amount >= 7.5) {
|
|
96
|
-
amountCents = TIP_PRESETS[10];
|
|
97
|
-
amount = 10;
|
|
98
|
-
} else if (amount >= 3) {
|
|
99
|
-
amountCents = TIP_PRESETS[5];
|
|
100
|
-
amount = 5;
|
|
101
|
-
} else {
|
|
102
|
-
amountCents = TIP_PRESETS[1];
|
|
103
|
-
amount = 1;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Call instant tip API
|
|
107
|
-
const apiUrl = config.getApiUrl();
|
|
108
|
-
|
|
109
|
-
// Generate idempotency key to prevent duplicate tips from retries
|
|
110
|
-
// Key is based on: sender + recipient + amount + timestamp (1-minute bucket)
|
|
111
|
-
const timeBucket = Math.floor(Date.now() / 60000); // 1-minute buckets
|
|
112
|
-
const idempotencyKey = `${myHandle}:${recipient}:${amountCents}:${timeBucket}`;
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
const response = await fetch(`${apiUrl}/api/tips/instant`, {
|
|
116
|
-
method: 'POST',
|
|
117
|
-
headers: {
|
|
118
|
-
'Content-Type': 'application/json',
|
|
119
|
-
'Authorization': `Bearer ${token}`,
|
|
120
|
-
'Idempotency-Key': idempotencyKey
|
|
121
|
-
},
|
|
122
|
-
body: JSON.stringify({
|
|
123
|
-
to: recipient,
|
|
124
|
-
amount_cents: amountCents,
|
|
125
|
-
message,
|
|
126
|
-
context
|
|
127
|
-
})
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const result = await response.json();
|
|
131
|
-
|
|
132
|
-
if (!response.ok) {
|
|
133
|
-
// Handle specific error cases
|
|
134
|
-
if (result.error === 'insufficient_balance') {
|
|
135
|
-
return {
|
|
136
|
-
display: `❌ **Insufficient USDC balance**\n\nYou need USDC to tip. Your balance: $${result.balance_usdc}\n\n` +
|
|
137
|
-
`Get USDC at [bridge.base.org](${result.help_url})`
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (result.error === 'recipient_no_wallet') {
|
|
142
|
-
return {
|
|
143
|
-
display: `❌ **${displayHandle(recipient)} can't receive tips yet**\n\n` +
|
|
144
|
-
`They need to complete their wallet setup first.`
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (result.error === 'rate_limited') {
|
|
149
|
-
return {
|
|
150
|
-
display: `⏳ **Rate limit reached**\n\n${result.message}\n\nTry again in ${Math.ceil(result.reset_in_seconds / 60)} minutes.`
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return {
|
|
155
|
-
display: `❌ **Tip failed**\n\n${result.message || 'Please try again.'}`
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Success!
|
|
160
|
-
let display = `✅ **Tipped ${displayHandle(recipient)} $${amount} USDC**\n\n`;
|
|
161
|
-
|
|
162
|
-
display += `💰 Amount: $${amount}.00\n`;
|
|
163
|
-
display += `📤 To: ${displayHandle(recipient)}\n`;
|
|
164
|
-
display += `📥 Fee: $0.00 (0%)\n`;
|
|
165
|
-
display += `✨ Net to creator: $${amount}.00\n`;
|
|
166
|
-
|
|
167
|
-
if (message) {
|
|
168
|
-
display += `\n💬 _"${message}"_\n`;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
display += `\n🔗 [View on Explorer](${result.explorer_url})`;
|
|
172
|
-
|
|
173
|
-
// Build response with actions
|
|
174
|
-
const response_obj = {
|
|
175
|
-
display,
|
|
176
|
-
tx_hash: result.tx_hash,
|
|
177
|
-
explorer_url: result.explorer_url
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
// Add follow-up actions
|
|
181
|
-
response_obj.actions = formatActions(actions.afterTip ? actions.afterTip(recipient) : actions.afterDm(recipient));
|
|
182
|
-
|
|
183
|
-
return response_obj;
|
|
184
|
-
|
|
185
|
-
} catch (error) {
|
|
186
|
-
console.error('[tip] Error:', error);
|
|
187
|
-
return {
|
|
188
|
-
display: `❌ **Tip failed**\n\nError: ${error.message}\n\nPlease try again.`
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
module.exports = { definition, handler };
|
package/tools/wallet.js
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe_wallet - Unified wallet dashboard
|
|
3
|
-
*
|
|
4
|
-
* The "smoothbrain" view - everything in one place:
|
|
5
|
-
* - USD earnings (fiat)
|
|
6
|
-
* - $VIBE tokens (engagement currency)
|
|
7
|
-
* - Vesting schedule
|
|
8
|
-
* - Quick actions
|
|
9
|
-
*
|
|
10
|
-
* Examples:
|
|
11
|
-
* - "vibe wallet"
|
|
12
|
-
* - "check my balance"
|
|
13
|
-
* - "show my $VIBE"
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
const fetch = require('node-fetch');
|
|
17
|
-
|
|
18
|
-
module.exports = {
|
|
19
|
-
name: 'vibe_wallet',
|
|
20
|
-
description: 'Check your wallet: USD earnings, $VIBE tokens, vesting schedule, and available actions.',
|
|
21
|
-
|
|
22
|
-
inputSchema: {
|
|
23
|
-
type: 'object',
|
|
24
|
-
properties: {
|
|
25
|
-
view: {
|
|
26
|
-
type: 'string',
|
|
27
|
-
description: 'Which view: dashboard (default), vesting, history',
|
|
28
|
-
enum: ['dashboard', 'vesting', 'history'],
|
|
29
|
-
default: 'dashboard'
|
|
30
|
-
},
|
|
31
|
-
limit: {
|
|
32
|
-
type: 'number',
|
|
33
|
-
description: 'Number of transactions/items to show (for history view)',
|
|
34
|
-
default: 10
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
async execute({ view = 'dashboard', limit = 10 }, context) {
|
|
40
|
-
try {
|
|
41
|
-
const handle = context.handle;
|
|
42
|
-
|
|
43
|
-
if (!handle) {
|
|
44
|
-
return {
|
|
45
|
-
success: false,
|
|
46
|
-
error: 'Not authenticated. Use vibe init first.'
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const apiUrl = process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
|
|
51
|
-
|
|
52
|
-
// Handle different views
|
|
53
|
-
if (view === 'vesting') {
|
|
54
|
-
return await fetchVestingSchedule(apiUrl, handle, context.token);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (view === 'history') {
|
|
58
|
-
return await fetchHistory(apiUrl, handle, limit, context.token);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Default: dashboard view
|
|
62
|
-
return await fetchDashboard(apiUrl, handle, context.token);
|
|
63
|
-
|
|
64
|
-
} catch (error) {
|
|
65
|
-
return {
|
|
66
|
-
success: false,
|
|
67
|
-
error: 'Failed to fetch wallet',
|
|
68
|
-
details: error.message
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Fetch unified dashboard
|
|
76
|
-
*/
|
|
77
|
-
async function fetchDashboard(apiUrl, handle, token) {
|
|
78
|
-
const response = await fetch(
|
|
79
|
-
`${apiUrl}/api/wallet/dashboard?handle=${handle}`,
|
|
80
|
-
{ headers: { 'Authorization': `Bearer ${token}` } }
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
const result = await response.json();
|
|
84
|
-
|
|
85
|
-
if (!response.ok) {
|
|
86
|
-
return {
|
|
87
|
-
success: false,
|
|
88
|
-
error: 'Failed to fetch wallet dashboard',
|
|
89
|
-
details: result.error
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Build formatted output
|
|
94
|
-
const usd = result.usd;
|
|
95
|
-
const vibe = result.vibe;
|
|
96
|
-
const summary = result.summary;
|
|
97
|
-
const actions = result.actions || [];
|
|
98
|
-
|
|
99
|
-
// USD section
|
|
100
|
-
const usdSection = usd.available.cents > 0
|
|
101
|
-
? `💵 USD Earnings
|
|
102
|
-
Available: ${usd.available.display}
|
|
103
|
-
${usd.held.cents > 0 ? `Held: ${usd.held.display}\n ` : ''}Total earned: ${usd.total_earned.display}
|
|
104
|
-
${usd.can_withdraw ? '✅ Ready to withdraw' : usd.payout_enabled ? '⏳ No balance to withdraw' : '⚠️ Connect bank to withdraw'}`
|
|
105
|
-
: `💵 USD Earnings
|
|
106
|
-
No earnings yet. Complete gigs to earn!`;
|
|
107
|
-
|
|
108
|
-
// $VIBE section
|
|
109
|
-
const vibeSection = `
|
|
110
|
-
💜 $VIBE Tokens
|
|
111
|
-
Spendable: ${vibe.liquid} $VIBE
|
|
112
|
-
Vesting: ${vibe.vesting} $VIBE
|
|
113
|
-
─────────────────
|
|
114
|
-
Total: ${vibe.total} $VIBE
|
|
115
|
-
|
|
116
|
-
${vibe.upcoming.this_week > 0 ? `📅 +${vibe.upcoming.this_week} unlocks this week` : ''}
|
|
117
|
-
${vibe.upcoming.this_month > 0 && vibe.upcoming.this_month !== vibe.upcoming.this_week ? `📅 +${vibe.upcoming.this_month} unlocks this month` : ''}
|
|
118
|
-
${vibe.next_unlock ? `⏰ Next: ${vibe.next_unlock.amount} $VIBE in ${vibe.next_unlock.days} days` : ''}
|
|
119
|
-
|
|
120
|
-
Daily: ${vibe.daily.earned}/${vibe.daily.cap} earned today
|
|
121
|
-
${'█'.repeat(Math.floor(vibe.daily.percent / 10))}${'░'.repeat(10 - Math.floor(vibe.daily.percent / 10))} ${vibe.daily.percent}%`;
|
|
122
|
-
|
|
123
|
-
// Actions section
|
|
124
|
-
const actionsSection = actions.length > 0
|
|
125
|
-
? `\n🎯 Actions\n${actions.slice(0, 3).map(a => ` • ${a.label}: ${a.description}`).join('\n')}`
|
|
126
|
-
: '';
|
|
127
|
-
|
|
128
|
-
const formatted = `
|
|
129
|
-
╭───────────────────────────────────╮
|
|
130
|
-
│ 💰 WALLET: @${handle.padEnd(17)}│
|
|
131
|
-
╰───────────────────────────────────╯
|
|
132
|
-
|
|
133
|
-
${usdSection}
|
|
134
|
-
|
|
135
|
-
${vibeSection.trim()}
|
|
136
|
-
${actionsSection}
|
|
137
|
-
|
|
138
|
-
Tip: Use "vibe wallet --view vesting" for full schedule
|
|
139
|
-
`.trim();
|
|
140
|
-
|
|
141
|
-
return {
|
|
142
|
-
success: true,
|
|
143
|
-
handle,
|
|
144
|
-
usd: result.usd,
|
|
145
|
-
vibe: result.vibe,
|
|
146
|
-
actions: result.actions,
|
|
147
|
-
formatted
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Fetch vesting schedule
|
|
153
|
-
*/
|
|
154
|
-
async function fetchVestingSchedule(apiUrl, handle, token) {
|
|
155
|
-
const response = await fetch(
|
|
156
|
-
`${apiUrl}/api/vibe/vesting?handle=${handle}`,
|
|
157
|
-
{ headers: { 'Authorization': `Bearer ${token}` } }
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
const result = await response.json();
|
|
161
|
-
|
|
162
|
-
if (!response.ok) {
|
|
163
|
-
return {
|
|
164
|
-
success: false,
|
|
165
|
-
error: 'Failed to fetch vesting schedule',
|
|
166
|
-
details: result.error
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Format vesting schedule
|
|
171
|
-
const summary = result.summary;
|
|
172
|
-
const unlocks = result.unlock_schedule || [];
|
|
173
|
-
const breakdown = result.activity_breakdown || [];
|
|
174
|
-
|
|
175
|
-
const scheduleLines = unlocks.slice(0, 8).map(week => {
|
|
176
|
-
const bar = '█'.repeat(Math.min(10, Math.ceil(week.total_amount / 10)));
|
|
177
|
-
return ` ${week.week_label.padEnd(12)} +${week.total_amount} $VIBE ${bar}`;
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
const breakdownLines = breakdown.slice(0, 5).map(act => {
|
|
181
|
-
return ` ${act.reason_display.padEnd(24)} ${act.amount} $VIBE`;
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
const formatted = `
|
|
185
|
-
╭───────────────────────────────────╮
|
|
186
|
-
│ 📅 VESTING SCHEDULE: @${handle.padEnd(10)}│
|
|
187
|
-
╰───────────────────────────────────╯
|
|
188
|
-
|
|
189
|
-
Summary
|
|
190
|
-
Liquid (spendable): ${summary.liquid} $VIBE
|
|
191
|
-
Vesting (locked): ${summary.vesting} $VIBE
|
|
192
|
-
─────────────────────────────
|
|
193
|
-
Total: ${summary.total} $VIBE
|
|
194
|
-
|
|
195
|
-
${result.next_unlock ? `Next Unlock
|
|
196
|
-
${result.next_unlock.amount} $VIBE in ${result.next_unlock.days_remaining} days
|
|
197
|
-
(earned from: ${result.next_unlock.reason})
|
|
198
|
-
` : ''}
|
|
199
|
-
Upcoming Unlocks by Week
|
|
200
|
-
${scheduleLines.length > 0 ? scheduleLines.join('\n') : ' No tokens vesting'}
|
|
201
|
-
|
|
202
|
-
Earned By Activity
|
|
203
|
-
${breakdownLines.length > 0 ? breakdownLines.join('\n') : ' No activity yet'}
|
|
204
|
-
|
|
205
|
-
ℹ️ Tokens vest over ${result.vesting_period_days} days to reward long-term builders.
|
|
206
|
-
`.trim();
|
|
207
|
-
|
|
208
|
-
return {
|
|
209
|
-
success: true,
|
|
210
|
-
handle,
|
|
211
|
-
summary: result.summary,
|
|
212
|
-
schedule: result.unlock_schedule,
|
|
213
|
-
breakdown: result.activity_breakdown,
|
|
214
|
-
formatted
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Fetch transaction history
|
|
220
|
-
*/
|
|
221
|
-
async function fetchHistory(apiUrl, handle, limit, token) {
|
|
222
|
-
const response = await fetch(
|
|
223
|
-
`${apiUrl}/api/vibe/history?handle=${handle}&limit=${limit}`,
|
|
224
|
-
{ headers: { 'Authorization': `Bearer ${token}` } }
|
|
225
|
-
);
|
|
226
|
-
|
|
227
|
-
const result = await response.json();
|
|
228
|
-
|
|
229
|
-
if (!response.ok) {
|
|
230
|
-
return {
|
|
231
|
-
success: false,
|
|
232
|
-
error: 'Failed to fetch history',
|
|
233
|
-
details: result.error
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const transactions = result.transactions || [];
|
|
238
|
-
|
|
239
|
-
const txLines = transactions.map(tx => {
|
|
240
|
-
const icon = tx.amount > 0 ? '↓' : '↑';
|
|
241
|
-
const sign = tx.amount > 0 ? '+' : '';
|
|
242
|
-
const status = tx.status === 'vesting' ? '🔒' : '✓';
|
|
243
|
-
const date = new Date(tx.created_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
|
|
244
|
-
return ` ${icon} ${sign}${tx.amount} $VIBE ${tx.reason.padEnd(20)} ${status} ${date}`;
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
const formatted = `
|
|
248
|
-
╭───────────────────────────────────╮
|
|
249
|
-
│ 📜 HISTORY: @${handle.padEnd(17)}│
|
|
250
|
-
╰───────────────────────────────────╯
|
|
251
|
-
|
|
252
|
-
Balance: ${result.balance.liquid} liquid / ${result.balance.vesting} vesting
|
|
253
|
-
|
|
254
|
-
Recent Transactions
|
|
255
|
-
${txLines.length > 0 ? txLines.join('\n') : ' No transactions yet'}
|
|
256
|
-
|
|
257
|
-
${result.pagination.has_more ? `\n(showing ${limit} of more...)` : ''}
|
|
258
|
-
|
|
259
|
-
Legend: ↓ earned ↑ spent 🔒 vesting ✓ liquid
|
|
260
|
-
`.trim();
|
|
261
|
-
|
|
262
|
-
return {
|
|
263
|
-
success: true,
|
|
264
|
-
handle,
|
|
265
|
-
balance: result.balance,
|
|
266
|
-
transactions: result.transactions,
|
|
267
|
-
formatted
|
|
268
|
-
};
|
|
269
|
-
}
|