@ledgerhq/coin-framework 0.3.5 → 0.3.6-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.eslintrc.js +8 -46
  2. package/CHANGELOG.md +13 -0
  3. package/package.json +9 -18
  4. package/src/account/accountId.ts +20 -30
  5. package/src/account/accountName.ts +1 -4
  6. package/src/account/balanceHistoryCache.ts +18 -37
  7. package/src/account/groupOperations.ts +4 -6
  8. package/src/account/helpers.test.ts +6 -26
  9. package/src/account/helpers.ts +33 -66
  10. package/src/account/ordering.ts +10 -18
  11. package/src/account/pending.ts +6 -15
  12. package/src/account/serialization.ts +8 -19
  13. package/src/account/support.ts +8 -18
  14. package/src/account.test.ts +25 -40
  15. package/src/bot/specs.ts +24 -43
  16. package/src/bot/types.ts +1 -1
  17. package/src/bridge/getAddressWrapper.ts +5 -13
  18. package/src/bridge/jsHelpers.ts +215 -259
  19. package/src/cache.ts +4 -4
  20. package/src/currencies/BigNumberToLocaleString.test.ts +25 -33
  21. package/src/currencies/BigNumberToLocaleString.ts +3 -8
  22. package/src/currencies/CurrencyURIScheme.ts +1 -3
  23. package/src/currencies/chopCurrencyUnitDecimals.ts +1 -4
  24. package/src/currencies/formatCurrencyUnit.ts +11 -21
  25. package/src/currencies/index.ts +1 -4
  26. package/src/currencies/localeUtility.ts +2 -4
  27. package/src/currencies/parseCurrencyUnit.ts +1 -4
  28. package/src/currencies/sanitizeValueString.ts +1 -1
  29. package/src/currencies/support.ts +3 -9
  30. package/src/derivation.test.ts +1 -4
  31. package/src/derivation.ts +45 -95
  32. package/src/errors.test.ts +1 -1
  33. package/src/errors.ts +2 -6
  34. package/src/mocks/account.ts +27 -80
  35. package/src/mocks/fixtures/nfts.test.ts +2 -6
  36. package/src/mocks/fixtures/nfts.ts +12 -38
  37. package/src/mocks/helpers.ts +2 -8
  38. package/src/nft/nftId.ts +2 -2
  39. package/src/operation.test.ts +6 -31
  40. package/src/operation.ts +12 -26
  41. package/src/transaction/common.ts +9 -22
