UNPKG

@ledgerhq/coin-stellar

Version:
237 lines 11.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const expect_1 = __importDefault(require("expect")); const invariant_1 = __importDefault(require("invariant")); const bignumber_js_1 = __importDefault(require("bignumber.js")); const devices_1 = require("@ledgerhq/devices"); const currencies_1 = require("@ledgerhq/cryptoassets/currencies"); const currencies_2 = require("@ledgerhq/coin-framework/currencies"); const specs_1 = require("@ledgerhq/coin-framework/bot/specs"); const tokens_1 = require("@ledgerhq/cryptoassets/tokens"); const bot_deviceActions_1 = require("./bot-deviceActions"); const currency = (0, currencies_1.getCryptoCurrencyById)("stellar"); const minAmountCutoff = (0, currencies_2.parseCurrencyUnit)(currency.units[0], "0.1"); const reserve = (0, currencies_2.parseCurrencyUnit)(currency.units[0], "1.5"); const MAX_FEE = 5000; const USDC_CODE = "USDC"; const USDC_ISSUER = "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN"; const USDC_ASSET_ID = `${USDC_CODE}:${USDC_ISSUER}`; const MIN_ASSET_BALANCE = (0, currencies_2.parseCurrencyUnit)(currency.units[0], "0.01"); const findAssetUSDC = (subAccounts) => (subAccounts || []).find(s => s.id.endsWith(USDC_ASSET_ID)); const stellar = { name: "Stellar", currency, appQuery: { model: devices_1.DeviceModelId.nanoSP, appName: "Stellar", }, genericDeviceAction: bot_deviceActions_1.acceptTransaction, testTimeout: 2 * 60 * 1000, minViableAmount: minAmountCutoff, mutations: [ { name: "move ~50% XLM", feature: "send", maxRun: 1, transaction: ({ account, siblings, bridge, maxSpendable }) => { (0, invariant_1.default)(maxSpendable.gt(minAmountCutoff), "XLM balance is too low"); const transaction = bridge.createTransaction(account); const sibling = (0, specs_1.pickSiblings)(siblings, 4); const recipient = sibling.freshAddress; let amount = maxSpendable.div(1.9 + 0.2 * Math.random()).integerValue(); if (!sibling.used && amount.lt(reserve)) { (0, invariant_1.default)(maxSpendable.gt(reserve.plus(minAmountCutoff)), "not enough XLM funds to send to new account"); amount = reserve; } const updates = [ { recipient, // Setting higher max fee here to make sure transaction doesn't // time out. fees: new bignumber_js_1.default(MAX_FEE), }, { amount, }, ]; if (Math.random() < 0.5) { updates.push({ memoType: "MEMO_TEXT", memoValue: "Ledger Live", }); } return { transaction, updates, }; }, test: ({ account, accountBeforeTransaction, operation, transaction }) => { // We don't know what the final fee will be until after the tx is // submitted. Using higher max fee to make sure tx doesn't time out. (0, specs_1.botTest)("account balance decreased with operation", () => (0, expect_1.default)(account.balance.toNumber()).toBeLessThanOrEqual(accountBeforeTransaction.balance.minus(operation.value).toNumber())); if (transaction.memoValue) { (0, specs_1.botTest)("operation memo", () => (0, expect_1.default)(operation.extra).toMatchObject({ memo: transaction.memoValue, })); } const getType = () => { switch (transaction.mode) { case "send": return "send"; case "changeTrust": return /change_trust/; default: return ""; } }; (0, specs_1.botTest)("transaction mode", () => (0, expect_1.default)(transaction.mode).toMatch(getType())); }, }, { name: "Send max XLM", feature: "sendMax", maxRun: 1, transaction: ({ account, siblings, bridge, maxSpendable }) => { (0, invariant_1.default)(maxSpendable.gt(minAmountCutoff), "XLM balance is too low"); const transaction = bridge.createTransaction(account); const sibling = (0, specs_1.pickSiblings)(siblings, 4); const recipient = sibling.freshAddress; const updates = [ { recipient, // Setting higher max fee here to make sure transaction doesn't // time out. fees: new bignumber_js_1.default(MAX_FEE), }, { useAllAmount: true, }, ]; if (Math.random() < 0.5) { updates.push({ memoType: "MEMO_TEXT", memoValue: "Ledger Live", }); } return { transaction, updates, }; }, test: ({ account, accountBeforeTransaction, operation, transaction }) => { // We don't know what the final fee will be until after the tx is // submitted. Using higher max fee to make sure tx doesn't time out. (0, specs_1.botTest)("balance decreased with operation", () => (0, expect_1.default)(account.balance.toNumber()).toBeLessThanOrEqual(accountBeforeTransaction.balance.minus(operation.value).toNumber())); if (transaction.memoValue) { (0, specs_1.botTest)("operation memo", () => (0, expect_1.default)(operation.extra).toMatchObject({ memo: transaction.memoValue, })); } const getType = () => { switch (transaction.mode) { case "send": return "send"; case "changeTrust": return /change_trust/; default: return ""; } }; (0, specs_1.botTest)("transaction mode", () => (0, expect_1.default)(transaction.mode).toMatch(getType())); }, }, { name: "add USDC asset", feature: "tokens", maxRun: 1, transaction: ({ account, bridge, maxSpendable }) => { (0, invariant_1.default)(maxSpendable.gt(reserve), "XLM balance is too low 1"); (0, invariant_1.default)(account.subAccounts && !findAssetUSDC(account.subAccounts), "already have subaccounts"); const assetUSDC = findAssetUSDC((0, tokens_1.listTokensForCryptoCurrency)(account.currency)); (0, invariant_1.default)(assetUSDC, "USDC asset not found"); const transaction = bridge.createTransaction(account); const updates = [ { mode: "changeTrust", // Setting higher max fee here to make sure transaction doesn't // time out. fees: new bignumber_js_1.default(MAX_FEE), }, { assetCode: USDC_CODE, assetIssuer: USDC_ISSUER, }, ]; return { transaction, updates, }; }, test: ({ account }) => { const assetId = `${USDC_CODE}:${USDC_ISSUER}`; const hasAsset = account.subAccounts?.find(a => a.id.endsWith(assetId)); (0, specs_1.botTest)("has asset", () => (0, expect_1.default)(hasAsset).toBeTruthy()); }, }, { name: "move ~50% USDC asset", feature: "tokens", maxRun: 1, transaction: ({ account, siblings, bridge, maxSpendable }) => { (0, invariant_1.default)(maxSpendable.gt(minAmountCutoff), "XLM balance is too low"); const usdcSubAccount = findAssetUSDC(account?.subAccounts); (0, invariant_1.default)(usdcSubAccount, "USDC asset not found"); (0, invariant_1.default)(usdcSubAccount?.balance.gt(MIN_ASSET_BALANCE), "USDC balance is too low"); const siblingWithAssetUSDC = siblings.find(s => findAssetUSDC(s.subAccounts)); (0, invariant_1.default)(siblingWithAssetUSDC, "No siblings with USDC asset"); if (!usdcSubAccount || !siblingWithAssetUSDC) { throw new Error("No USDC asset or sibling with USDC asset"); } const transaction = bridge.createTransaction(account); const recipient = siblingWithAssetUSDC.freshAddress; const amount = usdcSubAccount.balance.div(1.9 + 0.2 * Math.random()).integerValue(); const updates = [ { recipient, }, { subAccountId: usdcSubAccount.id, }, { amount, // Setting higher max fee here to make sure transaction doesn't // time out. fees: new bignumber_js_1.default(MAX_FEE), }, ]; if (Math.random() < 0.5) { updates.push({ memoType: "MEMO_TEXT", memoValue: "Ledger Live", }); } return { transaction, updates, }; }, test: ({ account, accountBeforeTransaction, operation, transaction, status }) => { const asset = findAssetUSDC(account?.subAccounts); const assetBeforeTx = findAssetUSDC(accountBeforeTransaction?.subAccounts); (0, specs_1.botTest)("asset balance decreased with operation", () => (0, expect_1.default)(asset?.balance.toString()).toBe(assetBeforeTx?.balance.minus(status.amount).toString())); if (transaction.memoValue) { (0, specs_1.botTest)("operation memo", () => (0, expect_1.default)(operation.extra).toMatchObject({ memo: transaction.memoValue, })); } }, }, ], }; exports.default = { stellar, }; //# sourceMappingURL=bot-specs.js.map