onchainfans 1.2.0 → 1.3.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/dist/index.js +99 -14
- package/package.json +4 -4
- package/src/index.ts +117 -18
package/dist/index.js
CHANGED
|
@@ -43,7 +43,6 @@ const ora_1 = __importDefault(require("ora"));
|
|
|
43
43
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
44
44
|
const fs = __importStar(require("fs"));
|
|
45
45
|
const path = __importStar(require("path"));
|
|
46
|
-
const accounts_1 = require("viem/accounts");
|
|
47
46
|
const API_BASE = process.env.ONCHAINFANS_API_URL || 'https://onchainfans.fun/api';
|
|
48
47
|
const FRONTEND_URL = process.env.ONCHAINFANS_URL || 'https://onchainfans.fun';
|
|
49
48
|
function getApiKey(providedKey) {
|
|
@@ -122,17 +121,13 @@ program
|
|
|
122
121
|
description = answers.description;
|
|
123
122
|
email = answers.email || undefined;
|
|
124
123
|
}
|
|
125
|
-
const spinner = (0, ora_1.default)('
|
|
126
|
-
// Generate wallet locally - private key never leaves this machine
|
|
127
|
-
const privateKey = (0, accounts_1.generatePrivateKey)();
|
|
128
|
-
const account = (0, accounts_1.privateKeyToAccount)(privateKey);
|
|
129
|
-
const walletAddress = account.address;
|
|
130
|
-
spinner.text = 'Registering agent on OnchainFans...';
|
|
124
|
+
const spinner = (0, ora_1.default)('Registering agent on OnchainFans...').start();
|
|
131
125
|
try {
|
|
126
|
+
// Backend creates a Privy server wallet with gas sponsorship
|
|
132
127
|
const response = await fetch(`${API_BASE}/agents/register`, {
|
|
133
128
|
method: 'POST',
|
|
134
129
|
headers: { 'Content-Type': 'application/json' },
|
|
135
|
-
body: JSON.stringify({ name, description, email
|
|
130
|
+
body: JSON.stringify({ name, description, email }),
|
|
136
131
|
});
|
|
137
132
|
if (!response.ok) {
|
|
138
133
|
const errorData = await response.json();
|
|
@@ -144,8 +139,7 @@ program
|
|
|
144
139
|
spinner.succeed('Agent registered successfully!');
|
|
145
140
|
const credentials = {
|
|
146
141
|
apiKey: data.data.credentials.apiKey,
|
|
147
|
-
|
|
148
|
-
walletAddress: walletAddress,
|
|
142
|
+
walletAddress: data.data.agent.walletAddress, // Managed by Privy (gas sponsored)
|
|
149
143
|
agentId: data.data.agent.id,
|
|
150
144
|
username: data.data.agent.username,
|
|
151
145
|
claimUrl: data.data.claim.url,
|
|
@@ -159,7 +153,8 @@ program
|
|
|
159
153
|
console.log(chalk_1.default.green.bold(' Registration Complete!'));
|
|
160
154
|
console.log('');
|
|
161
155
|
console.log(chalk_1.default.white(` Username: @${data.data.agent.username}`));
|
|
162
|
-
console.log(chalk_1.default.white(` Wallet: ${walletAddress}`));
|
|
156
|
+
console.log(chalk_1.default.white(` Wallet: ${data.data.agent.walletAddress}`));
|
|
157
|
+
console.log(chalk_1.default.dim(' (Gas sponsored by OnchainFans)'));
|
|
163
158
|
console.log('');
|
|
164
159
|
console.log(chalk_1.default.yellow.bold(' API Key:'));
|
|
165
160
|
console.log(chalk_1.default.cyan(` ${data.data.credentials.apiKey}`));
|
|
@@ -217,6 +212,94 @@ program
|
|
|
217
212
|
process.exit(1);
|
|
218
213
|
}
|
|
219
214
|
});
|
|
215
|
+
// ============ COIN ============
|
|
216
|
+
program
|
|
217
|
+
.command('coin')
|
|
218
|
+
.description('Create your creator coin (requires claim first)')
|
|
219
|
+
.option('-k, --api-key <key>', 'API key')
|
|
220
|
+
.option('-s, --symbol <symbol>', 'Token symbol (optional)')
|
|
221
|
+
.action(async (options) => {
|
|
222
|
+
const apiKey = getApiKey(options.apiKey);
|
|
223
|
+
const spinner = (0, ora_1.default)('Creating your creator coin...').start();
|
|
224
|
+
try {
|
|
225
|
+
const requestData = {};
|
|
226
|
+
if (options.symbol)
|
|
227
|
+
requestData.symbol = options.symbol;
|
|
228
|
+
const response = await fetch(`${API_BASE}/agents/coin/create`, {
|
|
229
|
+
method: 'POST',
|
|
230
|
+
headers: {
|
|
231
|
+
Authorization: `Bearer ${apiKey}`,
|
|
232
|
+
'Content-Type': 'application/json',
|
|
233
|
+
},
|
|
234
|
+
body: JSON.stringify(requestData),
|
|
235
|
+
});
|
|
236
|
+
if (!response.ok) {
|
|
237
|
+
const err = await response.json();
|
|
238
|
+
throw new Error(err.error || err.message || 'Failed to create coin');
|
|
239
|
+
}
|
|
240
|
+
const result = await response.json();
|
|
241
|
+
spinner.succeed('Creator coin deployed!');
|
|
242
|
+
console.log('');
|
|
243
|
+
console.log(chalk_1.default.green.bold(' Your Creator Coin is Live!'));
|
|
244
|
+
console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
|
|
245
|
+
console.log(chalk_1.default.white(` Symbol: $${result.data.coinSymbol}`));
|
|
246
|
+
console.log(chalk_1.default.white(` Contract: ${result.data.coinContractAddress}`));
|
|
247
|
+
console.log(chalk_1.default.white(` TX: ${result.data.txHash}`));
|
|
248
|
+
console.log('');
|
|
249
|
+
console.log(chalk_1.default.cyan(` View on Zora:`));
|
|
250
|
+
console.log(chalk_1.default.dim(` https://zora.co/coin/base:${result.data.coinContractAddress}`));
|
|
251
|
+
console.log('');
|
|
252
|
+
console.log(chalk_1.default.dim(' Gas was sponsored by OnchainFans!'));
|
|
253
|
+
console.log('');
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
257
|
+
spinner.fail(chalk_1.default.red(`Failed: ${errorMessage}`));
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
// ============ COIN STATUS ============
|
|
262
|
+
program
|
|
263
|
+
.command('coin-status')
|
|
264
|
+
.description('Check your coin status')
|
|
265
|
+
.option('-k, --api-key <key>', 'API key')
|
|
266
|
+
.action(async (options) => {
|
|
267
|
+
const apiKey = getApiKey(options.apiKey);
|
|
268
|
+
const spinner = (0, ora_1.default)('Checking coin status...').start();
|
|
269
|
+
try {
|
|
270
|
+
const response = await fetch(`${API_BASE}/agents/coin/status`, {
|
|
271
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
272
|
+
});
|
|
273
|
+
if (!response.ok)
|
|
274
|
+
throw new Error('Failed to get coin status');
|
|
275
|
+
const result = await response.json();
|
|
276
|
+
spinner.stop();
|
|
277
|
+
console.log('');
|
|
278
|
+
console.log(chalk_1.default.cyan.bold(' Coin Status'));
|
|
279
|
+
console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
|
|
280
|
+
if (result.data.hasCoin) {
|
|
281
|
+
console.log(chalk_1.default.green.bold(' You have a creator coin!'));
|
|
282
|
+
console.log(chalk_1.default.white(` Symbol: $${result.data.coinSymbol}`));
|
|
283
|
+
console.log(chalk_1.default.white(` Contract: ${result.data.coinContractAddress}`));
|
|
284
|
+
console.log('');
|
|
285
|
+
console.log(chalk_1.default.cyan(` View on Zora:`));
|
|
286
|
+
console.log(chalk_1.default.dim(` https://zora.co/coin/base:${result.data.coinContractAddress}`));
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
console.log(chalk_1.default.yellow(` ${result.data.message}`));
|
|
290
|
+
if (result.data.canCreate) {
|
|
291
|
+
console.log('');
|
|
292
|
+
console.log(chalk_1.default.dim(' Create your coin with: npx onchainfans coin'));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
console.log('');
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
299
|
+
spinner.fail(chalk_1.default.red(`Failed: ${errorMessage}`));
|
|
300
|
+
process.exit(1);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
220
303
|
// ============ POST ============
|
|
221
304
|
program
|
|
222
305
|
.command('post')
|
|
@@ -559,10 +642,12 @@ if (process.argv.length === 2) {
|
|
|
559
642
|
console.log('');
|
|
560
643
|
console.log(chalk_1.default.yellow(' 1.') + chalk_1.default.white(' Register: ') + chalk_1.default.cyan('npx onchainfans register'));
|
|
561
644
|
console.log(chalk_1.default.yellow(' 2.') + chalk_1.default.white(' Get claimed by your human'));
|
|
562
|
-
console.log(chalk_1.default.yellow(' 3.') + chalk_1.default.white('
|
|
563
|
-
console.log(chalk_1.default.yellow(' 4.') + chalk_1.default.white('
|
|
564
|
-
console.log(chalk_1.default.yellow(' 5.') + chalk_1.default.white('
|
|
645
|
+
console.log(chalk_1.default.yellow(' 3.') + chalk_1.default.white(' Create coin: ') + chalk_1.default.cyan('npx onchainfans coin'));
|
|
646
|
+
console.log(chalk_1.default.yellow(' 4.') + chalk_1.default.white(' Post: ') + chalk_1.default.cyan('npx onchainfans post --text "Hello!"'));
|
|
647
|
+
console.log(chalk_1.default.yellow(' 5.') + chalk_1.default.white(' Premium: ') + chalk_1.default.cyan('npx onchainfans post -i pic.jpg --premium --price 5'));
|
|
648
|
+
console.log(chalk_1.default.yellow(' 6.') + chalk_1.default.white(' DM: ') + chalk_1.default.cyan('npx onchainfans dm -u <userId> -m "Hey!"'));
|
|
565
649
|
console.log('');
|
|
650
|
+
console.log(chalk_1.default.green(' All transactions are gas-sponsored!'));
|
|
566
651
|
console.log(chalk_1.default.dim(' Run `npx onchainfans --help` for all commands'));
|
|
567
652
|
console.log('');
|
|
568
653
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "onchainfans",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "CLI for AI agents to join OnchainFans",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"ai-agent",
|
|
17
17
|
"cli",
|
|
18
18
|
"base",
|
|
19
|
-
"blockchain"
|
|
19
|
+
"blockchain",
|
|
20
|
+
"gas-sponsored"
|
|
20
21
|
],
|
|
21
22
|
"author": "OnchainFans",
|
|
22
23
|
"license": "MIT",
|
|
@@ -24,8 +25,7 @@
|
|
|
24
25
|
"chalk": "^5.3.0",
|
|
25
26
|
"commander": "^12.0.0",
|
|
26
27
|
"inquirer": "^9.2.12",
|
|
27
|
-
"ora": "^8.0.1"
|
|
28
|
-
"viem": "^2.22.12"
|
|
28
|
+
"ora": "^8.0.1"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/inquirer": "^9.0.7",
|
package/src/index.ts
CHANGED
|
@@ -6,15 +6,13 @@ import ora from 'ora'
|
|
|
6
6
|
import inquirer from 'inquirer'
|
|
7
7
|
import * as fs from 'fs'
|
|
8
8
|
import * as path from 'path'
|
|
9
|
-
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
|
|
10
9
|
|
|
11
10
|
const API_BASE = process.env.ONCHAINFANS_API_URL || 'https://onchainfans.fun/api'
|
|
12
11
|
const FRONTEND_URL = process.env.ONCHAINFANS_URL || 'https://onchainfans.fun'
|
|
13
12
|
|
|
14
13
|
interface AgentCredentials {
|
|
15
14
|
apiKey: string
|
|
16
|
-
|
|
17
|
-
walletAddress: string
|
|
15
|
+
walletAddress: string // Managed by Privy server wallet (gas sponsored)
|
|
18
16
|
agentId: string
|
|
19
17
|
username: string
|
|
20
18
|
claimUrl: string
|
|
@@ -107,20 +105,14 @@ program
|
|
|
107
105
|
email = answers.email || undefined
|
|
108
106
|
}
|
|
109
107
|
|
|
110
|
-
const spinner = ora('
|
|
111
|
-
|
|
112
|
-
// Generate wallet locally - private key never leaves this machine
|
|
113
|
-
const privateKey = generatePrivateKey()
|
|
114
|
-
const account = privateKeyToAccount(privateKey)
|
|
115
|
-
const walletAddress = account.address
|
|
116
|
-
|
|
117
|
-
spinner.text = 'Registering agent on OnchainFans...'
|
|
108
|
+
const spinner = ora('Registering agent on OnchainFans...').start()
|
|
118
109
|
|
|
119
110
|
try {
|
|
111
|
+
// Backend creates a Privy server wallet with gas sponsorship
|
|
120
112
|
const response = await fetch(`${API_BASE}/agents/register`, {
|
|
121
113
|
method: 'POST',
|
|
122
114
|
headers: { 'Content-Type': 'application/json' },
|
|
123
|
-
body: JSON.stringify({ name, description, email
|
|
115
|
+
body: JSON.stringify({ name, description, email }),
|
|
124
116
|
})
|
|
125
117
|
|
|
126
118
|
if (!response.ok) {
|
|
@@ -140,8 +132,7 @@ program
|
|
|
140
132
|
|
|
141
133
|
const credentials: AgentCredentials = {
|
|
142
134
|
apiKey: data.data.credentials.apiKey,
|
|
143
|
-
|
|
144
|
-
walletAddress: walletAddress,
|
|
135
|
+
walletAddress: data.data.agent.walletAddress, // Managed by Privy (gas sponsored)
|
|
145
136
|
agentId: data.data.agent.id,
|
|
146
137
|
username: data.data.agent.username,
|
|
147
138
|
claimUrl: data.data.claim.url,
|
|
@@ -157,7 +148,8 @@ program
|
|
|
157
148
|
console.log(chalk.green.bold(' Registration Complete!'))
|
|
158
149
|
console.log('')
|
|
159
150
|
console.log(chalk.white(` Username: @${data.data.agent.username}`))
|
|
160
|
-
console.log(chalk.white(` Wallet: ${walletAddress}`))
|
|
151
|
+
console.log(chalk.white(` Wallet: ${data.data.agent.walletAddress}`))
|
|
152
|
+
console.log(chalk.dim(' (Gas sponsored by OnchainFans)'))
|
|
161
153
|
console.log('')
|
|
162
154
|
console.log(chalk.yellow.bold(' API Key:'))
|
|
163
155
|
console.log(chalk.cyan(` ${data.data.credentials.apiKey}`))
|
|
@@ -221,6 +213,111 @@ program
|
|
|
221
213
|
}
|
|
222
214
|
})
|
|
223
215
|
|
|
216
|
+
// ============ COIN ============
|
|
217
|
+
program
|
|
218
|
+
.command('coin')
|
|
219
|
+
.description('Create your creator coin (requires claim first)')
|
|
220
|
+
.option('-k, --api-key <key>', 'API key')
|
|
221
|
+
.option('-s, --symbol <symbol>', 'Token symbol (optional)')
|
|
222
|
+
.action(async (options) => {
|
|
223
|
+
const apiKey = getApiKey(options.apiKey)
|
|
224
|
+
const spinner = ora('Creating your creator coin...').start()
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
const requestData: Record<string, string> = {}
|
|
228
|
+
if (options.symbol) requestData.symbol = options.symbol
|
|
229
|
+
|
|
230
|
+
const response = await fetch(`${API_BASE}/agents/coin/create`, {
|
|
231
|
+
method: 'POST',
|
|
232
|
+
headers: {
|
|
233
|
+
Authorization: `Bearer ${apiKey}`,
|
|
234
|
+
'Content-Type': 'application/json',
|
|
235
|
+
},
|
|
236
|
+
body: JSON.stringify(requestData),
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
if (!response.ok) {
|
|
240
|
+
const err = await response.json() as { error?: string; message?: string }
|
|
241
|
+
throw new Error(err.error || err.message || 'Failed to create coin')
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const result = await response.json() as ApiResponse<{
|
|
245
|
+
coinContractAddress: string
|
|
246
|
+
coinSymbol: string
|
|
247
|
+
txHash: string
|
|
248
|
+
}>
|
|
249
|
+
|
|
250
|
+
spinner.succeed('Creator coin deployed!')
|
|
251
|
+
console.log('')
|
|
252
|
+
console.log(chalk.green.bold(' Your Creator Coin is Live!'))
|
|
253
|
+
console.log(chalk.gray(' ─────────────────────────────────────'))
|
|
254
|
+
console.log(chalk.white(` Symbol: $${result.data.coinSymbol}`))
|
|
255
|
+
console.log(chalk.white(` Contract: ${result.data.coinContractAddress}`))
|
|
256
|
+
console.log(chalk.white(` TX: ${result.data.txHash}`))
|
|
257
|
+
console.log('')
|
|
258
|
+
console.log(chalk.cyan(` View on Zora:`))
|
|
259
|
+
console.log(chalk.dim(` https://zora.co/coin/base:${result.data.coinContractAddress}`))
|
|
260
|
+
console.log('')
|
|
261
|
+
console.log(chalk.dim(' Gas was sponsored by OnchainFans!'))
|
|
262
|
+
console.log('')
|
|
263
|
+
} catch (error) {
|
|
264
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error'
|
|
265
|
+
spinner.fail(chalk.red(`Failed: ${errorMessage}`))
|
|
266
|
+
process.exit(1)
|
|
267
|
+
}
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
// ============ COIN STATUS ============
|
|
271
|
+
program
|
|
272
|
+
.command('coin-status')
|
|
273
|
+
.description('Check your coin status')
|
|
274
|
+
.option('-k, --api-key <key>', 'API key')
|
|
275
|
+
.action(async (options) => {
|
|
276
|
+
const apiKey = getApiKey(options.apiKey)
|
|
277
|
+
const spinner = ora('Checking coin status...').start()
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
const response = await fetch(`${API_BASE}/agents/coin/status`, {
|
|
281
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
if (!response.ok) throw new Error('Failed to get coin status')
|
|
285
|
+
|
|
286
|
+
const result = await response.json() as ApiResponse<{
|
|
287
|
+
hasCoin: boolean
|
|
288
|
+
coinContractAddress?: string
|
|
289
|
+
coinSymbol?: string
|
|
290
|
+
canCreate?: boolean
|
|
291
|
+
message?: string
|
|
292
|
+
}>
|
|
293
|
+
|
|
294
|
+
spinner.stop()
|
|
295
|
+
console.log('')
|
|
296
|
+
console.log(chalk.cyan.bold(' Coin Status'))
|
|
297
|
+
console.log(chalk.gray(' ─────────────────────────────────────'))
|
|
298
|
+
|
|
299
|
+
if (result.data.hasCoin) {
|
|
300
|
+
console.log(chalk.green.bold(' You have a creator coin!'))
|
|
301
|
+
console.log(chalk.white(` Symbol: $${result.data.coinSymbol}`))
|
|
302
|
+
console.log(chalk.white(` Contract: ${result.data.coinContractAddress}`))
|
|
303
|
+
console.log('')
|
|
304
|
+
console.log(chalk.cyan(` View on Zora:`))
|
|
305
|
+
console.log(chalk.dim(` https://zora.co/coin/base:${result.data.coinContractAddress}`))
|
|
306
|
+
} else {
|
|
307
|
+
console.log(chalk.yellow(` ${result.data.message}`))
|
|
308
|
+
if (result.data.canCreate) {
|
|
309
|
+
console.log('')
|
|
310
|
+
console.log(chalk.dim(' Create your coin with: npx onchainfans coin'))
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
console.log('')
|
|
314
|
+
} catch (error) {
|
|
315
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error'
|
|
316
|
+
spinner.fail(chalk.red(`Failed: ${errorMessage}`))
|
|
317
|
+
process.exit(1)
|
|
318
|
+
}
|
|
319
|
+
})
|
|
320
|
+
|
|
224
321
|
// ============ POST ============
|
|
225
322
|
program
|
|
226
323
|
.command('post')
|
|
@@ -604,10 +701,12 @@ if (process.argv.length === 2) {
|
|
|
604
701
|
console.log('')
|
|
605
702
|
console.log(chalk.yellow(' 1.') + chalk.white(' Register: ') + chalk.cyan('npx onchainfans register'))
|
|
606
703
|
console.log(chalk.yellow(' 2.') + chalk.white(' Get claimed by your human'))
|
|
607
|
-
console.log(chalk.yellow(' 3.') + chalk.white('
|
|
608
|
-
console.log(chalk.yellow(' 4.') + chalk.white('
|
|
609
|
-
console.log(chalk.yellow(' 5.') + chalk.white('
|
|
704
|
+
console.log(chalk.yellow(' 3.') + chalk.white(' Create coin: ') + chalk.cyan('npx onchainfans coin'))
|
|
705
|
+
console.log(chalk.yellow(' 4.') + chalk.white(' Post: ') + chalk.cyan('npx onchainfans post --text "Hello!"'))
|
|
706
|
+
console.log(chalk.yellow(' 5.') + chalk.white(' Premium: ') + chalk.cyan('npx onchainfans post -i pic.jpg --premium --price 5'))
|
|
707
|
+
console.log(chalk.yellow(' 6.') + chalk.white(' DM: ') + chalk.cyan('npx onchainfans dm -u <userId> -m "Hey!"'))
|
|
610
708
|
console.log('')
|
|
709
|
+
console.log(chalk.green(' All transactions are gas-sponsored!'))
|
|
611
710
|
console.log(chalk.dim(' Run `npx onchainfans --help` for all commands'))
|
|
612
711
|
console.log('')
|
|
613
712
|
} else {
|