package/.eslintrc.js CHANGED
@@ -1,57 +1,19 @@
1
1
  module.exports = {
2
- parser: "@typescript-eslint/parser",
3
2
  env: {
4
3
  browser: true,
5
4
  es6: true,
6
- node: true,
7
- jest: true,
8
5
  },
9
- extends: [
10
- "eslint:recommended",
11
- "plugin:@typescript-eslint/eslint-recommended",
12
- "plugin:@typescript-eslint/recommended",
13
- "prettier",
6
+ overrides: [
7
+ {
8
+ files: ["src/**/*.test.{ts,tsx}"],
9
+ env: {
10
+ "jest/globals": true,
11
+ },
12
+ plugins: ["jest"],
13
+ },
14
14
  ],
15
- globals: {
16
- Atomics: "readonly",
17
- SharedArrayBuffer: "readonly",
18
- },
19
- plugins: ["@typescript-eslint", "prettier"],
20
15
  rules: {
21
16
  "no-console": ["error", { allow: ["warn", "error"] }],
22
- "linebreak-style": ["error", "unix"],
23
- semi: ["error", "always"],
24
- "no-unused-vars": "off",
25
- "import/prefer-default-export": 0,
26
- "no-plusplus": 0,
27
- "no-underscore-dangle": 0,
28
- "prefer-template": 0,
29
- "no-await-in-loop": 0,
30
- "no-restricted-syntax": 0,
31
- "consistent-return": 0,
32
- "no-lonely-if": 0,
33
- "no-use-before-define": 0,
34
- "no-nested-ternary": 0,
35
- "import/no-cycle": 0,
36
- "no-multi-assign": 0,
37
- "guard-for-in": 0,
38
- "no-continue": 0,
39
- "lines-between-class-members": 0,
40
- "prefer-destructuring": 0,
41
- "prettier/prettier": "error",
42
- "@typescript-eslint/no-use-before-define": "off",
43
- "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
44
17
  "@typescript-eslint/no-empty-function": "off",
45
- "@typescript-eslint/no-namespace": ["error", { allowDeclarations: true }],
46
- "@typescript-eslint/no-explicit-any": 0,
47
- "@typescript-eslint/ban-types": [
48
- "error",
49
- {
50
- extendDefaults: true,
51
- types: {
52
- "{}": false,
53
- },
54
- },
55
- ],
56
18
  },
57
19
  };
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @ledgerhq/coin-framework
2
2
 
3
+ ## 0.3.6-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`9adc1862dd`](https://github.com/LedgerHQ/ledger-live/commit/9adc1862dda605a722d19f3b6895bd324834c914), [`4a1454beb3`](https://github.com/LedgerHQ/ledger-live/commit/4a1454beb3f86405ba2686e07879c12a7d35ad8e), [`809065c571`](https://github.com/LedgerHQ/ledger-live/commit/809065c57198646a49adea112b9d799e35a57d25), [`d1aa522db7`](https://github.com/LedgerHQ/ledger-live/commit/d1aa522db75f7ea850efe412abaa4dc7d37af6b7), [`ebe5b07afe`](https://github.com/LedgerHQ/ledger-live/commit/ebe5b07afec441ea3e2d9103da9e1175972add47)]:
8
+ - @ledgerhq/errors@6.12.7-next.0
9
+ - @ledgerhq/cryptoassets@9.8.0-next.0
10
+ - @ledgerhq/types-cryptoassets@7.2.1-next.0
11
+ - @ledgerhq/types-live@6.35.1-next.0
12
+ - @ledgerhq/devices@8.0.4-next.0
13
+ - @ledgerhq/hw-transport@6.28.5-next.0
14
+ - @ledgerhq/live-portfolio@0.0.8-next.0
15
+
3
16
  ## 0.3.5
4
17
 
5
18
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/coin-framework",
3
- "version": "0.3.5",
3
+ "version": "0.3.6-next.0",
4
4
  "description": "Ledger framework for Coin integration",
5
5
  "keywords": [
6
6
  "Ledger",
@@ -61,33 +61,24 @@
61
61
  "prando": "^6.0.1",
62
62
  "rxjs": "^6.6.7",
63
63
  "rxjs-compat": "^6.6.7",
64
- "@ledgerhq/cryptoassets": "^9.7.0",
65
- "@ledgerhq/devices": "^8.0.3",
66
- "@ledgerhq/errors": "^6.12.6",
67
- "@ledgerhq/hw-transport": "^6.28.4",
64
+ "@ledgerhq/cryptoassets": "^9.8.0-next.0",
65
+ "@ledgerhq/devices": "^8.0.4-next.0",
66
+ "@ledgerhq/errors": "^6.12.7-next.0",
67
+ "@ledgerhq/hw-transport": "^6.28.5-next.0",
68
68
  "@ledgerhq/live-env": "^0.3.0",
69
- "@ledgerhq/live-portfolio": "^0.0.7",
69
+ "@ledgerhq/live-portfolio": "^0.0.8-next.0",
70
70
  "@ledgerhq/live-promise": "^0.0.1",
71
71
  "@ledgerhq/logs": "^6.10.1",
72
- "@ledgerhq/types-cryptoassets": "^7.2.0",
73
- "@ledgerhq/types-live": "^6.35.0"
72
+ "@ledgerhq/types-cryptoassets": "^7.2.1-next.0",
73
+ "@ledgerhq/types-live": "^6.35.1-next.0"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@types/invariant": "^2.2.2",
77
77
  "@types/jest": "^29.2.4",
78
78
  "@types/lodash": "^4.14.191",
79
79
  "@types/numeral": "^2.0.2",
80
- "@typescript-eslint/eslint-plugin": "^5.46.1",
81
- "@typescript-eslint/parser": "^5.46.1",
82
80
  "cross-env": "^7.0.3",
83
- "eslint": "^7.32.0",
84
- "eslint-config-prettier": "^8.3.0",
85
- "eslint-config-typescript": "^3.0.0",
86
- "eslint-formatter-pretty": "^3.0.1",
87
- "eslint-plugin-prettier": "^3.4.0",
88
- "eslint-plugin-typescript": "^0.14.0",
89
81
  "jest": "^28.1.1",
90
- "prettier": "^2.8.1",
91
82
  "timemachine": "^0.3.2",
92
83
  "ts-jest": "^28.0.5"
93
84
  },
@@ -97,7 +88,7 @@
97
88
  "prewatch": "pnpm build",
98
89
  "watch": "tsc --watch",
99
90
  "doc": "documentation readme src/** --section=API --pe ts --re ts --re d.ts",
100
- "lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx",
91
+ "lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx --cache",
101
92
  "lint:fix": "pnpm lint --fix",
102
93
  "test": "cross-env TZ=America/New_York jest"
103
94
  }
