Socket
Socket
Sign inDemoInstall

coffee-crypto-cli

Package Overview
Dependencies
75
Maintainers
1
Versions
43
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.2.1-canary-e39dcca.0 to 2.0.0

dist/types.js

9

.prettierrc.json
{
"semi": true,
"singleQuote": true,
"arrowParens": "avoid",
"bracketSpacing": true,
"printWidth": 80,
"bracketSpacing": true,
"semi": false,
"tabWidth": 2,
"useTabs": false,
"trailingComma": "none",
"arrowParens": "avoid"
"trailingComma": "none"
}

@@ -5,10 +5,23 @@ # Changelog

## 1.2.0 (2022-09-15)
## [2.0.0](https://github.com/zidious/crypto-cli/compare/v1.2.0...v2.0.0) (2023-11-29)
### ⚠ BREAKING CHANGES
- simplify CLI usage (#63)
- use kebab casing (#59)
### Features
* add ability to export coin data via JSON and/or CSV with new `--save` flag ([#30](https://github.com/zidious/crypto-cli/issues/30)) ([7b2e5cd](https://github.com/zidious/crypto-cli/commit/7b2e5cd957588d9bca3a4da9042ce36472cfc3f2))
- simplify CLI usage ([#63](https://github.com/zidious/crypto-cli/issues/63)) ([6a61b55](https://github.com/zidious/crypto-cli/commit/6a61b55152c54b2e99677a977fdbfd82ad9da76a))
### Bug Fixes
- use kebab casing ([#59](https://github.com/zidious/crypto-cli/issues/59)) ([8439643](https://github.com/zidious/crypto-cli/commit/84396435ba0fe5afc5032c3b79b29eea4f24755d))
## 1.2.0 (2022-09-15)
### Features
- add ability to export coin data via JSON and/or CSV with new `--save` flag ([#30](https://github.com/zidious/crypto-cli/issues/30)) ([7b2e5cd](https://github.com/zidious/crypto-cli/commit/7b2e5cd957588d9bca3a4da9042ce36472cfc3f2))
## 1.1.0 (2022-07-30)

@@ -15,0 +28,0 @@

import { format, logSuccess } from '../utils.js';
export const priceStats = ({ name, current_price, total_volume, high_24h, low_24h, percent24h, athPrice, athPercent }, { price, priceChange, high, low, volume, ath, athChange }) => {
const priceRes = `${name}: ${format(current_price)}`;
let priceChangeRes;
let volumeRes;
let highRes;
let lowRes;
let athRes;
let athChangeRes;
if (priceChange) {
priceChangeRes = `change (24H): ${percent24h.toFixed(2)}%`;
export const priceStats = ({ results, flags }) => {
for (const result of results) {
const priceRes = `${result.name}: ${format(result.current_price)}`;
let priceChangeRes;
let volumeRes;
let highRes;
let lowRes;
let athRes;
let athChangeRes;
if (flags.priceChange) {
priceChangeRes = `change (24H): ${result.price_change_24h.toFixed(2)}%`;
}
if (flags.high) {
highRes = `high (24H): ${format(result.high_24h)}`;
}
if (flags.low) {
lowRes = `low (24H): ${format(result.low_24h)}`;
}
if (flags.volume) {
volumeRes = `volume (24H): ${format(result.total_volume)}`;
}
if (flags.ath) {
athRes = `ATH: ${format(result.ath)}`;
}
if (flags.athChange) {
athChangeRes = `ATH (%): ${result.atl_change_percentage.toFixed(2)}%`;
}
logSuccess([
priceRes,
priceChangeRes,
volumeRes,
highRes,
lowRes,
athRes,
athChangeRes
]
.filter(Boolean)
.join(' - '));
}
if (high) {
highRes = `high (24H): ${format(high_24h)}`;
}
if (low) {
lowRes = `low (24H): ${format(low_24h)}`;
}
if (volume) {
volumeRes = `volume (24H): ${format(total_volume)}`;
}
if (ath) {
athRes = `ATH: ${format(athPrice)}`;
}
if (athChange) {
athChangeRes = `ATH (%): ${athPercent.toFixed(2)}%`;
}
logSuccess([priceRes, priceChangeRes, volumeRes, highRes, lowRes, athRes, athChangeRes]
.filter(Boolean)
.join(' - '));
};
import fs from 'fs';
import { parseAsync } from 'json2csv';
import { logError, logSuccess } from '../utils.js';
import { formatFileName, logError, logSuccess } from '../utils.js';
import { CSVEXT, JSONEXT } from '../constants.js';
export const saveCoinData = async (options, exportData) => {
export const saveCoinData = async ({ options, results }) => {
if (!options) {
return;
}
const fileExts = options.toLowerCase().split(',');

@@ -10,2 +13,6 @@ if (!fileExts.some(fileExt => fileExt.toLowerCase() === JSONEXT || fileExt.toLowerCase() === CSVEXT)) {

}
const exportData = [];
for (const result of results) {
exportData.push(result);
}
logSuccess('Exporting coin data...');

@@ -33,7 +40,2 @@ if (fileExts.includes(JSONEXT)) {

};
const formatFileName = (coinName, fileExt) => {
/* use unix timestamp, resolves conflict of same filenames */
const timestamp = new Date().valueOf();
return `${coinName.toLowerCase()}-${timestamp}.${fileExt}`;
};
const formatCsvFile = async (coin) => {

@@ -70,3 +72,3 @@ return await parseAsync(coin, {

label: 'All Time High',
value: 'all_time_high'
value: 'ath'
},

@@ -73,0 +75,0 @@ {

@@ -1,3 +0,2 @@

/** contstants */
export const JSONEXT = 'json';
export const CSVEXT = 'csv';
#!/usr/bin/env node
import meow from 'meow';
import { app } from './app.js';
import CoinGeckoAPI from '@crypto-coffee/coingecko-api';
import { logError } from './utils.js';
import { saveCoinData } from './actions/saveCoinData.js';
import { priceStats } from './actions/priceStats.js';
const cli = meow(`
Usage:
$ crypto --price <coin name> <additional flags>
$ crypto <coin ticker(s)> <additional flags>
Options:
--price, --p - coin name
--priceChange, --pc - coin price change (%) in the past 24 hours
--volume, --v - coin volume in the past 24 hours
--high - highest price sold in the past 24 hours
--low - lowest price sold in the past 24 hours
--ath - coin all time high price
--athChange, --athc - percent price change from ATH
--version - current version of the crypto-cli tool
--save - export all coin data to CSV and/or JSON
--price-change, --pc Coin price change (%) in the past 24 hours
--volume, --v Coin volume in the past 24 hours
--ath-change, -athc Percent price change from the all time high
--high, --h Highest price sold in the past 24 hours
--low, --l Lowest price sold in the past 24 hours
--ath Coin all time high price
--save json,csv Save coin data via JSON and/or CSV
--version Current version
Examples:
$crypto --price bitcoin --pc
$crypto bitcoin --pc
>> bitoin: $1337 - change (24H): 13.37%
$crypto bitcoin,ethereum
>> bitcoin: $1337
>> ethereum: $1337
Save coin data:
$crypto --save json
$crypto --save json,csv
$crypto bitcoin --save json
$crypto bitcoin --save json,csv
`, {
importMeta: import.meta,
flags: {
price: {
type: 'string',
isMultiple: true,
alias: 'p'
},
priceChange: {

@@ -43,6 +44,8 @@ type: 'boolean',

high: {
type: 'boolean'
type: 'boolean',
alias: 'h'
},
low: {
type: 'boolean'
type: 'boolean',
alias: 'l'
},

@@ -61,2 +64,28 @@ ath: {

});
app(cli.input[0], cli.flags);
const app = async () => {
const { save } = cli.flags;
const coinTickers = cli.input[0];
if (!coinTickers) {
logError('No coin name provided. Check `crypto --help` for help');
}
const gecko = new CoinGeckoAPI.default();
const results = await gecko.coinMarkets({
vs_currency: 'usd',
ids: coinTickers
});
if (!results.length) {
logError(`Unknown coin: ${coinTickers}`);
}
priceStats({
results,
flags: cli.flags
});
await saveCoinData({
options: save,
results
});
process.exit(0);
};
app().catch(error => {
logError(`An error occured: ${error.message}\n Please report the issue here: https://github.com/Zidious/crypto-cli`);
});

@@ -18,1 +18,6 @@ import chalk from 'chalk';

};
export const formatFileName = (coinName, fileExt) => {
/* use unix timestamp, resolves conflict of same filenames */
const timestamp = new Date().valueOf();
return `${coinName.toLowerCase()}-${timestamp}.${fileExt}`;
};
{
"name": "coffee-crypto-cli",
"version": "1.2.1-canary-e39dcca.0",
"version": "2.0.0",
"description": "Cryptocurrency CLI price tool",

@@ -22,2 +22,3 @@ "main": "dist/index.js",

"test": "mocha 'src/*.test.ts'",
"lint": "eslint --fix",
"prepare": "husky install",

@@ -40,21 +41,22 @@ "precommit": "lint-staged"

"@types/mocha": "^10.0.1",
"@types/node": "^20.3.3",
"@typescript-eslint/eslint-plugin": "^5.61.0",
"@typescript-eslint/parser": "^5.54.0",
"chai": "^4.3.7",
"eslint": "^8.44.0",
"execa": "^7.1.1",
"@types/node": "^20.6.0",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
"chai": "^4.3.8",
"eslint": "^8.49.0",
"execa": "^8.0.1",
"husky": "^8.0.3",
"lint-staged": "^13.2.3",
"lint-staged": "^14.0.1",
"mocha": "^10.2.0",
"prettier": "^2.8.8",
"prettier": "^3.0.3",
"rimraf": "^4.3.0",
"ts-node": "^10.9.1",
"typescript": "^5.1.6"
"typescript": "^5.2.2"
},
"lint-staged": {
"*.{md,ts}": [
"*.ts": [
"eslint --fix",
"prettier --write"
]
],
"*.md": "prettier --write"
},

@@ -61,0 +63,0 @@ "keywords": [

@@ -24,11 +24,7 @@ # crypto-cli

```sh
yarn add global coffee-crypto-cli
```
## Usage
```sh
$ crypto --price bitcoin --volume --ath
>> Bitcoin: $20,000 - volume: $13,337 - ATH: $68,000
$ crypto bitcoin
>> Bitcoin: $20,000
```

@@ -38,66 +34,17 @@

Note: `--price, --p` is required for any of the subsequent flags.
| Name | Description |
| ------------------------ | ------------------------------------------- |
| `--price-change`, `--pc` | Coin price change (%) in the past 24 hours |
| `--volume`, `--v` | Coin volume in the past 24 hours |
| `--ath-change`, `--athc` | Percent price change from the all time high |
| `--high`, `--h` | Highest price sold in the past 24 hours |
| `--low`, `--l` | Lowest price sold in the past 24 hours |
| `--ath` | Coin all time high price |
| `--save json,csv` | Save coin data via JSON and/or CSV |
| `--help` | Flag description and usage examples |
| `--version` | Current version |
```sh
--price, --p - coin name
```
Coin price change (%) in the past 24 hours.
```sh
--priceChange, --pc
```
Coin volume in the past 24 hours.
```sh
--volume, --v
```
Highest price sold in the past 24 hours.
```sh
--high
```
Lowest price sold in the past 24 hours.
```sh
--low
```
Coin all time high price.
```sh
--ath
```
Percent price change from the all time high.
```sh
--athChange, --athc
```
Save coin data via JSON and/or CSV
```sh
--save json
--save json,csv
```
CLI help message.
```sh
--help
```
Current version.
```sh
--version
```
## Local Development
First things first, we'll need to clone the repo, install the dependencies, and, build the project.
Clone the repo, install the dependencies, and, build the project.

@@ -109,9 +56,9 @@ ```sh

```sh
yarn install && yarn build
yarn install --frozen-lockfile && yarn build
```
To run the CLI locally, use the below command followed by the flag you want to run.
To run the CLI locally:
```sh
node dist/index.js --price bitcoin
node dist/index.js bitcoin
```

@@ -118,0 +65,0 @@

@@ -1,67 +0,52 @@

import { format, logSuccess } from '../utils.js';
import type { Flags } from '../constants.js';
import { format, logSuccess } from '../utils.js'
import type { PriceStatsParams } from '../types.js'
interface PriceStatsParams {
name: string;
current_price: number;
total_volume: number;
high_24h: number;
low_24h: number;
percent24h: number;
athPrice: number;
athPercent: number;
}
export const priceStats = ({ results, flags }: PriceStatsParams): void => {
for (const result of results) {
const priceRes = `${result.name}: ${format(result.current_price)}`
let priceChangeRes
let volumeRes
let highRes
let lowRes
let athRes
let athChangeRes
type PriceStatFlags = Omit<Flags, 'save'>;
if (flags.priceChange) {
priceChangeRes = `change (24H): ${result.price_change_24h.toFixed(2)}%`
}
export const priceStats = (
{
name,
current_price,
total_volume,
high_24h,
low_24h,
percent24h,
athPrice,
athPercent
}: PriceStatsParams,
{ price, priceChange, high, low, volume, ath, athChange }: PriceStatFlags
): void => {
const priceRes = `${name}: ${format(current_price)}`;
let priceChangeRes;
let volumeRes;
let highRes;
let lowRes;
let athRes;
let athChangeRes;
if (flags.high) {
highRes = `high (24H): ${format(result.high_24h)}`
}
if (priceChange) {
priceChangeRes = `change (24H): ${percent24h.toFixed(2)}%`;
}
if (flags.low) {
lowRes = `low (24H): ${format(result.low_24h)}`
}
if (high) {
highRes = `high (24H): ${format(high_24h)}`;
}
if (flags.volume) {
volumeRes = `volume (24H): ${format(result.total_volume)}`
}
if (low) {
lowRes = `low (24H): ${format(low_24h)}`;
}
if (flags.ath) {
athRes = `ATH: ${format(result.ath)}`
}
if (volume) {
volumeRes = `volume (24H): ${format(total_volume)}`;
}
if (flags.athChange) {
athChangeRes = `ATH (%): ${result.atl_change_percentage.toFixed(2)}%`
}
if (ath) {
athRes = `ATH: ${format(athPrice)}`;
logSuccess(
[
priceRes,
priceChangeRes,
volumeRes,
highRes,
lowRes,
athRes,
athChangeRes
]
.filter(Boolean)
.join(' - ')
)
}
if (athChange) {
athChangeRes = `ATH (%): ${athPercent.toFixed(2)}%`;
}
logSuccess(
[priceRes, priceChangeRes, volumeRes, highRes, lowRes, athRes, athChangeRes]
.filter(Boolean)
.join(' - ')
);
};
}

@@ -1,13 +0,18 @@

import fs from 'fs';
import { parseAsync } from 'json2csv';
import { logError, logSuccess } from '../utils.js';
import { CSVEXT, JSONEXT } from '../constants.js';
import type { ExportData } from '../constants.js';
import fs from 'fs'
import { parseAsync } from 'json2csv'
import { formatFileName, logError, logSuccess } from '../utils.js'
import { CSVEXT, JSONEXT } from '../constants.js'
import { CoinMarkets } from '@crypto-coffee/coingecko-api/dist/types.js'
import type { SaveCoinDataParams } from '../types.js'
export const saveCoinData = async (
options: string,
exportData: ExportData[]
) => {
const fileExts = options.toLowerCase().split(',');
export const saveCoinData = async ({
options,
results
}: SaveCoinDataParams) => {
if (!options) {
return
}
const fileExts = options.toLowerCase().split(',')
if (

@@ -21,25 +26,35 @@ !fileExts.some(

'Unable to export, unsupported file extension.\nPlease Check `crypto --help` for help'
);
)
}
logSuccess('Exporting coin data...');
const exportData: Partial<CoinMarkets>[] = []
for (const result of results) {
exportData.push(result)
}
logSuccess('Exporting coin data...')
if (fileExts.includes(JSONEXT)) {
writeFile(exportData, JSONEXT);
writeFile(exportData, JSONEXT)
}
if (fileExts.includes(CSVEXT)) {
await writeFile(exportData, CSVEXT);
await writeFile(exportData, CSVEXT)
}
logSuccess('Export complete.');
};
logSuccess('Export complete.')
}
const writeFile = async (exportData: ExportData[], fileExt: string) => {
const writeFile = async (
exportData: Partial<CoinMarkets>[],
fileExt: string
) => {
for (const coin of exportData) {
const data =
fileExt === JSONEXT ? JSON.stringify(coin) : await formatCsvFile(coin);
fileExt === JSONEXT ? JSON.stringify(coin) : await formatCsvFile(coin)
try {
fs.writeFileSync(formatFileName(coin.name as string, fileExt), data, {
encoding: 'utf8'
});
})
} catch (error) {

@@ -50,16 +65,9 @@ logError(

}`
);
)
}
}
};
}
const formatFileName = (coinName: string, fileExt: string): string => {
/* use unix timestamp, resolves conflict of same filenames */
const timestamp = new Date().valueOf();
return `${coinName.toLowerCase()}-${timestamp}.${fileExt}`;
};
const formatCsvFile = async (coin: ExportData): Promise<string> => {
return await parseAsync(coin as Readonly<ExportData>, {
const formatCsvFile = async (coin: Partial<CoinMarkets>): Promise<string> => {
return await parseAsync(coin, {
delimiter: ',',

@@ -94,3 +102,3 @@ excelStrings: false,

label: 'All Time High',
value: 'all_time_high'
value: 'ath'
},

@@ -102,3 +110,3 @@ {

]
});
};
})
}

@@ -1,17 +0,2 @@

/** contstants */
export const JSONEXT = 'json';
export const CSVEXT = 'csv';
/** types */
export type ExportData = Record<string, string | number>;
export interface Flags {
price: string[];
priceChange: boolean;
volume: boolean;
high: boolean;
low: boolean;
ath: boolean;
athChange: boolean;
save: string;
}
export const JSONEXT = 'json'
export const CSVEXT = 'csv'

@@ -1,29 +0,30 @@

import 'mocha';
import { assert } from 'chai';
import { execa, ExecaError, ExecaReturnValue } from 'execa';
import path from 'path';
import { fileURLToPath } from 'url';
import 'mocha'
import { assert } from 'chai'
import { execa, ExecaError, ExecaReturnValue } from 'execa'
import path from 'path'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url);
const CLI = path.resolve(path.dirname(__filename), '..', 'dist', 'index.js');
const __filename = fileURLToPath(import.meta.url)
const CLI = path.resolve(path.dirname(__filename), '..', 'dist', 'index.js')
describe('crypto-cli', () => {
// TODO: Skipping tests, we're getting rate limited: https://github.com/Zidious/crypto-cli/issues/17
describe.skip('crypto-cli', () => {
describe('no flags provided', () => {
it('returns error', async () => {
let err: ExecaError | null = null;
let err: ExecaError | null = null
try {
await execa(CLI, []);
await execa(CLI, [])
} catch (error) {
err = error as ExecaError;
err = error as ExecaError
}
assert.isNotNull(err);
assert.isNotNull(err)
assert.equal(
err?.stderr,
'No coin name provided. Check `crypto --help` for help'
);
assert.equal(err?.exitCode, 1);
});
});
)
assert.equal(err?.exitCode, 1)
})
})

@@ -34,26 +35,26 @@ describe('flags', () => {

it('returns the price', async () => {
const results = await execa(CLI, ['--price', 'bitcoin']);
const results = await execa(CLI, ['--price', 'bitcoin'])
/* price will vary this output is always returned if successful */
assert.include(results.stdout, 'Bitcoin: $');
assert.equal(results.exitCode, 0);
});
});
assert.include(results.stdout, 'Bitcoin: $')
assert.equal(results.exitCode, 0)
})
})
describe('with a invalid coin name', () => {
it('returns the price', async () => {
let err: ExecaError | null = null;
let err: ExecaError | null = null
try {
await execa(CLI, ['--price', 'abcd']);
await execa(CLI, ['--price', 'abcd'])
} catch (error) {
err = error as ExecaError;
err = error as ExecaError
}
assert.isNotNull(err);
assert.equal(err?.stderr, 'Unknown coin: abcd');
assert.equal(err?.exitCode, 1);
});
});
});
assert.isNotNull(err)
assert.equal(err?.stderr, 'Unknown coin: abcd')
assert.equal(err?.exitCode, 1)
})
})
})

