From 73527de08a043a5769d49b5f1efdb04cf51f4eb2 Mon Sep 17 00:00:00 2001 From: dynst <148708712+dynst@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:00:00 +0000 Subject: [PATCH 01/11] avoid calling .toString() on type 'any' --- packages/cosmwasm-stargate/src/cosmwasmclient.ts | 2 +- packages/json-rpc/src/workers/dummyservice.worker.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cosmwasm-stargate/src/cosmwasmclient.ts b/packages/cosmwasm-stargate/src/cosmwasmclient.ts index 06ac6f9fdc..6d0010600c 100644 --- a/packages/cosmwasm-stargate/src/cosmwasmclient.ts +++ b/packages/cosmwasm-stargate/src/cosmwasmclient.ts @@ -167,7 +167,7 @@ export class CosmWasmClient { const account = await this.forceGetQueryClient().auth.account(searchAddress); return account ? accountFromAny(account) : null; } catch (error: any) { - if (/rpc error: code = NotFound/i.test(error.toString())) { + if (/rpc error: code = NotFound/i.test(String(error))) { return null; } throw error; diff --git a/packages/json-rpc/src/workers/dummyservice.worker.ts b/packages/json-rpc/src/workers/dummyservice.worker.ts index 2c7bc9bca4..f6fce572f6 100644 --- a/packages/json-rpc/src/workers/dummyservice.worker.ts +++ b/packages/json-rpc/src/workers/dummyservice.worker.ts @@ -23,7 +23,7 @@ function handleRequest(event: MessageEvent): JsonRpcResponse { id: requestId, error: { code: jsonRpcCode.invalidRequest, - message: error.toString(), + message: String(error), }, }; return errorResponse; From cc8703115266fc7c3ac1ede951a70273a998a06c Mon Sep 17 00:00:00 2001 From: dynst <148708712+dynst@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:00:00 +0000 Subject: [PATCH 02/11] type-narrowing on a json array before calling .map --- packages/stargate/src/logs.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/stargate/src/logs.ts b/packages/stargate/src/logs.ts index 1e97d56031..34fabf7940 100644 --- a/packages/stargate/src/logs.ts +++ b/packages/stargate/src/logs.ts @@ -58,7 +58,12 @@ export function parseRawLog(input: string | undefined): readonly Log[] { // Cosmos SDK >= 0.50 gives us an empty string here. This should be handled like undefined. if (!input) return []; - const logsToParse = JSON.parse(input).map(({ events }: { events: readonly unknown[] }, i: number) => ({ + const parsedInput = JSON.parse(input); + if (!Array.isArray(parsedInput)) { + throw new Error("rawLog must be an array"); + } + + const logsToParse = parsedInput.map(({ events }: { events: readonly unknown[] }, i: number) => ({ msg_index: i, events, log: "", From 19fe3656071c12a26054d45345908f87c92cc3a6 Mon Sep 17 00:00:00 2001 From: dynst <148708712+dynst@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:00:00 +0000 Subject: [PATCH 03/11] ledger-amino: add type annotation to Transport hack --- packages/ledger-amino/src/ledgersigner.spec.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/ledger-amino/src/ledgersigner.spec.ts b/packages/ledger-amino/src/ledgersigner.spec.ts index 8d2ac311ca..2b266b3d34 100644 --- a/packages/ledger-amino/src/ledgersigner.spec.ts +++ b/packages/ledger-amino/src/ledgersigner.spec.ts @@ -31,10 +31,11 @@ async function createTransport(): Promise { } // HACK: Use a variable to get webpack to ignore this const nodeJsTransportPackageName = "@ledgerhq/hw-transport-node-hid"; - const { default: TransportClass } = + const TransportClass: typeof Transport = ( platform === "node" ? await import(nodeJsTransportPackageName) - : await import("@ledgerhq/hw-transport-webusb"); + : await import("@ledgerhq/hw-transport-webusb") + ).default; return TransportClass.create(interactiveTimeout, interactiveTimeout); } From 9c4f80c6410f1e2ec8daf4f407b36428a6e611a8 Mon Sep 17 00:00:00 2001 From: dynst <148708712+dynst@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:00:00 +0000 Subject: [PATCH 04/11] ledger-amino: return type in demo --- packages/ledger-amino/src/demo/web.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/ledger-amino/src/demo/web.ts b/packages/ledger-amino/src/demo/web.ts index 6178f692b4..6e35584a97 100644 --- a/packages/ledger-amino/src/demo/web.ts +++ b/packages/ledger-amino/src/demo/web.ts @@ -60,7 +60,7 @@ window.updateMessage = (accountNumberInput: unknown) => { signDocTextArea.textContent = createSignDoc(accountNumber, address); }; -window.setPath = (accountNumberInput: unknown) => { +const setPath = (accountNumberInput: unknown): void => { assert(typeof accountNumberInput === "string"); const accountNumber = Uint53.fromString(accountNumberInput).toNumber(); @@ -68,6 +68,7 @@ window.setPath = (accountNumberInput: unknown) => { const pathInput = document.getElementById("path"); pathInput.value = path; }; +window.setPath = setPath; // This must be called by the user an cannot be done on load (see "TransportWebUSBGestureRequired"). window.createSigner = async function createSigner(): Promise { @@ -103,7 +104,7 @@ window.getAccounts = async function getAccounts(signer: LedgerSigner | undefined // Show address block accountNumberInput1.max = accounts.length - 1; accountNumberInput1.value = accountNumber; - window.setPath(accountNumber.toString()); + setPath(accountNumber.toString()); // Sign block accountNumberInput2.max = accounts.length - 1; From 00b373b24791632f7400ea48548a03564213df02 Mon Sep 17 00:00:00 2001 From: dynst <148708712+dynst@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:00:00 +0000 Subject: [PATCH 05/11] ledger-amino: coerce error to string in demo --- packages/ledger-amino/src/demo/web.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ledger-amino/src/demo/web.ts b/packages/ledger-amino/src/demo/web.ts index 6e35584a97..345d3d47bb 100644 --- a/packages/ledger-amino/src/demo/web.ts +++ b/packages/ledger-amino/src/demo/web.ts @@ -114,7 +114,7 @@ window.getAccounts = async function getAccounts(signer: LedgerSigner | undefined signDocTextArea.textContent = createSignDoc(accountNumber, address); } catch (error) { console.error(error); - accountsDiv.textContent = error; + accountsDiv.textContent = String(error); } }; @@ -142,6 +142,6 @@ window.sign = async function sign(signer: LedgerSigner | undefined): Promise Date: Tue, 11 Nov 2025 00:00:00 +0000 Subject: [PATCH 06/11] ledger-amino: assign strings to forms --- packages/ledger-amino/src/demo/web.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ledger-amino/src/demo/web.ts b/packages/ledger-amino/src/demo/web.ts index 345d3d47bb..9f85ea17ac 100644 --- a/packages/ledger-amino/src/demo/web.ts +++ b/packages/ledger-amino/src/demo/web.ts @@ -102,13 +102,13 @@ window.getAccounts = async function getAccounts(signer: LedgerSigner | undefined const accountNumber = 0; // Show address block - accountNumberInput1.max = accounts.length - 1; - accountNumberInput1.value = accountNumber; + accountNumberInput1.max = String(accounts.length - 1); + accountNumberInput1.value = String(accountNumber); setPath(accountNumber.toString()); // Sign block - accountNumberInput2.max = accounts.length - 1; - accountNumberInput2.value = accountNumber; + accountNumberInput2.max = String(accounts.length - 1); + accountNumberInput2.value = String(accountNumber); const address = accounts[0].address; addressInput.value = address; signDocTextArea.textContent = createSignDoc(accountNumber, address); From cf41d5b75adf23ec0e0e66ef879aa31714ff2b64 Mon Sep 17 00:00:00 2001 From: dynst <148708712+dynst@users.noreply.github.com> Date: Tue, 11 Nov 2025 00:00:00 +0000 Subject: [PATCH 07/11] ledger-amino: add type safety to web forms --- packages/ledger-amino/src/demo/web.ts | 31 ++++++++++++++++----------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/packages/ledger-amino/src/demo/web.ts b/packages/ledger-amino/src/demo/web.ts index 9f85ea17ac..07573fe5b6 100644 --- a/packages/ledger-amino/src/demo/web.ts +++ b/packages/ledger-amino/src/demo/web.ts @@ -9,7 +9,12 @@ import TransportWebUSB from "@ledgerhq/hw-transport-webusb"; import { LedgerSigner } from "../ledgersigner"; declare const window: any; -declare const document: any; + +const getElement = (id: string): HTMLInputElement => { + const e = document.getElementById(id); + assert(e instanceof HTMLInputElement, "got the wrong element!"); + return e; +}; const accountNumbers = [0, 1, 2, 10]; const paths = accountNumbers.map(makeCosmoshubPath); @@ -54,9 +59,9 @@ window.updateMessage = (accountNumberInput: unknown) => { } const address = accounts[accountNumber].address; - const addressInput = document.getElementById("address"); + const addressInput = getElement("address"); addressInput.value = address; - const signDocTextArea = document.getElementById("sign-doc"); + const signDocTextArea = getElement("sign-doc"); signDocTextArea.textContent = createSignDoc(accountNumber, address); }; @@ -65,7 +70,7 @@ const setPath = (accountNumberInput: unknown): void => { const accountNumber = Uint53.fromString(accountNumberInput).toNumber(); const path = pathToString(paths[accountNumber]); - const pathInput = document.getElementById("path"); + const pathInput = getElement("path"); pathInput.value = path; }; window.setPath = setPath; @@ -85,11 +90,11 @@ window.getAccounts = async function getAccounts(signer: LedgerSigner | undefined console.error("Please wait for transport to connect"); return; } - const accountNumberInput1 = document.getElementById("account-number1"); - const accountNumberInput2 = document.getElementById("account-number2"); - const addressInput = document.getElementById("address"); - const accountsDiv = document.getElementById("accounts"); - const signDocTextArea = document.getElementById("sign-doc"); + const accountNumberInput1 = getElement("account-number1"); + const accountNumberInput2 = getElement("account-number2"); + const addressInput = getElement("address"); + const accountsDiv = getElement("accounts"); + const signDocTextArea = getElement("sign-doc"); accountsDiv.textContent = "Loading..."; try { @@ -123,7 +128,7 @@ window.showAddress = async function showAddress(signer: LedgerSigner | undefined console.error("Please wait for transport to connect"); return; } - const path = stringToPath(document.getElementById("path").value); + const path = stringToPath(getElement("path").value); await signer.showAddress(path); }; @@ -132,12 +137,12 @@ window.sign = async function sign(signer: LedgerSigner | undefined): Promise Date: Tue, 11 Nov 2025 00:00:00 +0000 Subject: [PATCH 08/11] enable '@typescript-eslint/no-unsafe-call' lint --- eslint.config.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 484d418ca5..f54d6b205e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -145,7 +145,6 @@ export default [ "@typescript-eslint/no-shadow": "warn", "@typescript-eslint/no-unsafe-argument": "off", "@typescript-eslint/no-unsafe-assignment": "off", - "@typescript-eslint/no-unsafe-call": "off", "@typescript-eslint/no-unsafe-member-access": "off", "@typescript-eslint/no-unsafe-return": "off", From 888d15e95c180391481b363059dfb815286198f0 Mon Sep 17 00:00:00 2001 From: dynst <148708712+dynst@users.noreply.github.com> Date: Tue, 11 Nov 2025 00:00:00 +0000 Subject: [PATCH 09/11] ledger-amino: add return type --- packages/ledger-amino/src/demo/web.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ledger-amino/src/demo/web.ts b/packages/ledger-amino/src/demo/web.ts index 07573fe5b6..28378e99ab 100644 --- a/packages/ledger-amino/src/demo/web.ts +++ b/packages/ledger-amino/src/demo/web.ts @@ -50,7 +50,7 @@ function createSignDoc(accountNumber: number, address: string): string { return JSON.stringify(signDoc, null, 2); } -window.updateMessage = (accountNumberInput: unknown) => { +window.updateMessage = (accountNumberInput: unknown): void => { assert(typeof accountNumberInput === "string"); const accountNumber = Uint53.fromString(accountNumberInput).toNumber(); const account = accounts[accountNumber]; From 3998cb53d2207f00ac3721767129521f2f1a32cb Mon Sep 17 00:00:00 2001 From: dynst <148708712+dynst@users.noreply.github.com> Date: Tue, 11 Nov 2025 00:00:00 +0000 Subject: [PATCH 10/11] ledger-amino: remove 'window: any' from web demo code --- packages/ledger-amino/src/demo/web.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/ledger-amino/src/demo/web.ts b/packages/ledger-amino/src/demo/web.ts index 28378e99ab..9add6d0128 100644 --- a/packages/ledger-amino/src/demo/web.ts +++ b/packages/ledger-amino/src/demo/web.ts @@ -8,8 +8,6 @@ import TransportWebUSB from "@ledgerhq/hw-transport-webusb"; import { LedgerSigner } from "../ledgersigner"; -declare const window: any; - const getElement = (id: string): HTMLInputElement => { const e = document.getElementById(id); assert(e instanceof HTMLInputElement, "got the wrong element!"); @@ -50,7 +48,7 @@ function createSignDoc(accountNumber: number, address: string): string { return JSON.stringify(signDoc, null, 2); } -window.updateMessage = (accountNumberInput: unknown): void => { +const updateMessage = (accountNumberInput: unknown): void => { assert(typeof accountNumberInput === "string"); const accountNumber = Uint53.fromString(accountNumberInput).toNumber(); const account = accounts[accountNumber]; @@ -73,10 +71,9 @@ const setPath = (accountNumberInput: unknown): void => { const pathInput = getElement("path"); pathInput.value = path; }; -window.setPath = setPath; // This must be called by the user an cannot be done on load (see "TransportWebUSBGestureRequired"). -window.createSigner = async function createSigner(): Promise { +const createSigner = async function createSigner(): Promise { const interactiveTimeout = 120_000; const ledgerTransport = await TransportWebUSB.create(interactiveTimeout, interactiveTimeout); return new LedgerSigner(ledgerTransport, { @@ -85,7 +82,7 @@ window.createSigner = async function createSigner(): Promise { }); }; -window.getAccounts = async function getAccounts(signer: LedgerSigner | undefined): Promise { +const getAccounts = async function getAccounts(signer: LedgerSigner | undefined): Promise { if (signer === undefined) { console.error("Please wait for transport to connect"); return; @@ -123,7 +120,7 @@ window.getAccounts = async function getAccounts(signer: LedgerSigner | undefined } }; -window.showAddress = async function showAddress(signer: LedgerSigner | undefined): Promise { +const showAddress = async function showAddress(signer: LedgerSigner | undefined): Promise { if (signer === undefined) { console.error("Please wait for transport to connect"); return; @@ -132,7 +129,7 @@ window.showAddress = async function showAddress(signer: LedgerSigner | undefined await signer.showAddress(path); }; -window.sign = async function sign(signer: LedgerSigner | undefined): Promise { +const sign = async function sign(signer: LedgerSigner | undefined): Promise { if (signer === undefined) { console.error("Please wait for transport to connect"); return; @@ -150,3 +147,5 @@ window.sign = async function sign(signer: LedgerSigner | undefined): Promise Date: Tue, 11 Nov 2025 00:00:00 +0000 Subject: [PATCH 11/11] stargate: don't construct an Array --- packages/stargate/src/multisignature.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/stargate/src/multisignature.ts b/packages/stargate/src/multisignature.ts index 05a1dd8a07..0d02c679b3 100644 --- a/packages/stargate/src/multisignature.ts +++ b/packages/stargate/src/multisignature.ts @@ -36,11 +36,12 @@ export function makeMultisignedTx( ): TxRaw { const addresses = Array.from(signatures.keys()); const prefix = fromBech32(addresses[0]).prefix; + const pubkeys = multisigPubkey.value.pubkeys; - const signers: boolean[] = Array(multisigPubkey.value.pubkeys.length).fill(false); + const signers = new Array(pubkeys.length).fill(false); const signaturesList = new Array(); - for (let i = 0; i < multisigPubkey.value.pubkeys.length; i++) { - const signerAddress = pubkeyToAddress(multisigPubkey.value.pubkeys[i], prefix); + for (let i = 0; i < pubkeys.length; i++) { + const signerAddress = pubkeyToAddress(pubkeys[i], prefix); const signature = signatures.get(signerAddress); if (signature) { signers[i] = true;