Skip to content

Commit

Permalink
Merge branch 'develop' into feat/add-dot-entrypoints
Browse files Browse the repository at this point in the history
  • Loading branch information
adammino-ledger committed Dec 6, 2024
2 parents 28c7394 + 2d6b3d8 commit fa184cc
Show file tree
Hide file tree
Showing 16 changed files with 79 additions and 27 deletions.
7 changes: 7 additions & 0 deletions .changeset/rude-bats-fold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@ledgerhq/coin-stacks": minor
"live-mobile": minor
"@ledgerhq/live-common": minor
---

Truncate Stacks memos in the input to prevent the transaction validation from failing
5 changes: 5 additions & 0 deletions .changeset/seven-ravens-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ledger-live-desktop": minor
---

LLD: LIVE-15143 use a debounce on the memotag field
8 changes: 4 additions & 4 deletions .github/workflows/build-and-test-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ jobs:
uses: LedgerHQ/ledger-live/.github/workflows/test-design-system-reusable.yml@develop
secrets: inherit

test-web-tools:
name: "Test Web Tools"
build-web-tools:
name: "Build Web Tools"
needs: determine-affected
if: ${{contains(needs.determine-affected.outputs.paths, 'apps/web-tools') && !github.event.pull_request.head.repo.fork}}
uses: LedgerHQ/ledger-live/.github/workflows/test-web-tools-reusable.yml@develop
uses: LedgerHQ/ledger-live/.github/workflows/build-web-tools-reusable.yml@develop
secrets: inherit

test-cli:
Expand All @@ -97,7 +97,7 @@ jobs:
- test-mobile-e2e
- test-libraries
- test-design-system
- test-web-tools
- build-web-tools
- test-cli
runs-on: ubuntu-22.04
if: always() && !cancelled()
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/build-and-test-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ jobs:
uses: LedgerHQ/ledger-live/.github/workflows/test-design-system-reusable.yml@develop
secrets: inherit

test-web-tools:
name: "Test Web Tools"
uses: LedgerHQ/ledger-live/.github/workflows/test-web-tools-reusable.yml@develop
build-web-tools:
name: "Build Web Tools"
uses: LedgerHQ/ledger-live/.github/workflows/build-web-tools-reusable.yml@develop
secrets: inherit

test-cli:
Expand All @@ -72,7 +72,7 @@ jobs:
- test-mobile-e2e
- test-libraries
- test-design-system
- test-web-tools
- build-web-tools
- test-cli
runs-on: ubuntu-22.04
if: always() && !cancelled()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "Web Tools Tests"
name: "Build Web Tools"

on:
workflow_call:
Expand All @@ -16,8 +16,8 @@ permissions:
contents: read

jobs:
test-web-tools:
name: "Test web-tools"
build-web-tools:
name: "Build web-tools"
env:
NODE_OPTIONS: "--max-old-space-size=7168"
FORCE_COLOR: 3
Expand All @@ -42,7 +42,7 @@ jobs:
run: pnpm turbo run build --filter="@ledgerhq/web-tools" --api="http://127.0.0.1:${{ steps.setup-caches.outputs.port }}" --token="${{ secrets.TURBOREPO_SERVER_TOKEN }}" --team="foo"

report:
needs: test-web-tools
needs: build-web-tools
if: ${{ !cancelled() && github.event_name == 'workflow_dispatch' }}
runs-on: ubuntu-22.04
steps:
Expand All @@ -58,15 +58,15 @@ jobs:
const fs = require("fs");
const statuses = {
tool: {
pass: ${{ needs.test-web-tools.result == 'success' }},
status: "${{ needs.test-web-tools.result }}",
pass: ${{ needs.build-web-tools.result == 'success' }},
status: "${{ needs.build-web-tools.result }}",
}
};
const summary = `### Common Tools
${statuses.tool.pass ? "Common Tools are fine" : "Common Tools tests failed"}
- ${statuses.tool.pass ? "✅" : "❌"} **Common Tools* tests* ended with status \`${statuses.tool.status}\`
${statuses.tool.pass ? "Common Tools are fine" : "Common Tools build failed"}
- ${statuses.tool.pass ? "✅" : "❌"} **Common Tools* build* ended with status \`${statuses.tool.status}\`
`;
const actions = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import { render, screen, fireEvent } from "tests/testUtils";
import MemoTagField from "../components/MemoTagField";

