From e387d6ad82b0cfc9333379833a11ec20d361686e Mon Sep 17 00:00:00 2001
From: Nawfel Senoussi <nawfelsen@mbp-de-nawfel.home>
Date: Sun, 24 Mar 2024 17:41:25 +0100
Subject: [PATCH] refacto project structure

---
 index.ts                            |  97 +++++--------------------
 src/handlers/handlers.ts            | 105 ++++++++++++++++++++++++++++
 src/services/association.service.ts |  24 ++++++-
 src/services/contract.service.ts    |  33 +++++++++
 src/services/index.ts               |   9 +++
 src/services/proposal.service.ts    |  45 +++++++++++-
 src/services/token.service.ts       |  20 +++++-
 src/types/Association.ts            |   2 +-
 src/types/Proposal.ts               |   2 +
 src/{ => utils}/getRole.ts          |   3 +
 10 files changed, 255 insertions(+), 85 deletions(-)
 create mode 100644 src/handlers/handlers.ts
 create mode 100644 src/services/contract.service.ts
 create mode 100644 src/services/index.ts
 rename src/{ => utils}/getRole.ts (83%)

diff --git a/index.ts b/index.ts
index 7816593..f7402dd 100644
--- a/index.ts
+++ b/index.ts
@@ -1,13 +1,17 @@
+// IMPORT EXTERNAL LIBS
 import { Command } from 'commander';
 import chalk from 'chalk';
 import fs from "fs";
 import { TezosToolkit } from '@taquito/taquito';
 import { InMemorySigner } from '@taquito/signer';
+
+// IMPORT UTILS
 import { askQuestion } from './src/utils/askQuestion.js';
-import { getBalance } from './src/services/balance.service.js';
 import { getAsciiArtText } from './src/utils/getAsciiArtText.js';
-import { createFAToken } from './src/services/token.service.js';
-import { Role } from './src/types/Role.js';
+import { getRole } from './src/utils/getRole.js';
+
+// IMPORT HANDLERS
+import { handleAdminChoice, handleAdherentChoice, handleConnectedChoice } from './src/handlers/handlers.js';
 
 const tezos = new TezosToolkit('https://ghostnet.ecadinfra.com');
 const program = new Command();
