Skip to content

Commit

Permalink
fix(llm): ✂️ truncate some coins memo on the recipient step of the se…
Browse files Browse the repository at this point in the history
…nd flow (#8340)

* fix(llm): fix the "Memo is too long" issue of Algorand

* fix(llm): truncate Solana's memo too

* fix(llm): truncate ICP's memo

* chore: update change log

* chore(llm): remove extra changes on Solana

* chore: update the LL-common non imported file
  • Loading branch information
thesan authored Nov 14, 2024
1 parent 1eb489b commit 4bee69b
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 3 deletions.
6 changes: 6 additions & 0 deletions .changeset/metal-walls-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"live-mobile": minor
"@ledgerhq/live-common": patch
---

Truncate some coins memo on the recipient step of the send flow
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from "react";

import { ALGORAND_MAX_MEMO_SIZE } from "@ledgerhq/live-common/families/algorand/logic";
import type { Transaction as AlgorandTransaction } from "@ledgerhq/live-common/families/algorand/types";
import type { MemoTagInputProps } from "LLM/features/MemoTag/types";
import { GenericMemoTagInput } from "LLM/features/MemoTag/components/GenericMemoTagInput";

export default (props: MemoTagInputProps<AlgorandTransaction>) => (
<GenericMemoTagInput
{...props}
textToValue={text => text.slice(0, ALGORAND_MAX_MEMO_SIZE)}
valueToTxPatch={value => tx => ({ ...tx, memo: value || undefined })}
/>
);
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import React from "react";

import { Transaction as ICPTransaction } from "@ledgerhq/live-common/families/internet_computer/types";
import { MAX_MEMO_VALUE } from "@ledgerhq/live-common/families/internet_computer/consts";
import type { Transaction as ICPTransaction } from "@ledgerhq/live-common/families/internet_computer/types";
import type { MemoTagInputProps } from "LLM/features/MemoTag/types";
import { GenericMemoTagInput } from "LLM/features/MemoTag/components/GenericMemoTagInput";

export default (props: MemoTagInputProps<ICPTransaction>) => (
<GenericMemoTagInput
{...props}
textToValue={text => text.replace(/\D/g, "")}
textToValue={text => {
const value = Math.min(MAX_MEMO_VALUE, Number(text.replace(/\D/g, "")));
return value ? String(value) : "";
}}
valueToTxPatch={value => tx => ({ ...tx, memo: value || undefined })}
/>
);
5 changes: 4 additions & 1 deletion apps/ledger-live-mobile/src/families/solana/MemoTagInput.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import merge from "lodash/merge";
import React from "react";

import { Transaction as SolanaTransaction } from "@ledgerhq/live-common/families/solana/types";
import { MAX_MEMO_LENGTH } from "@ledgerhq/live-common/families/solana/logic";
import type { Transaction as SolanaTransaction } from "@ledgerhq/live-common/families/solana/types";
import type { MemoTagInputProps } from "LLM/features/MemoTag/types";
import { GenericMemoTagInput } from "LLM/features/MemoTag/components/GenericMemoTagInput";
import { truncateUtf8 } from "LLM/utils/truncateUtf8";

export default (props: MemoTagInputProps<SolanaTransaction>) => (
<GenericMemoTagInput
{...props}
textToValue={text => truncateUtf8(text, MAX_MEMO_LENGTH)}
valueToTxPatch={value => tx =>
merge({}, tx, { model: { uiState: { memo: value || undefined } } })
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { truncateUtf8 } from "../truncateUtf8";

test("truncateUtf8", () => {
expect(truncateUtf8("hello world", 0)).toBe("");
expect(truncateUtf8("hello world", 50)).toBe("hello world");
expect(truncateUtf8("hello world", 1)).toBe("h");
expect(truncateUtf8("hello world", 5)).toBe("hello");
expect(truncateUtf8("👋💬🌎", 4)).toBe("👋");
expect(truncateUtf8("👋💬🌎", 3)).toBe("");
expect(truncateUtf8("👋💬🌎", 12)).toBe("👋💬🌎");
expect(truncateUtf8("👋💬🌎", 11)).toBe("👋💬");
});
16 changes: 16 additions & 0 deletions apps/ledger-live-mobile/src/newArch/utils/truncateUtf8.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export function truncateUtf8(str: string, maxBytes: number) {
const totalBytesLength = Buffer.from(str).byteLength;
if (totalBytesLength <= maxBytes) return str;
if (totalBytesLength === str.length) return str.slice(0, maxBytes);

// NOTE in js strings characters above U+FFFF (i.e outside the Basic Multilingual Plane) are represented by two UTF-16 code units
// the spread operator will split these strings correctly with some "characters" being strings of length 2.
let byteLen = 0;
let charLen = 0;
for (const char of [...str]) {
byteLen += Buffer.from(char).byteLength;
if (byteLen > maxBytes) return str.slice(0, charLen);
charLen += char.length;
}
return str;
}
1 change: 1 addition & 0 deletions libs/ledger-live-common/.unimportedrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"src/e2e/speculos.ts",
"src/explorer.ts",
"src/explorers.ts",
"src/families/algorand/logic.ts",
"src/families/algorand/tokens.ts",
"src/families/algorand/types.ts",
"src/families/bitcoin/descriptor.ts",
Expand Down
2 changes: 2 additions & 0 deletions libs/ledger-live-common/src/families/algorand/logic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Encapsulate for LLD et LLM
export * from "@ledgerhq/coin-algorand/logic";

0 comments on commit 4bee69b

Please sign in to comment.