describe("MemoTagField", () => {
beforeAll(() => {
jest.useFakeTimers();
});

afterAll(() => {
jest.useRealTimers();
});

it("renders MemoTagField with label and text field", () => {
render(<MemoTagField showLabel={true} />);
expect(screen.getByText(/Tag \/ Memo/gi)).toBeInTheDocument();
Expand All @@ -19,12 +27,14 @@ describe("MemoTagField", () => {
expect(screen.queryByText(/Tag \/ Memo/gi)).not.toBeInTheDocument();
});

it("should call onChange when input value changes", () => {
it("should call onChange when input value changes with a debounce", () => {
const handleChange = jest.fn();
render(<MemoTagField onChange={handleChange} />);
fireEvent.change(screen.getByPlaceholderText(/Enter Tag \/ Memo/gi), {
target: { value: "new memo" },
});
expect(handleChange).not.toHaveBeenCalled();
jest.runAllTimers();
expect(handleChange).toHaveBeenCalledTimes(1);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from "react";
import React, { useState, useEffect } from "react";
import Input, { Props as InputBaseProps } from "~/renderer/components/Input";
import { useDebounce } from "@ledgerhq/live-common//hooks/useDebounce";
import Label from "~/renderer/components/Label";
import Box from "~/renderer/components/Box";
import { useTranslation } from "react-i18next";
import { Flex, Text, Tooltip } from "@ledgerhq/react-ui";
import styled from "styled-components";
import InfoCircle from "~/renderer/icons/InfoCircle";

const TooltipContainer = styled(Box)`
background-color: ${({ theme }) => theme.colors.palette.neutral.c100};
padding: 10px;
Expand All @@ -30,6 +30,7 @@ type MemoTagFieldProps = InputBaseProps & {
placeholder?: string;
label?: string;
tooltipText?: string;
validationHandler?: (newValue: string) => string;
};

const MemoTagField = ({
Expand All @@ -44,8 +45,20 @@ const MemoTagField = ({
placeholder,
label,
tooltipText,
validationHandler,
}: MemoTagFieldProps) => {
const { t } = useTranslation();
const [memoValue, setMemoValue] = useState(value);
const debouncedMemoValue = useDebounce(memoValue, 300);

useEffect(() => {
if (debouncedMemoValue !== value) onChange?.(debouncedMemoValue || "");
}, [debouncedMemoValue, onChange, value]);

const handleChange = (newValue: string) => {
setMemoValue(validationHandler ? validationHandler(newValue) : newValue);
};

return (
<Box flow={1}>
{showLabel && (
Expand All @@ -68,10 +81,10 @@ const MemoTagField = ({
<Flex justifyContent="end">{CaracterCountComponent && <CaracterCountComponent />}</Flex>
<Input
placeholder={placeholder ?? t("MemoTagField.placeholder")}
onChange={onChange}
onChange={handleChange}
warning={warning}
error={error}
value={value}
value={memoValue}
spellCheck="false"
ff="Inter"
maxMemoLength={maxMemoLength}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const MemoField = ({ onChange, account, transaction, status, autoFocus }: MemoTa

const onTransferIdFieldChange = useCallback(
(value: string) => {
value = value.replace(/\D/g, "");
if (value !== "") onChange(bridge.updateTransaction(transaction, { transferId: value }));
else onChange(bridge.updateTransaction(transaction, { transferId: undefined }));
},
Expand All @@ -32,6 +31,7 @@ const MemoField = ({ onChange, account, transaction, status, autoFocus }: MemoTa
onChange={onTransferIdFieldChange}
spellCheck="false"
autoFocus={autoFocus}
validationHandler={newValue => newValue.replace(/\D/g, "")}
/>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const TagField = ({ onChange, account, transaction, autoFocus }: Props) => {
const onChangeTag = useCallback(
(str: string) => {
const bridge = getAccountBridge(account);
const tag = BigNumber(str.replace(/[^0-9]/g, ""));
const tag = BigNumber(str);
const patch = {
tag:
!tag.isNaN() &&
Expand All @@ -37,6 +37,7 @@ const TagField = ({ onChange, account, transaction, autoFocus }: Props) => {
value={String(transaction.tag || "")}
onChange={onChangeTag}
autoFocus={autoFocus}
validationHandler={str => str.replace(/[^0-9]/g, "")}
/>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const e2eDelegationAccounts = [
xrayTicket: "B2CQA-2740, B2CQA-2770",
},
{
delegate: new Delegate(Account.SOL_1, "0.001", "Ledger by Figment"),
delegate: new Delegate(Account.SOL_1, "0.001", "Ledger by Chorus One"),
xrayTicket: "B2CQA-2742",
},
{
Expand All @@ -28,7 +28,7 @@ const validators = [
xrayTicket: "B2CQA-2731, B2CQA-2763",
},
{
delegate: new Delegate(Account.SOL_2, "0.001", "Ledger by Figment"),
delegate: new Delegate(Account.SOL_2, "0.001", "Ledger by Chorus One"),
xrayTicket: "B2CQA-2730, B2CQA-2764",
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { GenericMemoTagInput } from "LLM/features/MemoTag/components/GenericMemo
export default (props: MemoTagInputProps<AlgorandTransaction>) => (
<GenericMemoTagInput
{...props}
textToValue={text => text.slice(0, ALGORAND_MAX_MEMO_SIZE)}
maxLength={ALGORAND_MAX_MEMO_SIZE}
valueToTxPatch={value => tx => ({ ...tx, memo: value || undefined })}
/>
);
9 changes: 9 additions & 0 deletions apps/ledger-live-mobile/src/families/stacks/MemoTagInput.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import React from "react";

import { STACKS_MAX_MEMO_SIZE } from "@ledgerhq/live-common/families/stacks/constants";
import type { Transaction as StacksTransaction } from "@ledgerhq/live-common/families/stacks/types";
import type { MemoTagInputProps } from "LLM/features/MemoTag/types";
import { GenericMemoTagInput } from "LLM/features/MemoTag/components/GenericMemoTagInput";
import { truncateUtf8 } from "LLM/utils/truncateUtf8";

// `TextInputProps.maxLength` can not be used here because it counts the length of the string instead of the byte size.
// E.g.
// Javascript will evaluate a 16👍 emojis string as 34 characters.
// While this string is in fact encoded in 68B in UTF8 which is well above STX limit.
// `truncateUtf8` will truncate the string correctly, which is 8👍 with 2 characters to spare.

export default (props: MemoTagInputProps<StacksTransaction>) => (
<GenericMemoTagInput
{...props}
textToValue={text => truncateUtf8(text, STACKS_MAX_MEMO_SIZE)}
valueToTxPatch={value => tx => ({ ...tx, memo: value || undefined })}
/>
);
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "@ledgerhq/errors";
import { AccountBridge } from "@ledgerhq/types-live";
import BigNumber from "bignumber.js";
import { STACKS_MAX_MEMO_SIZE } from "../contants";
import { StacksMemoTooLong } from "../errors";
import { Transaction, TransactionStatus } from "../types";
import { validateAddress } from "./utils/addresses";
Expand Down Expand Up @@ -44,7 +45,9 @@ export const getTransactionStatus: AccountBridge<Transaction>["getTransactionSta

if (amount.lte(0)) errors.amount = new AmountRequired();
if (totalSpent.gt(spendableBalance)) errors.amount = new NotEnoughBalance();
if (memo && memo.length > 34) errors.transaction = new StacksMemoTooLong();

const memoBytesLength = Buffer.from(memo ?? "", "utf-8").byteLength;
if (memoBytesLength > STACKS_MAX_MEMO_SIZE) errors.transaction = new StacksMemoTooLong();

return {
errors,
Expand Down
1 change: 1 addition & 0 deletions libs/coin-modules/coin-stacks/src/contants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const STACKS_MAX_MEMO_SIZE = 34;
1 change: 1 addition & 0 deletions libs/ledger-live-common/.unimportedrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
"src/families/solana/react.ts",
"src/families/solana/staking.ts",
"src/families/solana/types.ts",
"src/families/stacks/constants.ts",
"src/families/stacks/deviceTransactionConfig.ts",
"src/families/stacks/types.ts",
"src/families/stellar/types.ts",
Expand Down
2 changes: 2 additions & 0 deletions libs/ledger-live-common/src/families/stacks/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Encapsulate for LLD & LLM
export * from "@ledgerhq/coin-stacks/contants";

0 comments on commit fa184cc

Please sign in to comment.