From 5bd5c1ee3d2869a7a0bd966f0da4f01168a0d885 Mon Sep 17 00:00:00 2001
From: Nawfel Senoussi <nawfelsen@mbp-de-nawfel.home>
Date: Sat, 30 Mar 2024 15:32:59 +0100
Subject: [PATCH] handle token choice and remove admin token role

---
 index.ts                                      | 40 +++++----
 .../association/associationHandlers.ts        | 17 +++-
 src/handlers/roleHandlers.ts                  | 41 +++------
 src/services/association.service.ts           | 15 +++-
 src/services/token.service.ts                 | 16 +++-
 src/types/Role.ts                             |  2 +-
 src/utils/getRole.ts                          |  9 +-
 src/utils/hasToken.ts                         |  8 ++
 test/handlers/roleHandlers.spec.ts            | 85 +++++++------------
 9 files changed, 123 insertions(+), 110 deletions(-)
 create mode 100644 src/utils/hasToken.ts

diff --git a/index.ts b/index.ts
index 35435c1..e188a3b 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 9a3aae9..b5fac02 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 0a6e981..6e6a5d7 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 91bf7a0..7ebd20e 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 59bc223..983f279 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 8991a38..241cb05 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 eb44996..5aaaa55 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 0000000..ed88d53
--- /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 5485838..7eaae2a 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(() => {})
-- 
GitLab