diff --git a/index.ts b/index.ts index 35435c142a3e16ff1e896bbd38c7b3ca8f9e88b1..e188a3b5cf42196eb6747fa6f292ee01dc8c56db 100644 --- a/index.ts +++ b/index.ts @@ -14,7 +14,9 @@ import { getRole } from './src/utils/getRole.js' import { type WalletData } from './src/types/WalletData.js' // IMPORT HANDLERS -import { handleAdminAssociationChoice, handleAdherentChoice, handleConnectedChoice, handleAdminFATokenChoice } from './src/handlers/roleHandlers.js' +import { handleAdminChoice, handleAdherentChoice, handleConnectedChoice } from './src/handlers/roleHandlers.js' +import { type Role } from './src/types/Role.js' +import { handleHasToken } from './src/utils/hasToken.js' const tezos = new TezosToolkit('https://ghostnet.tezos.marigold.dev') const program = new Command() @@ -35,12 +37,13 @@ program.command('main') // DISPLAY HEADER await getAsciiArtText() - console.log('\n') - console.log(chalk.bgBlue(`Vous êtes connecté en tant que ${getRole(tezos)}`)) - console.log('\n') // START MAIN APPLICATION while (true) { + const role: Role = await getRole(tezos) + + console.log(chalk.bgBlue(`\nVous êtes connecté en tant que ${role}\n`)) + const questions = [ { type: 'list', @@ -49,31 +52,32 @@ program.command('main') choices: [] } ] - switch (getRole(tezos)) { - case 'ADMIN_FA_TOKEN': - questions[0].choices = ['Créer une association', 'Créer un token', 'Bruler des tokens', 'Voir mon portefeuille'] - await inquirer.prompt(questions).then(async (answers: { choice: string }) => { - await handleAdminFATokenChoice(answers.choice, tezos) - }) - break - case 'ADMIN_ASSOCIATION': - questions[0].choices = ['Créer un token', 'Bruler des tokens', 'Résoudre une proposition', 'Clôturer une proposition', 'Voir les propositions', 'Voir mon portefeuille'] + switch (role) { + case 'ADMIN': + questions[0].choices = ['Résoudre une proposition', 'Clôturer une proposition', 'Voir les propositions', 'Créer un token'] + + if (await handleHasToken(tezos)) { questions[0].choices.push('Bruler des tokens') } + await inquirer.prompt(questions).then(async (answers: { choice: string }) => { - await handleAdminAssociationChoice(answers.choice, tezos) + await handleAdminChoice(answers.choice, tezos) }) break case 'ADHERENT': // VOTER POUR UNE PROPOSITION // CLOTURER ET RESOUDRE LES PROPOSITIONS DONT IL EST LE CREATEUR - // SI A UN TOKEN IL PEUT LE BRULER - questions[0].choices = ['Faire une proposition', 'Créer un token', 'Voir mon portefeuille'] + questions[0].choices = ['Faire une proposition', 'Créer un token'] + + if (await handleHasToken(tezos)) { questions[0].choices.push('Bruler des tokens') } + await inquirer.prompt(questions).then(async (answers: { choice: string }) => { await handleAdherentChoice(answers.choice, tezos) }) break case 'CONNECTED': - // CREE UNE ASSO SI A UN TOKEN - questions[0].choices = ['Rejoindre une association', 'Créer un token', 'Voir les associations', "Voir les détails d'une association", 'Voir mon portefeuille'] + questions[0].choices = ['Rejoindre une association', 'Voir les associations', "Voir les détails d'une association", 'Créer un token'] + + if (await handleHasToken(tezos)) { questions[0].choices.push('Bruler des tokens', 'Créer une association') } + await inquirer.prompt(questions).then(async (answers: { choice: string }) => { await handleConnectedChoice(answers.choice, tezos) }) diff --git a/src/handlers/association/associationHandlers.ts b/src/handlers/association/associationHandlers.ts index 9a3aae9afe6251297ae790f6626f56df8413e28f..b5fac0292877dbbea21ad9f104f11654e57229a1 100644 --- a/src/handlers/association/associationHandlers.ts +++ b/src/handlers/association/associationHandlers.ts @@ -5,7 +5,7 @@ import { type TezosToolkit } from '@taquito/taquito' import { type Association } from '../../types/Association.js' // IMPORT SERVICES -import { createAssociation, getAssociationDetails, getAssociations, joinAssociation } from '../../services/association.service.js' +import { createAssociation, getAssociationDetails, getAssociations, isAdminOfAssociation, joinAssociation } from '../../services/association.service.js' import inquirer from 'inquirer' /** @@ -132,4 +132,17 @@ async function handleGetAssociationDetails (associations: string[], tezos: Tezos } } -export { handleCreateAssociation, handleJoinAssociation, handleGetAssociations, handleGetAssociationDetails } +/** + * Handles the process of is admin. + * @param {TezosToolkit} tezos - The TezosToolkit instance used for blockchain operations. + * @returns {Promise<boolean>} A promise with a boolean of is admin. + */ +async function handleIsAdmin (tezos: TezosToolkit): Promise<boolean> { + try { + return await isAdminOfAssociation(tezos) + } catch (error) { + throw new Error(`${error}`) + } +} + +export { handleCreateAssociation, handleJoinAssociation, handleGetAssociations, handleGetAssociationDetails, handleIsAdmin } diff --git a/src/handlers/roleHandlers.ts b/src/handlers/roleHandlers.ts index 0a6e981350b3a642a7fea46c61b3b80286edf5ba..6e6a5d7f00c996ae9e93db29eeaef50354a0873d 100644 --- a/src/handlers/roleHandlers.ts +++ b/src/handlers/roleHandlers.ts @@ -13,38 +13,12 @@ import { showProposals } from '../features/proposal/showProposals.js' import { closeProposal } from '../features/proposal/closeProposal.js' /** - * 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 'Créer une association': - await createAssociation(tezos) - break - case 'Créer un token': - await createToken(tezos) - break - case 'Bruler des tokens': - await burnToken(tezos) - break - case 'Voir mon portefeuille': - await showBalance(tezos) - break - default: - console.log(chalk.bgRedBright('\nChoix invalide\n')) - break - } -} - -/** - * Handles association administrator actions based on the specified choice. + * Handles 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> { +async function handleAdminChoice (choice: string, tezos: TezosToolkit): Promise<void> { switch (choice) { case 'Créer un token': await createToken(tezos) @@ -87,6 +61,9 @@ async function handleAdherentChoice (choice: string, tezos: TezosToolkit): Promi case 'Voir mon portefeuille': await showBalance(tezos) break + case 'Bruler des tokens': + await burnToken(tezos) + break default: console.log(chalk.bgRedBright('\nChoix invalide\n')) break @@ -116,10 +93,16 @@ async function handleConnectedChoice (choice: string, tezos: TezosToolkit): Prom case 'Voir mon portefeuille': await showBalance(tezos) break + case 'Créer une association': + await createAssociation(tezos) + break + case 'Bruler des tokens': + await burnToken(tezos) + break default: console.log(chalk.bgRedBright('\nChoix invalide\n')) break } } -export { handleAdminAssociationChoice, handleAdminFATokenChoice, handleAdherentChoice, handleConnectedChoice } +export { handleAdminChoice, handleAdherentChoice, handleConnectedChoice } diff --git a/src/services/association.service.ts b/src/services/association.service.ts index 91bf7a0cb7034ad6ef9902db902e58fe92b7824b..7ebd20ea49038d1f4dc5b99d673674d56eed776c 100644 --- a/src/services/association.service.ts +++ b/src/services/association.service.ts @@ -2,7 +2,7 @@ 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 = 'KT1HEyhspXn3Bt2opakTvaRFkwSMZbmqvXGM' +const address = 'KT1Vvjy6eWKztgFkraPYGqkvaiRcLmF2mxAJ' const mockAssociations: Association[] = [ { @@ -55,4 +55,15 @@ async function getAssociationDetails (associationName: string, tezos: TezosToolk return associationDetails } -export { createAssociation, joinAssociation, getAssociations, getAssociationDetails } +async function isAdminOfAssociation (tezos: TezosToolkit): Promise<boolean> { + const contract = await tezos.contract.at(address) + + const executionContextParams = { + viewCaller: contract.address + } + + const isAdmin: boolean = await contract.contractViews.isAdmin('Test').executeView(executionContextParams) + return isAdmin +} + +export { createAssociation, joinAssociation, getAssociations, getAssociationDetails, isAdminOfAssociation } diff --git a/src/services/token.service.ts b/src/services/token.service.ts index 59bc22395b03f9282b0bf99e32d1aa913ca050ba..983f279ee1a9ea8a6f26ba2a9fe996d4d8932d8b 100644 --- a/src/services/token.service.ts +++ b/src/services/token.service.ts @@ -19,4 +19,18 @@ async function burnToken (amount: number, tezos: TezosToolkit): Promise<void> { // await op.confirmation() } -export { createFAToken, burnToken } +// NEED UPDATE ENTRYPOINT !! +async function hasToken (tezos: TezosToolkit): Promise<boolean> { + // const contract = await tezos.contract.at(address) + + // const executionContextParams = { + // viewCaller: contract.address + // } + // const op: Operation = await contract.methodsObject.hasToken().executeView(executionContextParams) + + // await op.confirmation() + + return false +} + +export { createFAToken, burnToken, hasToken } diff --git a/src/types/Role.ts b/src/types/Role.ts index 8991a38074958b6dcd801b5d90033a3fb9c3dca4..241cb05c1160a84473c17767eddd09f8df050ac1 100644 --- a/src/types/Role.ts +++ b/src/types/Role.ts @@ -1 +1 @@ -export type Role = 'ADMIN_ASSOCIATION' | 'ADHERENT' | 'CONNECTED' | 'ADMIN_FA_TOKEN' +export type Role = 'ADMIN' | 'ADHERENT' | 'CONNECTED' diff --git a/src/utils/getRole.ts b/src/utils/getRole.ts index eb449964ef96bde32ed2b10fb176c8a27832ff93..5aaaa553ffcd46e2fa0151ddac1fe47546d6f3b2 100644 --- a/src/utils/getRole.ts +++ b/src/utils/getRole.ts @@ -1,12 +1,11 @@ import { type TezosToolkit } from '@taquito/taquito' import { type Role } from '../types/Role' +// import { handleIsAdmin } from '../handlers/association/associationHandlers.js' -export function getRole (tezos: TezosToolkit): Role { - // IF HAS TOKEN && HAS ASSOCIATION -> ADMIN +export async function getRole (tezos: TezosToolkit): Promise<Role> { + // const isAdmin = await handleIsAdmin(tezos) - // IF HAS TOKEN -> ADHERENT - - // ELSE -> CONNECTED + // if (isAdmin) return 'ADMIN' // TEMPORARY return 'CONNECTED' diff --git a/src/utils/hasToken.ts b/src/utils/hasToken.ts new file mode 100644 index 0000000000000000000000000000000000000000..ed88d53e234d1776aeef20e93d20bb7a6367e39a --- /dev/null +++ b/src/utils/hasToken.ts @@ -0,0 +1,8 @@ +import { type TezosToolkit } from '@taquito/taquito' +import { hasToken } from '../services/token.service.js' + +async function handleHasToken (tezos: TezosToolkit): Promise<boolean> { + return await hasToken(tezos) +} + +export { handleHasToken } diff --git a/test/handlers/roleHandlers.spec.ts b/test/handlers/roleHandlers.spec.ts index 548583809da244e38295b5e334cb13710268a869..7eaae2a1e63a6b1bb7dd5e469f022999506374eb 100644 --- a/test/handlers/roleHandlers.spec.ts +++ b/test/handlers/roleHandlers.spec.ts @@ -1,5 +1,5 @@ import { type TezosToolkit } from '@taquito/taquito' -import { handleAdminFATokenChoice, handleAdminAssociationChoice, handleAdherentChoice, handleConnectedChoice } from '../../src/handlers/roleHandlers' +import { handleAdminChoice, handleAdherentChoice, handleConnectedChoice } from '../../src/handlers/roleHandlers' import { vi, describe, it, expect, beforeEach } from 'vitest' import chalk from 'chalk' import { createAssociation } from '../../src/features/association/createAssociation' @@ -64,53 +64,10 @@ describe('roleHandlers', () => { vi.clearAllMocks() }) - describe('handleAdminFATokenChoice', () => { - describe('when choice is "Créer une association"', () => { - it('should call createAssociation', async () => { - await handleAdminFATokenChoice('Créer une association', mockedTezosToolkit) - - expect(createAssociation).toBeCalled() - }) - }) - - describe('when choice is "Créer un token"', () => { - it('should call createToken', async () => { - await handleAdminFATokenChoice('Créer un token', mockedTezosToolkit) - - expect(createToken).toBeCalled() - }) - }) - - describe('when choice is "Bruler des tokens"', () => { - it('should call burnToken', async () => { - await handleAdminFATokenChoice('Bruler des tokens', mockedTezosToolkit) - - expect(burnToken).toBeCalled() - }) - }) - - describe('when choice is "Voir mon portefeuille"', () => { - it('should call showBalance', async () => { - await handleAdminFATokenChoice('Voir mon portefeuille', mockedTezosToolkit) - - expect(showBalance).toBeCalled() - }) - }) - - describe('when choice is invalid', () => { - it('should log "Choix invalide"', async () => { - const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}) - await handleAdminFATokenChoice('invalid', mockedTezosToolkit) - - expect(consoleSpy).toHaveBeenCalledWith(chalk.bgRedBright('\nChoix invalide\n')) - }) - }) - }) - - describe('handleAdminAssociationChoice', () => { + describe('handleAdminChoice', () => { describe('when choice is "Créer un token"', () => { it('should call createToken', async () => { - await handleAdminAssociationChoice('Créer un token', mockedTezosToolkit) + await handleAdminChoice('Créer un token', mockedTezosToolkit) expect(createToken).toBeCalled() }) @@ -118,7 +75,7 @@ describe('roleHandlers', () => { describe('when choice is "Bruler des tokens"', () => { it('should call burnToken', async () => { - await handleAdminAssociationChoice('Bruler des tokens', mockedTezosToolkit) + await handleAdminChoice('Bruler des tokens', mockedTezosToolkit) expect(burnToken).toBeCalled() }) @@ -126,7 +83,7 @@ describe('roleHandlers', () => { describe('when choice is "Résoudre une proposition"', () => { it('should call resolveProposal', async () => { - await handleAdminAssociationChoice('Résoudre une proposition', mockedTezosToolkit) + await handleAdminChoice('Résoudre une proposition', mockedTezosToolkit) expect(resolveProposal).toBeCalled() }) @@ -134,7 +91,7 @@ describe('roleHandlers', () => { describe('when choice is "Voir les propositions"', () => { it('should call showProposals', async () => { - await handleAdminAssociationChoice('Voir les propositions', mockedTezosToolkit) + await handleAdminChoice('Voir les propositions', mockedTezosToolkit) expect(showProposals).toBeCalled() }) @@ -142,7 +99,7 @@ describe('roleHandlers', () => { describe('when choice is "Clôturer une proposition"', () => { it('should call closeProposal', async () => { - await handleAdminAssociationChoice('Clôturer une proposition', mockedTezosToolkit) + await handleAdminChoice('Clôturer une proposition', mockedTezosToolkit) expect(closeProposal).toBeCalled() }) @@ -150,7 +107,7 @@ describe('roleHandlers', () => { describe('when choice is "Voir mon portefeuille"', () => { it('should call showBalance', async () => { - await handleAdminAssociationChoice('Voir mon portefeuille', mockedTezosToolkit) + await handleAdminChoice('Voir mon portefeuille', mockedTezosToolkit) expect(showBalance).toBeCalled() }) @@ -160,7 +117,7 @@ describe('roleHandlers', () => { it('should log "Choix invalide"', async () => { const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}) - await handleAdminAssociationChoice('invalid', mockedTezosToolkit) + await handleAdminChoice('invalid', mockedTezosToolkit) expect(consoleSpy).toHaveBeenCalledWith(chalk.bgRedBright('\nChoix invalide\n')) }) @@ -192,6 +149,14 @@ describe('roleHandlers', () => { }) }) + describe('when choice is "Bruler des tokens"', () => { + it('should call burnToken', async () => { + await handleAdminChoice('Bruler des tokens', mockedTezosToolkit) + + expect(burnToken).toBeCalled() + }) + }) + describe('when choice is invalid', () => { it('should log "Choix invalide"', async () => { const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}) @@ -235,6 +200,22 @@ describe('roleHandlers', () => { }) }) + describe('when choice is "Créer une association"', () => { + it('should call createAssociation', async () => { + await handleConnectedChoice('Créer une association', mockedTezosToolkit) + + expect(createAssociation).toBeCalled() + }) + }) + + describe('when choice is "Bruler des tokens"', () => { + it('should call burnToken', async () => { + await handleAdminChoice('Bruler des tokens', mockedTezosToolkit) + + expect(burnToken).toBeCalled() + }) + }) + describe('when choice is invalid', () => { it('should log "Choix invalide"', async () => { const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})