@@ -4,17 +4,10 @@ import { asDerivationMode } from "../derivation";
4
4
  import { getCryptoCurrencyById, findTokenById } from "../currencies";
5
5
  import { findTokenByAddressInCurrency } from "@ledgerhq/cryptoassets";
6
6
  import type { AccountIdParams, DerivationMode } from "@ledgerhq/types-live";
7
- import type {
8
- CryptoCurrency,
9
- TokenCurrency,
10
- } from "@ledgerhq/types-cryptoassets";
7
+ import type { CryptoCurrency, TokenCurrency } from "@ledgerhq/types-cryptoassets";
11
8
 
12
9
  function ensureNoColon(value: string, ctx: string): string {
13
- invariant(
14
- !value.includes(":"),
15
- "AccountId '%s' component must not use colon",
16
- ctx
17
- );
10
+ invariant(!value.includes(":"), "AccountId '%s' component must not use colon", ctx);
18
11
  return value;
19
12
  }
20
13
 
@@ -25,18 +18,15 @@ export function encodeAccountId({
25
18
  xpubOrAddress,
26
19
  derivationMode,
27
20
  }: AccountIdParams): string {
28
- return `${ensureNoColon(type, "type")}:${ensureNoColon(
29
- version,
30
- "version"
31
- )}:${ensureNoColon(currencyId, "currencyId")}:${ensureNoColon(
32
- xpubOrAddress,
33
- "xpubOrAddress"
34
- )}:${ensureNoColon(derivationMode, "derivationMode")}`;
21
+ return `${ensureNoColon(type, "type")}:${ensureNoColon(version, "version")}:${ensureNoColon(
22
+ currencyId,
23
+ "currencyId",
24
+ )}:${ensureNoColon(xpubOrAddress, "xpubOrAddress")}:${ensureNoColon(
25
+ derivationMode,
26
+ "derivationMode",
27
+ )}`;
35
28
  }
