diff --git a/index.ts b/index.ts index 1661b238c46357e888d19dd624c90a4a3fa3f50b..23822823401a26c3e3f5d713fa75cfe64980677f 100644 --- a/index.ts +++ b/index.ts @@ -16,7 +16,7 @@ import { type WalletData } from './src/types/WalletData.js' // IMPORT HANDLERS import { handleAdminChoice, handleAdherentChoice, handleConnectedChoice } from './src/handlers/roleHandlers.js' import { type Role } from './src/types/Role.js' -import { handleHasToken } from './src/utils/hasToken.js' +import { hasToken } from './src/features/token/hasToken.js' const tezos = new TezosToolkit('https://ghostnet.tezos.marigold.dev') const program = new Command() @@ -54,29 +54,28 @@ program.command('main') ] switch (role) { case 'ADMIN': - questions[0].choices = ['Résoudre une proposition', 'Clôturer une proposition', 'Voir les propositions', 'Créer un token'] + questions[0].choices = ['Résoudre une proposition', 'Clôturer une proposition', 'Voir les propositions', 'Créer un token', 'Voir ma balance de tokens'] - if (await handleHasToken(tezos)) { questions[0].choices.push('Brûler un token') } + if (await hasToken(tezos)) { questions[0].choices.push('Brûler un token') } await inquirer.prompt(questions).then(async (answers: { choice: string }) => { await handleAdminChoice(answers.choice, tezos) }) break case 'ADHERENT': - // VOTER POUR UNE PROPOSITION - // CLOTURER ET RESOUDRE LES PROPOSITIONS DONT IL EST LE CREATEUR - questions[0].choices = ['Faire une proposition', 'Voter pour une proposition', 'Voir les propositions', 'Créer un token'] + // TODO: CLOTURER ET RESOUDRE LES PROPOSITIONS DONT IL EST LE CREATEUR + questions[0].choices = ['Faire une proposition', 'Voter pour une proposition', 'Voir les propositions', 'Créer un token', 'Voir ma balance de tokens'] - if (await handleHasToken(tezos)) { questions[0].choices.push('Brûler un token') } + if (await hasToken(tezos)) { questions[0].choices.push('Brûler un token') } await inquirer.prompt(questions).then(async (answers: { choice: string }) => { await handleAdherentChoice(answers.choice, tezos) }) break case 'CONNECTED': - questions[0].choices = ['Rejoindre une association', 'Voir les associations', "Voir les détails d'une association", 'Créer un token'] + questions[0].choices = ['Rejoindre une association', 'Voir les associations', "Voir les détails d'une association", 'Créer un token', 'Voir ma balance de tokens'] - if (await handleHasToken(tezos)) { questions[0].choices.push('Brûler un token', 'Créer une association') } + if (await hasToken(tezos)) { questions[0].choices.push('Brûler un token', 'Créer une association') } await inquirer.prompt(questions).then(async (answers: { choice: string }) => { await handleConnectedChoice(answers.choice, tezos) diff --git a/src/features/token/hasToken.ts b/src/features/token/hasToken.ts new file mode 100644 index 0000000000000000000000000000000000000000..841f9e0e56a442ef88c4532f444f337eea5c513f --- /dev/null +++ b/src/features/token/hasToken.ts @@ -0,0 +1,22 @@ +import { type TezosToolkit } from '@taquito/taquito' +import chalk from 'chalk' +import { handleGetTokenBalance } from '../../handlers/token/tokenHandlers.js' + +/** + * Return if there's a token. + * @param {TezosToolkit} tezos - The instance of the Tezos toolkit. + * @returns {Promise<boolean>} A promise resolved once the token balance is displayed. + */ +async function hasToken (tezos: TezosToolkit): Promise<boolean> { + let hasToken = false + await handleGetTokenBalance(tezos).then((response) => { + hasToken = response > 0 + }).catch((error) => { + console.log(chalk.bgRed(`\n${error.message}`)) + return false + }) + + return hasToken +} + +export { hasToken } diff --git a/src/features/token/showTokenBalance.ts b/src/features/token/showTokenBalance.ts new file mode 100644 index 0000000000000000000000000000000000000000..f95571f4303312543be68fc08ed3f641d89fd663 --- /dev/null +++ b/src/features/token/showTokenBalance.ts @@ -0,0 +1,18 @@ +import { type TezosToolkit } from '@taquito/taquito' +import chalk from 'chalk' +import { handleGetTokenBalance } from '../../handlers/token/tokenHandlers.js' + +/** + * Displays token balance. + * @param {TezosToolkit} tezos - The instance of the Tezos toolkit. + * @returns {Promise<void>} A promise resolved once the token balance is displayed. + */ +async function showTokenBalance (tezos: TezosToolkit): Promise<void> { + await handleGetTokenBalance(tezos).then((response) => { + console.log(`${chalk.cyan('Nombre de token:')} ${chalk.yellow(response)}`) + }).catch((error) => { + console.log(chalk.bgRed(`\n${error.message}`)) + }) +} + +export { showTokenBalance } diff --git a/src/handlers/roleHandlers.ts b/src/handlers/roleHandlers.ts index b10e92049ca63f17f37ba9401f45af600b68e3c1..c461aa67e3aa4654721eb5092839409be49097cd 100644 --- a/src/handlers/roleHandlers.ts +++ b/src/handlers/roleHandlers.ts @@ -12,6 +12,7 @@ import { resolveProposal } from '../features/proposal/resolveProposal.js' import { showProposals } from '../features/proposal/showProposals.js' import { closeProposal } from '../features/proposal/closeProposal.js' import { voteProposal } from '../features/proposal/voteProposal.js' +import { showTokenBalance } from '../features/token/showTokenBalance.js' /** * Handles administrator actions based on the specified choice. @@ -36,6 +37,9 @@ async function handleAdminChoice (choice: string, tezos: TezosToolkit): Promise< case 'Voir les propositions': await showProposals(tezos) break + case 'Voir ma balance de tokens': + await showTokenBalance(tezos) + break case 'Voir mon portefeuille': await showBalance(tezos) break @@ -71,6 +75,9 @@ async function handleAdherentChoice (choice: string, tezos: TezosToolkit): Promi case 'Brûler un token': await burnToken(tezos) break + case 'Voir ma balance de tokens': + await showTokenBalance(tezos) + break default: console.log(chalk.bgRedBright('\nChoix invalide\n')) break @@ -106,6 +113,9 @@ async function handleConnectedChoice (choice: string, tezos: TezosToolkit): Prom case 'Brûler un token': await burnToken(tezos) break + case 'Voir ma balance de tokens': + await showTokenBalance(tezos) + break default: console.log(chalk.bgRedBright('\nChoix invalide\n')) break diff --git a/src/handlers/token/tokenHandlers.ts b/src/handlers/token/tokenHandlers.ts index 710e399aa230852077249613b0d6a3cd5e9cc764..7108f7b5b2672297cdde3a173f2c974ac966d015 100644 --- a/src/handlers/token/tokenHandlers.ts +++ b/src/handlers/token/tokenHandlers.ts @@ -2,7 +2,7 @@ import { type TezosToolkit } from '@taquito/taquito' // IMPORT SERVICE -import { burnToken, createFAToken } from '../../services/token.service.js' +import { burnToken, createFAToken, getTokenBalance } from '../../services/token.service.js' import inquirer from 'inquirer' /** @@ -57,4 +57,17 @@ async function handleBurnToken (tezos: TezosToolkit): Promise<void> { } } -export { handleCreateToken, handleBurnToken } +/** + * Handles the process of get token balance. + * @param {TezosToolkit} tezos - The TezosToolkit instance used for blockchain operations. + * @returns {Promise<void>} A promise resolved once the retrieve process is complete. + */ +async function handleGetTokenBalance (tezos: TezosToolkit): Promise<number> { + try { + return await getTokenBalance(tezos) + } catch (error) { + throw new Error(`${error}`) + } +} + +export { handleCreateToken, handleBurnToken, handleGetTokenBalance } diff --git a/src/services/token.service.ts b/src/services/token.service.ts index 19bfaa28286134049b15aa47ef4006546c721fc1..5e3a5ee65775b096ea841376beef25266c73a8d0 100644 --- a/src/services/token.service.ts +++ b/src/services/token.service.ts @@ -16,18 +16,15 @@ async function burnToken (tezos: TezosToolkit): Promise<void> { await op.confirmation() } -// 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) +async function getTokenBalance (tezos: TezosToolkit): Promise<number> { + const contract = await tezos.contract.at(address) - // await op.confirmation() + const executionContextParams = { + viewCaller: contract.address + } + const balance = await contract.contractViews.get_balance(await tezos.signer.publicKeyHash()).executeView(executionContextParams) - return true + return balance.token.toNumber() } -export { createFAToken, burnToken, hasToken } +export { createFAToken, burnToken, getTokenBalance } diff --git a/src/utils/hasToken.ts b/src/utils/hasToken.ts deleted file mode 100644 index ed88d53e234d1776aeef20e93d20bb7a6367e39a..0000000000000000000000000000000000000000 --- a/src/utils/hasToken.ts +++ /dev/null @@ -1,8 +0,0 @@ -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 190dc699d50be570d2b94f9fab1ab9a98159be21..21c2bdc79c6548a12c240f3801a0f692e0796b00 100644 --- a/test/handlers/roleHandlers.spec.ts +++ b/test/handlers/roleHandlers.spec.ts @@ -12,6 +12,7 @@ import { showAssociations } from '../../src/features/association/showAssociation import { resolveProposal } from '../../src/features/proposal/resolveProposal' import { showProposals } from '../../src/features/proposal/showProposals' import { closeProposal } from '../../src/features/proposal/closeProposal' +import { showTokenBalance } from '../../src/features/token/showTokenBalance' vi.mock('../../src/features/association/createAssociation', () => ({ createAssociation: vi.fn() @@ -57,6 +58,10 @@ vi.mock('../../src/features/proposal/showProposals', () => ({ showProposals: vi.fn() })) +vi.mock('../../src/features/token/showTokenBalance', () => ({ + showTokenBalance: vi.fn() +})) + const mockedTezosToolkit = {} as unknown as TezosToolkit describe('roleHandlers', () => { @@ -105,6 +110,14 @@ describe('roleHandlers', () => { }) }) + describe('when choice is "Voir ma balance de tokens"', () => { + it('should call showTokenBalance', async () => { + await handleAdminChoice('Voir ma balance de tokens', mockedTezosToolkit) + + expect(showTokenBalance).toBeCalled() + }) + }) + describe('when choice is "Voir mon portefeuille"', () => { it('should call showBalance', async () => { await handleAdminChoice('Voir mon portefeuille', mockedTezosToolkit) @@ -151,7 +164,7 @@ describe('roleHandlers', () => { describe('when choice is "Brûler un token"', () => { it('should call burnToken', async () => { - await handleAdminChoice('Brûler un token', mockedTezosToolkit) + await handleAdherentChoice('Brûler un token', mockedTezosToolkit) expect(burnToken).toBeCalled() }) @@ -159,12 +172,20 @@ describe('roleHandlers', () => { describe('when choice is "Voir les propositions"', () => { it('should call showProposals', async () => { - await handleAdminChoice('Voir les propositions', mockedTezosToolkit) + await handleAdherentChoice('Voir les propositions', mockedTezosToolkit) expect(showProposals).toBeCalled() }) }) + describe('when choice is "Voir ma balance de tokens"', () => { + it('should call showTokenBalance', async () => { + await handleAdherentChoice('Voir ma balance de tokens', mockedTezosToolkit) + + expect(showTokenBalance).toBeCalled() + }) + }) + describe('when choice is invalid', () => { it('should log "Choix invalide"', async () => { const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}) @@ -218,12 +239,20 @@ describe('roleHandlers', () => { describe('when choice is "Brûler un token"', () => { it('should call burnToken', async () => { - await handleAdminChoice('Brûler un token', mockedTezosToolkit) + await handleConnectedChoice('Brûler un token', mockedTezosToolkit) expect(burnToken).toBeCalled() }) }) + describe('when choice is "Voir ma balance de tokens"', () => { + it('should call showTokenBalance', async () => { + await handleConnectedChoice('Voir ma balance de tokens', mockedTezosToolkit) + + expect(showTokenBalance).toBeCalled() + }) + }) + describe('when choice is invalid', () => { it('should log "Choix invalide"', async () => { const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})