Skip to content

Commit

Permalink
feat: Improve cli errors (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
valiafetisov authored Jul 17, 2024
1 parent 4a78825 commit 6ca82c9
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 75 deletions.
109 changes: 50 additions & 59 deletions cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { hideBin } from 'yargs/helpers';
import { envPath, getProvider, getSigner } from './src/network.js';
import { getVariables, setVariable } from './src/configure.js';
import { createAttestation, getAtttestationEventsByAttester, getSpellEvents, getSpellStatus, revokeAttestation } from './src/attestations.js';
import { formatAttestationEvent } from './src/helpers.js';
import { formatAttestationEvent, handleErrors, prettify } from './src/helpers.js';

yargs(hideBin(process.argv))
.parserConfiguration({
Expand Down Expand Up @@ -39,22 +39,16 @@ yargs(hideBin(process.argv))
requiresArg: true,
});
},
async (argv) => {
async argv => handleErrors(argv.verbose, async ({ printSuccess }) => {
const options = {
userAddress: argv.userAddress,
userPseudonym: argv.userPseudonym,
teamName: argv.teamName,
};
console.info(
`Attempting to create identity attestation for ${JSON.stringify(
options,
null,
2,
)}...`,
);
const { url } = await createAttestation(await getProvider(), 'identity', options);
console.info(`Successfully created new identity attestation: ${url}`);
},
console.info(`Attempting to create identity attestation for ${prettify(options)}...`);
const { url } = await createAttestation(await getProvider(), 'identity', options, argv.verbose);
printSuccess(`Successfully created new identity attestation: ${url}`);
}),
)
.command(
'create-spell',
Expand Down Expand Up @@ -90,23 +84,17 @@ yargs(hideBin(process.argv))
requiresArg: true,
});
},
async (argv) => {
async argv => handleErrors(argv.verbose, async ({ printSuccess }) => {
const options = {
payloadId: argv.payloadId,
crafter: argv.crafter,
reviewerA: argv.reviewerA,
reviewerB: argv.reviewerB,
};
console.info(
`Attempting to create Spell attestation for ${JSON.stringify(
options,
null,
2,
)}...`,
);
const { url } = await createAttestation(await getProvider(), 'spell', options);
console.info(`Successfully created new Spell attestation: ${url}`);
},
console.info(`Attempting to create Spell attestation for ${prettify(options)}...`);
const { url } = await createAttestation(await getProvider(), 'spell', options, argv.verbose);
printSuccess(`Successfully created new Spell attestation: ${url}`);
}),
)
.command(
'create-deployment',
Expand Down Expand Up @@ -135,28 +123,22 @@ yargs(hideBin(process.argv))
requiresArg: true,
});
},
async (argv) => {
async argv => handleErrors(argv.verbose, async ({ printSuccess }) => {
const options = {
payloadId: argv.payloadId,
payloadAddress: argv.payloadAddress,
payloadHash: argv.payloadHash,
};
console.info(
`Attempting to create deployment attestation for ${JSON.stringify(
options,
null,
2,
)}...`,
);
const { url } = await createAttestation(await getProvider(), 'deployment', options);
console.info(`Successfully created new deployment attestation: ${url}`);
},
console.info(`Attempting to create deployment attestation for ${prettify(options)}...`);
const { url } = await createAttestation(await getProvider(), 'deployment', options, argv.verbose);
printSuccess(`Successfully created new deployment attestation: ${url}`);
}),
)
.command(
'revoke [attestation-uid]',
'Revoke existing attestation',
() => {},
async (argv) => {
async argv => handleErrors(argv.verbose, async ({ printSuccess }) => {
const attestationUid = argv.attestationUid;
if (!attestationUid) {
console.info(`No [attestation-uid] provided, attempting to fetch all attestations that are possible to revoke...`);
Expand All @@ -170,53 +152,62 @@ yargs(hideBin(process.argv))
return;
}
console.info(`Attempting to revoke attestation ${attestationUid}...`);
const { url } = await revokeAttestation(await getProvider(), attestationUid);
console.info(`Successfully revoked attestation: ${url}`);
},
const { url } = await revokeAttestation(await getProvider(), attestationUid, argv.verbose);
printSuccess(`Successfully revoked attestation: ${url}`);
}),
)
.command(
'status [payload-id]',
'Get status of existing spell',
() => {},
async (argv) => {
async argv => handleErrors(argv.verbose, async ({ printSuccess, printError }) => {
const payloadId = argv.payloadId;
if (payloadId) {
console.info(`Attempting to fetch current status of ${payloadId}...`);
const spellStatus = await getSpellStatus(await getProvider(), payloadId);
console.info(spellStatus.message);
if (!spellStatus.events.length) {
console.info(`No previous attestation events found for "${payloadId}"`);
} else {
console.table(spellStatus.events.map(formatAttestationEvent));
if (!payloadId) {
console.info(`Attempting to fetch all previously attested Spells...`);
const spellAttestations = await getSpellEvents(await getProvider());
if (spellAttestations.length === 0) {
console.info(`No previous Spell attestation events found`);
return;
}
console.info(`Found the following Spell attestation events:`);
console.table(spellAttestations.map(formatAttestationEvent));
return;
}
console.info(`Attempting to fetch all previously attested Spells...`);
const spellAttestations = await getSpellEvents(await getProvider());
if (spellAttestations.length === 0) {
console.info(`No previous Spell attestation events found`);
return;
console.info(`Attempting to fetch current status of ${payloadId}...`);
const spellStatus = await getSpellStatus(await getProvider(), payloadId);
if (!spellStatus.events.length) {
console.info(`No previous attestation events found for "${payloadId}"`);
} else {
console.table(spellStatus.events.map(formatAttestationEvent));
}
console.info(`Found the following Spell attestation events:`);
console.table(spellAttestations.map(formatAttestationEvent));
},
if (spellStatus.reason) {
printError(spellStatus.message);
} else {
printSuccess(spellStatus.message);
}
}),
)
.command(
'configure [key] [value]',
'Configure env variables',
() => {},
(argv) => {
async argv => handleErrors(argv.verbose, async ({ printSuccess }) => {
if (!argv.key || !argv.value) {
console.info('To configure a variable, please provide its [key] and [value], for example:');
console.info('npx spell-attester configure RPC_URL http://...');
console.info(`\nCurrently set variables (found in "${envPath}"):`);
console.info(JSON.stringify(getVariables(envPath), null, 4));
console.info(prettify(getVariables(envPath)));
return;
}
setVariable(envPath, argv.key, argv.value);
console.info(`Variable "${argv.key}" was successfully saved into "${envPath}"`);
},
printSuccess(`Variable "${argv.key}" was successfully saved into "${envPath}"`);
}),
)
.strictCommands()
.demandCommand(1)
.option('verbose', {
type: 'boolean',
description: 'Run with verbose logging',
requiresArg: false,
})
.parse();
79 changes: 69 additions & 10 deletions cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "spell-attester",
"version": "0.0.14",
"version": "0.0.15",
"description": "CLI for the Maker Spell Attestation contracts",
"repository": {
"type": "git",
Expand All @@ -27,6 +27,7 @@
"license": "GPL-3.0-or-later",
"dependencies": {
"@ethereum-attestation-service/eas-sdk": "^0.29.1",
"chalk": "^5.3.0",
"dotenv": "^16.4.5",
"ethers": "^5.7.2",
"yargs": "^17.7.2"
Expand Down
16 changes: 11 additions & 5 deletions cli/src/attestations.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import ethers from 'ethers';
import { NO_EXPIRATION, ZERO_ADDRESS } from '@ethereum-attestation-service/eas-sdk';
import { getEasAttesterContract, getEasRegistryContract, getSpellAttesterContract } from './contracts.js';
import { getConfig, getDateFromBlockNumber, getSigner } from './network.js';
import { decodeAttestationData, encodeAttestationData } from './helpers.js';
import { decodeAttestationData, decodeErrorMessage, encodeAttestationData } from './helpers.js';

const generateAttestationUrl = async function (provider, attestationId) {
const config = await getConfig(provider);
Expand All @@ -28,7 +28,7 @@ export const getAttestationData = async function (provider, attestationId) {
};
};

export const createAttestation = async function (provider, name, options) {
export const createAttestation = async function (provider, name, options, verbose) {
// Get relevant data
const spellAttester = await getSpellAttesterContract(provider);
const schemaId = await spellAttester.schemaNameToSchemaId(ethers.utils.formatBytes32String(name));
Expand Down Expand Up @@ -57,11 +57,14 @@ export const createAttestation = async function (provider, name, options) {
url: await generateAttestationUrl(provider, attestationId),
};
} catch (error) {
throw new Error(`Attestation can not be created: ${error?.error?.reason || error?.reason || error}`);
if (verbose) {
console.error(error);
}
throw new Error(`Attestation can not be created: ${decodeErrorMessage(error)}`);
}
};

export const revokeAttestation = async function (provider, attestationId) {
export const revokeAttestation = async function (provider, attestationId, verbose) {
// Get relevant data
const easAttester = (await getEasAttesterContract(provider)).connect(getSigner(provider));
const attestation = await getAttestation(provider, attestationId);
Expand All @@ -83,7 +86,10 @@ export const revokeAttestation = async function (provider, attestationId) {
url: await generateAttestationUrl(provider, attestationId),
};
} catch (error) {
throw new Error(`Attestation can not be revoked: ${error?.error?.reason || error?.reason}`);
if (verbose) {
console.error(error);
}
throw new Error(`Attestation can not be revoked: ${decodeErrorMessage(error)}`);
}
};

Expand Down
Loading

0 comments on commit 6ca82c9

Please sign in to comment.