@@ -68,14 +69,14 @@ describe('with multiple `--price` flags', () => {

'ethereum'
]);
])
assert.include(results.stdout, 'Bitcoin: $');
assert.include(results.stdout, 'Ethereum: $');
assert.equal(results.exitCode, 0);
});
});
assert.include(results.stdout, 'Bitcoin: $')
assert.include(results.stdout, 'Ethereum: $')
assert.equal(results.exitCode, 0)
})
})
describe('with valid and invalid coin names', () => {
it('returns the price', async () => {
let err: ExecaError | null = null;
let results: ExecaReturnValue<string> | null = null;
let err: ExecaError | null = null
let results: ExecaReturnValue<string> | null = null
try {

@@ -88,16 +89,16 @@ /* we only return valid coin names so it should ignore invalid coin names */

'bitcoin'
]);
])
} catch (error) {
err = error as ExecaError;
err = error as ExecaError
}
assert.isNull(err);
assert.include(results?.stdout, 'Bitcoin: $');
assert.notInclude(results?.stdout, 'abcd: $');
assert.equal(results?.exitCode, 0);
});
});
});
assert.isNull(err)
assert.include(results?.stdout, 'Bitcoin: $')
assert.notInclude(results?.stdout, 'abcd: $')
assert.equal(results?.exitCode, 0)
})
})
})
describe('with `--priceChange, --pc`', () => {
describe('with `--price-change, --pc`', () => {
describe('with a valid coin name', () => {

@@ -109,10 +110,10 @@ it('returns the price change percentage', async () => {

'--priceChange'
]);
])
assert.include(results.stdout, 'Bitcoin: $');
assert.include(results.stdout, 'change (24H): ');
assert.equal(results.exitCode, 0);
});
});
});
assert.include(results.stdout, 'Bitcoin: $')
assert.include(results.stdout, 'change (24H): ')
assert.equal(results.exitCode, 0)
})
})
})

