diff --git a/index.ts b/index.ts index fdfbc23b32a4fcd55f3fcdffdc54efd31bc65623..663f2d895c70986be9f65314aa9743d33d7d2508 100644 --- a/index.ts +++ b/index.ts @@ -14,9 +14,9 @@ import { getRole } from './src/utils/getRole.js' import { type WalletData } from './src/types/WalletData.js' // IMPORT HANDLERS -import { handleAdminChoice, handleAdherentChoice, handleConnectedChoice } from './src/handlers/handlers.js' +import { handleAdminAssociationChoice, handleAdherentChoice, handleConnectedChoice, handleAdminFATokenChoice } from './src/handlers/roleHandlers.js' -const tezos = new TezosToolkit('https://ghostnet.ecadinfra.com') +const tezos = new TezosToolkit('https://ghostnet.tezos.marigold.dev/') const program = new Command() program.name('my-asso') @@ -42,16 +42,20 @@ program.command('main') while (true) { let choice: string switch (getRole(tezos)) { - case 'ADMIN': - choice = await askQuestion(`${chalk.yellow('Que souhaitez-vous faire ?')} \n\n1: Créer une association\n2: Créer un token\n3: Voir mon portefeuille\n0: Quitter\n`) - await handleAdminChoice(choice, tezos) + case 'ADMIN_FA_TOKEN': + choice = await askQuestion(`${chalk.yellow('Que souhaitez-vous faire ?')} \n\n1: Créer une association\n2: Créer un token\n3: Bruler mes tokens\n4: Voir mon portefeuille\n0: Quitter\n`) + await handleAdminFATokenChoice(choice, tezos) + break + case 'ADMIN_ASSOCIATION': + choice = await askQuestion(`${chalk.yellow('Que souhaitez-vous faire ?')} \n\n1: Créer un token\n2: Bruler mes tokens\n3: Voir mon portefeuille\n0: Quitter\n`) + await handleAdminAssociationChoice(choice, tezos) break case 'ADHERENT': - choice = await askQuestion(`${chalk.yellow('Que souhaitez-vous faire ?')} \n\n1: Faire une proposition\n2: Voir mon portefeuille\n0: Quitter\n`) + choice = await askQuestion(`${chalk.yellow('Que souhaitez-vous faire ?')} \n\n1: Faire une proposition\n2: Créer un token FA\n3: Voir mon portefeuille\n0: Quitter\n`) await handleAdherentChoice(choice, tezos) break case 'CONNECTED': - choice = await askQuestion(`${chalk.yellow('Que souhaitez-vous faire ?')} \n\n1: Rejoindre une association\n2: Voir mon portefeuille\n0: Quitter\n`) + choice = await askQuestion(`${chalk.yellow('Que souhaitez-vous faire ?')} \n\n1: Rejoindre une association\n2: Créer un token FA\n3: Voir les associations\n4: Voir mon portefeuille\n0: Quitter\n`) await handleConnectedChoice(choice, tezos) break } diff --git a/src/handlers/handlers.ts b/src/handlers/handlers.ts index 69c41c804ee125c32a0809d0f6484de6f9771a67..3dd42fe80045fd388fedb067df6295e2c33488a2 100644 --- a/src/handlers/handlers.ts +++ b/src/handlers/handlers.ts @@ -11,16 +11,17 @@ import { type Proposal } from '../types/Proposal.js' // IMPORT SERVICES import { getBalance } from '../services/balance.service.js' -import { createAssociation, joinAssociation } from '../services/association.service.js' +import { createAssociation, getAssociationDetails, getAssociations, joinAssociation } from '../services/association.service.js' import { createProposal } from '../services/proposal.service.js' -import { createFA21Contract } from '../services/contract.service.js' +import { createFAToken } from '../services/contract.service.js' +import { burnToken } from '../services/token.service.js' /** * Handles the process of creating an association. * @param {TezosToolkit} tezos - The TezosToolkit instance used for blockchain operations. * @returns {Promise<void>} A promise resolved once the association creation process is complete. */ -async function handleCreateAsssociation (tezos: TezosToolkit): Promise<void> { +async function handleCreateAssociation (tezos: TezosToolkit): Promise<void> { const name = await askQuestion(chalk.yellow('Nom: ')) const description = await askQuestion(chalk.yellow('Description: ')) const association: Association = { @@ -34,7 +35,7 @@ async function handleCreateAsssociation (tezos: TezosToolkit): Promise<void> { console.log(op.hash) console.log(chalk.green('\nVotre association a été crée !!\n')) } catch { - console.log("Erreur lors de la création de l'association") + console.log(chalk.bgRedBright("\nErreur lors de la création de l'association\n")) } } @@ -47,11 +48,11 @@ async function handleCreateToken (tezos: TezosToolkit): Promise<void> { const nbTokenFungible: string = await askQuestion(chalk.yellow('Nombre de token fongible: ')) try { - const op = await createFA21Contract(nbTokenFungible, tezos) + const op = await createFAToken(nbTokenFungible, tezos) console.log(op.hash) console.log(chalk.green('\nVotre token a été créé !!\n')) } catch { - console.log('Erreur lors de la création du token') + console.log(chalk.bgRedBright('\nErreur lors de la création du token\n')) } } @@ -65,7 +66,7 @@ async function handleGetBalance (tezos: TezosToolkit): Promise<void> { const balance = await getBalance(tezos) console.log(`\nSolde du portefeuille: ${balance} ꜩ\n`) } catch { - console.log('Erreur lors de la récupération de votre portefeuille') + console.log(chalk.bgRedBright('\nErreur lors de la récupération de votre portefeuille\n')) } } @@ -88,7 +89,7 @@ async function handleCreateProposal (tezos: TezosToolkit): Promise<void> { console.log(op.hash) console.log(chalk.green('\nVous avez soumis une proposition !!\n')) } catch { - console.log('Erreur lors de la création de la proposition') + console.log(chalk.bgRedBright('\nErreur lors de la création de la proposition\n')) } } @@ -106,78 +107,63 @@ async function handleJoinAssociation (tezos: TezosToolkit): Promise<void> { console.log(op.hash) console.log(chalk.green('\nVous avez soumis une proposition !!\n')) } catch { - console.log("Erreur lors de l'inscription à l'association") + // ERREUR -> PAS ASSEZ DE TOKEN + // ERREUR -> ASSOCIATION NON EXISTANTE + console.log(chalk.bgRedBright("\nErreur lors de l'inscription à l'association\n")) } console.log(chalk.green("\nVous avez rejoint l'association !!\n")) } /** - * Handles administrator actions based on the specified choice. - * @param {string} choice - The administrator's choice. + * Handles the process of listing associations. * @param {TezosToolkit} tezos - The TezosToolkit instance used for blockchain operations. - * @returns {Promise<void>} A promise resolved once the processing is complete. + * @returns {Promise<void>} A promise resolved once the joining process is complete. */ -async function handleAdminChoice (choice: string, tezos: TezosToolkit): Promise<void> { - switch (choice) { - case '0': - break - case '1': - await handleCreateAsssociation(tezos) - break - case '2': - await handleCreateToken(tezos) - break - case '3': - await handleGetBalance(tezos) - break - default: - console.log(chalk.bgRedBright('\nChoix invalide\n')) - break +async function handleGetAssociations (tezos: TezosToolkit): Promise<void> { + try { + console.log('Récupération des associations en cours...') + const op = await getAssociations(tezos) + console.log(op.hash) + // LISTER LES ASSOCIATIONS + } catch { + console.log(chalk.bgRedBright('\nErreur lors de la récupération des associations\n')) } } /** - * Handles adherent actions based on the specified choice. - * @param {string} choice - The adherent's choice. + * Handles the process of getting association details. * @param {TezosToolkit} tezos - The TezosToolkit instance used for blockchain operations. - * @returns {Promise<void>} A promise resolved once the processing is complete. + * @returns {Promise<void>} A promise resolved once the joining process is complete. */ -async function handleAdherentChoice (choice: string, tezos: TezosToolkit): Promise<void> { - switch (choice) { - case '0': - break - case '1': - await handleCreateProposal(tezos) - break - case '2': - await handleGetBalance(tezos) - break - default: - console.log(chalk.bgRedBright('\nChoix invalide\n')) - break +async function handleGetAssociationDetails (tezos: TezosToolkit): Promise<void> { + const name = await askQuestion(chalk.yellow("Nom de l'association: ")) + + try { + console.log("Récupération des détails de l'association en cours...") + const op = await getAssociationDetails(name, tezos) + console.log(op.hash) + // RETURN ASSOCIATIONS + } catch { + console.log(chalk.bgRedBright("\nErreur lors de la récupération des détails de l'association\n")) } } /** - * Handles connected actions based on the specified choice. - * @param {string} choice - The connected's choice. + * Handles the process of creating a proposal. * @param {TezosToolkit} tezos - The TezosToolkit instance used for blockchain operations. - * @returns {Promise<void>} A promise resolved once the processing is complete. + * @returns {Promise<void>} A promise resolved once the proposal creation process is complete. */ -async function handleConnectedChoice (choice: string, tezos: TezosToolkit): Promise<void> { - switch (choice) { - case '0': - break - case '1': - await handleJoinAssociation(tezos) - break - case '2': - await handleGetBalance(tezos) - break - default: - console.log(chalk.bgRedBright('\nChoix invalide\n')) - break +async function handleBurnToken (tezos: TezosToolkit): Promise<void> { + const nbTokenToBurn = await askQuestion(chalk.yellow('Nombre de token à bruler: ')) + + try { + console.log('Brulure des tokens en cours...') + const op = await burnToken(Number(nbTokenToBurn), tezos) + console.log(op.hash) + console.log(chalk.green('\nVous avez bruler vos tokens !!\n')) + } catch { + console.log(chalk.bgRedBright('\nErreur lors de la brulure de vos tokens\n')) } } -export { handleCreateAsssociation, handleCreateToken, handleGetBalance, handleCreateProposal, handleJoinAssociation, handleAdminChoice, handleAdherentChoice, handleConnectedChoice } +export { handleCreateAssociation, handleCreateToken, handleGetBalance, handleCreateProposal, handleJoinAssociation, handleGetAssociations, handleGetAssociationDetails, handleBurnToken } diff --git a/src/handlers/roleHandlers.ts b/src/handlers/roleHandlers.ts new file mode 100644 index 0000000000000000000000000000000000000000..d81b60a8a29521c6ebcc8e2652b36010de876809 --- /dev/null +++ b/src/handlers/roleHandlers.ts @@ -0,0 +1,111 @@ +import { type TezosToolkit } from '@taquito/taquito' +import { handleBurnToken, handleCreateAssociation, handleCreateProposal, handleCreateToken, handleGetAssociations, handleGetBalance, handleJoinAssociation } from './handlers' +import chalk from 'chalk' + +/** + * Handles fa token administrator actions based on the specified choice. + * @param {string} choice - The administrator's choice. + * @param {TezosToolkit} tezos - The TezosToolkit instance used for blockchain operations. + * @returns {Promise<void>} A promise resolved once the processing is complete. + */ +async function handleAdminFATokenChoice (choice: string, tezos: TezosToolkit): Promise<void> { + switch (choice) { + case '0': + break + case '1': + await handleCreateAssociation(tezos) + break + case '2': + await handleCreateToken(tezos) + break + case '3': + await handleBurnToken(tezos) + break + case '4': + await handleGetBalance(tezos) + break + default: + console.log(chalk.bgRedBright('\nChoix invalide\n')) + break + } +} + +/** + * Handles association administrator actions based on the specified choice. + * @param {string} choice - The administrator's choice. + * @param {TezosToolkit} tezos - The TezosToolkit instance used for blockchain operations. + * @returns {Promise<void>} A promise resolved once the processing is complete. + */ +async function handleAdminAssociationChoice (choice: string, tezos: TezosToolkit): Promise<void> { + switch (choice) { + case '0': + break + case '1': + await handleCreateToken(tezos) + break + case '2': + await handleBurnToken(tezos) + break + case '3': + await handleGetBalance(tezos) + break + default: + console.log(chalk.bgRedBright('\nChoix invalide\n')) + break + } +} + +/** + * Handles adherent actions based on the specified choice. + * @param {string} choice - The adherent's choice. + * @param {TezosToolkit} tezos - The TezosToolkit instance used for blockchain operations. + * @returns {Promise<void>} A promise resolved once the processing is complete. + */ +async function handleAdherentChoice (choice: string, tezos: TezosToolkit): Promise<void> { + switch (choice) { + case '0': + break + case '1': + await handleCreateProposal(tezos) + break + case '2': + await handleCreateToken(tezos) + break + case '3': + await handleGetBalance(tezos) + break + default: + console.log(chalk.bgRedBright('\nChoix invalide\n')) + break + } +} + +/** + * Handles connected actions based on the specified choice. + * @param {string} choice - The connected's choice. + * @param {TezosToolkit} tezos - The TezosToolkit instance used for blockchain operations. + * @returns {Promise<void>} A promise resolved once the processing is complete. + */ +async function handleConnectedChoice (choice: string, tezos: TezosToolkit): Promise<void> { + switch (choice) { + case '0': + break + case '1': + await handleJoinAssociation(tezos) + break + case '2': + await handleCreateToken(tezos) + break + case '3': + await handleGetAssociations(tezos) + break + case '4': + await handleGetBalance(tezos) + break + default: + console.log(chalk.bgRedBright('\nChoix invalide\n')) + break + } +} + +export { handleAdminAssociationChoice, handleAdminFATokenChoice, handleAdherentChoice, handleConnectedChoice } diff --git a/src/services/association.service.ts b/src/services/association.service.ts index a3f8a1455be0ee04857436d7a86505c6f55e78a8..23c065a5dbd0bd571377339e41fa28e272183fe6 100644 --- a/src/services/association.service.ts +++ b/src/services/association.service.ts @@ -2,13 +2,13 @@ import { type Operation, type TezosToolkit } from '@taquito/taquito' import { type Association } from '../types/Association' // NEED UPDATE ADDRESS !! (SMART CONTRACT 1: Registre des associations) -const address = 'KT1QZJzhSPQ89K4eC59tmQYCt44qph7wXoJu' +const address = 'KT1PCg4GbtF5LQQhHmY4t1qNYVspnitKGHgm' // NEED UPDATE ENTRYPOINT !! async function createAssociation (association: Association, tezos: TezosToolkit): Promise<Operation> { const contract = await tezos.contract.at(address) - const op: Operation = await contract.methodsObject.createAssociation(association).send() + const op: Operation = await contract.methodsObject.registerAssociation(association).send() await op.confirmation() return op } diff --git a/src/services/contract.service.ts b/src/services/contract.service.ts index 620a6876142ed2dbde9c0f223ef6555331e9520a..5acfa45e78582f69a14d7caf4bfdec3ba5ec229b 100644 --- a/src/services/contract.service.ts +++ b/src/services/contract.service.ts @@ -4,9 +4,9 @@ import { type Operation, type TezosToolkit } from '@taquito/taquito' const address = 'KT1QZJzhSPQ89K4eC59tmQYCt44qph7wXoJu' // NEED UPDATE ENTRYPOINT !! -async function createFA21Contract (nbTokenFongible: string, tezos: TezosToolkit): Promise<Operation> { +async function createFAToken (nbTokenFongible: string, tezos: TezosToolkit): Promise<Operation> { const contract = await tezos.contract.at(address) - const op: Operation = await contract.methodsObject.createFA21Contract(nbTokenFongible).send() + const op: Operation = await contract.methodsObject.createFAToken(nbTokenFongible).send() await op.confirmation() return op @@ -30,4 +30,4 @@ async function deployDAOContract (contrat: string, tezos: TezosToolkit): Promise return op } -export { createFA21Contract, createDAOContract, deployDAOContract } +export { createFAToken, createDAOContract, deployDAOContract } diff --git a/src/types/Role.ts b/src/types/Role.ts index 241cb05c1160a84473c17767eddd09f8df050ac1..8991a38074958b6dcd801b5d90033a3fb9c3dca4 100644 --- a/src/types/Role.ts +++ b/src/types/Role.ts @@ -1 +1 @@ -export type Role = 'ADMIN' | 'ADHERENT' | 'CONNECTED' +export type Role = 'ADMIN_ASSOCIATION' | 'ADHERENT' | 'CONNECTED' | 'ADMIN_FA_TOKEN' diff --git a/src/utils/getRole.ts b/src/utils/getRole.ts index 8b0c0067692b276f3c02611c5656f7561add1d4d..e21034dc158515d6afc37015b9999c909fb262e2 100644 --- a/src/utils/getRole.ts +++ b/src/utils/getRole.ts @@ -9,5 +9,5 @@ export function getRole (tezos: TezosToolkit): Role { // ELSE -> CONNECTED // TEMPORARY - return 'ADHERENT' + return 'ADMIN_FA_TOKEN' } diff --git a/test/handlers/roleHandlers.spec.ts b/test/handlers/roleHandlers.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..3ec72c594cdaa490baebf66f74a25b24ffec5e48 --- /dev/null +++ b/test/handlers/roleHandlers.spec.ts @@ -0,0 +1,221 @@ +import { type TezosToolkit } from '@taquito/taquito' +import { handleAdminFATokenChoice, handleAdminAssociationChoice, handleAdherentChoice, handleConnectedChoice } from '../../src/handlers/roleHandlers' +import { handleCreateAssociation, handleCreateToken, handleBurnToken, handleGetBalance, handleCreateProposal, handleJoinAssociation, handleGetAssociations } from '../../src/handlers/handlers' +import { vi, describe, it, expect, afterEach } from 'vitest' +import chalk from 'chalk' + +vi.mock('../../src/handlers/handlers', () => ({ + handleCreateAssociation: vi.fn(), + handleCreateToken: vi.fn(), + handleBurnToken: vi.fn(), + handleGetBalance: vi.fn(), + handleCreateProposal: vi.fn(), + handleJoinAssociation: vi.fn(), + handleGetAssociations: vi.fn() +})) + +const mockedTezosToolkit = {} as unknown as TezosToolkit + +describe('roleHandlers', () => { + afterEach(() => { + vi.restoreAllMocks() + }) + + describe('handleAdminFATokenChoice', () => { + describe('when choice is "0"', () => { + it('should not call any handler', async () => { + await handleAdminFATokenChoice('0', mockedTezosToolkit) + + expect(handleCreateAssociation).not.toHaveBeenCalled() + expect(handleCreateToken).not.toHaveBeenCalled() + expect(handleBurnToken).not.toHaveBeenCalled() + expect(handleGetBalance).not.toHaveBeenCalled() + }) + }) + + describe('when choice is "1"', () => { + it('should call handleCreateAssociation', async () => { + await handleAdminFATokenChoice('1', mockedTezosToolkit) + + expect(handleCreateAssociation).toBeCalled() + }) + }) + + describe('when choice is "2"', () => { + it('should call handleCreateToken', async () => { + await handleAdminFATokenChoice('2', mockedTezosToolkit) + + expect(handleCreateToken).toBeCalled() + }) + }) + + describe('when choice is "3"', () => { + it('should call handleBurnToken', async () => { + await handleAdminFATokenChoice('3', mockedTezosToolkit) + + expect(handleBurnToken).toBeCalled() + }) + }) + + describe('when choice is "4"', () => { + it('should call handleGetBalance', async () => { + await handleAdminFATokenChoice('4', mockedTezosToolkit) + + expect(handleGetBalance).toBeCalled() + }) + }) + + describe('when choice is invalid', () => { + it('should log "Choix invalide"', async () => { + const consoleSpy = vi.spyOn(console, 'log') + await handleAdminFATokenChoice('invalid', mockedTezosToolkit) + + expect(consoleSpy).toHaveBeenCalledWith(chalk.bgRedBright('\nChoix invalide\n')) + }) + }) + }) + + describe('handleAdminAssociationChoice', () => { + describe('when choice is "0"', () => { + it('should not call any handler', async () => { + await handleAdminAssociationChoice('0', mockedTezosToolkit) + + expect(handleCreateToken).not.toHaveBeenCalled() + expect(handleBurnToken).not.toHaveBeenCalled() + expect(handleGetBalance).not.toHaveBeenCalled() + }) + }) + + describe('when choice is "1"', () => { + it('should call handleCreateToken', async () => { + await handleAdminAssociationChoice('1', mockedTezosToolkit) + + expect(handleCreateToken).toBeCalled() + }) + }) + + describe('when choice is "2"', () => { + it('should call handleBurnToken', async () => { + await handleAdminAssociationChoice('2', mockedTezosToolkit) + + expect(handleBurnToken).toBeCalled() + }) + }) + + describe('when choice is "3"', () => { + it('should call handleGetBalance', async () => { + await handleAdminAssociationChoice('3', mockedTezosToolkit) + + expect(handleGetBalance).toBeCalled() + }) + }) + + describe('when choice is invalid', () => { + it('should log "Choix invalide"', async () => { + const consoleSpy = vi.spyOn(console, 'log') + await handleAdminAssociationChoice('invalid', mockedTezosToolkit) + + expect(consoleSpy).toHaveBeenCalledWith(chalk.bgRedBright('\nChoix invalide\n')) + }) + }) + }) + + describe('handleAdherentChoice', () => { + describe('when choice is "0"', () => { + it('should not call any handler', async () => { + await handleAdherentChoice('0', mockedTezosToolkit) + + expect(handleCreateProposal).not.toHaveBeenCalled() + expect(handleCreateToken).not.toHaveBeenCalled() + expect(handleGetBalance).not.toHaveBeenCalled() + }) + }) + + describe('when choice is "1"', () => { + it('should call handleCreateProposal', async () => { + await handleAdherentChoice('1', mockedTezosToolkit) + + expect(handleCreateProposal).toBeCalled() + }) + }) + + describe('when choice is "2"', () => { + it('should call handleCreateToken', async () => { + await handleAdherentChoice('2', mockedTezosToolkit) + + expect(handleCreateToken).toBeCalled() + }) + }) + + describe('when choice is "3"', () => { + it('should call handleGetBalance', async () => { + await handleAdherentChoice('3', mockedTezosToolkit) + + expect(handleGetBalance).toBeCalled() + }) + }) + + describe('when choice is invalid', () => { + it('should log "Choix invalide"', async () => { + const consoleSpy = vi.spyOn(console, 'log') + await handleAdherentChoice('invalid', mockedTezosToolkit) + + expect(consoleSpy).toHaveBeenCalledWith(chalk.bgRedBright('\nChoix invalide\n')) + }) + }) + }) + + describe('handleConnectedChoice', () => { + describe('when choice is "0"', () => { + it('should not call any handler', async () => { + await handleConnectedChoice('0', mockedTezosToolkit) + + expect(handleJoinAssociation).not.toHaveBeenCalled() + expect(handleCreateToken).not.toHaveBeenCalled() + expect(handleGetAssociations).not.toHaveBeenCalled() + expect(handleGetBalance).not.toHaveBeenCalled() + }) + }) + + describe('when choice is "1"', () => { + it('should call handleJoinAssociation', async () => { + await handleConnectedChoice('1', mockedTezosToolkit) + + expect(handleJoinAssociation).toBeCalled() + }) + }) + + describe('when choice is "2"', () => { + it('should call handleCreateToken', async () => { + await handleConnectedChoice('2', mockedTezosToolkit) + + expect(handleCreateToken).toBeCalled() + }) + }) + + describe('when choice is "3"', () => { + it('should call handleGetAssociations', async () => { + await handleConnectedChoice('3', mockedTezosToolkit) + + expect(handleGetAssociations).toBeCalled() + }) + }) + + describe('when choice is "4"', () => { + it('should call handleGetBalance', async () => { + await handleConnectedChoice('4', mockedTezosToolkit) + + expect(handleGetBalance).toBeCalled() + }) + }) + + describe('when choice is invalid', () => { + it('should log "Choix invalide"', async () => { + const consoleSpy = vi.spyOn(console, 'log') + await handleConnectedChoice('invalid', mockedTezosToolkit) + + expect(consoleSpy).toHaveBeenCalledWith(chalk.bgRedBright('\nChoix invalide\n')) + }) + }) + }) +})