@@ -32,86 +36,23 @@ program
   .action(async () => {
     await getAsciiArtText()
     console.log(`\n`);
-
-    // Définir un moyen de connaître le rôle 
-    let role: Role;
-    role = "ADMIN";
-    console.log(chalk.bgBlue(`Vous êtes connecté en tant que ${role}\n`))
+    console.log(chalk.bgBlue(`Vous êtes connecté en tant que ${getRole(tezos)}\n`))
 
     while (true) {
-      // IF ADMIN
-      if(role === "ADMIN") {
-        const 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`);
-
-        if (choice === '0') {
+      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);
           break;
-        }
-        
-        if (choice === '1') {
-          const name = await askQuestion(chalk.yellow('Nom: '));
-          const description = await askQuestion(chalk.yellow('Description: '));
-          const association = {
-            name: name,
-            description: description
-          };
-
-          console.log("Création du token en cours...")
-          const op = await createFAToken(tezos);
-
-          console.log(op.hash);
-  
-          console.log(chalk.green("\nVotre association a été crée !!\n"));
-          // Faire l'appel a create association
-        } else if (choice === '2') {
-          const nbTokenFungible = await askQuestion(chalk.yellow('Nombre de token fongible: '));
-          // Faire le call pour créer un token
-          console.log(chalk.green("\nVotre token a été créé !!\n"));
-        } else if (choice === '3') {
-          const balance = await getBalance(tezos);
-          console.log(`\nSolde du portefeuille: ${balance} ꜩ\n`);
-        } else {
-          console.log('Choix invalide');
-        }
-      }
-      
-      // IF ADHERENT
-      if(role === "ADHERENT" as Role) {
-        const choice = await askQuestion(`${chalk.yellow('Que souhaitez-vous faire ?')} \n\n1: Faire une proposition\n2: Voir mon portefeuille\n0: Quitter\n`);
-
-        if (choice === '0') {
+        case "ADHERENT":
+          choice = await askQuestion(`${chalk.yellow('Que souhaitez-vous faire ?')} \n\n1: Faire une proposition\n2: Voir mon portefeuille\n0: Quitter\n`);
+          await handleAdherentChoice(choice, tezos);
           break;
-        }
-
-        if (choice === '1') {  
-          console.log(chalk.green("\nVous avez soumis une proposition !!\n"));
-          // Faire l'appel a post proposal association
-        } else if (choice === '2') {
-          const balance = await getBalance(tezos);
-          console.log(`\nSolde du portefeuille: ${balance} ꜩ\n`);
-        } else {
-          console.log('Choix invalide');
-        }
-      }
-
-      // IF CONNECTED
-      if(role === "CONNECTED" as Role) {
-        const choice = await askQuestion(`${chalk.yellow('Que souhaitez-vous faire ?')} \n\n1: Rejoindre une association\n2: Voir mon portefeuille\n0: Quitter\n`);
-
-        if (choice === '0') {
+        case "CONNECTED":
+          choice = await askQuestion(`${chalk.yellow('Que souhaitez-vous faire ?')} \n\n1: Rejoindre une association\n2: Voir mon portefeuille\n0: Quitter\n`);
+          await handleConnectedChoice(choice, tezos);
           break;
-        }
-
-        if (choice === '1') {
-          const name = await askQuestion(chalk.yellow("Nom de l'association: "));
-  
-          console.log(chalk.green("\nVous avez rejoint l'association !!\n"));
-          // Faire l'appel a join association
-        } else if (choice === '2') {
-          const balance = await getBalance(tezos);
-          console.log(`\nSolde du portefeuille: ${balance} ꜩ\n`);
-        } else {
-          console.log('Choix invalide');
-        }
       }
     }
   });
diff --git a/src/handlers/handlers.ts b/src/handlers/handlers.ts
new file mode 100644
index 0000000..03254e4
--- /dev/null
+++ b/src/handlers/handlers.ts
@@ -0,0 +1,105 @@
+// IMPORT EXTERNAL LIBS
+import chalk from 'chalk';
+import { TezosToolkit } from '@taquito/taquito';
+
+// IMPORT UTILS
+import { askQuestion } from '../utils/askQuestion.js';
+
+// IMPORT TYPES
+import { Association } from '../types/Association.js';
+
+// IMPORT SERVICES
+import { getBalance } from '../services/balance.service.js';
+import { createAssociation } from '../services/association.service.js';
+
+async function handleCreateAsssociation(tezos: TezosToolkit) {
+    const name = await askQuestion(chalk.yellow('Nom: '));
+    const description = await askQuestion(chalk.yellow('Description: '));
+    const association: Association = {
+      name: name,
+      description: description
+    };
+  
+    console.log("Création du token en cours...");
+    try {
+      const op = await createAssociation(association, tezos);
+      console.log(op.hash);
+      console.log(chalk.green("\nVotre association a été crée !!\n"));
+    } catch {
+      console.log("Erreur lors de la création du token");
+    }
+}
+  
+async function handleCreateToken(tezos: TezosToolkit) {
+    const nbTokenFungible = await askQuestion(chalk.yellow('Nombre de token fongible: '));
+    // Faire le call pour créer un token
+    console.log(chalk.green("\nVotre token a été créé !!\n"));
+}
+
+async function handleGetBalance(tezos: TezosToolkit) {
+    const balance = await getBalance(tezos);
+    console.log(`\nSolde du portefeuille: ${balance} ꜩ\n`);
+}
+
+async function handleCreateProposal(tezos: TezosToolkit) {
+    console.log(chalk.green("\nVous avez soumis une proposition !!\n"));
+    // Faire l'appel a post proposal association
+}
+
+async function handleJoinAssociation(tezos: TezosToolkit) {
+    const name = await askQuestion(chalk.yellow("Nom de l'association: "));
+    console.log(chalk.green("\nVous avez rejoint l'association !!\n"));
+}
+
+async function handleAdminChoice(choice: string, tezos: TezosToolkit) {
+    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('Choix invalide');
+          break;
+      }
+}
+
+async function handleAdherentChoice(choice: string, tezos: TezosToolkit) {
+    switch(choice) {
+        case "0":
+          break;
+        case "1":
+          await handleCreateProposal(tezos);
+          break;
+        case "2":
+          await handleGetBalance(tezos);
+          break;
+        default:
+          console.log('Choix invalide');
+          break;
+      }
+}
+
+async function handleConnectedChoice(choice: string, tezos: TezosToolkit) {
+    switch(choice) {
+        case "0":
+          break;
+        case "1":
+          await handleJoinAssociation(tezos);
+          break;
+        case "2":
+          await handleGetBalance(tezos);
+          break;
+        default:
+          console.log('Choix invalide');
+          break;
+      }
+}
+
+export { handleCreateAsssociation, handleCreateToken, handleGetBalance, handleCreateProposal, handleJoinAssociation, handleAdminChoice, handleAdherentChoice, handleConnectedChoice }
\ No newline at end of file
diff --git a/src/services/association.service.ts b/src/services/association.service.ts
index 017cec1..a157711 100644
--- a/src/services/association.service.ts
+++ b/src/services/association.service.ts
@@ -1,7 +1,7 @@
 import { Operation, TezosToolkit } from '@taquito/taquito';
 import { Association } from '../types/Association';
 
-// NEED UPDATE ADDRESS !!
+// NEED UPDATE ADDRESS !! (SMART CONTRACT 1: Registre des associations)
 const address = "KT1QZJzhSPQ89K4eC59tmQYCt44qph7wXoJu"
 
 // NEED UPDATE ENTRYPOINT !!
@@ -20,6 +20,24 @@ async function joinAssociation(associationName: string, tezos: TezosToolkit): Pr
   
     await op.confirmation();
     return op;
-  }
+}
+
+// NEED UPDATE ENTRYPOINT !!
+async function getAssociations(tezos: TezosToolkit): Promise<Operation> {
+    const contract = await tezos.contract.at(address);
+    const op: Operation = await contract.methodsObject.getAssociations().send();
+  
+    await op.confirmation();
+    return op;
+}
+
+// NEED UPDATE ENTRYPOINT !!
+async function getAssociationDetails(associationName: string, tezos: TezosToolkit): Promise<Operation> {
+    const contract = await tezos.contract.at(address);
+    const op: Operation = await contract.methodsObject.getAssociationsDetails(associationName).send();
+  
+    await op.confirmation();
+    return op;
+}
 
-export { createAssociation }
\ No newline at end of file
+export { createAssociation, joinAssociation, getAssociations, getAssociationDetails }
\ No newline at end of file
diff --git a/src/services/contract.service.ts b/src/services/contract.service.ts
new file mode 100644
index 0000000..4854546
--- /dev/null
+++ b/src/services/contract.service.ts
@@ -0,0 +1,33 @@
+import { Operation, TezosToolkit } from '@taquito/taquito';
+
+// NEED UPDATE ADDRESS !! (SMART CONTRACT 3: Factory de Token)
+const address = "KT1QZJzhSPQ89K4eC59tmQYCt44qph7wXoJu"
+
+// NEED UPDATE ENTRYPOINT !!
+async function createFA21Contract(tezos: TezosToolkit): Promise<Operation> {
+  const contract = await tezos.contract.at(address);
+  const op: Operation = await contract.methodsObject.createFA21Contract().send();
+
+  await op.confirmation();
+  return op;
+}
+
+// NEED UPDATE ENTRYPOINT !!
+async function createDAOContract(tezos: TezosToolkit): Promise<Operation> {
+    const contract = await tezos.contract.at(address);
+    const op: Operation = await contract.methodsObject.createDAOContract().send();
+  
+    await op.confirmation();
+    return op;
+}
+
+// NEED UPDATE ENTRYPOINT !!
+async function deployDAOContract(contrat: string, tezos: TezosToolkit): Promise<Operation> {
+    const contract = await tezos.contract.at(address);
+    const op: Operation = await contract.methodsObject.deployDAOContract(contrat).send();
+  
+    await op.confirmation();
+    return op;
+}
+
+export { createFA21Contract, createDAOContract, deployDAOContract }
\ No newline at end of file
diff --git a/src/services/index.ts b/src/services/index.ts
new file mode 100644
index 0000000..d7e5ad5
--- /dev/null
+++ b/src/services/index.ts
@@ -0,0 +1,9 @@
+export * from "./association.service";
+
+export * from "./balance.service";
+
+export * from "./contract.service";
+
+export * from "./proposal.service";
+
+export * from "./token.service";
\ No newline at end of file
diff --git a/src/services/proposal.service.ts b/src/services/proposal.service.ts
index e8003a8..fc9dd27 100644
--- a/src/services/proposal.service.ts
+++ b/src/services/proposal.service.ts
@@ -1,7 +1,7 @@
 import { Operation, TezosToolkit } from '@taquito/taquito';
 import { Proposal } from '../types/Proposal';
 
-// NEED UPDATE ADDRESS !!
+// NEED UPDATE ADDRESS !! (SMART CONTRACT 2: Factory de DAO)
 const address = "KT1QZJzhSPQ89K4eC59tmQYCt44qph7wXoJu"
 
 // NEED UPDATE ENTRYPOINT !!
@@ -13,4 +13,45 @@ async function createProposal(proposal: Proposal, tezos: TezosToolkit): Promise<
   return op;
 }
 
-export { createProposal }
\ No newline at end of file
+// NEED UPDATE ENTRYPOINT !!
+async function voteForProposal(proposalName: string, vote: boolean, tezos: TezosToolkit): Promise<Operation> {
+    const proposalVote = {
+        proposalName: proposalName,
+        proposalVote: vote
+    } 
+
+    const contract = await tezos.contract.at(address);
+    const op: Operation = await contract.methodsObject.voteForProposal(proposalVote).send();
+  
+    await op.confirmation();
+    return op;
+}
+
+// NEED UPDATE ENTRYPOINT !!
+async function closeProposal(proposalName: string, tezos: TezosToolkit): Promise<Operation> {
+    const contract = await tezos.contract.at(address);
+    const op: Operation = await contract.methodsObject.closeProposal(proposalName).send();
+  
+    await op.confirmation();
+    return op;
+}
+
+// NEED UPDATE ENTRYPOINT !!
+async function resolveProposal(proposalName: string, tezos: TezosToolkit): Promise<Operation> {
+    const contract = await tezos.contract.at(address);
+    const op: Operation = await contract.methodsObject.resolveProposal(proposalName).send();
+  
+    await op.confirmation();
+    return op;
+}
+
+// NEED UPDATE ENTRYPOINT !!
+async function viewVoteInProgressProposal(proposalName: string, tezos: TezosToolkit): Promise<Operation> {
+    const contract = await tezos.contract.at(address);
+    const op: Operation = await contract.methodsObject.viewVoteInProgressProposal(proposalName).send();
+  
+    await op.confirmation();
+    return op;
+}
+
+export { createProposal, voteForProposal, viewVoteInProgressProposal, closeProposal, resolveProposal }
\ No newline at end of file
diff --git a/src/services/token.service.ts b/src/services/token.service.ts
index 3d0bab7..fdce089 100644
--- a/src/services/token.service.ts
+++ b/src/services/token.service.ts
@@ -12,4 +12,22 @@ async function createFAToken(tezos: TezosToolkit): Promise<Operation> {
   return op;
 }
 
-export { createFAToken }
\ No newline at end of file
+// NEED UPDATE ENTRYPOINT !!
+async function burnToken(amount: number, tezos: TezosToolkit): Promise<Operation> {
+    const contract = await tezos.contract.at(address);
+    const op: Operation = await contract.methodsObject.burnToken(amount).send();
+  
+    await op.confirmation();
+    return op;
+}
+
+// NEED UPDATE ENTRYPOINT !!
+async function buyToken(amount: number, tezos: TezosToolkit): Promise<Operation> {
+    const contract = await tezos.contract.at(address);
+    const op: Operation = await contract.methodsObject.buyToken(amount).send();
+  
+    await op.confirmation();
+    return op;
+}
+
+export { createFAToken, burnToken, buyToken }
\ No newline at end of file
diff --git a/src/types/Association.ts b/src/types/Association.ts
index e3240a7..0e4faa9 100644
--- a/src/types/Association.ts
+++ b/src/types/Association.ts
@@ -1,6 +1,6 @@
 export type Association = {
     name: string;
     description: string;
-    tokenReference: string;
+    tokenReference?: string;
     entranceFee?: number;
 }
\ No newline at end of file
diff --git a/src/types/Proposal.ts b/src/types/Proposal.ts
index 260a6fd..b3fb3cb 100644
--- a/src/types/Proposal.ts
+++ b/src/types/Proposal.ts
@@ -2,4 +2,6 @@ export type Proposal = {
     title: string;
     description: string;
     fct: () => void;
+    participationRate?: number;
+    approveRate?: number;
 }
\ No newline at end of file
diff --git a/src/getRole.ts b/src/utils/getRole.ts
similarity index 83%
rename from src/getRole.ts
rename to src/utils/getRole.ts
index 0962a6a..349eaaf 100644
--- a/src/getRole.ts
+++ b/src/utils/getRole.ts
@@ -6,4 +6,7 @@ export function getRole(tezos: TezosToolkit) {
     // IF HAS TOKEN -> ADHERENT
 
     // ELSE -> CONNECTED
+
+    // TEMPORARY
+    return "ADHERENT"
 }
\ No newline at end of file
-- 
GitLab