1
- import { composeContext } from "@ai16z/eliza/src/context" ;
2
- import { generateObject } from "@ai16z/eliza/src/generation" ;
1
+ import {
2
+ composeContext ,
3
+ generateImage ,
4
+ generateText ,
5
+ generateObject ,
6
+ } from "@ai16z/eliza" ;
3
7
import {
4
8
ActionExample ,
5
9
HandlerCallback ,
@@ -8,56 +12,31 @@ import {
8
12
ModelClass ,
9
13
State ,
10
14
type Action ,
11
- } from "@ai16z/eliza/src/types " ;
15
+ } from "@ai16z/eliza" ;
12
16
import { idlFactory } from "../canisters/pick-pump/index.did" ;
13
17
import { _SERVICE } from "../canisters/pick-pump/index.did.d" ;
14
18
import { ActorCreator , CreateMemeTokenArg } from "../types" ;
15
19
import { unwrapOption , wrapOption } from "../utils/common/types/options" ;
16
20
import { unwrapRustResultMap } from "../utils/common/types/results" ;
17
21
import { icpWalletProvider } from "../providers/wallet" ;
18
-
19
- const createTokenTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined.
20
-
21
- Based on the user's description, generate appropriate values for a new token:
22
- - Create a suitable token name
23
- - Generate a 3-4 letter symbol based on the name
24
- - Write a clear description
25
- - Use "https://icptoken.default.logo" as default logo URL
26
- - Set other fields to null
27
-
28
- Example response:
29
- \`\`\`json
30
- {
31
- "name": "My ICP Token",
32
- "symbol": "MIT",
33
- "description": "A fun meme token on ICP",
34
- "logo": "https://icptoken.default.logo",
35
- "website": null,
36
- "twitter": null,
37
- "telegram": null
38
- }
39
- \`\`\`
40
-
41
- {{recentMessages}}
42
-
43
- Generate appropriate token information based on the user's description.
44
- Respond with a JSON markdown block containing only the generated values.` ;
22
+ import { uploadFileToWeb3Storage } from "../apis/uploadFile" ;
23
+ import { createTokenTemplate , logoPromptTemplate } from './prompts/token' ;
24
+ import { CANISTER_IDS } from '../constants/canisters' ;
45
25
46
26
async function createTokenTransaction (
47
27
creator : ActorCreator ,
48
28
tokenInfo : CreateMemeTokenArg
49
- ) : Promise < any > {
29
+ ) {
50
30
const actor : _SERVICE = await creator (
51
31
idlFactory ,
52
- "bn4fo-iyaaa-aaaap-akp6a-cai"
32
+ CANISTER_IDS . PICK_PUMP
53
33
) ;
54
-
55
34
const result = await actor . create_token ( {
56
35
...tokenInfo ,
57
- name : tokenInfo . name ?? "My ICP Token" ,
58
- symbol : tokenInfo . symbol ?? "MIT" ,
59
- description : tokenInfo . description ?? "A fun meme token on ICP" ,
60
- logo : "https://icptoken.default. logo" ,
36
+ name : tokenInfo . name ,
37
+ symbol : tokenInfo . symbol ,
38
+ description : tokenInfo . description ,
39
+ logo : tokenInfo . logo ,
61
40
twitter : wrapOption ( tokenInfo . twitter ) ,
62
41
website : wrapOption ( tokenInfo . website ) ,
63
42
telegram : wrapOption ( tokenInfo . telegram ) ,
@@ -67,6 +46,12 @@ async function createTokenTransaction(
67
46
result ,
68
47
( ok ) => ( {
69
48
...ok ,
49
+ id : ok . id . toString ( ) ,
50
+ created_at : ok . created_at . toString ( ) ,
51
+ available_token : ok . available_token . toString ( ) ,
52
+ volume_24h : ok . volume_24h . toString ( ) ,
53
+ last_tx_time : ok . last_tx_time . toString ( ) ,
54
+ market_cap_icp : ok . market_cap_icp . toString ( ) ,
70
55
twitter : unwrapOption ( ok . twitter ) ,
71
56
website : unwrapOption ( ok . website ) ,
72
57
telegram : unwrapOption ( ok . telegram ) ,
@@ -77,21 +62,82 @@ async function createTokenTransaction(
77
62
) ;
78
63
}
79
64
65
+ async function generateTokenLogo (
66
+ description : string ,
67
+ runtime : IAgentRuntime
68
+ ) : Promise < string | null > {
69
+ const logoPrompt = `Create a fun and memorable logo for a cryptocurrency token with these characteristics: ${ description } . The logo should be simple, iconic, and suitable for a meme token. Style: minimal, bold colors, crypto-themed.` ;
70
+
71
+ const result = await generateImage (
72
+ {
73
+ prompt : logoPrompt ,
74
+ width : 512 ,
75
+ height : 512 ,
76
+ count : 1 ,
77
+ } ,
78
+ runtime as any
79
+ ) ;
80
+
81
+ if ( result . success && result . data && result . data . length > 0 ) {
82
+ return result . data [ 0 ] ;
83
+ }
84
+
85
+ return null ;
86
+ }
87
+
80
88
export const executeCreateToken : Action = {
81
89
name : "CREATE_TOKEN" ,
82
- similes : [ "CREATE_COIN" , "MINT_TOKEN" , "DEPLOY_TOKEN" , "CREATE_ICP_TOKEN" ] ,
90
+ similes : [
91
+ "CREATE_PICKPUMP_TOKEN" ,
92
+ "MINT_PICKPUMP" ,
93
+ "PICKPUMP_TOKEN" ,
94
+ "PP_TOKEN" ,
95
+ "PICKPUMP发币" ,
96
+ "PP发币" ,
97
+ "在PICKPUMP上发币" ,
98
+ "PICKPUMP代币" ,
99
+ ] ,
100
+ description :
101
+ "Create a new meme token on PickPump platform (Internet Computer). This action helps users create and launch tokens specifically on the PickPump platform." ,
83
102
validate : async ( runtime : IAgentRuntime , message : Memory ) => {
84
- console . log ( "Message:" , message ) ;
85
- return true ;
103
+ const keywords = [
104
+ "pickpump" ,
105
+ "pp" ,
106
+ "皮克帮" ,
107
+ "token" ,
108
+ "coin" ,
109
+ "代币" ,
110
+ "币" ,
111
+ "create" ,
112
+ "mint" ,
113
+ "launch" ,
114
+ "deploy" ,
115
+ "创建" ,
116
+ "发行" ,
117
+ "铸造" ,
118
+ ] ;
119
+
120
+ const messageText = (
121
+ typeof message . content === "string"
122
+ ? message . content
123
+ : message . content . text || ""
124
+ ) . toLowerCase ( ) ;
125
+
126
+ return keywords . some ( ( keyword ) => messageText . includes ( keyword . toLowerCase ( ) ) ) ;
86
127
} ,
87
- description : "Create a new token on Internet Computer." ,
88
128
handler : async (
89
129
runtime : IAgentRuntime ,
90
130
message : Memory ,
91
- state : State ,
92
- _options : { [ key : string ] : unknown } ,
131
+ state : State | undefined ,
132
+ _options : { [ key : string ] : unknown } | undefined ,
93
133
callback ?: HandlerCallback
94
- ) : Promise < boolean > => {
134
+ ) : Promise < void > => {
135
+ callback ?.( {
136
+ text : "🔄 Creating meme token..." ,
137
+ action : "CREATE_TOKEN" ,
138
+ type : "processing" ,
139
+ } ) ;
140
+
95
141
if ( ! state ) {
96
142
state = ( await runtime . composeState ( message ) ) as State ;
97
143
} else {
@@ -109,20 +155,28 @@ export const executeCreateToken: Action = {
109
155
modelClass : ModelClass . LARGE ,
110
156
} ) ;
111
157
112
- console . log ( "Response:" , response ) ;
158
+ const logoPromptContext = composeContext ( {
159
+ state,
160
+ template : logoPromptTemplate . replace (
161
+ "{{description}}" ,
162
+ response . description
163
+ ) ,
164
+ } ) ;
113
165
114
- // Validate required fields
115
- if (
116
- ! response . name ||
117
- ! response . symbol ||
118
- ! response . description ||
119
- ! response . logo
120
- ) {
121
- const responseMsg = {
122
- text : "I need the token name, symbol, description, and logo URL to create a token" ,
123
- } ;
124
- callback ?.( responseMsg ) ;
125
- return true ;
166
+ const logoPrompt = await generateText ( {
167
+ runtime,
168
+ context : logoPromptContext ,
169
+ modelClass : ModelClass . SMALL ,
170
+ } ) ;
171
+
172
+ const logo = await generateTokenLogo ( logoPrompt , runtime ) ;
173
+ if ( ! logo ) {
174
+ throw new Error ( "Failed to generate token logo" ) ;
175
+ }
176
+
177
+ const logoUploadResult = await uploadFileToWeb3Storage ( logo ) ;
178
+ if ( ! logoUploadResult . urls ?. gateway ) {
179
+ throw new Error ( "Failed to upload logo to Web3Storage" ) ;
126
180
}
127
181
128
182
try {
@@ -131,50 +185,61 @@ export const executeCreateToken: Action = {
131
185
message ,
132
186
state
133
187
) ;
188
+
134
189
const creator = wallet . createActor ;
135
190
const createTokenResult = await createTokenTransaction ( creator , {
136
191
name : response . name ,
137
192
symbol : response . symbol ,
138
193
description : response . description ,
139
- website : response . website ,
140
- twitter : response . twitter ,
141
- telegram : response . telegram ,
194
+ logo : logoUploadResult . urls . gateway ,
142
195
} ) ;
143
196
144
- console . log ( "Token created successfully:" , createTokenResult ) ;
145
197
const responseMsg = {
146
- text : `Token ${ response . name } (${ response . symbol } ) created successfully on ICP! ` ,
198
+ text : `✨ Created new meme token:\n🪙 ${ response . name } (${ response . symbol } )\n📝 ${ response . description } ` ,
147
199
data : createTokenResult ,
200
+ action : "CREATE_TOKEN" ,
201
+ type : "success" ,
148
202
} ;
149
-
150
203
callback ?.( responseMsg ) ;
151
- return true ;
152
- } catch ( error ) {
153
- console . error ( "Error creating token:" , error ) ;
204
+ } catch ( error : any ) {
154
205
const responseMsg = {
155
206
text : `Failed to create token: ${ error . message } ` ,
207
+ action : "CREATE_TOKEN" ,
208
+ type : "error" ,
156
209
} ;
157
210
callback ?.( responseMsg ) ;
158
- return false ;
159
211
}
160
212
} ,
161
213
examples : [
162
214
[
163
215
{
164
216
user : "{{user1}}" ,
165
- content : "I want to create a token for dog lovers " ,
217
+ content : "I want to create a space cat token on PickPump " ,
166
218
} ,
167
219
{
168
220
user : "{{user2}}" ,
169
221
content : {
170
- text : "Creating new ICP token WOOF ..." ,
222
+ text : "Creating space cat token on PickPump ..." ,
171
223
action : "CREATE_TOKEN" ,
172
224
} ,
173
225
} ,
174
226
{
175
227
user : "{{user2}}" ,
176
228
content : {
177
- text : "Token created successfully on Internet Computer!" ,
229
+ text : "✨ Token created successfully!" ,
230
+ } ,
231
+ } ,
232
+ ] ,
233
+ [
234
+ {
235
+ user : "{{user1}}" ,
236
+ content : "Help me create a pizza-themed funny token on PP" ,
237
+ } ,
238
+ {
239
+ user : "{{user2}}" ,
240
+ content : {
241
+ text : "Creating pizza token on PickPump..." ,
242
+ action : "CREATE_TOKEN" ,
178
243
} ,
179
244
} ,
180
245
] ,
0 commit comments