77 */
88
99import { type FastifyReply , type FastifyRequest } from 'fastify'
10- import { type Static } from '@sinclair/typebox'
11- import { TokenMetadataSchema } from '../schemas/taskSchema.ts'
1210import TaskBoardIPFS from '../ipfs/TaskBoardIPFS.ts'
11+ import { Task } from '../../../objects/BoardTask.ts'
1312import { TaskToken } from '../../../objects/TaskToken.ts'
13+ import dotenv from 'dotenv'
1414
15- type TokenBody = Static < typeof TokenMetadataSchema >
16-
15+ dotenv . config ( )
1716
1817export function createTaskController ( IPFS : TaskBoardIPFS ) {
19- return async ( request : FastifyRequest < { Body : TokenBody } > , reply : FastifyReply ) => {
18+ return async ( request : FastifyRequest , reply : FastifyReply ) => {
2019 try {
21- const token = TaskToken . fromJSON ( request . body )
22- const cid = await IPFS . addTask ( token )
23- return reply . code ( 201 ) . send ( { ...token . toJSON ( ) , createdAt : token . task . createdAt , ipfsCid : cid } )
20+ // Fastify multipart: use await request.parts() for async iterator
21+ if ( ! request . isMultipart ( ) ) {
22+ return reply . code ( 400 ) . send ( { error : "Expected multipart/form-data" } ) ;
23+ }
24+ const parts = request . parts ( ) ;
25+ let fields : any = { } ;
26+ let resourcesBuffer : any [ ] = [ ] ;
27+ let imageBuffer : any = null ;
28+
29+ for await ( const part of parts ) {
30+ if ( part . type === 'file' ) {
31+ if ( part . fieldname === 'image' ) {
32+ imageBuffer = part . toBuffer ( ) ;
33+ } else if ( part . fieldname === 'resources' ) {
34+ resourcesBuffer . push ( part . toBuffer ( ) ) ;
35+ }
36+ } else {
37+ fields [ part . fieldname ] = part . value ;
38+ }
39+ }
40+
41+ if ( ! imageBuffer ) {
42+ return reply . code ( 400 ) . send ( { error : "Required token image" , message : "Missing token image." } ) ;
43+ }
44+
45+ // Parse JSON fields
46+ const data = JSON . parse ( fields . data ) ;
47+
48+ // Upload resources to IPFS
49+ const resourceUris : string [ ] = [ ] ;
50+ for ( const buffer of resourcesBuffer ) {
51+ const cid = await IPFS . uploadBytes ( new Uint8Array ( buffer ) ) ;
52+ resourceUris . push ( `ipfs://${ cid } ` ) ;
53+ }
54+
55+ // Upload image to IPFS
56+ let imageUri : string = "" ;
57+ const imageCid = await IPFS . uploadBytes ( new Uint8Array ( imageBuffer ) ) ;
58+ imageUri = `ipfs://${ imageCid } ` ;
59+
60+
61+ // Build Task and TaskToken
62+ const task = new Task ( {
63+ ...data . task ,
64+ resources : resourceUris ,
65+ } ) ;
66+ const token = new TaskToken ( {
67+ ...data . token ,
68+ image : imageUri ,
69+ task,
70+ } ) ;
71+
72+ // Upload TaskToken to IPFS
73+ const cid = await IPFS . addTask ( token ) ;
74+ console . log ( "Task uploaded: " , cid ) ;
75+ return reply . code ( 201 ) . send ( { cid } ) ;
2476 } catch ( error ) {
25- request . log . error ( error )
26- return reply . code ( 500 ) . send ( {
77+ request . log . error ( error ) ;
78+ return reply . code ( 500 ) . send ( {
2779 error : 'Failed to create task' ,
2880 message : 'Could not create task. Please try again later.'
29- } )
81+ } ) ;
3082 }
3183 }
3284}
@@ -78,4 +130,12 @@ export function deleteTaskController(IPFS: TaskBoardIPFS) {
78130 } )
79131 }
80132 }
133+ }
134+
135+ export function getContractAddressController ( ) {
136+ return async ( request : FastifyRequest , reply : FastifyReply ) => {
137+ const address = process . env . CONTRACT_ADDRESS ;
138+ if ( ! address ) return reply . code ( 500 ) . send ( { error : "Contract address not set" } ) ;
139+ return { address } ;
140+ }
81141}
0 commit comments