diff --git a/.changeset/chatty-buses-drop.md b/.changeset/chatty-buses-drop.md new file mode 100644 index 00000000..a845151c --- /dev/null +++ b/.changeset/chatty-buses-drop.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/src/__snapshots__/cli.test.ts.snap b/src/__snapshots__/cli.test.ts.snap new file mode 100644 index 00000000..e8358137 --- /dev/null +++ b/src/__snapshots__/cli.test.ts.snap @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`cli tests should match help output 1`] = ` +"cli.js [command] + +Commands: + cli.js print-api3readerproxyv1-address Prints the dApp-specific + Api3ReaderProxyV1 address + cli.js compute-dapp-id Computes the dApp ID for a given dApp + alias and chain ID + +Options: + --version Show version number [boolean] + --help Show help [boolean]" +`; + +exports[`cli tests should succeed print-api3readerproxyv1-address on mantle 1`] = ` +"dApp alias: lendle +chain: Mantle +dAPI name: ETH/USD +• Please confirm that https://market.api3.org/mantle/eth-usd points to an active feed. +• Your proxy is at https://mantlescan.xyz/address/0x776E79D916e49BBDb8FEe0F43fF148C2Ed3bE125 +Please confirm that there is a contract deployed at this address before using it." +`; + +exports[`cli tests should succeed print-api3readerproxyv1-address on sonic 1`] = ` +"dApp alias: mach-finance +chain: Sonic +dAPI name: S/USD +• Please confirm that https://market.api3.org/sonic/s-usd points to an active feed. +• Your proxy is at https://sonicscan.org/address/0x2551A2a96988829D2a55c3b02b88E138023D1cE8 +Please confirm that there is a contract deployed at this address before using it." +`; diff --git a/src/cli.test.ts b/src/cli.test.ts new file mode 100644 index 00000000..36da66c8 --- /dev/null +++ b/src/cli.test.ts @@ -0,0 +1,127 @@ +import { execSync } from 'node:child_process'; + +import { goSync } from '@api3/promise-utils'; + +const CLI_EXECUTABLE = 'dist/src/cli.js'; + +type CommandArg = [string, string | number | boolean]; + +describe('cli tests', () => { + const execCommand = (command: string, ...args: CommandArg[]) => { + const formattedCommand = [command, ...args.flatMap(([c, a]) => [c, String(a)])].join(' '); + const goExecSync = goSync(() => + execSync(`node ${CLI_EXECUTABLE} ${formattedCommand}`, { + stdio: ['pipe', 'pipe', 'pipe'], + }) + ); + if (!goExecSync.success) { + // rethrow the output of the CLI + throw new Error((goExecSync.error as any).reason.stderr.toString().trim()); + } + + const stdout = goExecSync.data?.toString().trim() || ''; + return stdout; + }; + + it('should throw an error for an unknown chain id', () => { + expect(() => { + execCommand('compute-dapp-id', ['--dapp-alias', 'lendle'], ['--chain-id', '0']); + }).toThrow('⚠️ Chain with ID 0 is not known'); + }); + + it('should throw an error for an unknown dApp alias', () => { + expect(() => { + execCommand('compute-dapp-id', ['--dapp-alias', 'unsupported-dapp'], ['--chain-id', '5000']); + }).toThrow('⚠️ Could not find any record for alias "unsupported-dapp"'); + }); + + it('should throw an error for unsupported chain ID', () => { + expect(() => { + execCommand('compute-dapp-id', ['--dapp-alias', 'lendle'], ['--chain-id', '1']); + }).toThrow('⚠️ dApp alias "lendle" is not available on chain "Ethereum"'); + }); + + it('should return an invalid output if strict is false', () => { + const output = execCommand( + 'compute-dapp-id', + ['--dapp-alias', 'unsupported-dapp'], + ['--chain-id', '0'], + ['--strict', false] + ); + expect(output).toMatch( + 'dApp alias: unsupported-dapp\nchain: 0\n\n• dApp ID: 113044575011858809962820051290270246401920929513853405225169263442003318378526' + ); + }); + + it('should compute dApp ID for lendle on mantle', () => { + const output = execCommand('compute-dapp-id', ['--dapp-alias', 'lendle'], ['--chain-id', '5000']); + expect(output).toMatch( + 'dApp alias: lendle\nchain: Mantle\n\n• dApp ID: 3006187377348428698321862179080566497381498372321749245241868771911713393091' + ); + }); + + it('should compute dApp ID for mach-finance on sonic', () => { + const output = execCommand('compute-dapp-id', ['--dapp-alias', 'mach-finance'], ['--chain-id', '146']); + expect(output).toMatch( + 'dApp alias: mach-finance\nchain: Sonic\n\n• dApp ID: 103191103032841018751746810000516216875988320776131204933373404128958541332502' + ); + }); + + it('should match help output', () => { + const output = execCommand('help'); + expect(output).toMatchSnapshot(); + }); + + it('should throw an error for an unknown chain id while checking Api3ReaderProxyV1 address', () => { + expect(() => { + execCommand( + 'print-api3readerproxyv1-address', + ['--dapp-alias', 'unsupported-dapp'], + ['--chain-id', '0'], + ['--dapi-name', 'ETH/USD'] + ); + }).toThrow('Chain with ID 0 is not known'); + }); + + it('should throw an error for an unknown dApp alias while checking Api3ReaderProxyV1 address', () => { + expect(() => { + execCommand( + 'print-api3readerproxyv1-address', + ['--dapp-alias', 'unsupported-dapp'], + ['--chain-id', '5000'], + ['--dapi-name', 'ETH/USD'] + ); + }).toThrow('⚠️ Could not find any record for alias "unsupported-dapp"'); + }); + + it('should throw an error for an unsupported dApi name', () => { + expect(() => { + execCommand( + 'print-api3readerproxyv1-address', + ['--dapp-alias', 'lendle'], + ['--chain-id', '5000'], + ['--dapi-name', 'UNSUPPORTED/USD'] + ); + }).toThrow('⚠️ Attempted to read the feed and failed'); + }); + + it('should succeed print-api3readerproxyv1-address on mantle', () => { + const output = execCommand( + 'print-api3readerproxyv1-address', + ['--dapp-alias', 'lendle'], + ['--chain-id', '5000'], + ['--dapi-name', 'ETH/USD'] + ); + expect(output).toMatchSnapshot(); + }); + + it('should succeed print-api3readerproxyv1-address on sonic', () => { + const output = execCommand( + 'print-api3readerproxyv1-address', + ['--dapp-alias', 'mach-finance'], + ['--chain-id', '146'], + ['--dapi-name', 'S/USD'] + ); + expect(output).toMatchSnapshot(); + }); +});