diff --git a/eslint.config.js b/eslint.config.js index 0b8775668..78fe8baa0 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -87,6 +87,33 @@ export default tseslint.config( ], }, }, + { + files: ["sdks/js-sdk/test/**/*.ts"], + rules: { + "@typescript-eslint/no-floating-promises": "off", + "@typescript-eslint/no-unsafe-member-access": "off", + "@typescript-eslint/no-unsafe-assignment": "off", + "@typescript-eslint/no-unsafe-return": "off", + "@typescript-eslint/no-unsafe-argument": "off", + "@typescript-eslint/no-unsafe-call": "off", + "@typescript-eslint/no-confusing-void-expression": "off", + "@typescript-eslint/require-await": "off", + "@typescript-eslint/await-thenable": "off", + "@typescript-eslint/no-unnecessary-condition": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/only-throw-error": "off", + "@typescript-eslint/unbound-method": "off", + "@typescript-eslint/no-misused-promises": "off", + "@typescript-eslint/no-unnecessary-type-arguments": "off", + "@typescript-eslint/no-unnecessary-type-assertion": "off", + "@typescript-eslint/no-deprecated": "off", + "@typescript-eslint/restrict-plus-operands": "off", + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "no-empty": "off", + }, + }, { files: ["sdks/**/*.ts"], rules: { diff --git a/sdks/js-sdk/bench/index.ts b/sdks/js-sdk/bench/index.ts index d0de643b1..d1ed7c01a 100644 --- a/sdks/js-sdk/bench/index.ts +++ b/sdks/js-sdk/bench/index.ts @@ -6,4 +6,5 @@ const main = async () => { await decodeSuite(); }; +// eslint-disable-next-line @typescript-eslint/no-floating-promises main(); diff --git a/sdks/js-sdk/src/ApiClient.ts b/sdks/js-sdk/src/ApiClient.ts index 9b59580ab..16b5aa53f 100644 --- a/sdks/js-sdk/src/ApiClient.ts +++ b/sdks/js-sdk/src/ApiClient.ts @@ -117,6 +117,7 @@ const isAbortError = (err?: Error): boolean => { }; const isAuthError = (err?: GrpcError | Error): boolean => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison if (err && "code" in err && err.code === ERR_CODE_UNAUTHENTICATED) { return true; } @@ -189,6 +190,7 @@ export default class HttpApiClient implements ApiClient { ): ReturnType { try { return await retry( + // eslint-disable-next-line @typescript-eslint/unbound-method MessageApi.Query, [ req, @@ -203,6 +205,7 @@ export default class HttpApiClient implements ApiClient { ); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (e: any) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument throw GrpcError.fromObject(e); } } @@ -212,6 +215,7 @@ export default class HttpApiClient implements ApiClient { req: messageApi.BatchQueryRequest, ): ReturnType { return retry( + // eslint-disable-next-line @typescript-eslint/unbound-method MessageApi.BatchQuery, [ req, @@ -236,6 +240,7 @@ export default class HttpApiClient implements ApiClient { headers.set("Authorization", `Bearer ${authToken}`); try { return await retry( + // eslint-disable-next-line @typescript-eslint/unbound-method MessageApi.Publish, [ req, @@ -253,7 +258,9 @@ export default class HttpApiClient implements ApiClient { // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (e: any) { // Try at most 2X. If refreshing the auth token doesn't work the first time, it won't work the second time + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument if (isNotAuthError(e) || attemptNumber >= 1) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument throw GrpcError.fromObject(e); } await this.authCache?.refresh(); @@ -270,6 +277,7 @@ export default class HttpApiClient implements ApiClient { const abortController = new AbortController(); const doSubscribe = async () => { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition while (true) { const startTime = new Date().getTime(); try { @@ -290,6 +298,7 @@ export default class HttpApiClient implements ApiClient { onConnectionLost?.(); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (err: any) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument if (isAbortError(err) || abortController.signal.aborted) { return; } @@ -303,10 +312,13 @@ export default class HttpApiClient implements ApiClient { } } }; + // eslint-disable-next-line @typescript-eslint/no-floating-promises doSubscribe(); return { + // eslint-disable-next-line @typescript-eslint/require-await unsubscribe: async () => { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition abortController?.abort(); }, }; @@ -369,6 +381,7 @@ export default class HttpApiClient implements ApiClient { const endTimeNs = toNanoString(endTime); let cursor: messageApi.Cursor | undefined; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition while (true) { const pagingInfo: messageApi.PagingInfo = { limit: pageSize, @@ -390,6 +403,7 @@ export default class HttpApiClient implements ApiClient { } if (result.pagingInfo?.cursor) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition cursor = result.pagingInfo?.cursor; } else { return; @@ -495,6 +509,7 @@ export default class HttpApiClient implements ApiClient { return this._subscribe( params, + // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression (env) => callback(normalizeEnvelope(env)), onConnectionLost, ); diff --git a/sdks/js-sdk/src/Client.ts b/sdks/js-sdk/src/Client.ts index f5aa64a5a..7a12f9e95 100644 --- a/sdks/js-sdk/src/Client.ts +++ b/sdks/js-sdk/src/Client.ts @@ -135,7 +135,7 @@ export type ContentOptions = { /** * Allow configuring codecs for additional content types */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unnecessary-type-arguments codecs: ContentCodec[]; /** @@ -267,7 +267,7 @@ export default class Client { private _backupClient: BackupClient; private readonly _conversations: Conversations; - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unnecessary-type-arguments private _codecs: Map>; private _maxContentSize: number; @@ -314,7 +314,7 @@ export default class Client { * @param opts specify how to to connect to the network */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unnecessary-type-arguments static async create[] = []>( wallet: Signer | WalletClient | null, opts?: Partial & { codecs?: ContentCodecs }, @@ -350,6 +350,7 @@ export default class Client { * impersonate a user on the XMTP network and read the user's * messages. */ + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters static async getKeys( wallet: Signer | WalletClient | null, opts?: Partial & { codecs?: U }, @@ -390,6 +391,7 @@ export default class Client { } // gracefully shut down the client + // eslint-disable-next-line @typescript-eslint/require-await async close(): Promise { return undefined; } @@ -530,6 +532,7 @@ export default class Client { // Else do the single address case const keyBundle = await this.getUserContact(peerAddress); return keyBundle !== undefined; + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { // Instead of throwing, a bad address should just return false. return false; @@ -571,6 +574,7 @@ export default class Client { } try { peerAddress = getAddress(peerAddress); // EIP55 normalize the address case. + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { return false; } @@ -584,6 +588,7 @@ export default class Client { throw new Error("Missing content topic"); } + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!bytes || !bytes.length) { throw new Error("Cannot publish empty message"); } @@ -608,9 +613,10 @@ export default class Client { * Register a codec to be automatically used for encoding/decoding * messages of the given Content Type */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unnecessary-type-arguments registerCodec>( codec: Codec, + // eslint-disable-next-line @typescript-eslint/prefer-return-this-type ): Client> { const id = codec.contentType; const key = `${id.authorityId}/${id.typeId}`; @@ -622,7 +628,7 @@ export default class Client { * Find a matching codec for a given `ContentTypeId` from the * client's codec registry */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unnecessary-type-arguments codecFor(contentType: ContentTypeId): ContentCodec | undefined { const key = `${contentType.authorityId}/${contentType.typeId}`; const codec = this._codecs.get(key); @@ -649,6 +655,7 @@ export default class Client { const contentType = options?.contentType || ContentTypeText; const codec = this.codecFor(contentType); if (!codec) { + // eslint-disable-next-line @typescript-eslint/restrict-plus-operands throw new Error("unknown content type " + contentType); } const encoded = codec.encode(content, this); @@ -691,12 +698,15 @@ export default class Client { const codec = this.codecFor(contentType); if (codec) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment content = codec.decode(encodedContent as EncodedContent, this); } else { + // eslint-disable-next-line @typescript-eslint/restrict-plus-operands error = new Error("unknown content type " + contentType); } return { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment content, contentType, error, @@ -707,6 +717,7 @@ export default class Client { listInvitations(opts?: ListMessagesOptions): Promise { return this.listEnvelopes( buildUserInviteTopic(this.address), + // eslint-disable-next-line @typescript-eslint/require-await async (env) => env, opts, ); @@ -795,7 +806,9 @@ async function getUserContactFromNetwork( const keyBundle = decodeContactBundle(env.message); let address: string | undefined; try { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition address = await keyBundle?.walletSignatureAddress(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { address = undefined; } @@ -828,6 +841,7 @@ async function getUserContactsFromNetwork( return Promise.all( peerAddresses.map(async (address: string, index: number) => { const envelopes = topicToEnvelopes[index]; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!envelopes) { return undefined; } @@ -835,6 +849,7 @@ async function getUserContactsFromNetwork( if (!env.message) continue; try { const keyBundle = decodeContactBundle(env.message); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition const signingAddress = await keyBundle?.walletSignatureAddress(); if (address.toLowerCase() === signingAddress.toLowerCase()) { return keyBundle; diff --git a/sdks/js-sdk/src/Compression.ts b/sdks/js-sdk/src/Compression.ts index 782426bae..bc0c2472a 100644 --- a/sdks/js-sdk/src/Compression.ts +++ b/sdks/js-sdk/src/Compression.ts @@ -51,6 +51,7 @@ export function readStreamFromBytes( return new ReadableStream({ pull(controller) { if (position >= bytes.length) { + // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression return controller.close(); } let end = position + chunkSize; diff --git a/sdks/js-sdk/src/ContactBundle.ts b/sdks/js-sdk/src/ContactBundle.ts index 3be2c30a3..a95197877 100644 --- a/sdks/js-sdk/src/ContactBundle.ts +++ b/sdks/js-sdk/src/ContactBundle.ts @@ -11,6 +11,7 @@ export function decodeContactBundle( let cb: contact.ContactBundle; try { cb = contact.ContactBundle.decode(bytes); + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { const pb = publicKey.PublicKeyBundle.decode(bytes); cb = { v1: { keyBundle: new PublicKeyBundle(pb) }, v2: undefined }; diff --git a/sdks/js-sdk/src/Contacts.ts b/sdks/js-sdk/src/Contacts.ts index b8524b3e9..05ab61c0b 100644 --- a/sdks/js-sdk/src/Contacts.ts +++ b/sdks/js-sdk/src/Contacts.ts @@ -1,6 +1,5 @@ import { createConsentMessage } from "@xmtp/consent-proof-signature"; import { messageApi, privatePreferences, type invitation } from "@xmtp/proto"; -// eslint-disable-next-line camelcase import type { DecryptResponse_Response } from "@xmtp/proto/ts/dist/types/keystore_api/v1/keystore.pb"; import { hashMessage, hexToBytes } from "viem"; import { ecdsaSignerKey } from "@/crypto/Signature"; @@ -140,7 +139,6 @@ export class ConsentList { const decryptedMessageEntries = Array.from(messageMap.keys()).map( (key, index) => - // eslint-disable-next-line camelcase [key, responses[index]] as [string, DecryptResponse_Response], ); @@ -199,6 +197,7 @@ export class ConsentList { await this.client.keystore.getPrivatePreferencesTopic(); return Stream.create( + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this.client, [contentTopic], async (envelope) => { @@ -236,6 +235,7 @@ export class ConsentList { const messageEntries = ( await this.client.listEnvelopes( contentTopic, + // eslint-disable-next-line @typescript-eslint/require-await async ({ message, timestampNs }: EnvelopeWithMessage) => [timestampNs, message] as [string | undefined, Uint8Array], { @@ -309,6 +309,7 @@ export class ConsentList { [valueKey]: [...values, entry.value], }, }; + // eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter }, {} as PrivatePreferencesAction); // get envelopes to publish (there should only be one) @@ -319,7 +320,9 @@ export class ConsentList { await this.client.publishEnvelopes(envelopes); // persist newly published private preference to keystore + // eslint-disable-next-line @typescript-eslint/no-floating-promises this.client.keystore.savePrivatePreferences( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion new Map([[envelopes[0].timestamp!.getTime().toString(), action]]), ); @@ -397,6 +400,7 @@ export class Contacts { return result; } }, + // eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter [] as string[], ); if (validConsentProofAddresses.length) { diff --git a/sdks/js-sdk/src/Invitation.ts b/sdks/js-sdk/src/Invitation.ts index 2bbf67729..aae6b5c67 100644 --- a/sdks/js-sdk/src/Invitation.ts +++ b/sdks/js-sdk/src/Invitation.ts @@ -17,7 +17,7 @@ export type InvitationContext = { export class InvitationV1 implements invitation.InvitationV1 { topic: string; context: InvitationContext | undefined; - aes256GcmHkdfSha256: invitation.InvitationV1_Aes256gcmHkdfsha256; // eslint-disable-line camelcase + aes256GcmHkdfSha256: invitation.InvitationV1_Aes256gcmHkdfsha256; consentProof: invitation.ConsentProofPayload | undefined; constructor({ @@ -31,6 +31,7 @@ export class InvitationV1 implements invitation.InvitationV1 { } if ( !aes256GcmHkdfSha256 || + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition !aes256GcmHkdfSha256.keyMaterial || !aes256GcmHkdfSha256.keyMaterial.length ) { @@ -117,6 +118,7 @@ export class SealedInvitationV1 implements invitation.SealedInvitationV1 { private _invitation?: InvitationV1; constructor({ headerBytes, ciphertext }: invitation.SealedInvitationV1) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!headerBytes || !headerBytes.length) { throw new Error("Missing header bytes"); } @@ -204,6 +206,7 @@ export class SealedInvitation implements invitation.SealedInvitation { return new SealedInvitation(invitation.SealedInvitation.decode(bytes)); } + // eslint-disable-next-line @typescript-eslint/require-await static async fromEnvelope( env: messageApi.Envelope, ): Promise { diff --git a/sdks/js-sdk/src/Message.ts b/sdks/js-sdk/src/Message.ts index cd14d58a9..a9ed17a1d 100644 --- a/sdks/js-sdk/src/Message.ts +++ b/sdks/js-sdk/src/Message.ts @@ -58,7 +58,7 @@ class MessageBase { // Message header carries the sender and recipient keys used to protect message. // Message timestamp is set by the sender. export class MessageV1 extends MessageBase implements proto.MessageV1 { - header: proto.MessageHeaderV1; // eslint-disable-line camelcase + header: proto.MessageHeaderV1; // wallet address derived from the signature of the message recipient senderAddress: string | undefined; conversation = undefined; @@ -96,6 +96,7 @@ export class MessageV1 extends MessageBase implements proto.MessageV1 { // wallet address derived from the signature of the message recipient get recipientAddress(): string | undefined { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!this.header?.recipient?.identityKey) { return undefined; } @@ -125,6 +126,7 @@ export class MessageV1 extends MessageBase implements proto.MessageV1 { const message = proto.Message.decode(bytes); const [headerBytes] = headerBytesAndCiphertext(message); const header = proto.MessageHeaderV1.decode(headerBytes); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!header) { throw new Error("missing message header"); } @@ -389,6 +391,7 @@ function conversationReferenceToConversation( nsToDate(reference.createdNs), ); } + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (version === "v2") { return new ConversationV2( client, @@ -399,6 +402,7 @@ function conversationReferenceToConversation( reference.consentProofPayload, ); } + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions throw new Error(`Unknown conversation version ${version}`); } diff --git a/sdks/js-sdk/src/Stream.ts b/sdks/js-sdk/src/Stream.ts index 5553ed648..20cf4b1d7 100644 --- a/sdks/js-sdk/src/Stream.ts +++ b/sdks/js-sdk/src/Stream.ts @@ -65,6 +65,7 @@ export default class Stream { if (contentTopicUpdater) { const topics = contentTopicUpdater(msg); if (topics) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises this.resubscribeToTopics(topics); } } @@ -83,6 +84,7 @@ export default class Stream { }; } + // eslint-disable-next-line @typescript-eslint/require-await private async start(): Promise { if (!this.callback) { throw new Error("Missing callback for stream"); @@ -92,8 +94,10 @@ export default class Stream { { contentTopics: this.topics, }, + // eslint-disable-next-line @typescript-eslint/no-misused-promises async (env: messageApi.Envelope) => { if (!this.callback) return; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition await this?.callback(env); }, this.onConnectionLost, @@ -136,6 +140,7 @@ export default class Stream { } this.callback = undefined; this.resolvers.forEach((resolve) => + // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression resolve({ value: undefined, done: true }), ); return { value: undefined, done: true }; @@ -164,6 +169,7 @@ export default class Stream { throw new Error("Missing callback for stream"); } + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (typeof this.subscriptionManager?.updateContentTopics === "function") { return this.subscriptionManager.updateContentTopics(topics); } @@ -174,8 +180,10 @@ export default class Stream { { contentTopics: this.topics, }, + // eslint-disable-next-line @typescript-eslint/no-misused-promises async (env: messageApi.Envelope) => { if (!this.callback) return; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition await this?.callback(env); }, this.onConnectionLost, diff --git a/sdks/js-sdk/src/conversations/Conversation.ts b/sdks/js-sdk/src/conversations/Conversation.ts index 6d7af2f15..48222adc9 100644 --- a/sdks/js-sdk/src/conversations/Conversation.ts +++ b/sdks/js-sdk/src/conversations/Conversation.ts @@ -299,6 +299,7 @@ export class ConversationV1 } else { topics = [topic]; } + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument const { payload } = await this.client.encodeContent(content, options); const msg = await this.createMessage( payload, @@ -774,6 +775,7 @@ export class ConversationV2 const signed = proto.SignedContent.decode(decrypted); if ( !signed.sender?.identityKey || + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition !signed.sender?.preKey || !signed.signature ) { @@ -785,6 +787,7 @@ export class ConversationV2 // Verify the signature const digest = await sha256(concat(msg.headerBytes, signed.payload)); if ( + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition !new SignedPublicKey(signed.sender?.preKey).verify( new Signature(signed.signature), digest, @@ -819,6 +822,7 @@ export class ConversationV2 options?: SendOptions, ): Promise { const { payload, shouldPush } = await this.client.encodeContent( + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument content, options, ); @@ -902,6 +906,7 @@ async function validatePrekeys(signed: proto.SignedContent) { // this is required to chain the prekey-signed message to the identity key // and finally to the user's wallet address const senderPreKey = signed.sender?.preKey; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!senderPreKey || !senderPreKey.signature || !senderPreKey.keyBytes) { throw new Error("missing pre-key or pre-key signature"); } diff --git a/sdks/js-sdk/src/conversations/Conversations.ts b/sdks/js-sdk/src/conversations/Conversations.ts index 2440b467e..2403e4b20 100644 --- a/sdks/js-sdk/src/conversations/Conversations.ts +++ b/sdks/js-sdk/src/conversations/Conversations.ts @@ -314,6 +314,7 @@ export default class Conversations { // Temporarily create a convo to decrypt the message const convo = new ConversationV1( this.client, + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion peerAddress as string, msg.sent, ); @@ -368,7 +369,8 @@ export default class Conversations { this.client, msg.recipientAddress?.toLowerCase() === this.client.address.toLowerCase() - ? (msg.senderAddress as string) + ? // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + (msg.senderAddress as string) : (msg.recipientAddress as string), msg.sent, ); @@ -418,6 +420,7 @@ export default class Conversations { gen.return = async () => { // Returning the stream will cause the iteration to end inside the generator // The generator will then return on its own + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition await str?.return(); return { value: undefined, done: true }; }; @@ -432,6 +435,7 @@ export default class Conversations { const messages = await this.client.listEnvelopes( topic, (env) => { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!env.message) { throw new Error("empty envelope"); } @@ -459,6 +463,7 @@ export default class Conversations { this.client.publicKeyBundle, ); seenPeers.set(peerAddress, message.sent); + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { continue; } @@ -542,6 +547,7 @@ export default class Conversations { return newItemMatch; } return this.createV2Convo( + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion contact as SignedPublicKeyBundle, context, consentProof, @@ -561,6 +567,7 @@ export default class Conversations { createdNs: dateToNs(timestamp), consentProof, }); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!payload || !conversation) { throw new Error("Required field not returned from Keystore"); } diff --git a/sdks/js-sdk/src/crypto/PrivateKey.ts b/sdks/js-sdk/src/crypto/PrivateKey.ts index 95b6bcb58..5f292a6eb 100644 --- a/sdks/js-sdk/src/crypto/PrivateKey.ts +++ b/sdks/js-sdk/src/crypto/PrivateKey.ts @@ -27,7 +27,7 @@ export class SignedPrivateKey implements privateKey.SignedPrivateKey, KeySigner { createdNs: Long; // time the key was generated, ns since epoch - secp256k1: secp256k1; // eslint-disable-line camelcase + secp256k1: secp256k1; publicKey: SignedPublicKey; // caches corresponding PublicKey constructor(obj: privateKey.SignedPrivateKey) { @@ -182,7 +182,7 @@ export class SignedPrivateKey // LEGACY: PrivateKey represents a secp256k1 private key. export class PrivateKey implements privateKey.PrivateKey { timestamp: Long; - secp256k1: secp256k1; // eslint-disable-line camelcase + secp256k1: secp256k1; publicKey: PublicKey; // caches corresponding PublicKey constructor(obj: privateKey.PrivateKey) { diff --git a/sdks/js-sdk/src/crypto/PrivateKeyBundle.ts b/sdks/js-sdk/src/crypto/PrivateKeyBundle.ts index 4efd6ce43..d49223d71 100644 --- a/sdks/js-sdk/src/crypto/PrivateKeyBundle.ts +++ b/sdks/js-sdk/src/crypto/PrivateKeyBundle.ts @@ -20,6 +20,7 @@ export class PrivateKeyBundleV2 implements proto.PrivateKeyBundleV2 { throw new Error("missing identity key"); } this.identityKey = new SignedPrivateKey(bundle.identityKey); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition this.preKeys = (bundle.preKeys || []).map((k) => new SignedPrivateKey(k)); } @@ -79,12 +80,14 @@ export class PrivateKeyBundleV2 implements proto.PrivateKeyBundleV2 { myPreKey: SignedPublicKey, isRecipient: boolean, ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!peer.identityKey || !peer.preKey) { throw new Error("invalid peer key bundle"); } if (!(await peer.identityKey.verifyKey(peer.preKey))) { throw new Error("peer preKey signature invalid"); } + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!this.identityKey) { throw new Error("missing identity key"); } @@ -157,6 +160,7 @@ export class PrivateKeyBundleV1 implements proto.PrivateKeyBundleV1 { throw new Error("missing identity key"); } this.identityKey = new PrivateKey(bundle.identityKey); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition this.preKeys = (bundle.preKeys || []).map((k) => new PrivateKey(k)); } @@ -226,12 +230,14 @@ export class PrivateKeyBundleV1 implements proto.PrivateKeyBundleV1 { myPreKey: PublicKey, isRecipient: boolean, ): Promise { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!peer.identityKey || !peer.preKey) { throw new Error("invalid peer key bundle"); } if (!(await peer.identityKey.verifyKey(peer.preKey))) { throw new Error("peer preKey signature invalid"); } + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!this.identityKey) { throw new Error("missing identity key"); } diff --git a/sdks/js-sdk/src/crypto/PublicKey.ts b/sdks/js-sdk/src/crypto/PublicKey.ts index 78d94bf67..aed402aea 100644 --- a/sdks/js-sdk/src/crypto/PublicKey.ts +++ b/sdks/js-sdk/src/crypto/PublicKey.ts @@ -32,9 +32,10 @@ export class UnsignedPublicKey implements publicKey.UnsignedPublicKey { // it can also be ms since epoch; use MS_NS_TIMESTAMP_THRESHOLD to distinguish // the two cases. createdNs: Long; - secp256k1Uncompressed: secp256k1Uncompressed; // eslint-disable-line camelcase + secp256k1Uncompressed: secp256k1Uncompressed; constructor(obj: publicKey.UnsignedPublicKey) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!obj?.secp256k1Uncompressed) { throw new Error("invalid public key"); } @@ -113,6 +114,7 @@ export class SignedPublicKey signature: Signature; constructor(obj: publicKey.SignedPublicKey) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!obj.keyBytes) { throw new Error("missing key bytes"); } diff --git a/sdks/js-sdk/src/crypto/Signature.ts b/sdks/js-sdk/src/crypto/Signature.ts index 48f44d237..185d726a7 100644 --- a/sdks/js-sdk/src/crypto/Signature.ts +++ b/sdks/js-sdk/src/crypto/Signature.ts @@ -41,6 +41,7 @@ export function ecdsaSignerKey( signature.bytes, signature.recovery, ); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition return bytes ? new UnsignedPublicKey({ secp256k1Uncompressed: { bytes }, @@ -51,9 +52,9 @@ export function ecdsaSignerKey( export default class Signature implements signature.Signature { // SECP256k1/SHA256 ECDSA signature - ecdsaCompact: ECDSACompactWithRecovery | undefined; // eslint-disable-line camelcase + ecdsaCompact: ECDSACompactWithRecovery | undefined; // SECP256k1/keccak256 ECDSA signature created with Signer.signMessage (see WalletSigner) - walletEcdsaCompact: ECDSACompactWithRecovery | undefined; // eslint-disable-line camelcase + walletEcdsaCompact: ECDSACompactWithRecovery | undefined; constructor(obj: Partial) { if (obj.ecdsaCompact) { @@ -99,6 +100,7 @@ export default class Signature implements signature.Signature { } else { throw new Error("invalid v1 signature"); } + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition return bytes ? new PublicKey({ secp256k1Uncompressed: { bytes }, diff --git a/sdks/js-sdk/src/crypto/SignedEciesCiphertext.ts b/sdks/js-sdk/src/crypto/SignedEciesCiphertext.ts index c195a87d8..20c45173e 100644 --- a/sdks/js-sdk/src/crypto/SignedEciesCiphertext.ts +++ b/sdks/js-sdk/src/crypto/SignedEciesCiphertext.ts @@ -37,6 +37,7 @@ export default class SignedEciesCiphertext ciphertext: ciphertext.SignedEciesCiphertext_Ecies; constructor({ eciesBytes, signature }: ciphertext.SignedEciesCiphertext) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!eciesBytes || !eciesBytes.length) { throw new Error("eciesBytes is empty"); } diff --git a/sdks/js-sdk/src/crypto/ecies.ts b/sdks/js-sdk/src/crypto/ecies.ts index 0df1ea45c..1e7d31c52 100644 --- a/sdks/js-sdk/src/crypto/ecies.ts +++ b/sdks/js-sdk/src/crypto/ecies.ts @@ -71,6 +71,7 @@ function getAes( op: "encrypt" | "decrypt", ): (iv: Buffer, key: Buffer, data: Buffer) => Promise { return function (iv: Buffer, key: Uint8Array, data: Uint8Array) { + // eslint-disable-next-line @typescript-eslint/no-misused-promises return new Promise(function (resolve) { const importAlgorithm = { name: "AES-CBC" }; const keyp = subtle.importKey("raw", key, importAlgorithm, false, [op]); @@ -211,14 +212,18 @@ export function derive( export async function encrypt( publicKeyTo: Buffer, msg: Buffer, + // eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents opts?: { ephemPrivateKey?: Buffer; iv?: Buffer } | undefined, ) { opts = opts || {}; // Take IV from opts or generate randomly + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition const iv = opts?.iv || randomBytes(16); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition let ephemPrivateKey = opts?.ephemPrivateKey || randomBytes(32); // There is a very unlikely possibility that it is not a valid key while (!isValidPrivateKey(ephemPrivateKey)) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (opts?.ephemPrivateKey) { throw new Error("ephemPrivateKey is not valid"); } diff --git a/sdks/js-sdk/src/crypto/selfEncryption.browser.ts b/sdks/js-sdk/src/crypto/selfEncryption.browser.ts index aecaeebd7..f35c41bde 100644 --- a/sdks/js-sdk/src/crypto/selfEncryption.browser.ts +++ b/sdks/js-sdk/src/crypto/selfEncryption.browser.ts @@ -3,11 +3,8 @@ ***********************************************************************************************/ import init, { - // eslint-disable-next-line camelcase generate_private_preferences_topic, - // eslint-disable-next-line camelcase user_preferences_decrypt, - // eslint-disable-next-line camelcase user_preferences_encrypt, } from "@xmtp/user-preferences-bindings-wasm/web"; import type { PrivateKey } from "./PrivateKey"; @@ -20,7 +17,7 @@ export async function userPreferencesEncrypt( await init(); const publicKey = identityKey.publicKey.secp256k1Uncompressed.bytes; const privateKey = identityKey.secp256k1.bytes; - // eslint-disable-next-line camelcase + return user_preferences_encrypt(publicKey, privateKey, payload); } @@ -32,7 +29,7 @@ export async function userPreferencesDecrypt( await init(); const publicKey = identityKey.publicKey.secp256k1Uncompressed.bytes; const privateKey = identityKey.secp256k1.bytes; - // eslint-disable-next-line camelcase + return user_preferences_decrypt(publicKey, privateKey, payload); } @@ -40,6 +37,6 @@ export async function generateUserPreferencesTopic(identityKey: PrivateKey) { // wait for WASM to be initialized await init(); const privateKey = identityKey.secp256k1.bytes; - // eslint-disable-next-line camelcase + return generate_private_preferences_topic(privateKey); } diff --git a/sdks/js-sdk/src/crypto/selfEncryption.bundler.ts b/sdks/js-sdk/src/crypto/selfEncryption.bundler.ts index 56a6ffc82..61e96420f 100644 --- a/sdks/js-sdk/src/crypto/selfEncryption.bundler.ts +++ b/sdks/js-sdk/src/crypto/selfEncryption.bundler.ts @@ -3,37 +3,37 @@ ***********************************************************************************************/ import { - // eslint-disable-next-line camelcase generate_private_preferences_topic, - // eslint-disable-next-line camelcase user_preferences_decrypt, - // eslint-disable-next-line camelcase user_preferences_encrypt, } from "@xmtp/user-preferences-bindings-wasm/bundler"; import type { PrivateKey } from "./PrivateKey"; +// eslint-disable-next-line @typescript-eslint/require-await export async function userPreferencesEncrypt( identityKey: PrivateKey, payload: Uint8Array, ) { const publicKey = identityKey.publicKey.secp256k1Uncompressed.bytes; const privateKey = identityKey.secp256k1.bytes; - // eslint-disable-next-line camelcase + return user_preferences_encrypt(publicKey, privateKey, payload); } +// eslint-disable-next-line @typescript-eslint/require-await export async function userPreferencesDecrypt( identityKey: PrivateKey, payload: Uint8Array, ) { const publicKey = identityKey.publicKey.secp256k1Uncompressed.bytes; const privateKey = identityKey.secp256k1.bytes; - // eslint-disable-next-line camelcase + return user_preferences_decrypt(publicKey, privateKey, payload); } +// eslint-disable-next-line @typescript-eslint/require-await export async function generateUserPreferencesTopic(identityKey: PrivateKey) { const privateKey = identityKey.secp256k1.bytes; - // eslint-disable-next-line camelcase + return generate_private_preferences_topic(privateKey); } diff --git a/sdks/js-sdk/src/crypto/selfEncryption.ts b/sdks/js-sdk/src/crypto/selfEncryption.ts index d37b3acbf..531ac463d 100644 --- a/sdks/js-sdk/src/crypto/selfEncryption.ts +++ b/sdks/js-sdk/src/crypto/selfEncryption.ts @@ -1,35 +1,35 @@ import { - // eslint-disable-next-line camelcase generate_private_preferences_topic, - // eslint-disable-next-line camelcase user_preferences_decrypt, - // eslint-disable-next-line camelcase user_preferences_encrypt, } from "@xmtp/user-preferences-bindings-wasm"; import type { PrivateKey } from "@/crypto/PrivateKey"; +// eslint-disable-next-line @typescript-eslint/require-await export async function userPreferencesEncrypt( identityKey: PrivateKey, payload: Uint8Array, ) { const publicKey = identityKey.publicKey.secp256k1Uncompressed.bytes; const privateKey = identityKey.secp256k1.bytes; - // eslint-disable-next-line camelcase + return user_preferences_encrypt(publicKey, privateKey, payload); } +// eslint-disable-next-line @typescript-eslint/require-await export async function userPreferencesDecrypt( identityKey: PrivateKey, payload: Uint8Array, ) { const publicKey = identityKey.publicKey.secp256k1Uncompressed.bytes; const privateKey = identityKey.secp256k1.bytes; - // eslint-disable-next-line camelcase + return user_preferences_decrypt(publicKey, privateKey, payload); } +// eslint-disable-next-line @typescript-eslint/require-await export async function generateUserPreferencesTopic(identityKey: PrivateKey) { const privateKey = identityKey.secp256k1.bytes; - // eslint-disable-next-line camelcase + return generate_private_preferences_topic(privateKey); } diff --git a/sdks/js-sdk/src/crypto/utils.ts b/sdks/js-sdk/src/crypto/utils.ts index 93bc5c0a3..aeeab071a 100644 --- a/sdks/js-sdk/src/crypto/utils.ts +++ b/sdks/js-sdk/src/crypto/utils.ts @@ -30,6 +30,7 @@ export function equalBytes(b1: Uint8Array, b2: Uint8Array): boolean { * Compute the Ethereum address from uncompressed PublicKey bytes */ export function computeAddress(bytes: Uint8Array) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion const publicKey = viemBytesToHex(bytes.slice(1)) as Hex; const hash = keccak256(publicKey); const address = hash.substring(hash.length - 40); diff --git a/sdks/js-sdk/src/keystore/InMemoryKeystore.ts b/sdks/js-sdk/src/keystore/InMemoryKeystore.ts index 155529d18..71d934115 100644 --- a/sdks/js-sdk/src/keystore/InMemoryKeystore.ts +++ b/sdks/js-sdk/src/keystore/InMemoryKeystore.ts @@ -239,6 +239,7 @@ export default class InMemoryKeystore implements KeystoreInterface { async (req) => { const { payload } = req; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!payload) { throw new KeystoreError( ErrorCode.ERROR_CODE_INVALID_INPUT, @@ -269,6 +270,7 @@ export default class InMemoryKeystore implements KeystoreInterface { async (req) => { const { payload } = req; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!payload) { throw new KeystoreError( ErrorCode.ERROR_CODE_INVALID_INPUT, @@ -415,6 +417,7 @@ export default class InMemoryKeystore implements KeystoreInterface { const sortedAddresses = [myAddress, theirAddress].sort(); const msgString = + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition (req.context?.conversationId || "") + sortedAddresses.join(); const msgBytes = new TextEncoder().encode(msgString); @@ -485,6 +488,7 @@ export default class InMemoryKeystore implements KeystoreInterface { Number.isInteger(prekeyIndex) ) { key = this.v1Keys.preKeys[prekeyIndex]; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!key) { throw new KeystoreError( ErrorCode.ERROR_CODE_NO_MATCHING_PREKEY, @@ -516,6 +520,7 @@ export default class InMemoryKeystore implements KeystoreInterface { return {}; } + // eslint-disable-next-line @typescript-eslint/require-await async getV1Conversations(): Promise { const convos = this.v1Store.topics.map( this.topicDataToV1ConversationReference.bind(this), @@ -524,6 +529,7 @@ export default class InMemoryKeystore implements KeystoreInterface { return { conversations: convos }; } + // eslint-disable-next-line @typescript-eslint/require-await async getV2Conversations(): Promise { const convos = this.v2Store.topics.map((invite) => topicDataToV2ConversationReference(invite as TopicData), @@ -538,10 +544,12 @@ export default class InMemoryKeystore implements KeystoreInterface { }); } + // eslint-disable-next-line @typescript-eslint/require-await async getPublicKeyBundle(): Promise { return this.v1Keys.getPublicKeyBundle(); } + // eslint-disable-next-line @typescript-eslint/require-await async getPrivateKeyBundle(): Promise { return this.v1Keys; } @@ -576,6 +584,7 @@ export default class InMemoryKeystore implements KeystoreInterface { jobType, lastRunNs, }: keystore.SetRefeshJobRequest): Promise { + // eslint-disable-next-line @typescript-eslint/await-thenable const key = await this.buildJobStorageKey(jobType); await this.jobStatePersistence.setItem( key, @@ -699,8 +708,10 @@ export default class InMemoryKeystore implements KeystoreInterface { // encrypted message const messages = responses.reduce((result, response) => { return response.result?.encrypted - ? result.concat(response.result?.encrypted) + ? // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + result.concat(response.result?.encrypted) : result; + // eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter }, [] as Uint8Array[]); const contentTopic = await this.getPrivatePreferencesTopic(); diff --git a/sdks/js-sdk/src/keystore/SnapKeystore.ts b/sdks/js-sdk/src/keystore/SnapKeystore.ts index 840947210..56b408760 100644 --- a/sdks/js-sdk/src/keystore/SnapKeystore.ts +++ b/sdks/js-sdk/src/keystore/SnapKeystore.ts @@ -22,12 +22,13 @@ export function SnapKeystore( for (const [method, rpc] of Object.entries( snapApiDefs, ) as SnapKeystoreApiEntries) { + // eslint-disable-next-line @typescript-eslint/require-await generatedMethods[method] = async (req?: SnapKeystoreApiRequestValues) => { if (!rpc.req) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-unsafe-return return snapRPC(method, rpc, undefined, snapMeta, snapId) as any; } - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-argument return snapRPC(method, rpc, req as any, snapMeta, snapId) as any; }; } @@ -35,6 +36,7 @@ export function SnapKeystore( return { ...generatedMethods, // Don't bother calling the keystore, since we already have the wallet address + // eslint-disable-next-line @typescript-eslint/require-await async getAccountAddress() { return walletAddress; }, diff --git a/sdks/js-sdk/src/keystore/conversationStores.ts b/sdks/js-sdk/src/keystore/conversationStores.ts index b82212f2b..9df42c23a 100644 --- a/sdks/js-sdk/src/keystore/conversationStores.ts +++ b/sdks/js-sdk/src/keystore/conversationStores.ts @@ -150,6 +150,7 @@ export class V1Store extends V2Store { return !!( topicData.topic && topicData.topic.length && + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition topicData.peerAddress?.length > 0 ); } diff --git a/sdks/js-sdk/src/keystore/persistence/BrowserStoragePersistence.ts b/sdks/js-sdk/src/keystore/persistence/BrowserStoragePersistence.ts index a52d835ad..cea6da240 100644 --- a/sdks/js-sdk/src/keystore/persistence/BrowserStoragePersistence.ts +++ b/sdks/js-sdk/src/keystore/persistence/BrowserStoragePersistence.ts @@ -13,6 +13,7 @@ export default class BrowserStoragePersistence implements Persistence { return new BrowserStoragePersistence(localStorage); } + // eslint-disable-next-line @typescript-eslint/require-await async getItem(key: string): Promise { const value = this.storage.getItem(key); if (value === null) { @@ -21,6 +22,7 @@ export default class BrowserStoragePersistence implements Persistence { return Uint8Array.from(Buffer.from(value, "binary")); } + // eslint-disable-next-line @typescript-eslint/require-await async setItem(key: string, value: Uint8Array): Promise { this.storage.setItem(key, Buffer.from(value).toString("binary")); } diff --git a/sdks/js-sdk/src/keystore/persistence/LocalStoragePonyfill.ts b/sdks/js-sdk/src/keystore/persistence/LocalStoragePonyfill.ts index 75f059d0a..3cb36448a 100644 --- a/sdks/js-sdk/src/keystore/persistence/LocalStoragePonyfill.ts +++ b/sdks/js-sdk/src/keystore/persistence/LocalStoragePonyfill.ts @@ -26,6 +26,7 @@ export default class LocalStoragePonyfill implements Storage { } key(index: number): string | null { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (index === undefined) { // This is the TypeError implemented in Chrome, Firefox throws "Storage.key: At least 1 // argument required, but only 0 passed". diff --git a/sdks/js-sdk/src/keystore/privatePreferencesStore.ts b/sdks/js-sdk/src/keystore/privatePreferencesStore.ts index 389564453..a574653e2 100644 --- a/sdks/js-sdk/src/keystore/privatePreferencesStore.ts +++ b/sdks/js-sdk/src/keystore/privatePreferencesStore.ts @@ -100,6 +100,7 @@ export class PrivatePreferencesStore { for (let i = 0; i < keys.length; i++) { // ignore duplicate actions if (!this.actionsMap.has(keys[i])) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.actionsMap.set(keys[i], actionsMap.get(keys[i])!); // indicate new value added isDirty = true; @@ -117,6 +118,7 @@ export class PrivatePreferencesStore { const sortedActions = new Map( [...this.actionsMap.entries()].sort( (a, b) => + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion fromNanoString(a[0])!.getTime() - fromNanoString(b[0])!.getTime(), ), ); diff --git a/sdks/js-sdk/src/keystore/providers/NetworkKeyManager.ts b/sdks/js-sdk/src/keystore/providers/NetworkKeyManager.ts index a84f72db2..25c724c79 100644 --- a/sdks/js-sdk/src/keystore/providers/NetworkKeyManager.ts +++ b/sdks/js-sdk/src/keystore/providers/NetworkKeyManager.ts @@ -100,6 +100,7 @@ export default class NetworkKeyManager { signature: sig as Hex, }); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, @typescript-eslint/no-misused-promises if (!valid) { throw new Error("invalid signature"); } @@ -121,6 +122,7 @@ export default class NetworkKeyManager { ): Promise<[PrivateKeyBundleV1, boolean]> { const [eBundle, needsUpdate] = getEncryptedBundle(bytes); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!eBundle.walletPreKey) { throw new Error("missing wallet pre-key"); } @@ -148,6 +150,7 @@ export default class NetworkKeyManager { const decrypted = await decrypt(ciphertext, secret); const [bundle, needsUpdate2] = getPrivateBundle(decrypted); return [bundle, needsUpdate || needsUpdate2]; + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { // Assert that the secret is length 65 (encoded signature + recovery byte) if (secret.length !== 65) { @@ -183,6 +186,7 @@ function getEncryptedBundle( if (b.v1) { return [b.v1, false]; } + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { return [proto.EncryptedPrivateKeyBundleV1.decode(bytes), true]; } @@ -199,6 +203,7 @@ function getPrivateBundle(bytes: Uint8Array): [PrivateKeyBundleV1, boolean] { throw new Error("V2 bundles not supported yet"); } return [b, false]; + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { // Adds a default fallback for older versions of the proto const b = proto.PrivateKeyBundleV1.decode(bytes); diff --git a/sdks/js-sdk/src/keystore/snapHelpers.ts b/sdks/js-sdk/src/keystore/snapHelpers.ts index f758dcf3a..6d40826c7 100644 --- a/sdks/js-sdk/src/keystore/snapHelpers.ts +++ b/sdks/js-sdk/src/keystore/snapHelpers.ts @@ -69,6 +69,7 @@ export async function snapRequest( if (typeof req === "string") { params.req = req; } + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition const response = await getEthereum()?.request({ method: "wallet_invokeSnap", params: { @@ -103,6 +104,7 @@ export type GetSnapsResponse = Record; export async function hasMetamaskWithSnaps() { const ethereum = getEthereum(); // Naive way of detecting snaps support + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (ethereum?.isMetaMask) { try { await ethereum.request({ @@ -114,6 +116,7 @@ export async function hasMetamaskWithSnaps() { } } if ( + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition typeof ethereum?.detected !== "undefined" && Array.isArray(ethereum.detected) ) { @@ -124,6 +127,7 @@ export async function hasMetamaskWithSnaps() { method: "wallet_getSnaps", }); // enforces MetaMask as provider + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition ethereum?.setProvider?.(provider); return true; @@ -134,6 +138,7 @@ export async function hasMetamaskWithSnaps() { } if ( + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition typeof ethereum?.providers !== "undefined" && Array.isArray(ethereum.providers) ) { @@ -157,6 +162,7 @@ export async function hasMetamaskWithSnaps() { } export async function getSnaps() { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition return await getEthereum()?.request({ method: "wallet_getSnaps", }); @@ -187,8 +193,10 @@ export async function getSnap( export async function connectSnap( snapId: string, + // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents params: Record<"version" | string, unknown> = {}, ) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition await getEthereum()?.request({ method: "wallet_requestSnaps", params: { diff --git a/sdks/js-sdk/src/keystore/utils.ts b/sdks/js-sdk/src/keystore/utils.ts index 093bc7441..2e6f72bd9 100644 --- a/sdks/js-sdk/src/keystore/utils.ts +++ b/sdks/js-sdk/src/keystore/utils.ts @@ -86,6 +86,7 @@ export const validateObject = ( for (const field of arrayFields) { const val = obj[field]; // @ts-expect-error does not know it's an array + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!val || !val?.length) { throw new KeystoreError( keystore.ErrorCode.ERROR_CODE_INVALID_INPUT, diff --git a/sdks/js-sdk/src/utils/async.ts b/sdks/js-sdk/src/utils/async.ts index 7a867fed7..0ffbb5403 100644 --- a/sdks/js-sdk/src/utils/async.ts +++ b/sdks/js-sdk/src/utils/async.ts @@ -14,6 +14,7 @@ export const promiseWithTimeout = ( let timeoutHandle: NodeJS.Timeout; const timeoutPromise = new Promise((_resolve, reject) => { timeoutHandle = setTimeout( + // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression () => reject(new Error(failureMessage)), timeoutMs, ); @@ -39,7 +40,9 @@ export async function retry any>( ): Promise>> { const currRetry = typeof retryCount === "number" ? retryCount : 1; try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const result = await fn(...args); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return return result; } catch (e) { if (!isRetryableFn(e as Error) || currRetry > maxRetries) { diff --git a/sdks/js-sdk/src/utils/keystore.ts b/sdks/js-sdk/src/utils/keystore.ts index a90c0766e..f302221ed 100644 --- a/sdks/js-sdk/src/utils/keystore.ts +++ b/sdks/js-sdk/src/utils/keystore.ts @@ -34,6 +34,7 @@ export const getResultOrThrow = < throw new Error("Missing ciphertext"); } + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if ("decrypted" in response.result && !response.result.decrypted) { throw new Error("Missing decrypted result"); } diff --git a/sdks/js-sdk/src/utils/topic.ts b/sdks/js-sdk/src/utils/topic.ts index 5fe55ff81..bc522fb30 100644 --- a/sdks/js-sdk/src/utils/topic.ts +++ b/sdks/js-sdk/src/utils/topic.ts @@ -42,7 +42,6 @@ export const buildUserPrivatePreferencesTopic = (identifier: string) => // validate that a topic only contains ASCII characters 33-127 export const isValidTopic = (topic: string): boolean => { - // eslint-disable-next-line no-control-regex const regex = /^[\x21-\x7F]+$/; const index = topic.indexOf("0/"); if (index !== -1) { diff --git a/sdks/js-sdk/src/utils/viem.ts b/sdks/js-sdk/src/utils/viem.ts index a931d0a73..19132413c 100644 --- a/sdks/js-sdk/src/utils/viem.ts +++ b/sdks/js-sdk/src/utils/viem.ts @@ -25,11 +25,13 @@ export function convertWalletClientToSigner( walletClient: WalletClient, ): Signer { const { account } = walletClient; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!account || !account.address) { throw new Error("WalletClient is not configured"); } return { + // eslint-disable-next-line @typescript-eslint/require-await getAddress: async () => account.address, signMessage: async (message: string | Uint8Array) => walletClient.signMessage({ diff --git a/sdks/js-sdk/test/Contacts.test.ts b/sdks/js-sdk/test/Contacts.test.ts index 0b10a64c6..4c50afa73 100644 --- a/sdks/js-sdk/test/Contacts.test.ts +++ b/sdks/js-sdk/test/Contacts.test.ts @@ -186,7 +186,6 @@ describe("Contacts", () => { await aliceClient.conversations.newConversation(bob.address); let numActions = 0; - // eslint-disable-next-line no-unreachable-loop for await (const action of aliceStream) { numActions++; expect(action.allowGroup).toBeUndefined(); diff --git a/sdks/js-sdk/test/ContentTypeTestKey.ts b/sdks/js-sdk/test/ContentTypeTestKey.ts index a805f4316..c650c2e67 100644 --- a/sdks/js-sdk/test/ContentTypeTestKey.ts +++ b/sdks/js-sdk/test/ContentTypeTestKey.ts @@ -30,7 +30,6 @@ export class TestKeyCodec implements ContentCodec { return new PublicKey(publicKey.PublicKey.decode(content.content)); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars fallback(content: PublicKey): string | undefined { return "publickey bundle"; } diff --git a/sdks/js-sdk/test/conversations/Conversations.test.ts b/sdks/js-sdk/test/conversations/Conversations.test.ts index bd5070697..72aa7641d 100644 --- a/sdks/js-sdk/test/conversations/Conversations.test.ts +++ b/sdks/js-sdk/test/conversations/Conversations.test.ts @@ -294,7 +294,6 @@ describe.sequential("Conversation streams", () => { await conversation.send("hi bob"); let numConversations = 0; - // eslint-disable-next-line no-unreachable-loop for await (const conversation of stream) { numConversations++; expect(conversation.peerAddress).toBe(bob.address); diff --git a/sdks/js-sdk/test/helpers.ts b/sdks/js-sdk/test/helpers.ts index 9b435e8c4..cb16d0199 100644 --- a/sdks/js-sdk/test/helpers.ts +++ b/sdks/js-sdk/test/helpers.ts @@ -134,7 +134,6 @@ export function wrapAsLedgerWallet(ethersWallet: Wallet): Signer { // A helper to replace a full Client in testing custom content types, // extracting just the codec registry aspect of the client. export class CodecRegistry { - // eslint-disable-next-line @typescript-eslint/no-explicit-any private _codecs: Map>; constructor() { @@ -142,14 +141,12 @@ export class CodecRegistry { this.registerCodec(new TextCodec()); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any registerCodec(codec: ContentCodec): void { const id = codec.contentType; const key = `${id.authorityId}/${id.typeId}`; this._codecs.set(key, codec); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any codecFor(contentType: ContentTypeId): ContentCodec | undefined { const key = `${contentType.authorityId}/${contentType.typeId}`; return this._codecs.get(key);