@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
147 lines • 6.99 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const getAccountShape_1 = require("../getAccountShape");
jest.mock("@ledgerhq/coin-framework/account/index", () => ({
encodeAccountId: jest.fn(() => "accId"),
}));
const mergeOpsMock = jest.fn();
jest.mock("@ledgerhq/coin-framework/bridge/jsHelpers", () => ({
mergeOps: (...args) => mergeOpsMock(...args),
}));
const listOperationsMock = jest.fn();
const getBalanceMock = jest.fn();
const lastBlockMock = jest.fn();
const getTokenFromAssetMock = jest.fn();
const chainSpecificGetAccountShapeMock = jest.fn();
jest.mock("../alpaca", () => ({
getAlpacaApi: () => ({
lastBlock: (...a) => lastBlockMock(...a),
getBalance: (...a) => getBalanceMock(...a),
listOperations: (...a) => listOperationsMock(...a),
getTokenFromAsset: (...a) => getTokenFromAssetMock(...a),
getChainSpecificRules: () => ({
getAccountShape: (...a) => chainSpecificGetAccountShapeMock(...a),
}),
}),
}));
const adaptCoreOperationToLiveOperationMock = jest.fn();
const extractBalanceMock = jest.fn();
jest.mock("../utils", () => ({
adaptCoreOperationToLiveOperation: (...a) => adaptCoreOperationToLiveOperationMock(...a),
extractBalance: (...a) => extractBalanceMock(...a),
}));
const inferSubOperationsMock = jest.fn();
jest.mock("@ledgerhq/coin-framework/serialization", () => ({
inferSubOperations: (...a) => inferSubOperationsMock(...a),
}));
const buildSubAccountsMock = jest.fn();
jest.mock("../buildSubAccounts", () => ({
buildSubAccounts: (...a) => buildSubAccountsMock(...a),
}));
// Test matrix for Stellar & XRP
const chains = [
{ currency: { id: "stellar", name: "Stellar" }, network: "testnet" },
{ currency: { id: "ripple", name: "XRP" }, network: "mainnet" },
{ currency: { id: "tezos", name: "Tezos" }, network: "mainnet" },
];
describe("genericGetAccountShape (stellar & xrp)", () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe.each(chains)("$currency.id", ({ currency, network }) => {
test("builds account shape with existing operations, pagination and sub accounts", async () => {
const oldOp = {
hash: "h1",
blockHeight: 10,
type: "OPT_IN",
extra: { pagingToken: "pt1", assetReference: "ar1", assetOwner: "ow1" },
};
const initialAccount = { operations: [oldOp], blockHeight: 10 };
extractBalanceMock.mockReturnValue({ value: "1000", locked: "300" });
getBalanceMock.mockResolvedValue([
{ asset: { type: "native" }, value: "1000", locked: "300" },
{ asset: { type: "token", symbol: "TOK1" }, value: "42" },
{ asset: { type: "token", symbol: "TOK_IGNORE" }, value: "5" },
]);
getTokenFromAssetMock.mockImplementation(asset => asset.symbol === "TOK1" ? { id: `${currency.id}_token1` } : null);
const coreOp = { hash: "h2", height: 12 };
listOperationsMock.mockResolvedValue([[coreOp]]);
adaptCoreOperationToLiveOperationMock.mockImplementation((_accId, op) => ({
hash: op.hash,
type: "IN",
blockHeight: 12,
extra: { assetReference: "ar2", assetOwner: "ow2" },
}));
mergeOpsMock.mockImplementation((oldOps, newOps) => [...newOps, ...oldOps]);
buildSubAccountsMock.mockReturnValue([
{ id: `${currency.id}_subAcc1`, type: "TokenAccount" },
]);
inferSubOperationsMock.mockImplementation(hash => hash === "h2" ? [{ id: `${currency.id}_subOp1` }] : []);
lastBlockMock.mockResolvedValue({ height: 123 });
const getShape = (0, getAccountShape_1.genericGetAccountShape)(network, currency.id);
const result = await getShape({
address: `${currency.id}_addr1`,
initialAccount,
currency,
derivationMode: "",
}, { paginationConfig: {} });
expect(chainSpecificGetAccountShapeMock).toHaveBeenCalledWith(`${currency.id}_addr1`);
expect(listOperationsMock).toHaveBeenCalledWith(`${currency.id}_addr1`, {
minHeight: 11,
order: "asc",
lastPagingToken: "pt1",
});
const assetsBalancePassed = buildSubAccountsMock.mock.calls[0][0].allTokenAssetsBalances;
expect(assetsBalancePassed).toEqual([
{ asset: { symbol: "TOK1", type: "token" }, value: "42" },
{ asset: { symbol: "TOK_IGNORE", type: "token" }, value: "5" },
]);
const assetOpsPassed = buildSubAccountsMock.mock.calls[0][0].operations;
expect(assetOpsPassed).toHaveLength(1);
expect(assetOpsPassed[0].hash).toBe("h2");
expect(result).toMatchObject({
balance: new bignumber_js_1.default(1000),
spendableBalance: new bignumber_js_1.default(700),
blockHeight: 123,
operationsCount: 2,
subAccounts: [{ id: `${currency.id}_subAcc1`, type: "TokenAccount" }],
operations: [
{
hash: "h2",
type: "IN",
blockHeight: 12,
subOperations: [{ id: `${currency.id}_subOp1` }],
extra: { assetReference: "ar2", assetOwner: "ow2" },
},
oldOp,
],
});
});
test("handles empty operations (no old ops, no new ops) and blockHeight=0", async () => {
getBalanceMock.mockResolvedValue([{ asset: { type: "native" }, value: "0", locked: "0" }]);
extractBalanceMock.mockReturnValue({ value: "0", locked: "0" });
listOperationsMock.mockResolvedValue([[]]);
buildSubAccountsMock.mockReturnValue([]);
const getShape = (0, getAccountShape_1.genericGetAccountShape)(network, currency.id);
const result = await getShape({
address: `${currency.id}_addr2`,
initialAccount: undefined,
currency,
derivationMode: "",
}, { paginationConfig: {} });
expect(result).toMatchObject({
operations: [],
blockHeight: 0,
operationsCount: 0,
subAccounts: [],
balance: new bignumber_js_1.default(0),
spendableBalance: new bignumber_js_1.default(0),
});
});
});
});
//# sourceMappingURL=getAccountShape.test.js.map