36
- export function encodeTokenAccountId(
37
- accountId: string,
38
- token: TokenCurrency
39
- ): string {
29
+ export function encodeTokenAccountId(accountId: string, token: TokenCurrency): string {
40
30
  return accountId + "+" + encodeURIComponent(token.id);
41
31
  }
42
32
  export function decodeTokenAccountId(id: string): {
@@ -81,13 +71,13 @@ export function getWalletName({
81
71
  }): string {
82
72
  return `${seedIdentifier}_${currency.id}_${derivationMode}`;
83
73
  }
84
- export const inferFamilyFromAccountId: (
85
- accountId: string
86
- ) => string | null | undefined = memoize((accountId) => {
87
- try {
88
- const { currencyId } = decodeAccountId(accountId);
89
- return getCryptoCurrencyById(currencyId).family;
90
- } catch (e) {
91
- return null;
92
- }
93
- });
74
+ export const inferFamilyFromAccountId: (accountId: string) => string | null | undefined = memoize(
75
+ accountId => {
76
+ try {
77
+ const { currencyId } = decodeAccountId(accountId);
78
+ return getCryptoCurrencyById(currencyId).family;
79
+ } catch (e) {
80
+ return null;
81
+ }
82
+ },
83
+ );
@@ -14,10 +14,7 @@ export const getAccountPlaceholderName = ({
14
14
  };
15
15
  export const getNewAccountPlaceholderName = getAccountPlaceholderName; // same naming
16
16
 
17
- export const validateNameEdition = (
18
- account: Account,
19
- name?: string | null | undefined
20
- ): string =>
17
+ export const validateNameEdition = (account: Account, name?: string | null | undefined): string =>
21
18
  (
22
19
  (name || account.name || "").replace(/\s+/g, " ").trim() ||
23
20
  account.name ||
@@ -27,7 +27,7 @@ function generateHistoryFromOperationsG(
27
27
  account: AccountLike,
28
28
  g: GranularityId, // partial=true allows a faster implementation that only recompose the last part of the history
29
29
  // to only use when we do not recalculate the history but we just want to access it
30
- partial = false
30
+ partial = false,
31
31
  ): BalanceHistoryDataCache {
32
32
  const { increment, startOf, maxDatapoints } = granularities[g];
33
33
  const latestDate = startOf(new Date()).getTime();
@@ -51,9 +51,7 @@ function generateHistoryFromOperationsG(
51
51
  // FIXME: added valueOf here to make typescript happy
52
52
  account.operations[i].date.valueOf() > date
53
53
  ) {
54
- balance = balance.minus(
55
- getOperationAmountNumberWithInternals(account.operations[i])
56
- );
54
+ balance = balance.minus(getOperationAmountNumberWithInternals(account.operations[i]));
57
55
  i++;
58
56
  }
59
57
 
@@ -71,9 +69,7 @@ function generateHistoryFromOperationsG(
71
69
  };
72
70
  }
73
71
 
74
- export function generateHistoryFromOperations(
75
- account: AccountLike
76
- ): BalanceHistoryCache {
72
+ export function generateHistoryFromOperations(account: AccountLike): BalanceHistoryCache {
77
73
  return {
78
74
  HOUR: generateHistoryFromOperationsG(account, "HOUR"),
79
75
  DAY: generateHistoryFromOperationsG(account, "DAY"),
@@ -84,10 +80,7 @@ export function generateHistoryFromOperations(
84
80
  /**
85
81
  * get the current balance history of the account. if possible from the cache.
86
82
  */
87
- export function getAccountHistoryBalances(
88
- account: AccountLike,
89
- g: GranularityId
90
- ): number[] {
83
+ export function getAccountHistoryBalances(account: AccountLike, g: GranularityId): number[] {
91
84
  const { balances, latestDate } = account.balanceHistoryCache[g];
92
85
  const { startOf } = granularities[g];
93
86
  const now = startOf(new Date()).getTime();
@@ -103,10 +96,7 @@ export function getAccountHistoryBalances(
103
96
  /**
104
97
  * utility used at the end of an account synchronisation to recalculate the balance history if necessary
105
98
  */
106
- export function recalculateAccountBalanceHistories(
107
- res: Account,
108
- prev: Account
109
- ): Account {
99
+ export function recalculateAccountBalanceHistories(res: Account, prev: Account): Account {
110
100
  // recalculate balance history cache
111
101
  if (prev.balanceHistoryCache === res.balanceHistoryCache) {
112
102
  // we only regenerate if it was not overriden by the implemenetation.
@@ -116,30 +106,21 @@ export function recalculateAccountBalanceHistories(
116
106
  const prevSubAccounts = prev.subAccounts;
117
107
  const nextSubAccounts = res.subAccounts;
118
108
 
119
- if (
120
- nextSubAccounts &&
121
- prevSubAccounts &&
122
- prevSubAccounts !== nextSubAccounts
123
- ) {
109
+ if (nextSubAccounts && prevSubAccounts && prevSubAccounts !== nextSubAccounts) {
124
110
  // when sub accounts changes, we need to recalculate
125
- res.subAccounts = nextSubAccounts.map(
126
- (subAccount: SubAccount): SubAccount => {
127
- const old = prevSubAccounts.find((a) => a.id === subAccount.id);
128
-
129
- if (
130
- !old ||
131
- old.balanceHistoryCache === subAccount.balanceHistoryCache
132
- ) {
133
- // we only regenerate if it was not overriden by the implemenetation.
134
- subAccount = {
135
- ...subAccount,
136
- balanceHistoryCache: generateHistoryFromOperations(subAccount),
137
- };
138
- }
139
-
140
- return subAccount;
111
+ res.subAccounts = nextSubAccounts.map((subAccount: SubAccount): SubAccount => {
112
+ const old = prevSubAccounts.find(a => a.id === subAccount.id);
113
+
114
+ if (!old || old.balanceHistoryCache === subAccount.balanceHistoryCache) {
115
+ // we only regenerate if it was not overriden by the implemenetation.
116
+ subAccount = {
117
+ ...subAccount,
118
+ balanceHistoryCache: generateHistoryFromOperations(subAccount),
119
+ };
141
120
  }
142
- );
121
+
122
+ return subAccount;
123
+ });
143
124
  }
144
125
 
145
126
  return res;
@@ -22,18 +22,16 @@ type GroupOpsByDayOpts = {
22
22
  };
23
23
 
24
24
  const hasStableOperation = (account: AccountLike, hash: string) =>
25
- account.operations.some((op) => op.hash === hash);
25
+ account.operations.some(op => op.hash === hash);
26
26
 
27
27
  /**
28
28
  * @memberof account
29
29
  */
30
30
  export function groupAccountsOperationsByDay(
31
31
  inputAccounts: AccountLikeArray,
32
- { count, withSubAccounts, filterOperation }: GroupOpsByDayOpts
32
+ { count, withSubAccounts, filterOperation }: GroupOpsByDayOpts,
33
33
  ): DailyOperations {
34
- const accounts = withSubAccounts
35
- ? flattenAccounts(inputAccounts)
36
- : inputAccounts;
34
+ const accounts = withSubAccounts ? flattenAccounts(inputAccounts) : inputAccounts;
37
35
  // Track indexes of account.operations[] for each account
38
36
  const indexes: number[] = Array(accounts.length).fill(0);
39
37
  // Track indexes of account.pendingOperations[] for each account
@@ -157,7 +155,7 @@ export function groupAccountsOperationsByDay(
157
155
  */
158
156
  export function groupAccountOperationsByDay(
159
157
  account: AccountLike,
160
- arg: GroupOpsByDayOpts
158
+ arg: GroupOpsByDayOpts,
161
159
  ): DailyOperations {
162
160
  const accounts: AccountLike[] = [account];
163
161
  return groupAccountsOperationsByDay(accounts, arg);
@@ -1,15 +1,5 @@
1
- import {
2
- CryptoCurrency,
3
- TokenCurrency,
4
- Unit,
5
- } from "@ledgerhq/types-cryptoassets";
6
- import {
7
- Account,
8
- ChildAccount,
9
- Operation,
10
- SubAccount,
11
- TokenAccount,
12
- } from "@ledgerhq/types-live";
1
+ import { CryptoCurrency, TokenCurrency, Unit } from "@ledgerhq/types-cryptoassets";
2
+ import { Account, ChildAccount, Operation, SubAccount, TokenAccount } from "@ledgerhq/types-live";
13
3
  import BigNumber from "bignumber.js";
14
4
  import {
15
5
  areAllOperationsLoaded,
@@ -20,11 +10,7 @@ import {
20
10
  getAccountUnit,
21
11
  getFeesCurrency,
22
12
  } from ".";
23
- import {
24
- isAccountEmpty,
25
- isAccountBalanceSignificant,
26
- clearAccount,
27
- } from "./helpers";
13
+ import { isAccountEmpty, isAccountBalanceSignificant, clearAccount } from "./helpers";
28
14
 
29
15
  const mockAccount = {} as Account;
30
16
  const childAccount = {
@@ -251,9 +237,7 @@ describe(getAccountSpendableBalance.name, () => {
251
237
  it("should return the account spendable balance", () => {
252
238
  const sampleAccountBalance = new BigNumber(10);
253
239
  mockAccount.spendableBalance = sampleAccountBalance;
254
- expect(getAccountSpendableBalance(mockAccount)).toEqual(
255
- sampleAccountBalance
256
- );
240
+ expect(getAccountSpendableBalance(mockAccount)).toEqual(sampleAccountBalance);
257
241
  });
258
242
  });
259
243
 
@@ -261,9 +245,7 @@ describe(getAccountSpendableBalance.name, () => {
261
245
  it("should return the account balance", () => {
262
246
  const sampleAccountBalance = new BigNumber(10);
263
247
  childAccount.balance = sampleAccountBalance;
264
- expect(getAccountSpendableBalance(childAccount)).toEqual(
265
- sampleAccountBalance
266
- );
248
+ expect(getAccountSpendableBalance(childAccount)).toEqual(sampleAccountBalance);
267
249
  });
268
250
  });
269
251
 
@@ -271,9 +253,7 @@ describe(getAccountSpendableBalance.name, () => {
271
253
  it("should return the token account spendable balance", () => {
272
254
  const sampleAccountBalance = new BigNumber(10);
273
255
  tokenAccount.spendableBalance = sampleAccountBalance;
274
- expect(getAccountSpendableBalance(tokenAccount)).toEqual(
275
- sampleAccountBalance
276
- );
256
+ expect(getAccountSpendableBalance(tokenAccount)).toEqual(sampleAccountBalance);
277
257
  });
278
258
  });
279
259
 
@@ -11,28 +11,22 @@ import type {
11
11
  TokenAccount,
12
12
  ChildAccount,
13
13
  } from "@ledgerhq/types-live";
14
- import {
15
- CryptoCurrency,
16
- TokenCurrency,
17
- Unit,
18
- } from "@ledgerhq/types-cryptoassets";
14
+ import { CryptoCurrency, TokenCurrency, Unit } from "@ledgerhq/types-cryptoassets";
19
15
 
20
16
  // By convention, a main account is the top level account
21
17
  // - in case of an Account is the account itself
22
18
  // - in case of a SubAccount it's the parentAccount
23
- export const getMainAccount = (
24
- account: AccountLike,
25
- parentAccount?: Account | null | undefined
26
- ): Account => {
19
+ export const getMainAccount = <A extends Account>(
20
+ account: A | SubAccount,
21
+ parentAccount?: A | null | undefined,
22
+ ): A => {
27
23
  const mainAccount = account.type === "Account" ? account : parentAccount;
28
24
  invariant(mainAccount, "an account is expected");
29
- return mainAccount as Account;
25
+ return mainAccount as A;
30
26
  };
31
27
 
32
28
  // Return the currency in which fees are paid for this account
33
- export const getFeesCurrency = (
34
- account?: AccountLike
35
- ): TokenCurrency | CryptoCurrency => {
29
+ export const getFeesCurrency = (account?: AccountLike): TokenCurrency | CryptoCurrency => {
36
30
  switch (account?.type) {
37
31
  case "Account":
38
32
  return account.feesCurrency || account.currency;
@@ -44,9 +38,7 @@ export const getFeesCurrency = (
44
38
  return account.token;
45
39
 
46
40
  default:
47
- throw new Error(
48
- "invalid account.type=" + (account as unknown as { type: string })?.type
49
- );
41
+ throw new Error("invalid account.type=" + (account as unknown as { type: string })?.type);
50
42
  }
51
43
  };
52
44
 
@@ -55,9 +47,7 @@ export const getFeesUnit = (currency: TokenCurrency | CryptoCurrency): Unit => {
55
47
  return currency.units[0];
56
48
  };
57
49
 
58
- export const getAccountCurrency = (
59
- account?: AccountLike
60
- ): TokenCurrency | CryptoCurrency => {
50
+ export const getAccountCurrency = (account?: AccountLike): TokenCurrency | CryptoCurrency => {
61
51
  switch (account?.type) {
62
52
  case "Account":
63
53
  case "ChildAccount":
@@ -67,9 +57,7 @@ export const getAccountCurrency = (
67
57
  return account.token;
68
58
 
69
59
  default:
70
- throw new Error(
71
- "invalid account.type=" + (account as unknown as { type: string })?.type
72
- );
60
+ throw new Error("invalid account.type=" + (account as unknown as { type: string })?.type);
73
61
  }
74
62
  };
75
63
 
@@ -118,8 +106,7 @@ export const getAccountSpendableBalance = (account: AccountLike): BigNumber => {
118
106
  };
119
107
 
120
108
  export const isAccountEmpty = (a: AccountLike): boolean => {
121
- const hasSubAccounts =
122
- a.type === "Account" && a.subAccounts && a.subAccounts.length;
109
+ const hasSubAccounts = a.type === "Account" && a.subAccounts && a.subAccounts.length;
123
110
  return a.operationsCount === 0 && a.balance.isZero() && !hasSubAccounts;
124
111
  };
125
112
 
@@ -135,15 +122,14 @@ export function areAllOperationsLoaded(account: AccountLike): boolean {
135
122
  return true;
136
123
  }
137
124
 
138
- export const isAccountBalanceSignificant = (a: AccountLike): boolean =>
139
- a.balance.gt(100);
125
+ export const isAccountBalanceSignificant = (a: AccountLike): boolean => a.balance.gt(100);
140
126
 
141
127
  // in future, could be a per currency thing
142
128
  // clear account to a bare minimal version that can be restored via sync
143
129
  // will preserve the balance to avoid user panic
144
130
  export function clearAccount<T extends AccountLike>(
145
131
  account: T,
146
- familyClean?: (account: Account) => void
132
+ familyClean?: (account: Account) => void,
147
133
  ): T {
148
134
  if (account.type === "TokenAccount") {
149
135
  return {
@@ -171,9 +157,7 @@ export function clearAccount<T extends AccountLike>(
171
157
  pendingOperations: [],
172
158
  subAccounts:
173
159
  (account as Account).subAccounts &&
174
- (account as Account).subAccounts?.map((acc) =>
175
- clearAccount(acc, familyClean)
176
- ),
160
+ (account as Account).subAccounts?.map(acc => clearAccount(acc, familyClean)),
177
161
  };
178
162
 
179
163
  familyClean?.(copy);
@@ -182,11 +166,8 @@ export function clearAccount<T extends AccountLike>(
182
166
  return copy as T;
183
167
  }
184
168
 
185
- export function findSubAccountById(
186
- account: Account,
187
- id: string
188
- ): SubAccount | null | undefined {
189
- return (account.subAccounts || []).find((a) => a.id === id);
169
+ export function findSubAccountById(account: Account, id: string): SubAccount | null | undefined {
170
+ return (account.subAccounts || []).find(a => a.id === id);
190
171
  }
191
172
 
192
173
  // get the token accounts of an account, ignoring those that are zero IF user don't want them
@@ -194,7 +175,7 @@ export function listSubAccounts(account: Account): SubAccount[] {
194
175
  const accounts = account.subAccounts || [];
195
176
 
196
177
  if (getEnv("HIDE_EMPTY_TOKEN_ACCOUNTS")) {
197
- return accounts.filter((a) => !a.balance.isZero());
178
+ return accounts.filter(a => !a.balance.isZero());
198
179
  }
199
180
 
200
181
  return accounts;
@@ -206,7 +187,7 @@ export type FlattenAccountsOptions = {
206
187
 
207
188
  export function flattenAccounts(
208
189
  topAccounts: AccountLikeArray,
209
- o: FlattenAccountsOptions = {}
190
+ o: FlattenAccountsOptions = {},
210
191
  ): AccountLike[] {
211
192
  const accounts: AccountLike[] = [];
212
193
 
@@ -236,9 +217,8 @@ export const shortAddressPreview = (addr: string, target = 20): string => {
236
217
  };
237
218
 
238
219
  export const isAccountBalanceUnconfirmed = (account: AccountLike): boolean =>
239
- account.pendingOperations.some(
240
- (op) => !account.operations.find((o) => o.hash === op.hash)
241
- ) || account.operations.some((op) => !op.blockHeight);
220
+ account.pendingOperations.some(op => !account.operations.find(o => o.hash === op.hash)) ||
221
+ account.operations.some(op => !op.blockHeight);
242
222
 
243
223
  export const isUpToDateAccount = (account: Account | null | undefined) => {
244
224
  if (!account) return true;
@@ -246,16 +226,12 @@ export const isUpToDateAccount = (account: Account | null | undefined) => {
246
226
  const { blockAvgTime } = currency;
247
227
  if (!blockAvgTime) return true;
248
228
  const outdated =
249
- // FIXME: same here, we need to use valueOf for typescript to compare dates
250
- Date.now().valueOf() - (lastSyncDate.valueOf() || 0) >
229
+ Date.now() - lastSyncDate.getTime() >
251
230
  blockAvgTime * 1000 + getEnv("SYNC_OUTDATED_CONSIDERED_DELAY");
252
231
  return !outdated;
253
232
  };
254
233
 
255
- export const makeEmptyTokenAccount = (
256
- account: Account,
257
- token: TokenCurrency
258
- ): TokenAccount => ({
234
+ export const makeEmptyTokenAccount = (account: Account, token: TokenCurrency): TokenAccount => ({
259
235
  type: "TokenAccount",
260
236
  id: account.id + "+" + token.contractAddress,
261
237
  parentId: account.id,
@@ -276,20 +252,18 @@ export const makeEmptyTokenAccount = (
276
252
  */
277
253
  export const accountWithMandatoryTokens = (
278
254
  account: Account,
279
- tokenCurrencies: TokenCurrency[]
255
+ tokenCurrencies: TokenCurrency[],
280
256
  ): Account => {
281
257
  const { subAccounts } = account;
282
258
  if (!subAccounts) return account;
283
- const existingTokens = subAccounts
284
- .map((a) => a.type === "TokenAccount" && a.token)
285
- .filter(Boolean);
259
+ const existingTokens = subAccounts.map(a => a.type === "TokenAccount" && a.token).filter(Boolean);
286
260
  const addition = tokenCurrencies
287
261
  .filter(
288
262
  (
289
- t // token of the same currency
290
- ) => t.parentCurrency === account.currency && !existingTokens.includes(t) // not yet in the sub accounts
263
+ t, // token of the same currency
264
+ ) => t.parentCurrency === account.currency && !existingTokens.includes(t), // not yet in the sub accounts
291
265
  )
292
- .map<TokenAccount>((token) => ({
266
+ .map<TokenAccount>(token => ({
293
267
  type: "TokenAccount",
294
268
  id: encodeTokenAccountId(account.id, token),
295
269
  parentId: account.id,
@@ -314,13 +288,11 @@ export const accountWithMandatoryTokens = (
314
288
  export const withoutToken = (account: Account, tokenId: string): Account => {
315
289
  const { subAccounts } = account;
316
290
  if (!subAccounts) return account;
317
- const tokenAccount = subAccounts.find(
318
- (a) => a.type === "TokenAccount" && a.token.id === tokenId
319
- );
291
+ const tokenAccount = subAccounts.find(a => a.type === "TokenAccount" && a.token.id === tokenId);
320
292
  if (!tokenAccount) return account;
321
293
  return {
322
294
  ...account,
323
- subAccounts: subAccounts.filter((sa) => sa.id !== tokenAccount.id),
295
+ subAccounts: subAccounts.filter(sa => sa.id !== tokenAccount.id),
324
296
  };
325
297
  };
326
298
 
@@ -330,7 +302,7 @@ export const withoutToken = (account: Account, tokenId: string): Account => {
330
302
  */
331
303
  export const findTokenAccountByCurrency = (
332
304
  tokenCurrency: TokenCurrency,
333
- accounts: Account[]
305
+ accounts: Account[],
334
306
  ):
335
307
  | {
336
308
  account?: SubAccount;
@@ -384,20 +356,15 @@ export function isSubAccount(account?: AccountLike): account is SubAccount {
384
356
  return isTokenAccount(account) || isChildAccount(account);
385
357
  }
386
358
 
387
- export function getParentAccount(
388
- account: AccountLike,
389
- accounts: AccountLike[]
390
- ): Account {
359
+ export function getParentAccount(account: AccountLike, accounts: AccountLike[]): Account {
391
360
  switch (account.type) {
392
361
  case "Account":
393
362
  return account;
394
363
  case "TokenAccount":
395
364
  case "ChildAccount": {
396
- const parentAccount = accounts.find((a) => a.id == account.parentId);
365
+ const parentAccount = accounts.find(a => a.id == account.parentId);
397
366
  if (!parentAccount) {
398
- throw new Error(
399
- "No 'parentAccount' account provided for token account"
400
- );
367
+ throw new Error("No 'parentAccount' account provided for token account");
401
368
  }
402
369
 
403
370
  return parentAccount as Account;