diff --git a/scripts/cc-cli/src/commands/collectCoins.ts b/scripts/cc-cli/src/commands/collectCoins.ts deleted file mode 100644 index d403a75a33..0000000000 --- a/scripts/cc-cli/src/commands/collectCoins.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Command, Option, OptionValues } from "commander"; -import { fatalErr } from "./registerAddress"; -import { newApi } from "../api"; -import { initCallerKeyring } from "../utils/account"; -import { requiredInput } from "../utils/parsing"; -import { isAddress } from "web3-validator"; -import { utils } from "ethers"; -import chalk from "chalk"; - -export function makeCollectCoinsCmd() { - const externalAddressOpt = new Option( - "-e, --external-address ", - "The previously registered external address that called the burn tx", - ); - - const burnTxHashOpt = new Option( - "-b, --burn-tx-hash ", - "The hash of the burn transaction", - ); - - return new Command("collect-coins") - .description("Swap GCRE for CTC") - .addOption(externalAddressOpt) - .addOption(burnTxHashOpt) - .action(collectCoinsActionSync); -} - -function collectCoinsActionSync(options: OptionValues) { - collectCoinsAction(options) - .then(() => { - console.log(chalk.green("Success!")); - process.exit(0); - }) - .catch((reason) => { - fatalErr( - `ERROR: The call to request_collect_coins was unsuccessful: ${ - reason as string - }`, - ); - }); -} - -async function collectCoinsAction(options: OptionValues) { - validateOptsOrExit(options); - - const { - extrinsics: { requestCollectCoins }, - } = await newApi(options.url); - const signer = await initCallerKeyring(options); - - const event = await requestCollectCoins( - options.externalAddress, - signer, - options.burnTxHash, - ); - await event.waitForVerification(800_000); -} - -function validateOptsOrExit(options: OptionValues) { - const externalAddress = requiredInput( - options.externalAddress.trim(), - "ERROR: externalAddress is required", - ); - const burnTxHash = requiredInput( - options.burnTxHash.trim(), - "ERROR: Burn transaction hash is required", - ); - - if (!isTxHashValid(burnTxHash)) { - fatalErr(`ERROR: The transaction hash is invalid: ${burnTxHash}`); - } - - if (!isExternalAddressValid(externalAddress)) { - fatalErr(`ERROR: The external address is invalid: ${externalAddress}`); - } -} - -export function isTxHashValid(hash: string): boolean { - // 32 byte hexadecimal, 64 character string, 66 with 0x prefix - return utils.isHexString(hash, 32); -} - -export function isExternalAddressValid(addr: string): boolean { - return isAddress(addr); -} diff --git a/scripts/cc-cli/src/test/integration-tests/collectCoins.test.ts b/scripts/cc-cli/src/test/integration-tests/collectCoins.test.ts deleted file mode 100644 index 65db431d93..0000000000 --- a/scripts/cc-cli/src/test/integration-tests/collectCoins.test.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { parseAmountInternal } from "../../utils/parsing"; -import { signSendAndWatch } from "../../utils/tx"; -import { fundFromSudo, randomTestAccount } from "./helpers"; -import { arg, retry, setArgIfUndef, setAuthorities } from "../../globalSetup"; -import execa from "execa"; -import { - Blockchain, - CreditcoinApi, - KeyringPair, - Wallet, - creditcoinApi, - providers, -} from "creditcoin-js"; -import { cryptoWaitReady } from "@polkadot/util-crypto"; -import { deployCtcContract, CREDO_PER_CTC } from "creditcoin-js/lib/ctc-deploy"; -import { - forElapsedBlocks, - testData, - tryRegisterAddress, -} from "creditcoin-js/lib/testUtils"; -import { describeIf } from "../../utils/tests"; -import { getBalance } from "../../utils/balance"; - -describeIf(arg("CREDITCOIN_EXECUTE_SETUP_AUTHORITY"), "collect-coins", () => { - let ccApi: CreditcoinApi; - let sudo: KeyringPair; - let caller: any; - - const { keyring, blockchain } = testData( - arg("CREDITCOIN_ETHEREUM_CHAIN") as Blockchain, - arg("CREDITCOIN_CREATE_WALLET"), - ); - - beforeAll(async () => { - // will deploy the contract and burn 3 CTC - await deployCtcContract( - (global as any).CREDITCOIN_CTC_CONTRACT_ADDRESS, - (global as any).CREDITCOIN_ETHEREUM_NODE_URL, - (global as any).CREDITCOIN_CTC_DEPLOYER_PRIVATE_KEY, - (3 * CREDO_PER_CTC).toString(), - ); - setArgIfUndef( - "CREDITCOIN_CTC_CONTRACT_ADDRESS", - process.env.CREDITCOIN_CTC_CONTRACT_ADDRESS, - ); - setArgIfUndef( - "CREDITCOIN_CTC_BURN_TX_HASH", - process.env.CREDITCOIN_CTC_BURN_TX_HASH, - ); - - await retry(5, async (resolve: any, reject: any) => { - await setAuthorities().then(resolve).catch(reject); - }).catch(() => { - console.log("Could not setup testing authorities"); - process.exit(1); - }); - - await cryptoWaitReady(); - - caller = randomTestAccount(false); - - ccApi = await creditcoinApi((global as any).CREDITCOIN_API_URL); - sudo = arg("CREDITCOIN_CREATE_SIGNER")(keyring, "sudo"); - - const { api } = ccApi; - - /* eslint-disable @typescript-eslint/naming-convention */ - const contract = api.createType( - "PalletCreditcoinOcwTasksCollectCoinsDeployedContract", - { - address: (global as any).CREDITCOIN_CTC_CONTRACT_ADDRESS, - chain: blockchain, - }, - ); - - await api.tx.sudo - .sudo(api.tx.creditcoin.setCollectCoinsContract(contract)) - .signAndSend(sudo, { nonce: -1 }); - }, 100_000); - - afterAll(async () => { - await ccApi.api.disconnect(); - }); - - test("e2e", async () => { - const { - api, - utils: { signAccountId }, - } = ccApi; - - const provider = new providers.JsonRpcProvider( - arg("CREDITCOIN_ETHEREUM_NODE_URL"), - ); - const deployerWallet = new Wallet( - arg("CREDITCOIN_CTC_DEPLOYER_PRIVATE_KEY"), - provider, - ); - - const fundTx = await fundFromSudo( - caller.address, - parseAmountInternal("5"), - arg("CREDITCOIN_API_URL"), - ); - await signSendAndWatch(fundTx, api, sudo); - - await tryRegisterAddress( - ccApi, - deployerWallet.address, - blockchain, - signAccountId(deployerWallet, caller.address), - caller.keyring, - (global as any).CREDITCOIN_REUSE_EXISTING_ADDRESSES, - ); - - // Read balance after register address call but prior to collect coins - const starting = await getBalance(caller.address, api); - - const url = arg("CREDITCOIN_API_URL") as string; - const txHash = arg("CREDITCOIN_CTC_BURN_TX_HASH") as string; - const collectResult = execa.commandSync( - `node dist/index.js collect-coins --url ${url} --external-address ${deployerWallet.address} --burn-tx-hash ${txHash}`, - { - env: { - CC_SECRET: caller.secret, - }, - }, - ); - - const collectOutput = collectResult.stdout.split("\n"); - expect(collectResult.failed).toBe(false); - expect(collectResult.exitCode).toBe(0); - expect(collectResult.stderr).toBe(""); - expect(collectOutput[collectOutput.length - 1]).toBe("Success!"); - - // wait for 2 more blocks - await forElapsedBlocks(api); - - // read the balance after collect coins - const ending = await getBalance(caller.address, api); - - // note: these are of type BN and .toBeGreaterThan() doesn't work - expect(ending.total > starting.total).toBe(true); - }, 900_000); -}); diff --git a/scripts/cc-cli/src/test/unit-tests/collect-coins.test.ts b/scripts/cc-cli/src/test/unit-tests/collect-coins.test.ts deleted file mode 100644 index 2a84e3e17e..0000000000 --- a/scripts/cc-cli/src/test/unit-tests/collect-coins.test.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { - isExternalAddressValid, - isTxHashValid, -} from "../../commands/collectCoins"; - -describe(isTxHashValid, () => { - test("should return true with a valid hash", () => { - expect( - isTxHashValid( - "0x2446f1fd773fbb9f080e674b60c6a033c7ed7427b8b9413cf28a2a4a6da9b56c", - ), - ).toBe(true); - }); - - test("should return false with missing '0x' prefix", () => { - expect( - isTxHashValid( - "2446f1fd773fbb9f080e674b60c6a033c7ed7427b8b9413cf28a2a4a6da9b56c", - ), - ).toBe(false); - }); - - test("should return false when tx hash length < 64 characters", () => { - expect( - isTxHashValid( - "0x2446f1fd773fbb9f080e674b60c6a033c7ed7427b8b9413cf28a2a4a6da9b56", - ), - ).toBe(false); - }); - - test("should return false when tx hash length > 64 characters", () => { - expect( - isTxHashValid( - "0x2446f1fd773fbb9f080e674b60c6a033c7ed7427b8b9413cf28a2a4a6da9b56ceeeeee", - ), - ).toBe(false); - }); - - test("should return false when called with empty string", () => { - expect(isTxHashValid("")).toBe(false); - }); - - test("Should return false when input has non hexadecimal character(s)", () => { - expect( - isTxHashValid( - "0x2446f1fd773fbb9f080e674b60-INVALID-d7427b8b9413cf28a2a4a6da9b56c", - ), - ).toBe(false); - }); -}); - -describe(isExternalAddressValid, () => { - test("should return true with valid address, prefixed with '0x'", () => { - expect( - isExternalAddressValid("0x71C7656EC7ab88b098defB751B7401B5f6d8976F"), - ).toBe(true); - }); - - test("should return true with valid address missing the '0x' prefix", () => { - expect( - isExternalAddressValid("71C7656EC7ab88b098defB751B7401B5f6d8976F"), - ).toBe(true); - }); - - test("Should return false when called with empty string", () => { - expect(isExternalAddressValid("")).toBe(false); - }); - - test("should return false when argument length < 42, including the '0x' prefix", () => { - expect( - isExternalAddressValid("0x71C7656EC7ab88b098defB751B7401B5f6d8976"), - ).toBe(false); - }); - - test("should return false when input has non hexadecimal characters", () => { - expect( - isExternalAddressValid("0x71C7656EC7ab88b098-INVALID-401B5f6d8976F"), - ).toBe(false); - }); - - test("should return false when argument length > 42, including the '0x' prefix", () => { - expect( - isExternalAddressValid("0x71C7656EC7ab88b098defB751B7401B5f6d8976FF"), - ).toBe(false); - }); - - test("should return false when argument length < 40, without the '0x' prefix", () => { - expect( - isExternalAddressValid("71C7656EC7ab88b098defB751B7401B5f6d8976"), - ).toBe(false); - }); - - test("should return false when argument length > 40, without the '0x' prefix", () => { - expect( - isExternalAddressValid("71C7656EC7ab88b098defB751B7401B5f6d8976FF"), - ).toBe(false); - }); -});