@@ -122,10 +123,10 @@ describe('with `--high`', () => {

it('returns the highest price sold in the previous 24H', async () => {
const results = await execa(CLI, ['--price', 'bitcoin', '--high']);
const results = await execa(CLI, ['--price', 'bitcoin', '--high'])
assert.include(results.stdout, 'Bitcoin: $');
assert.include(results.stdout, 'high (24H): ');
assert.equal(results.exitCode, 0);
});
});
});
assert.include(results.stdout, 'Bitcoin: $')
assert.include(results.stdout, 'high (24H): ')
assert.equal(results.exitCode, 0)
})
})
})

@@ -135,10 +136,10 @@ describe('with `--low`', () => {

it('returns the lowest price sold in the previous 24H', async () => {
const results = await execa(CLI, ['--price', 'bitcoin', '--low']);
const results = await execa(CLI, ['--price', 'bitcoin', '--low'])
assert.include(results.stdout, 'Bitcoin: $');
assert.include(results.stdout, 'low (24H): ');
assert.equal(results.exitCode, 0);
});
});
});
assert.include(results.stdout, 'Bitcoin: $')
assert.include(results.stdout, 'low (24H): ')
assert.equal(results.exitCode, 0)
})
})
})

@@ -148,10 +149,10 @@ describe('with `--volume`', () => {

it('returns the volume for a given coin', async () => {
const results = await execa(CLI, ['--price', 'bitcoin', '--volume']);
const results = await execa(CLI, ['--price', 'bitcoin', '--volume'])
assert.include(results.stdout, 'Bitcoin: $');
assert.include(results.stdout, 'volume (24H): ');
assert.equal(results.exitCode, 0);
});
});
});
assert.include(results.stdout, 'Bitcoin: $')
assert.include(results.stdout, 'volume (24H): ')
assert.equal(results.exitCode, 0)
})
})
})

