@ledgerhq/coin-cosmos 0.21.0-nightly.20251211024123 → 0.21.0-nightly.20251212024049
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.
- package/CHANGELOG.md +13 -11
- package/lib/bridge/index.d.ts.map +1 -1
- package/lib/bridge/index.js +2 -0
- package/lib/bridge/index.js.map +1 -1
- package/lib/bridge/index.test.d.ts +2 -0
- package/lib/bridge/index.test.d.ts.map +1 -0
- package/lib/bridge/index.test.js +68 -0
- package/lib/bridge/index.test.js.map +1 -0
- package/lib/buildTransaction.unit.test.d.ts +2 -0
- package/lib/buildTransaction.unit.test.d.ts.map +1 -0
- package/lib/buildTransaction.unit.test.js +736 -0
- package/lib/buildTransaction.unit.test.js.map +1 -0
- package/lib/chain/chain.unit.test.d.ts +2 -0
- package/lib/chain/chain.unit.test.d.ts.map +1 -0
- package/lib/chain/chain.unit.test.js +41 -0
- package/lib/chain/chain.unit.test.js.map +1 -0
- package/lib/helpers.unit.test.d.ts +2 -0
- package/lib/helpers.unit.test.d.ts.map +1 -0
- package/lib/helpers.unit.test.js +65 -0
- package/lib/helpers.unit.test.js.map +1 -0
- package/lib/mock.d.ts +5 -4
- package/lib/mock.d.ts.map +1 -1
- package/lib/mock.js +7 -0
- package/lib/mock.js.map +1 -1
- package/lib/network/Cosmos.unit.test.d.ts +2 -0
- package/lib/network/Cosmos.unit.test.d.ts.map +1 -0
- package/lib/network/Cosmos.unit.test.js +580 -0
- package/lib/network/Cosmos.unit.test.js.map +1 -0
- package/lib/prepareTransaction.unit.test.d.ts +2 -0
- package/lib/prepareTransaction.unit.test.d.ts.map +1 -0
- package/lib/prepareTransaction.unit.test.js +159 -0
- package/lib/prepareTransaction.unit.test.js.map +1 -0
- package/lib/synchronisation.integ.test.d.ts +2 -0
- package/lib/synchronisation.integ.test.d.ts.map +1 -0
- package/lib/synchronisation.integ.test.js +233 -0
- package/lib/synchronisation.integ.test.js.map +1 -0
- package/lib/synchronisation.test.d.ts +2 -0
- package/lib/synchronisation.test.d.ts.map +1 -0
- package/lib/synchronisation.test.js +65 -0
- package/lib/synchronisation.test.js.map +1 -0
- package/lib/synchronisation.unit.test.d.ts +2 -0
- package/lib/synchronisation.unit.test.d.ts.map +1 -0
- package/lib/synchronisation.unit.test.js +667 -0
- package/lib/synchronisation.unit.test.js.map +1 -0
- package/lib/validateAddress.d.ts +3 -0
- package/lib/validateAddress.d.ts.map +1 -0
- package/lib/validateAddress.js +52 -0
- package/lib/validateAddress.js.map +1 -0
- package/lib/validateAddress.test.d.ts +2 -0
- package/lib/validateAddress.test.d.ts.map +1 -0
- package/lib/validateAddress.test.js +125 -0
- package/lib/validateAddress.test.js.map +1 -0
- package/lib-es/bridge/index.d.ts.map +1 -1
- package/lib-es/bridge/index.js +2 -0
- package/lib-es/bridge/index.js.map +1 -1
- package/lib-es/bridge/index.test.d.ts +2 -0
- package/lib-es/bridge/index.test.d.ts.map +1 -0
- package/lib-es/bridge/index.test.js +66 -0
- package/lib-es/bridge/index.test.js.map +1 -0
- package/lib-es/buildTransaction.unit.test.d.ts +2 -0
- package/lib-es/buildTransaction.unit.test.d.ts.map +1 -0
- package/lib-es/buildTransaction.unit.test.js +731 -0
- package/lib-es/buildTransaction.unit.test.js.map +1 -0
- package/lib-es/chain/chain.unit.test.d.ts +2 -0
- package/lib-es/chain/chain.unit.test.d.ts.map +1 -0
- package/lib-es/chain/chain.unit.test.js +36 -0
- package/lib-es/chain/chain.unit.test.js.map +1 -0
- package/lib-es/helpers.unit.test.d.ts +2 -0
- package/lib-es/helpers.unit.test.d.ts.map +1 -0
- package/lib-es/helpers.unit.test.js +63 -0
- package/lib-es/helpers.unit.test.js.map +1 -0
- package/lib-es/mock.d.ts +5 -4
- package/lib-es/mock.d.ts.map +1 -1
- package/lib-es/mock.js +7 -0
- package/lib-es/mock.js.map +1 -1
- package/lib-es/network/Cosmos.unit.test.d.ts +2 -0
- package/lib-es/network/Cosmos.unit.test.d.ts.map +1 -0
- package/lib-es/network/Cosmos.unit.test.js +575 -0
- package/lib-es/network/Cosmos.unit.test.js.map +1 -0
- package/lib-es/prepareTransaction.unit.test.d.ts +2 -0
- package/lib-es/prepareTransaction.unit.test.d.ts.map +1 -0
- package/lib-es/prepareTransaction.unit.test.js +131 -0
- package/lib-es/prepareTransaction.unit.test.js.map +1 -0
- package/lib-es/synchronisation.integ.test.d.ts +2 -0
- package/lib-es/synchronisation.integ.test.d.ts.map +1 -0
- package/lib-es/synchronisation.integ.test.js +205 -0
- package/lib-es/synchronisation.integ.test.js.map +1 -0
- package/lib-es/synchronisation.test.d.ts +2 -0
- package/lib-es/synchronisation.test.d.ts.map +1 -0
- package/lib-es/synchronisation.test.js +60 -0
- package/lib-es/synchronisation.test.js.map +1 -0
- package/lib-es/synchronisation.unit.test.d.ts +2 -0
- package/lib-es/synchronisation.unit.test.d.ts.map +1 -0
- package/lib-es/synchronisation.unit.test.js +639 -0
- package/lib-es/synchronisation.unit.test.js.map +1 -0
- package/lib-es/validateAddress.d.ts +3 -0
- package/lib-es/validateAddress.d.ts.map +1 -0
- package/lib-es/validateAddress.js +22 -0
- package/lib-es/validateAddress.js.map +1 -0
- package/lib-es/validateAddress.test.d.ts +2 -0
- package/lib-es/validateAddress.test.d.ts.map +1 -0
- package/lib-es/validateAddress.test.js +97 -0
- package/lib-es/validateAddress.test.js.map +1 -0
- package/package.json +10 -10
- package/src/bridge/index.ts +2 -0
- package/src/mock.ts +21 -11
- package/src/validateAddress.test.ts +132 -0
- package/src/validateAddress.ts +27 -0
- package/tsconfig.json +8 -2
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as bech32 from "bech32";
|
|
2
|
+
import { findCryptoCurrencyById } from "@ledgerhq/cryptoassets";
|
|
3
|
+
import cryptoFactory from "./chain/chain";
|
|
4
|
+
export async function validateAddress(address, parameters) {
|
|
5
|
+
if (!parameters.currency) {
|
|
6
|
+
throw new Error("Missing currency parameter on address validation for Cosmos");
|
|
7
|
+
}
|
|
8
|
+
let isValid = true;
|
|
9
|
+
try {
|
|
10
|
+
bech32.decode(address);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
isValid = false;
|
|
14
|
+
}
|
|
15
|
+
const currency = findCryptoCurrencyById(parameters.currency.name.toLowerCase());
|
|
16
|
+
let prefix = "";
|
|
17
|
+
if (currency) {
|
|
18
|
+
prefix = cryptoFactory(currency.id).prefix;
|
|
19
|
+
}
|
|
20
|
+
return isValid && address.startsWith(prefix);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=validateAddress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateAddress.js","sourceRoot":"","sources":["../src/validateAddress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,aAAa,MAAM,eAAe,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAe,EACf,UAAwD;IAExD,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IAED,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,KAAK,CAAC;IAClB,CAAC;IACD,MAAM,QAAQ,GAAG,sBAAsB,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IAChF,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;IAC7C,CAAC;IAED,OAAO,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateAddress.test.d.ts","sourceRoot":"","sources":["../src/validateAddress.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { validateAddress } from "./validateAddress";
|
|
2
|
+
import * as bech32 from "bech32";
|
|
3
|
+
import { findCryptoCurrencyById } from "@ledgerhq/cryptoassets";
|
|
4
|
+
import cryptoFactory from "./chain/chain";
|
|
5
|
+
jest.mock("bech32");
|
|
6
|
+
jest.mock("@ledgerhq/cryptoassets");
|
|
7
|
+
jest.mock("./chain/chain");
|
|
8
|
+
describe("validateAddress", () => {
|
|
9
|
+
const mockedDecode = jest.mocked(bech32.decode);
|
|
10
|
+
const mockedFindCryptoCurrencyById = jest.mocked(findCryptoCurrencyById);
|
|
11
|
+
const mockedCryptoFactory = jest.mocked(cryptoFactory);
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
mockedDecode.mockClear();
|
|
14
|
+
mockedFindCryptoCurrencyById.mockClear();
|
|
15
|
+
mockedCryptoFactory.mockClear();
|
|
16
|
+
});
|
|
17
|
+
it("should throw an error when currency parameters is not provided", async () => {
|
|
18
|
+
try {
|
|
19
|
+
await validateAddress("some random address", {});
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
expect(error).toBeInstanceOf(Error);
|
|
23
|
+
expect(error.message).toEqual("Missing currency parameter on address validation for Cosmos");
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
it.each([true, false])("should only decode address when currency config not found and return expected value (%s)", async (expectedValue) => {
|
|
27
|
+
if (!expectedValue) {
|
|
28
|
+
mockedDecode.mockImplementationOnce(_address => {
|
|
29
|
+
throw new Error("Mocked Error from unit test");
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
mockedFindCryptoCurrencyById.mockReturnValueOnce(undefined);
|
|
33
|
+
const address = "some random address";
|
|
34
|
+
const parameters = {
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
36
|
+
currency: {
|
|
37
|
+
name: "cosmos",
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
const result = await validateAddress(address, parameters);
|
|
41
|
+
expect(result).toEqual(expectedValue);
|
|
42
|
+
expect(mockedDecode).toHaveBeenCalledTimes(1);
|
|
43
|
+
expect(mockedDecode).toHaveBeenCalledWith(address);
|
|
44
|
+
expect(mockedFindCryptoCurrencyById).toHaveBeenCalledTimes(1);
|
|
45
|
+
expect(mockedFindCryptoCurrencyById).toHaveBeenCalledWith(parameters.currency.name);
|
|
46
|
+
});
|
|
47
|
+
it.each([true, false])("should decode address, check prefix from currency config and return expected value (%s)", async (expectedValue) => {
|
|
48
|
+
const address = "cosmos: some random address";
|
|
49
|
+
const parameters = {
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
51
|
+
currency: {
|
|
52
|
+
id: "cosmos id",
|
|
53
|
+
name: "cosmos name",
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
mockedFindCryptoCurrencyById.mockReturnValueOnce(parameters.currency);
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
58
|
+
mockedCryptoFactory.mockReturnValueOnce({
|
|
59
|
+
prefix: expectedValue ? "cosmos" : "other",
|
|
60
|
+
});
|
|
61
|
+
const result = await validateAddress(address, parameters);
|
|
62
|
+
expect(result).toEqual(expectedValue);
|
|
63
|
+
expect(mockedDecode).toHaveBeenCalledTimes(1);
|
|
64
|
+
expect(mockedDecode).toHaveBeenCalledWith(address);
|
|
65
|
+
expect(mockedFindCryptoCurrencyById).toHaveBeenCalledTimes(1);
|
|
66
|
+
expect(mockedFindCryptoCurrencyById).toHaveBeenCalledWith(parameters.currency.name);
|
|
67
|
+
expect(mockedCryptoFactory).toHaveBeenCalledTimes(1);
|
|
68
|
+
expect(mockedCryptoFactory).toHaveBeenCalledWith(parameters.currency.id);
|
|
69
|
+
});
|
|
70
|
+
it("should return false when decode and prefix check fail", async () => {
|
|
71
|
+
mockedDecode.mockImplementationOnce(_address => {
|
|
72
|
+
throw new Error("Mocked Error from unit tests");
|
|
73
|
+
});
|
|
74
|
+
const address = "cosmos: some random address";
|
|
75
|
+
const parameters = {
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
77
|
+
currency: {
|
|
78
|
+
id: "cosmos id",
|
|
79
|
+
name: "cosmos name",
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
mockedFindCryptoCurrencyById.mockReturnValueOnce(parameters.currency);
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
84
|
+
mockedCryptoFactory.mockReturnValueOnce({
|
|
85
|
+
prefix: "juno:",
|
|
86
|
+
});
|
|
87
|
+
const result = await validateAddress(address, parameters);
|
|
88
|
+
expect(result).toEqual(false);
|
|
89
|
+
expect(mockedDecode).toHaveBeenCalledTimes(1);
|
|
90
|
+
expect(mockedDecode).toHaveBeenCalledWith(address);
|
|
91
|
+
expect(mockedFindCryptoCurrencyById).toHaveBeenCalledTimes(1);
|
|
92
|
+
expect(mockedFindCryptoCurrencyById).toHaveBeenCalledWith(parameters.currency.name);
|
|
93
|
+
expect(mockedCryptoFactory).toHaveBeenCalledTimes(1);
|
|
94
|
+
expect(mockedCryptoFactory).toHaveBeenCalledWith(parameters.currency.id);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=validateAddress.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateAddress.test.js","sourceRoot":"","sources":["../src/validateAddress.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/coin-cosmos",
|
|
3
|
-
"version": "0.21.0-nightly.
|
|
3
|
+
"version": "0.21.0-nightly.20251212024049",
|
|
4
4
|
"description": "Ledger Cosmos Coin integration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ledger",
|
|
@@ -59,16 +59,16 @@
|
|
|
59
59
|
"prando": "^6.0.1",
|
|
60
60
|
"rxjs": "7.8.2",
|
|
61
61
|
"semver": "^7.1.3",
|
|
62
|
-
"@ledgerhq/coin-framework": "^6.11.0-nightly.
|
|
63
|
-
"@ledgerhq/cryptoassets": "^13.35.0-nightly.
|
|
64
|
-
"@ledgerhq/devices": "8.8.0-nightly.
|
|
65
|
-
"@ledgerhq/errors": "^6.28.0-nightly.
|
|
66
|
-
"@ledgerhq/live-config": "^3.3.0-nightly.
|
|
67
|
-
"@ledgerhq/live-env": "^2.23.0-nightly.
|
|
68
|
-
"@ledgerhq/live-network": "^2.1.3-nightly.
|
|
62
|
+
"@ledgerhq/coin-framework": "^6.11.0-nightly.20251212024049",
|
|
63
|
+
"@ledgerhq/cryptoassets": "^13.35.0-nightly.20251212024049",
|
|
64
|
+
"@ledgerhq/devices": "8.8.0-nightly.20251212024049",
|
|
65
|
+
"@ledgerhq/errors": "^6.28.0-nightly.20251212024049",
|
|
66
|
+
"@ledgerhq/live-config": "^3.3.0-nightly.20251212024049",
|
|
67
|
+
"@ledgerhq/live-env": "^2.23.0-nightly.20251212024049",
|
|
68
|
+
"@ledgerhq/live-network": "^2.1.3-nightly.20251212024049",
|
|
69
69
|
"@ledgerhq/logs": "^6.13.0",
|
|
70
|
-
"@ledgerhq/types-cryptoassets": "^7.31.0-nightly.
|
|
71
|
-
"@ledgerhq/types-live": "^6.91.0-nightly.
|
|
70
|
+
"@ledgerhq/types-cryptoassets": "^7.31.0-nightly.20251212024049",
|
|
71
|
+
"@ledgerhq/types-live": "^6.91.0-nightly.20251212024049"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@types/invariant": "^2.2.2",
|
package/src/bridge/index.ts
CHANGED
|
@@ -29,6 +29,7 @@ import type { CosmosAccount, CosmosOperation, Transaction, TransactionStatus } f
|
|
|
29
29
|
import { CosmosSigner } from "../types/signer";
|
|
30
30
|
import { updateTransaction } from "../updateTransaction";
|
|
31
31
|
import { getPreloadStrategy, hydrate, preload } from "./preload";
|
|
32
|
+
import { validateAddress } from "../validateAddress";
|
|
32
33
|
|
|
33
34
|
const sync = makeSync({ getAccountShape });
|
|
34
35
|
|
|
@@ -80,6 +81,7 @@ function buildAccountBridge(
|
|
|
80
81
|
formatAccountSpecifics: formatters.formatAccountSpecifics,
|
|
81
82
|
formatOperationSpecifics: formatters.formatOperationSpecifics,
|
|
82
83
|
getSerializedAddressParameters,
|
|
84
|
+
validateAddress,
|
|
83
85
|
};
|
|
84
86
|
}
|
|
85
87
|
|
package/src/mock.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { BigNumber } from "bignumber.js";
|
|
2
2
|
import Prando from "prando";
|
|
3
3
|
import { genAddress, genHex } from "@ledgerhq/coin-framework/mocks/helpers";
|
|
4
|
-
import type { OperationType } from "@ledgerhq/types-live";
|
|
4
|
+
import type { Account, OperationType } from "@ledgerhq/types-live";
|
|
5
5
|
import preloadedData from "./preloadedData.mock";
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
import {
|
|
7
|
+
isCosmosAccount,
|
|
8
|
+
type CosmosAccount,
|
|
9
|
+
type CosmosDelegation,
|
|
10
|
+
type CosmosOperation,
|
|
11
|
+
type CosmosRedelegation,
|
|
12
|
+
type CosmosResources,
|
|
13
|
+
type CosmosUnbonding,
|
|
13
14
|
} from "./types";
|
|
14
15
|
const { validators } = preloadedData;
|
|
15
16
|
|
|
@@ -340,7 +341,10 @@ function genAccountEnhanceOperations(account: CosmosAccount, rng: Prando): Cosmo
|
|
|
340
341
|
* @memberof cosmos/mock
|
|
341
342
|
* @param {CosmosAccount} account
|
|
342
343
|
*/
|
|
343
|
-
function postSyncAccount(account:
|
|
344
|
+
function postSyncAccount(account: Account): Account {
|
|
345
|
+
if (!isCosmosAccount(account)) {
|
|
346
|
+
throw new Error("postSyncAccount must be called with a CosmosAccount type parameter");
|
|
347
|
+
}
|
|
344
348
|
const cosmosResources = account?.cosmosResources;
|
|
345
349
|
const delegatedBalance = cosmosResources?.delegatedBalance ?? new BigNumber(0);
|
|
346
350
|
const unbondingBalance = cosmosResources?.unbondingBalance ?? new BigNumber(0);
|
|
@@ -355,13 +359,19 @@ function postSyncAccount(account: CosmosAccount): CosmosAccount {
|
|
|
355
359
|
* @param {CosmosAccount} account
|
|
356
360
|
*/
|
|
357
361
|
function postScanAccount(
|
|
358
|
-
account:
|
|
362
|
+
account: Account,
|
|
359
363
|
{
|
|
360
364
|
isEmpty,
|
|
361
365
|
}: {
|
|
362
366
|
isEmpty: boolean;
|
|
363
367
|
},
|
|
364
|
-
):
|
|
368
|
+
): Account {
|
|
369
|
+
if (!isCosmosAccount(account)) {
|
|
370
|
+
throw new Error(
|
|
371
|
+
"postScanAccount from cosmos must be used with a CosmosAccount type as parameter",
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
|
|
365
375
|
if (isEmpty) {
|
|
366
376
|
account.cosmosResources = {
|
|
367
377
|
delegations: [],
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { validateAddress } from "./validateAddress";
|
|
2
|
+
import * as bech32 from "bech32";
|
|
3
|
+
import { findCryptoCurrencyById } from "@ledgerhq/cryptoassets";
|
|
4
|
+
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
5
|
+
import cryptoFactory from "./chain/chain";
|
|
6
|
+
import cosmosBase from "./chain/cosmosBase";
|
|
7
|
+
|
|
8
|
+
jest.mock("bech32");
|
|
9
|
+
jest.mock("@ledgerhq/cryptoassets");
|
|
10
|
+
jest.mock("./chain/chain");
|
|
11
|
+
|
|
12
|
+
describe("validateAddress", () => {
|
|
13
|
+
const mockedDecode = jest.mocked(bech32.decode);
|
|
14
|
+
const mockedFindCryptoCurrencyById = jest.mocked(findCryptoCurrencyById);
|
|
15
|
+
const mockedCryptoFactory = jest.mocked(cryptoFactory);
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
mockedDecode.mockClear();
|
|
19
|
+
mockedFindCryptoCurrencyById.mockClear();
|
|
20
|
+
mockedCryptoFactory.mockClear();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should throw an error when currency parameters is not provided", async () => {
|
|
24
|
+
try {
|
|
25
|
+
await validateAddress("some random address", {});
|
|
26
|
+
} catch (error) {
|
|
27
|
+
expect(error).toBeInstanceOf(Error);
|
|
28
|
+
expect((error as Error).message).toEqual(
|
|
29
|
+
"Missing currency parameter on address validation for Cosmos",
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it.each([true, false])(
|
|
35
|
+
"should only decode address when currency config not found and return expected value (%s)",
|
|
36
|
+
async (expectedValue: boolean) => {
|
|
37
|
+
if (!expectedValue) {
|
|
38
|
+
mockedDecode.mockImplementationOnce(_address => {
|
|
39
|
+
throw new Error("Mocked Error from unit test");
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
mockedFindCryptoCurrencyById.mockReturnValueOnce(undefined);
|
|
44
|
+
const address = "some random address";
|
|
45
|
+
const parameters = {
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
47
|
+
currency: {
|
|
48
|
+
name: "cosmos",
|
|
49
|
+
} as CryptoCurrency,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const result = await validateAddress(address, parameters);
|
|
53
|
+
|
|
54
|
+
expect(result).toEqual(expectedValue);
|
|
55
|
+
|
|
56
|
+
expect(mockedDecode).toHaveBeenCalledTimes(1);
|
|
57
|
+
expect(mockedDecode).toHaveBeenCalledWith(address);
|
|
58
|
+
|
|
59
|
+
expect(mockedFindCryptoCurrencyById).toHaveBeenCalledTimes(1);
|
|
60
|
+
expect(mockedFindCryptoCurrencyById).toHaveBeenCalledWith(parameters.currency.name);
|
|
61
|
+
},
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
it.each([true, false])(
|
|
65
|
+
"should decode address, check prefix from currency config and return expected value (%s)",
|
|
66
|
+
async (expectedValue: boolean) => {
|
|
67
|
+
const address = "cosmos: some random address";
|
|
68
|
+
const parameters = {
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
70
|
+
currency: {
|
|
71
|
+
id: "cosmos id",
|
|
72
|
+
name: "cosmos name",
|
|
73
|
+
} as CryptoCurrency,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
mockedFindCryptoCurrencyById.mockReturnValueOnce(parameters.currency);
|
|
77
|
+
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
79
|
+
mockedCryptoFactory.mockReturnValueOnce({
|
|
80
|
+
prefix: expectedValue ? "cosmos" : "other",
|
|
81
|
+
} as unknown as cosmosBase);
|
|
82
|
+
|
|
83
|
+
const result = await validateAddress(address, parameters);
|
|
84
|
+
|
|
85
|
+
expect(result).toEqual(expectedValue);
|
|
86
|
+
|
|
87
|
+
expect(mockedDecode).toHaveBeenCalledTimes(1);
|
|
88
|
+
expect(mockedDecode).toHaveBeenCalledWith(address);
|
|
89
|
+
|
|
90
|
+
expect(mockedFindCryptoCurrencyById).toHaveBeenCalledTimes(1);
|
|
91
|
+
expect(mockedFindCryptoCurrencyById).toHaveBeenCalledWith(parameters.currency.name);
|
|
92
|
+
|
|
93
|
+
expect(mockedCryptoFactory).toHaveBeenCalledTimes(1);
|
|
94
|
+
expect(mockedCryptoFactory).toHaveBeenCalledWith(parameters.currency.id);
|
|
95
|
+
},
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
it("should return false when decode and prefix check fail", async () => {
|
|
99
|
+
mockedDecode.mockImplementationOnce(_address => {
|
|
100
|
+
throw new Error("Mocked Error from unit tests");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const address = "cosmos: some random address";
|
|
104
|
+
const parameters = {
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
106
|
+
currency: {
|
|
107
|
+
id: "cosmos id",
|
|
108
|
+
name: "cosmos name",
|
|
109
|
+
} as CryptoCurrency,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
mockedFindCryptoCurrencyById.mockReturnValueOnce(parameters.currency);
|
|
113
|
+
|
|
114
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
115
|
+
mockedCryptoFactory.mockReturnValueOnce({
|
|
116
|
+
prefix: "juno:",
|
|
117
|
+
} as unknown as cosmosBase);
|
|
118
|
+
|
|
119
|
+
const result = await validateAddress(address, parameters);
|
|
120
|
+
|
|
121
|
+
expect(result).toEqual(false);
|
|
122
|
+
|
|
123
|
+
expect(mockedDecode).toHaveBeenCalledTimes(1);
|
|
124
|
+
expect(mockedDecode).toHaveBeenCalledWith(address);
|
|
125
|
+
|
|
126
|
+
expect(mockedFindCryptoCurrencyById).toHaveBeenCalledTimes(1);
|
|
127
|
+
expect(mockedFindCryptoCurrencyById).toHaveBeenCalledWith(parameters.currency.name);
|
|
128
|
+
|
|
129
|
+
expect(mockedCryptoFactory).toHaveBeenCalledTimes(1);
|
|
130
|
+
expect(mockedCryptoFactory).toHaveBeenCalledWith(parameters.currency.id);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AddressValidationCurrencyParameters } from "@ledgerhq/types-live";
|
|
2
|
+
import * as bech32 from "bech32";
|
|
3
|
+
import { findCryptoCurrencyById } from "@ledgerhq/cryptoassets";
|
|
4
|
+
import cryptoFactory from "./chain/chain";
|
|
5
|
+
|
|
6
|
+
export async function validateAddress(
|
|
7
|
+
address: string,
|
|
8
|
+
parameters: Partial<AddressValidationCurrencyParameters>,
|
|
9
|
+
): Promise<boolean> {
|
|
10
|
+
if (!parameters.currency) {
|
|
11
|
+
throw new Error("Missing currency parameter on address validation for Cosmos");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let isValid = true;
|
|
15
|
+
try {
|
|
16
|
+
bech32.decode(address);
|
|
17
|
+
} catch {
|
|
18
|
+
isValid = false;
|
|
19
|
+
}
|
|
20
|
+
const currency = findCryptoCurrencyById(parameters.currency.name.toLowerCase());
|
|
21
|
+
let prefix = "";
|
|
22
|
+
if (currency) {
|
|
23
|
+
prefix = cryptoFactory(currency.id).prefix;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return isValid && address.startsWith(prefix);
|
|
27
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -4,9 +4,15 @@
|
|
|
4
4
|
"declaration": true,
|
|
5
5
|
"declarationMap": true,
|
|
6
6
|
"downlevelIteration": true,
|
|
7
|
-
"lib": [
|
|
7
|
+
"lib": [
|
|
8
|
+
"es2020",
|
|
9
|
+
"dom"
|
|
10
|
+
],
|
|
8
11
|
"outDir": "lib",
|
|
9
12
|
"exactOptionalPropertyTypes": true
|
|
10
13
|
},
|
|
11
|
-
"include": [
|
|
14
|
+
"include": [
|
|
15
|
+
"src/**/*"
|
|
16
|
+
],
|
|
17
|
+
"exclude": []
|
|
12
18
|
}
|