@ledgerhq/coin-framework 0.7.1-hotfix.0 → 0.8.0-hotfix.1

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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @ledgerhq/coin-framework@0.7.0 build /home/runner/work/ledger-live/ledger-live/libs/coin-framework
2
+ > @ledgerhq/coin-framework@0.7.1-hotfix.0 build /home/runner/work/ledger-live/ledger-live/libs/coin-framework
3
3
  > tsc && tsc -m ES6 --outDir lib-es
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @ledgerhq/coin-framework
2
2
 
3
+ ## 0.8.0-hotfix.1
4
+
5
+ ### Minor Changes
6
+
7
+ - [#5042](https://github.com/LedgerHQ/ledger-live/pull/5042) [`3b4f7501cc`](https://github.com/LedgerHQ/ledger-live/commit/3b4f7501cc5f09be94a2994f20f9998898682975) Thanks [@lambertkevin](https://github.com/lambertkevin)! - Modify token ids encoding in `TokenAccounts` ids which could contain characters preventing the correct "deserialization" of those ids.
8
+
3
9
  ## 0.7.1-hotfix.0
4
10
 
5
11
  ### Patch Changes
@@ -1,5 +1,7 @@
1
1
  import type { AccountIdParams, DerivationMode } from "@ledgerhq/types-live";
2
2
  import type { CryptoCurrency, TokenCurrency } from "@ledgerhq/types-cryptoassets";
3
+ export declare function safeEncodeTokenId(tokenId: string): string;
4
+ export declare function safeDecodeTokenId(encodedTokenId: string): string;
3
5
  export declare function encodeAccountId({ type, version, currencyId, xpubOrAddress, derivationMode, }: AccountIdParams): string;
4
6
  export declare function encodeTokenAccountId(accountId: string, token: TokenCurrency): string;
5
7
  export declare function decodeTokenAccountId(id: string): {
@@ -1 +1 @@
1
- {"version":3,"file":"accountId.d.ts","sourceRoot":"","sources":["../../src/account/accountId.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAOlF,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,OAAO,EACP,UAAU,EACV,aAAa,EACb,cAAc,GACf,EAAE,eAAe,GAAG,MAAM,CAQ1B;AACD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,CAEpF;AACD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;CACzC,CAYA;AACD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAYlE;AAGD,wBAAgB,aAAa,CAAC,EAC5B,cAAc,EACd,cAAc,EACd,QAAQ,GACT,EAAE;IACD,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,cAAc,CAAC;CAC1B,GAAG,MAAM,CAET;AACD,eAAO,MAAM,wBAAwB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,SAS7E,CAAC"}
1
+ {"version":3,"file":"accountId.d.ts","sourceRoot":"","sources":["../../src/account/accountId.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAOlF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOzD;AAED,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAShE;AAED,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,OAAO,EACP,UAAU,EACV,aAAa,EACb,cAAc,GACf,EAAE,eAAe,GAAG,MAAM,CAQ1B;AACD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,CAEpF;AACD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;CACzC,CAYA;AACD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAYlE;AAGD,wBAAgB,aAAa,CAAC,EAC5B,cAAc,EACd,cAAc,EACd,QAAQ,GACT,EAAE;IACD,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,cAAc,CAAC;CAC1B,GAAG,MAAM,CAET;AACD,eAAO,MAAM,wBAAwB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,SAS7E,CAAC"}
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.inferFamilyFromAccountId = exports.getWalletName = exports.decodeAccountId = exports.decodeTokenAccountId = exports.encodeTokenAccountId = exports.encodeAccountId = void 0;
6
+ exports.inferFamilyFromAccountId = exports.getWalletName = exports.decodeAccountId = exports.decodeTokenAccountId = exports.encodeTokenAccountId = exports.encodeAccountId = exports.safeDecodeTokenId = exports.safeEncodeTokenId = void 0;
7
7
  const memoize_1 = __importDefault(require("lodash/memoize"));
8
8
  const invariant_1 = __importDefault(require("invariant"));
9
9
  const derivation_1 = require("../derivation");
@@ -13,17 +13,35 @@ function ensureNoColon(value, ctx) {
13
13
  (0, invariant_1.default)(!value.includes(":"), "AccountId '%s' component must not use colon", ctx);
14
14
  return value;
15
15
  }
16
+ function safeEncodeTokenId(tokenId) {
17
+ if (!tokenId)
18
+ return "";
19
+ const URIEncoded = encodeURIComponent(tokenId);
20
+ const dashUnderscoreSafe = URIEncoded.replace(/-/g, "~!dash!~").replace(/_/g, "~!underscore!~");
21
+ return dashUnderscoreSafe;
22
+ }
23
+ exports.safeEncodeTokenId = safeEncodeTokenId;
24
+ function safeDecodeTokenId(encodedTokenId) {
25
+ if (!encodedTokenId)
26
+ return "";
27
+ const dashUnderscoreUnsafe = encodedTokenId
28
+ .replace(/~!dash!~/g, "-")
29
+ .replace(/~!underscore!~/g, "_");
30
+ const decodedURIComponent = decodeURIComponent(dashUnderscoreUnsafe);
31
+ return decodedURIComponent;
32
+ }
33
+ exports.safeDecodeTokenId = safeDecodeTokenId;
16
34
  function encodeAccountId({ type, version, currencyId, xpubOrAddress, derivationMode, }) {
17
35
  return `${ensureNoColon(type, "type")}:${ensureNoColon(version, "version")}:${ensureNoColon(currencyId, "currencyId")}:${ensureNoColon(xpubOrAddress, "xpubOrAddress")}:${ensureNoColon(derivationMode, "derivationMode")}`;
18
36
  }
19
37
  exports.encodeAccountId = encodeAccountId;
20
38
  function encodeTokenAccountId(accountId, token) {
21
- return accountId + "+" + encodeURIComponent(token.id);
39
+ return accountId + "+" + safeEncodeTokenId(token.id);
22
40
  }
23
41
  exports.encodeTokenAccountId = encodeTokenAccountId;
24
42
  function decodeTokenAccountId(id) {
25
43
  const [accountId, tokenId] = id.split("+");
26
- const decodedTokenId = decodeURIComponent(tokenId);
44
+ const decodedTokenId = safeDecodeTokenId(tokenId);
27
45
  let token = (0, currencies_1.findTokenById)(decodedTokenId);
28
46
  if (!token) {
29
47
  const { currencyId } = decodeAccountId(accountId);
@@ -1 +1 @@
1
- {"version":3,"file":"accountId.js","sourceRoot":"","sources":["../../src/account/accountId.ts"],"names":[],"mappings":";;;;;;AAAA,6DAAqC;AACrC,0DAAkC;AAClC,8CAAiD;AACjD,8CAAqE;AACrE,yDAAsE;AAItE,SAAS,aAAa,CAAC,KAAa,EAAE,GAAW;IAC/C,IAAA,mBAAS,EAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,6CAA6C,EAAE,GAAG,CAAC,CAAC;IACpF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,OAAO,EACP,UAAU,EACV,aAAa,EACb,cAAc,GACE;IAChB,OAAO,GAAG,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,aAAa,CACzF,UAAU,EACV,YAAY,CACb,IAAI,aAAa,CAAC,aAAa,EAAE,eAAe,CAAC,IAAI,aAAa,CACjE,cAAc,EACd,gBAAgB,CACjB,EAAE,CAAC;AACN,CAAC;AAdD,0CAcC;AACD,SAAgB,oBAAoB,CAAC,SAAiB,EAAE,KAAoB;IAC1E,OAAO,SAAS,GAAG,GAAG,GAAG,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC;AAFD,oDAEC;AACD,SAAgB,oBAAoB,CAAC,EAAU;IAI7C,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,cAAc,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACnD,IAAI,KAAK,GAAG,IAAA,0BAAa,EAAC,cAAc,CAAC,CAAC;IAC1C,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,EAAE,UAAU,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAClD,KAAK,GAAG,IAAA,2CAA4B,EAAC,cAAc,EAAE,UAAU,CAAC,CAAC;KAClE;IACD,OAAO;QACL,SAAS;QACT,KAAK;KACN,CAAC;AACJ,CAAC;AAfD,oDAeC;AACD,SAAgB,eAAe,CAAC,SAAiB;IAC/C,IAAA,mBAAS,EAAC,OAAO,SAAS,KAAK,QAAQ,EAAE,2BAA2B,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,IAAA,mBAAS,EAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,4BAA4B,CAAC,CAAC;IAC/D,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC;IAC5E,OAAO;QACL,IAAI;QACJ,OAAO;QACP,UAAU;QACV,aAAa;QACb,cAAc,EAAE,IAAA,6BAAgB,EAAC,cAAc,CAAC;KACjD,CAAC;AACJ,CAAC;AAZD,0CAYC;AACD,wDAAwD;AACxD,uIAAuI;AACvI,SAAgB,aAAa,CAAC,EAC5B,cAAc,EACd,cAAc,EACd,QAAQ,GAKT;IACC,OAAO,GAAG,cAAc,IAAI,QAAQ,CAAC,EAAE,IAAI,cAAc,EAAE,CAAC;AAC9D,CAAC;AAVD,sCAUC;AACY,QAAA,wBAAwB,GAAqD,IAAA,iBAAO,EAC/F,SAAS,CAAC,EAAE;IACV,IAAI;QACF,MAAM,EAAE,UAAU,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAClD,OAAO,IAAA,kCAAqB,EAAC,UAAU,CAAC,CAAC,MAAM,CAAC;KACjD;IAAC,OAAO,CAAC,EAAE;QACV,OAAO,IAAI,CAAC;KACb;AACH,CAAC,CACF,CAAC"}
1
+ {"version":3,"file":"accountId.js","sourceRoot":"","sources":["../../src/account/accountId.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=accountId.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accountId.unit.test.d.ts","sourceRoot":"","sources":["../../src/account/accountId.unit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const accountId_1 = require("./accountId");
4
+ const currencies_1 = require("../currencies");
5
+ describe("coin-framework", () => {
6
+ describe("accountId", () => {
7
+ describe("safeEncodeTokenId", () => {
8
+ it("shouldn't throw with falsy tokenId", () => {
9
+ expect((0, accountId_1.safeEncodeTokenId)(null)).toBe("");
10
+ expect((0, accountId_1.safeEncodeTokenId)(undefined)).toBe("");
11
+ expect((0, accountId_1.safeEncodeTokenId)("")).toBe("");
12
+ });
13
+ it("should encode a token id by making it URI encoded and remove characters used for accountId splitting", () => {
14
+ const tokenId = "foo/bar-baz_qux+fred thud0123°?=/&$";
15
+ expect((0, accountId_1.safeEncodeTokenId)(tokenId)).not.toMatch(
16
+ // should match with any character exect those
17
+ new RegExp("[^a-z0-9.!~*'()%]", "gi"));
18
+ });
19
+ });
20
+ describe("safeDecodeTokenId", () => {
21
+ it("shouldn't throw with falsy encodedTokenId", () => {
22
+ expect((0, accountId_1.safeDecodeTokenId)(null)).toBe("");
23
+ expect((0, accountId_1.safeDecodeTokenId)(undefined)).toBe("");
24
+ expect((0, accountId_1.safeDecodeTokenId)("")).toBe("");
25
+ });
26
+ it("should decode a token id and remove all obfuscation", () => {
27
+ const encodedTokenId = "foo%2Fbar~!dash!~baz~!underscore!~qux%2Bfred%20thud0123456789%C2%B0";
28
+ expect((0, accountId_1.safeDecodeTokenId)(encodedTokenId)).toBe("foo/bar-baz_qux+fred thud0123456789°");
29
+ });
30
+ });
31
+ describe("encodeTokenAccountId", () => {
32
+ it("should return an URI and splitting safe tokenAccountId (no + - _ % \\ /)", () => {
33
+ const accountId = "js:2:0xkvn:";
34
+ const token = (0, currencies_1.getTokenById)("bsc/bep20/binance-peg_dai_token");
35
+ const tokenAccountId = (0, accountId_1.encodeTokenAccountId)(accountId, token);
36
+ expect(tokenAccountId).toBe("js:2:0xkvn:+bsc%2Fbep20%2Fbinance~!dash!~peg~!underscore!~dai~!underscore!~token");
37
+ expect(tokenAccountId).not.toMatch(
38
+ // should match with any character exect those
39
+ new RegExp("[^a-z0-9.!~*'()%:+]", "gi"));
40
+ // Should only contain 1 + character
41
+ expect(tokenAccountId.split("+").length).toBe(2);
42
+ });
43
+ });
44
+ describe("decodeTokenAccountId", () => {
45
+ it("should return an accountId and a token", () => {
46
+ expect((0, accountId_1.decodeTokenAccountId)("js:2:0xkvn:+bsc%2Fbep20%2Fbinance~!dash!~peg~!underscore!~dai~!underscore!~token")).toEqual({
47
+ accountId: "js:2:0xkvn:",
48
+ token: (0, currencies_1.getTokenById)("bsc/bep20/binance-peg_dai_token"),
49
+ });
50
+ });
51
+ });
52
+ });
53
+ });
54
+ //# sourceMappingURL=accountId.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accountId.unit.test.js","sourceRoot":"","sources":["../../src/account/accountId.unit.test.ts"],"names":[],"mappings":";;AAAA,2CAKqB;AACrB,8CAA6C;AAE7C,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QACzB,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;YACjC,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;gBAC5C,MAAM,CAAC,IAAA,6BAAiB,EAAC,IAAW,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAChD,MAAM,CAAC,IAAA,6BAAiB,EAAC,SAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACrD,MAAM,CAAC,IAAA,6BAAiB,EAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACzC,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,sGAAsG,EAAE,GAAG,EAAE;gBAC9G,MAAM,OAAO,GAAG,qCAAqC,CAAC;gBAEtD,MAAM,CAAC,IAAA,6BAAiB,EAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO;gBAC5C,8CAA8C;gBAC9C,IAAI,MAAM,CAAC,mBAAmB,EAAE,IAAI,CAAC,CACtC,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;YACjC,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;gBACnD,MAAM,CAAC,IAAA,6BAAiB,EAAC,IAAW,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAChD,MAAM,CAAC,IAAA,6BAAiB,EAAC,SAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACrD,MAAM,CAAC,IAAA,6BAAiB,EAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACzC,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;gBAC7D,MAAM,cAAc,GAClB,qEAAqE,CAAC;gBAExE,MAAM,CAAC,IAAA,6BAAiB,EAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;YACzF,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;YACpC,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;gBAClF,MAAM,SAAS,GAAG,aAAa,CAAC;gBAChC,MAAM,KAAK,GAAG,IAAA,yBAAY,EAAC,iCAAiC,CAAC,CAAC;gBAE9D,MAAM,cAAc,GAAG,IAAA,gCAAoB,EAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBAC9D,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CACzB,kFAAkF,CACnF,CAAC;gBACF,MAAM,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,OAAO;gBAChC,8CAA8C;gBAC9C,IAAI,MAAM,CAAC,qBAAqB,EAAE,IAAI,CAAC,CACxC,CAAC;gBACF,oCAAoC;gBACpC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACnD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;YACpC,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;gBAChD,MAAM,CACJ,IAAA,gCAAoB,EAClB,kFAAkF,CACnF,CACF,CAAC,OAAO,CAAC;oBACR,SAAS,EAAE,aAAa;oBACxB,KAAK,EAAE,IAAA,yBAAY,EAAC,iCAAiC,CAAC;iBACvD,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,5 +1,7 @@
1
1
  import type { AccountIdParams, DerivationMode } from "@ledgerhq/types-live";
2
2
  import type { CryptoCurrency, TokenCurrency } from "@ledgerhq/types-cryptoassets";
3
+ export declare function safeEncodeTokenId(tokenId: string): string;
4
+ export declare function safeDecodeTokenId(encodedTokenId: string): string;
3
5
  export declare function encodeAccountId({ type, version, currencyId, xpubOrAddress, derivationMode, }: AccountIdParams): string;
4
6
  export declare function encodeTokenAccountId(accountId: string, token: TokenCurrency): string;
5
7
  export declare function decodeTokenAccountId(id: string): {
@@ -1 +1 @@
1
- {"version":3,"file":"accountId.d.ts","sourceRoot":"","sources":["../../src/account/accountId.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAOlF,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,OAAO,EACP,UAAU,EACV,aAAa,EACb,cAAc,GACf,EAAE,eAAe,GAAG,MAAM,CAQ1B;AACD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,CAEpF;AACD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;CACzC,CAYA;AACD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAYlE;AAGD,wBAAgB,aAAa,CAAC,EAC5B,cAAc,EACd,cAAc,EACd,QAAQ,GACT,EAAE;IACD,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,cAAc,CAAC;CAC1B,GAAG,MAAM,CAET;AACD,eAAO,MAAM,wBAAwB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,SAS7E,CAAC"}
1
+ {"version":3,"file":"accountId.d.ts","sourceRoot":"","sources":["../../src/account/accountId.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAOlF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOzD;AAED,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAShE;AAED,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,OAAO,EACP,UAAU,EACV,aAAa,EACb,cAAc,GACf,EAAE,eAAe,GAAG,MAAM,CAQ1B;AACD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,CAEpF;AACD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;CACzC,CAYA;AACD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAYlE;AAGD,wBAAgB,aAAa,CAAC,EAC5B,cAAc,EACd,cAAc,EACd,QAAQ,GACT,EAAE;IACD,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,cAAc,CAAC;CAC1B,GAAG,MAAM,CAET;AACD,eAAO,MAAM,wBAAwB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,SAS7E,CAAC"}
@@ -7,15 +7,31 @@ function ensureNoColon(value, ctx) {
7
7
  invariant(!value.includes(":"), "AccountId '%s' component must not use colon", ctx);
8
8
  return value;
9
9
  }
10
+ export function safeEncodeTokenId(tokenId) {
11
+ if (!tokenId)
12
+ return "";
13
+ const URIEncoded = encodeURIComponent(tokenId);
14
+ const dashUnderscoreSafe = URIEncoded.replace(/-/g, "~!dash!~").replace(/_/g, "~!underscore!~");
15
+ return dashUnderscoreSafe;
16
+ }
17
+ export function safeDecodeTokenId(encodedTokenId) {
18
+ if (!encodedTokenId)
19
+ return "";
20
+ const dashUnderscoreUnsafe = encodedTokenId
21
+ .replace(/~!dash!~/g, "-")
22
+ .replace(/~!underscore!~/g, "_");
23
+ const decodedURIComponent = decodeURIComponent(dashUnderscoreUnsafe);
24
+ return decodedURIComponent;
25
+ }
10
26
  export function encodeAccountId({ type, version, currencyId, xpubOrAddress, derivationMode, }) {
11
27
  return `${ensureNoColon(type, "type")}:${ensureNoColon(version, "version")}:${ensureNoColon(currencyId, "currencyId")}:${ensureNoColon(xpubOrAddress, "xpubOrAddress")}:${ensureNoColon(derivationMode, "derivationMode")}`;
12
28
  }
13
29
  export function encodeTokenAccountId(accountId, token) {
14
- return accountId + "+" + encodeURIComponent(token.id);
30
+ return accountId + "+" + safeEncodeTokenId(token.id);
15
31
  }
16
32
  export function decodeTokenAccountId(id) {
17
33
  const [accountId, tokenId] = id.split("+");
18
- const decodedTokenId = decodeURIComponent(tokenId);
34
+ const decodedTokenId = safeDecodeTokenId(tokenId);
19
35
  let token = findTokenById(decodedTokenId);
20
36
  if (!token) {
21
37
  const { currencyId } = decodeAccountId(accountId);
@@ -1 +1 @@
1
- {"version":3,"file":"accountId.js","sourceRoot":"","sources":["../../src/account/accountId.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,gBAAgB,CAAC;AACrC,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAItE,SAAS,aAAa,CAAC,KAAa,EAAE,GAAW;IAC/C,SAAS,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,6CAA6C,EAAE,GAAG,CAAC,CAAC;IACpF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAC9B,IAAI,EACJ,OAAO,EACP,UAAU,EACV,aAAa,EACb,cAAc,GACE;IAChB,OAAO,GAAG,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,aAAa,CACzF,UAAU,EACV,YAAY,CACb,IAAI,aAAa,CAAC,aAAa,EAAE,eAAe,CAAC,IAAI,aAAa,CACjE,cAAc,EACd,gBAAgB,CACjB,EAAE,CAAC;AACN,CAAC;AACD,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,KAAoB;IAC1E,OAAO,SAAS,GAAG,GAAG,GAAG,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC;AACD,MAAM,UAAU,oBAAoB,CAAC,EAAU;IAI7C,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,cAAc,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACnD,IAAI,KAAK,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC;IAC1C,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,EAAE,UAAU,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAClD,KAAK,GAAG,4BAA4B,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;KAClE;IACD,OAAO;QACL,SAAS;QACT,KAAK;KACN,CAAC;AACJ,CAAC;AACD,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,SAAS,CAAC,OAAO,SAAS,KAAK,QAAQ,EAAE,2BAA2B,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,SAAS,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,4BAA4B,CAAC,CAAC;IAC/D,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC;IAC5E,OAAO;QACL,IAAI;QACJ,OAAO;QACP,UAAU;QACV,aAAa;QACb,cAAc,EAAE,gBAAgB,CAAC,cAAc,CAAC;KACjD,CAAC;AACJ,CAAC;AACD,wDAAwD;AACxD,uIAAuI;AACvI,MAAM,UAAU,aAAa,CAAC,EAC5B,cAAc,EACd,cAAc,EACd,QAAQ,GAKT;IACC,OAAO,GAAG,cAAc,IAAI,QAAQ,CAAC,EAAE,IAAI,cAAc,EAAE,CAAC;AAC9D,CAAC;AACD,MAAM,CAAC,MAAM,wBAAwB,GAAqD,OAAO,CAC/F,SAAS,CAAC,EAAE;IACV,IAAI;QACF,MAAM,EAAE,UAAU,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAClD,OAAO,qBAAqB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC;KACjD;IAAC,OAAO,CAAC,EAAE;QACV,OAAO,IAAI,CAAC;KACb;AACH,CAAC,CACF,CAAC"}
1
+ {"version":3,"file":"accountId.js","sourceRoot":"","sources":["../../src/account/accountId.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,gBAAgB,CAAC;AACrC,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAItE,SAAS,aAAa,CAAC,KAAa,EAAE,GAAW;IAC/C,SAAS,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,6CAA6C,EAAE,GAAG,CAAC,CAAC;IACpF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,kBAAkB,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IAEhG,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,cAAsB;IACtD,IAAI,CAAC,cAAc;QAAE,OAAO,EAAE,CAAC;IAE/B,MAAM,oBAAoB,GAAG,cAAc;SACxC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC;SACzB,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IACnC,MAAM,mBAAmB,GAAG,kBAAkB,CAAC,oBAAoB,CAAC,CAAC;IAErE,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAC9B,IAAI,EACJ,OAAO,EACP,UAAU,EACV,aAAa,EACb,cAAc,GACE;IAChB,OAAO,GAAG,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,aAAa,CACzF,UAAU,EACV,YAAY,CACb,IAAI,aAAa,CAAC,aAAa,EAAE,eAAe,CAAC,IAAI,aAAa,CACjE,cAAc,EACd,gBAAgB,CACjB,EAAE,CAAC;AACN,CAAC;AACD,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,KAAoB;IAC1E,OAAO,SAAS,GAAG,GAAG,GAAG,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACvD,CAAC;AACD,MAAM,UAAU,oBAAoB,CAAC,EAAU;IAI7C,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,cAAc,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAClD,IAAI,KAAK,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC;IAC1C,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,EAAE,UAAU,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAClD,KAAK,GAAG,4BAA4B,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;KAClE;IACD,OAAO;QACL,SAAS;QACT,KAAK;KACN,CAAC;AACJ,CAAC;AACD,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,SAAS,CAAC,OAAO,SAAS,KAAK,QAAQ,EAAE,2BAA2B,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,SAAS,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,4BAA4B,CAAC,CAAC;IAC/D,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC;IAC5E,OAAO;QACL,IAAI;QACJ,OAAO;QACP,UAAU;QACV,aAAa;QACb,cAAc,EAAE,gBAAgB,CAAC,cAAc,CAAC;KACjD,CAAC;AACJ,CAAC;AACD,wDAAwD;AACxD,uIAAuI;AACvI,MAAM,UAAU,aAAa,CAAC,EAC5B,cAAc,EACd,cAAc,EACd,QAAQ,GAKT;IACC,OAAO,GAAG,cAAc,IAAI,QAAQ,CAAC,EAAE,IAAI,cAAc,EAAE,CAAC;AAC9D,CAAC;AACD,MAAM,CAAC,MAAM,wBAAwB,GAAqD,OAAO,CAC/F,SAAS,CAAC,EAAE;IACV,IAAI;QACF,MAAM,EAAE,UAAU,EAAE,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAClD,OAAO,qBAAqB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC;KACjD;IAAC,OAAO,CAAC,EAAE;QACV,OAAO,IAAI,CAAC;KACb;AACH,CAAC,CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=accountId.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accountId.unit.test.d.ts","sourceRoot":"","sources":["../../src/account/accountId.unit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,52 @@
1
+ import { decodeTokenAccountId, encodeTokenAccountId, safeDecodeTokenId, safeEncodeTokenId, } from "./accountId";
2
+ import { getTokenById } from "../currencies";
3
+ describe("coin-framework", () => {
4
+ describe("accountId", () => {
5
+ describe("safeEncodeTokenId", () => {
6
+ it("shouldn't throw with falsy tokenId", () => {
7
+ expect(safeEncodeTokenId(null)).toBe("");
8
+ expect(safeEncodeTokenId(undefined)).toBe("");
9
+ expect(safeEncodeTokenId("")).toBe("");
10
+ });
11
+ it("should encode a token id by making it URI encoded and remove characters used for accountId splitting", () => {
12
+ const tokenId = "foo/bar-baz_qux+fred thud0123°?=/&$";
13
+ expect(safeEncodeTokenId(tokenId)).not.toMatch(
14
+ // should match with any character exect those
15
+ new RegExp("[^a-z0-9.!~*'()%]", "gi"));
16
+ });
17
+ });
18
+ describe("safeDecodeTokenId", () => {
19
+ it("shouldn't throw with falsy encodedTokenId", () => {
20
+ expect(safeDecodeTokenId(null)).toBe("");
21
+ expect(safeDecodeTokenId(undefined)).toBe("");
22
+ expect(safeDecodeTokenId("")).toBe("");
23
+ });
24
+ it("should decode a token id and remove all obfuscation", () => {
25
+ const encodedTokenId = "foo%2Fbar~!dash!~baz~!underscore!~qux%2Bfred%20thud0123456789%C2%B0";
26
+ expect(safeDecodeTokenId(encodedTokenId)).toBe("foo/bar-baz_qux+fred thud0123456789°");
27
+ });
28
+ });
29
+ describe("encodeTokenAccountId", () => {
30
+ it("should return an URI and splitting safe tokenAccountId (no + - _ % \\ /)", () => {
31
+ const accountId = "js:2:0xkvn:";
32
+ const token = getTokenById("bsc/bep20/binance-peg_dai_token");
33
+ const tokenAccountId = encodeTokenAccountId(accountId, token);
34
+ expect(tokenAccountId).toBe("js:2:0xkvn:+bsc%2Fbep20%2Fbinance~!dash!~peg~!underscore!~dai~!underscore!~token");
35
+ expect(tokenAccountId).not.toMatch(
36
+ // should match with any character exect those
37
+ new RegExp("[^a-z0-9.!~*'()%:+]", "gi"));
38
+ // Should only contain 1 + character
39
+ expect(tokenAccountId.split("+").length).toBe(2);
40
+ });
41
+ });
42
+ describe("decodeTokenAccountId", () => {
43
+ it("should return an accountId and a token", () => {
44
+ expect(decodeTokenAccountId("js:2:0xkvn:+bsc%2Fbep20%2Fbinance~!dash!~peg~!underscore!~dai~!underscore!~token")).toEqual({
45
+ accountId: "js:2:0xkvn:",
46
+ token: getTokenById("bsc/bep20/binance-peg_dai_token"),
47
+ });
48
+ });
49
+ });
50
+ });
51
+ });
52
+ //# sourceMappingURL=accountId.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accountId.unit.test.js","sourceRoot":"","sources":["../../src/account/accountId.unit.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/coin-framework",
3
- "version": "0.7.1-hotfix.0",
3
+ "version": "0.8.0-hotfix.1",
4
4
  "description": "Ledger framework for Coin integration",
5
5
  "keywords": [
6
6
  "Ledger",
@@ -11,6 +11,26 @@ function ensureNoColon(value: string, ctx: string): string {
11
11
  return value;
12
12
  }
13
13
 
14
+ export function safeEncodeTokenId(tokenId: string): string {
15
+ if (!tokenId) return "";
16
+
17
+ const URIEncoded = encodeURIComponent(tokenId);
18
+ const dashUnderscoreSafe = URIEncoded.replace(/-/g, "~!dash!~").replace(/_/g, "~!underscore!~");
19
+
20
+ return dashUnderscoreSafe;
21
+ }
22
+
23
+ export function safeDecodeTokenId(encodedTokenId: string): string {
24
+ if (!encodedTokenId) return "";
25
+
26
+ const dashUnderscoreUnsafe = encodedTokenId
27
+ .replace(/~!dash!~/g, "-")
28
+ .replace(/~!underscore!~/g, "_");
29
+ const decodedURIComponent = decodeURIComponent(dashUnderscoreUnsafe);
30
+
31
+ return decodedURIComponent;
32
+ }
33
+
14
34
  export function encodeAccountId({
15
35
  type,
16
36
  version,
@@ -27,14 +47,14 @@ export function encodeAccountId({
27
47
  )}`;
28
48
  }
29
49
  export function encodeTokenAccountId(accountId: string, token: TokenCurrency): string {
30
- return accountId + "+" + encodeURIComponent(token.id);
50
+ return accountId + "+" + safeEncodeTokenId(token.id);
31
51
  }
32
52
  export function decodeTokenAccountId(id: string): {
33
53
  accountId: string;
34
54
  token: TokenCurrency | null | undefined;
35
55
  } {
36
56
  const [accountId, tokenId] = id.split("+");
37
- const decodedTokenId = decodeURIComponent(tokenId);
57
+ const decodedTokenId = safeDecodeTokenId(tokenId);
38
58
  let token = findTokenById(decodedTokenId);
39
59
  if (!token) {
40
60
  const { currencyId } = decodeAccountId(accountId);
@@ -0,0 +1,73 @@
1
+ import {
2
+ decodeTokenAccountId,
3
+ encodeTokenAccountId,
4
+ safeDecodeTokenId,
5
+ safeEncodeTokenId,
6
+ } from "./accountId";
7
+ import { getTokenById } from "../currencies";
8
+
9
+ describe("coin-framework", () => {
10
+ describe("accountId", () => {
11
+ describe("safeEncodeTokenId", () => {
12
+ it("shouldn't throw with falsy tokenId", () => {
13
+ expect(safeEncodeTokenId(null as any)).toBe("");
14
+ expect(safeEncodeTokenId(undefined as any)).toBe("");
15
+ expect(safeEncodeTokenId("")).toBe("");
16
+ });
17
+
18
+ it("should encode a token id by making it URI encoded and remove characters used for accountId splitting", () => {
19
+ const tokenId = "foo/bar-baz_qux+fred thud0123°?=/&$";
20
+
21
+ expect(safeEncodeTokenId(tokenId)).not.toMatch(
22
+ // should match with any character exect those
23
+ new RegExp("[^a-z0-9.!~*'()%]", "gi"),
24
+ );
25
+ });
26
+ });
27
+ describe("safeDecodeTokenId", () => {
28
+ it("shouldn't throw with falsy encodedTokenId", () => {
29
+ expect(safeDecodeTokenId(null as any)).toBe("");
30
+ expect(safeDecodeTokenId(undefined as any)).toBe("");
31
+ expect(safeDecodeTokenId("")).toBe("");
32
+ });
33
+
34
+ it("should decode a token id and remove all obfuscation", () => {
35
+ const encodedTokenId =
36
+ "foo%2Fbar~!dash!~baz~!underscore!~qux%2Bfred%20thud0123456789%C2%B0";
37
+
38
+ expect(safeDecodeTokenId(encodedTokenId)).toBe("foo/bar-baz_qux+fred thud0123456789°");
39
+ });
40
+ });
41
+
42
+ describe("encodeTokenAccountId", () => {
43
+ it("should return an URI and splitting safe tokenAccountId (no + - _ % \\ /)", () => {
44
+ const accountId = "js:2:0xkvn:";
45
+ const token = getTokenById("bsc/bep20/binance-peg_dai_token");
46
+
47
+ const tokenAccountId = encodeTokenAccountId(accountId, token);
48
+ expect(tokenAccountId).toBe(
49
+ "js:2:0xkvn:+bsc%2Fbep20%2Fbinance~!dash!~peg~!underscore!~dai~!underscore!~token",
50
+ );
51
+ expect(tokenAccountId).not.toMatch(
52
+ // should match with any character exect those
53
+ new RegExp("[^a-z0-9.!~*'()%:+]", "gi"),
54
+ );
55
+ // Should only contain 1 + character
56
+ expect(tokenAccountId.split("+").length).toBe(2);
57
+ });
58
+ });
59
+
60
+ describe("decodeTokenAccountId", () => {
61
+ it("should return an accountId and a token", () => {
62
+ expect(
63
+ decodeTokenAccountId(
64
+ "js:2:0xkvn:+bsc%2Fbep20%2Fbinance~!dash!~peg~!underscore!~dai~!underscore!~token",
65
+ ),
66
+ ).toEqual({
67
+ accountId: "js:2:0xkvn:",
68
+ token: getTokenById("bsc/bep20/binance-peg_dai_token"),
69
+ });
70
+ });
71
+ });
72
+ });
73
+ });