@@ -161,12 +162,12 @@ describe('with `--ath`', () => {

it('returns the all time high price for a given coin', async () => {
const results = await execa(CLI, ['--price', 'bitcoin', '--ath']);
const results = await execa(CLI, ['--price', 'bitcoin', '--ath'])
assert.include(results.stdout, 'Bitcoin: $');
assert.include(results.stdout, 'ATH: $');
assert.equal(results.exitCode, 0);
});
});
});
assert.include(results.stdout, 'Bitcoin: $')
assert.include(results.stdout, 'ATH: $')
assert.equal(results.exitCode, 0)
})
})
})
describe('with `--athChange`', () => {
describe('with `--ath-change`', () => {
describe('with a valid coin name', () => {

@@ -178,10 +179,10 @@ it('returns the percentage from the all time high price', async () => {

'--athChange'
]);
])
assert.include(results.stdout, 'Bitcoin: $');
assert.include(results.stdout, 'ATH (%):');
assert.equal(results.exitCode, 0);
});
});
});
assert.include(results.stdout, 'Bitcoin: $')
assert.include(results.stdout, 'ATH (%):')
assert.equal(results.exitCode, 0)
})
})
})

@@ -196,10 +197,10 @@ describe('with `--save`', () => {

'csv'
]);
])
assert.include(results.stdout, 'Bitcoin: $');
assert.include(results.stdout, 'Exporting coin data...');
assert.include(results.stdout, 'Export complete.');
assert.equal(results.exitCode, 0);
});
});
assert.include(results.stdout, 'Bitcoin: $')
assert.include(results.stdout, 'Exporting coin data...')
assert.include(results.stdout, 'Export complete.')
assert.equal(results.exitCode, 0)
})
})

@@ -213,12 +214,12 @@ describe('give format json', () => {

'json'
]);
])
assert.include(results.stdout, 'Bitcoin: $');
assert.include(results.stdout, 'Exporting coin data...');
assert.include(results.stdout, 'Export complete.');
assert.equal(results.exitCode, 0);
});
});
});
});
});
assert.include(results.stdout, 'Bitcoin: $')
assert.include(results.stdout, 'Exporting coin data...')
assert.include(results.stdout, 'Export complete.')
assert.equal(results.exitCode, 0)
})
})
})
})
})
#!/usr/bin/env node
import meow from 'meow';
import { app } from './app.js';
import meow from 'meow'
import CoinGeckoAPI from '@crypto-coffee/coingecko-api'
import { logError } from './utils.js'
import { saveCoinData } from './actions/saveCoinData.js'
import type { Flags } from './types.js'
import { priceStats } from './actions/priceStats.js'

@@ -9,22 +13,25 @@ const cli = meow(

Usage:
$ crypto --price <coin name> <additional flags>
$ crypto <coin ticker(s)> <additional flags>
Options:
--price, --p - coin name
--priceChange, --pc - coin price change (%) in the past 24 hours
--volume, --v - coin volume in the past 24 hours
--high - highest price sold in the past 24 hours
--low - lowest price sold in the past 24 hours
--ath - coin all time high price
--athChange, --athc - percent price change from ATH
--version - current version of the crypto-cli tool
--save - export all coin data to CSV and/or JSON
--price-change, --pc Coin price change (%) in the past 24 hours
--volume, --v Coin volume in the past 24 hours
--ath-change, -athc Percent price change from the all time high
--high, --h Highest price sold in the past 24 hours
--low, --l Lowest price sold in the past 24 hours
--ath Coin all time high price
--save json,csv Save coin data via JSON and/or CSV
--version Current version
Examples:
$crypto --price bitcoin --pc
$crypto bitcoin --pc
>> bitoin: $1337 - change (24H): 13.37%
$crypto bitcoin,ethereum
>> bitcoin: $1337
>> ethereum: $1337
Save coin data:
$crypto --save json
$crypto --save json,csv
$crypto bitcoin --save json
$crypto bitcoin --save json,csv
`,

@@ -34,7 +41,2 @@ {

flags: {
price: {
type: 'string',
isMultiple: true,
alias: 'p'
},
priceChange: {

@@ -49,6 +51,8 @@ type: 'boolean',

high: {
type: 'boolean'
type: 'boolean',
alias: 'h'
},
low: {
type: 'boolean'
type: 'boolean',
alias: 'l'
},

@@ -67,4 +71,42 @@ ath: {

}
);
)
app(cli.input[0], cli.flags);
const app = async () => {
const { save } = cli.flags as Flags
const coinTickers = cli.input[0]
if (!coinTickers) {
logError('No coin name provided. Check `crypto --help` for help')
}
const gecko = new CoinGeckoAPI.default()
const results = await gecko.coinMarkets({
vs_currency: 'usd',
ids: coinTickers
})
if (!results.length) {
logError(`Unknown coin: ${coinTickers}`)
}
priceStats({
results,
flags: cli.flags as Flags
})
await saveCoinData({
options: save,
results
})
process.exit(0)
}
app().catch(error => {
logError(
`An error occured: ${
(error as Error).message
}\n Please report the issue here: https://github.com/Zidious/crypto-cli`
)
})

@@ -1,5 +0,5 @@

import chalk from 'chalk';
import chalk from 'chalk'
const ERROR = chalk.bold.red;
const SUCCESS = chalk.bold.green;
const ERROR = chalk.bold.red
const SUCCESS = chalk.bold.green

@@ -9,15 +9,22 @@ const formatter = new Intl.NumberFormat('en-US', {

currency: 'USD'
});
})
export const logError = (message: string) => {
console.error(ERROR(message));
process.exit(1);
};
console.error(ERROR(message))
process.exit(1)
}
export const logSuccess = (message: string) => {
console.log(SUCCESS(message));
};
console.log(SUCCESS(message))
}
export const format = (price: number) => {
return formatter.format(price);
};
return formatter.format(price)
}
export const formatFileName = (coinName: string, fileExt: string): string => {
/* use unix timestamp, resolves conflict of same filenames */
const timestamp = new Date().valueOf()
return `${coinName.toLowerCase()}-${timestamp}.${fileExt}`
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc